Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,62 +1,57 @@
<div class="row scroll-table mt-5 ml-0">
<table
class="table table-striped mb-0"
datatable
[dtTrigger]="dtTrigger"
[dtOptions]="dtOptions"
*ngIf="(reportDataSource$ | async) as dataSource">
<thead class="thead-blue">
<tr class="d-flex">
<th class="hidden-col">ID</th>
<th class="col md-col">User email</th>
<th class="col sm-col">Date</th>
<th class="col sm-col" title="Duration (hours)">Duration</th>
<th class="col x-sm-col" title="Time in">Time in</th>
<th class="col x-sm-col" title="Time out">Time out</th>
<th class="col md-col">Project</th>
<th class="hidden-col">Project ID</th>
<th class="col md-col">Customer</th>
<th class="hidden-col">Customer ID</th>
<th class="col md-col">Activity</th>
<th class="col lg-col">Ticket</th>
<th class="col lg-col">Description</th>
<th class="col lg-col">Technologies</th>
</tr>
</thead>
<app-loading-bar *ngIf="dataSource.isLoading"></app-loading-bar>
<tbody *ngIf="!dataSource.isLoading">
<tr class="d-flex" *ngFor="let entry of dataSource.data">
<td class="hidden-col">{{ entry.id }}</td>
<td class="col md-col">{{ entry.owner_email }}</td>
<td class="col sm-col">
{{ entry.start_date | date: 'MM/dd/yyyy' }}
</td>
<td class="col sm-col">
{{ entry.end_date | substractDate: entry.start_date }}
</td>
<td class="col x-sm-col">{{ entry.start_date | date: 'HH:mm' }}</td>
<td class="col x-sm-col">{{ entry.end_date | date: 'HH:mm' }}</td>
<td class="col md-col">{{ entry.project_name }}</td>
<td class="hidden-col">{{ entry.project_id }}</td>
<td class="col md-col">{{ entry.customer_name }}</td>
<td class="hidden-col">{{ entry.customer_id }}</td>
<td class="col md-col">{{ entry.activity_name }}</td>
<td class="col lg-col">
<ng-container *ngIf="entry.uri !== null">
<a [class.is-url]="isURL(entry.uri)" (click)="openURLInNewTab(entry.uri)">
<table class="table table-striped mb-0" datatable [dtTrigger]="dtTrigger" [dtOptions]="dtOptions" *ngIf="(reportDataSource$ | async) as dataSource">
<thead class="thead-blue">
<tr class="d-flex">
<th class="hidden-col">ID</th>
<th class="col md-col">User email</th>
<th class="col sm-col">Date</th>
<th class="col sm-col" title="Duration (hours)">Duration</th>
<th class="col x-sm-col" title="Time in">Time in</th>
<th class="col x-sm-col" title="Time out">Time out</th>
<th class="col md-col">Project</th>
<th class="hidden-col">Project ID</th>
<th class="col md-col">Customer</th>
<th class="hidden-col">Customer ID</th>
<th class="col md-col">Activity</th>
<th class="col lg-col">Ticket</th>
<th class="col lg-col">Description</th>
<th class="col lg-col">Technologies</th>
</tr>
</thead>
<app-loading-bar *ngIf="dataSource.isLoading"></app-loading-bar>
<tbody *ngIf="!dataSource.isLoading">
<tr class="d-flex" *ngFor="let entry of dataSource.data">
<td class="hidden-col">{{ entry.id }}</td>
<td class="col md-col">{{ entry.owner_email }}</td>
<td class="col sm-col">
{{ entry.start_date | date: 'MM/dd/yyyy' }}
</td>
<td class="col sm-col">
{{ entry.end_date | substractDate: entry.start_date }}
</td>
<td class="col x-sm-col">{{ dateTimeOffset.parseDateTimeOffset(entry.start_date,entry.timezone_offset) }}</td>
<td class="col x-sm-col">{{ dateTimeOffset.parseDateTimeOffset(entry.end_date , entry.timezone_offset) }}</td>
<td class="col md-col">{{ entry.project_name }}</td>
<td class="hidden-col">{{ entry.project_id }}</td>
<td class="col md-col">{{ entry.customer_name }}</td>
<td class="hidden-col">{{ entry.customer_id }}</td>
<td class="col md-col">{{ entry.activity_name }}</td>
<td class="col lg-col">
<ng-container *ngIf="entry.uri !== null">
<a [class.is-url]="isURL(entry.uri)" (click)="openURLInNewTab(entry.uri)">
{{ entry.uri }}
</a>
</ng-container>
</td>
<td class="col lg-col">{{ entry.description }}</td>
<td class="col lg-col">
<ng-container *ngIf="entry.technologies.length > 0">
<div *ngFor="let technology of entry.technologies" class="badge bg-secondary text-wrap">
{{ technology }}
</div>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</ng-container>
</td>
<td class="col lg-col">{{ entry.description }}</td>
<td class="col lg-col">
<ng-container *ngIf="entry.technologies.length > 0">
<div *ngFor="let technology of entry.technologies" class="badge bg-secondary text-wrap">
{{ technology }}
</div>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Entry } from 'src/app/modules/shared/models';
import { DataSource } from 'src/app/modules/shared/models/data-source.model';
import { EntryState } from '../../../time-clock/store/entry.reducer';
import { getReportDataSource } from '../../../time-clock/store/entry.selectors';
import { ParseDateTimeOffset } from '../../../shared/formatters/parse-date-time-offset/parse-date-time-offset';

@Component({
selector: 'app-time-entries-table',
Expand Down Expand Up @@ -60,9 +61,11 @@ export class TimeEntriesTableComponent implements OnInit, OnDestroy, AfterViewIn
isLoading$: Observable<boolean>;
reportDataSource$: Observable<DataSource<Entry>>;
rerenderTableSubscription: Subscription;
dateTimeOffset: ParseDateTimeOffset;

constructor(private store: Store<EntryState>) {
this.reportDataSource$ = this.store.pipe(select(getReportDataSource));
this.dateTimeOffset = new ParseDateTimeOffset();
}

ngOnInit(): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ParseDateTimeOffset } from './parse-date-time-offset';

describe('ParseDateToUtcComponent', () => {

it('returns converted date when his offset is 300', () => {
let parseTimeOffset = new ParseDateTimeOffset();
const date = '2022-03-30T13:00:00Z';
const timezone_offset = 300;
const dateOffset:string = '08:00';

expect(parseTimeOffset.parseDateTimeOffset(date, timezone_offset)).toEqual(dateOffset);
});

it('returns converted date when his offset is 420', () => {
let parseTimeOffset = new ParseDateTimeOffset();
const date = '2022-03-30T16:30:00Z';
const timezone_offset = 420;
const dateOffset:string = '09:30';

expect(parseTimeOffset.parseDateTimeOffset(date, timezone_offset)).toEqual(dateOffset);
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as moment from 'moment';

export class ParseDateTimeOffset {

parseDateTimeOffset(date:string, offset): string{
return moment.utc(date).utcOffset(-1*offset).format("HH:mm");
}
}
170 changes: 60 additions & 110 deletions src/app/modules/time-entries/pages/time-entries.component.html
Original file line number Diff line number Diff line change
@@ -1,135 +1,85 @@
<div>
<div>
<button
type="button"
(click)="newEntry()"
data-toggle="modal"
data-target="#editRecordsByDate"
class="btn btn-primary"
>
<div>
<button type="button" (click)="newEntry()" data-toggle="modal" data-target="#editRecordsByDate" class="btn btn-primary">
Add new entry
</button>
<button
type="button"
(click)="onDisplayModeChange()"
class="btn btn-primary float-right"
*ngIf="isFeatureToggleCalendarActive"
>
<button type="button" (click)="onDisplayModeChange()" class="btn btn-primary float-right" *ngIf="isFeatureToggleCalendarActive">
<em class="fas fa-list" *ngIf="displayGridView"></em>
<em class="fas fa-th" *ngIf="!displayGridView"></em>
</button>
</div>
<div style="height: 15px"></div>
<app-month-picker [selectedDate]="selectedDate" (dateSelected)="dateSelected($event)"></app-month-picker>
<div style="height: 15px"></div>
</div>
<div style="height: 15px"></div>
<app-month-picker [selectedDate]="selectedDate" (dateSelected)="dateSelected($event)"></app-month-picker>
<div style="height: 15px"></div>


<div id="gridView" [hidden]="!displayGridView">
<div *ngIf="timeEntriesDataSource$ | async as dataSource">
<app-loading-bar *ngIf="dataSource.isLoading"></app-loading-bar>
<app-calendar
*ngIf="!dataSource.isLoading"
[timeEntries$]="timeEntriesDataSource$"
[currentDate]="selectedDate.toDate()"
[calendarView]="calendarView"
(changeDate)="changeDate($event)"
(changeView)="changeView($event)"
(viewModal)="editEntry($event.id)"
(deleteTimeEntry)="openModal($event.timeEntry)"
>
</app-calendar>
<div id="gridView" [hidden]="!displayGridView">
<div *ngIf="timeEntriesDataSource$ | async as dataSource">
<app-loading-bar *ngIf="dataSource.isLoading"></app-loading-bar>
<app-calendar *ngIf="!dataSource.isLoading" [timeEntries$]="timeEntriesDataSource$" [currentDate]="selectedDate.toDate()" [calendarView]="calendarView" (changeDate)="changeDate($event)" (changeView)="changeView($event)" (viewModal)="editEntry($event.id)"
(deleteTimeEntry)="openModal($event.timeEntry)">
</app-calendar>
</div>
</div>
</div>

<div id="listView" [hidden]="displayGridView">
<table
class="table table-sm table-striped mb-0"
datatable
[dtTrigger]="dtTrigger"
[dtOptions]="dtOptions"
*ngIf="(timeEntriesDataSource$ | async) as dataSource">
<caption></caption>
<thead class="thead-blue">
<tr class="d-flex">
<th class="col">Date</th>
<th class="col">Time in - out</th>
<th class="col">Duration</th>
<th class="col">Customer</th>
<th class="col">Project</th>
<th class="col">Activity</th>
<th class="col"></th>
</tr>
</thead>
<app-loading-bar *ngIf="dataSource.isLoading"></app-loading-bar>
<tbody *ngIf="!dataSource.isLoading">
<tr class="d-flex" *ngFor="let entry of dataSource.data">
<td class="col">{{ entry.start_date | date: 'MM/dd/yyyy' }}</td>
<td class="col">{{ entry.start_date | date: 'HH:mm' }} - {{ entry.end_date | date: 'HH:mm' }}</td>
<td class="col">{{ entry.end_date | substractDate: entry.start_date }}</td>
<td class="col">{{ entry.customer_name }}</td>
<td class="col">{{ entry.project_name }}</td>
<td class="col">{{ entry.activity_name }}</td>
<td class="col">
<button
class="btn btn-sm btn-primary"
data-toggle="modal"
data-target="#editRecordsByDate"
(click)="editEntry(entry.id)"
>
<div id="listView" [hidden]="displayGridView">
<table class="table table-sm table-striped mb-0" datatable [dtTrigger]="dtTrigger" [dtOptions]="dtOptions" *ngIf="(timeEntriesDataSource$ | async) as dataSource">
<caption></caption>
<thead class="thead-blue">
<tr class="d-flex">
<th class="col">Date</th>
<th class="col">Time in - out</th>
<th class="col">Duration</th>
<th class="col">Customer</th>
<th class="col">Project</th>
<th class="col">Activity</th>
<th class="col"></th>
</tr>
</thead>
<app-loading-bar *ngIf="dataSource.isLoading"></app-loading-bar>
<tbody *ngIf="!dataSource.isLoading">
<tr class="d-flex" *ngFor="let entry of dataSource.data">
<td class="col">{{ entry.start_date | date: 'MM/dd/yyyy' }}</td>
<td class="col">{{ dateTimeOffset.parseDateTimeOffset(entry.start_date,entry.timezone_offset) }} - {{ dateTimeOffset.parseDateTimeOffset(entry.end_date,entry.timezone_offset) }}</td>
<td class="col">{{ entry.end_date | substractDate: entry.start_date }}</td>
<td class="col">{{ entry.customer_name }}</td>
<td class="col">{{ entry.project_name }}</td>
<td class="col">{{ entry.activity_name }}</td>
<td class="col">
<button class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editRecordsByDate" (click)="editEntry(entry.id)">
<i class="fa fa-edit fa-xs"></i>
</button>
<button
class="btn btn-sm btn-danger ml-2"
data-toggle="modal"
data-target="#deleteModal"
(click)="openModal(entry)"
>
<button class="btn btn-sm btn-danger ml-2" data-toggle="modal" data-target="#deleteModal" (click)="openModal(entry)">
<i class="fa fa-trash fa-xs"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>

<div class="modal fade" id="editRecordsByDate" tabindex="-1" role="dialog">
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content" cdkDrag (cdkDragEnded)="resetDraggablePosition($event)">
<div class="modal-header">
<h5 class="modal-title">{{ entryId ? 'Edit Entry' : 'New Entry' }}</h5>
<div>
<button class="btn shadow-none" data-bs-toggle="tooltip" title="Clean form values" (click)="detailsFields.cleanFieldsForm()">
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content" cdkDrag (cdkDragEnded)="resetDraggablePosition($event)">
<div class="modal-header">
<h5 class="modal-title">{{ entryId ? 'Edit Entry' : 'New Entry' }}</h5>
<div>
<button class="btn shadow-none" data-bs-toggle="tooltip" title="Clean form values" (click)="detailsFields.cleanFieldsForm()">
<em class="fa fa-eraser"> </em>
</button>
<button class="btn shadow-none" data-bs-toggle="tooltip" title="Drag modal" cdkDragHandle>
<button class="btn shadow-none" data-bs-toggle="tooltip" title="Drag modal" cdkDragHandle>
<em class="fa fa-grip-vertical"></em>
</button>
</div>
</div>
<div class="modal-body">
<app-details-fields [entryToEdit]="entry" (saveEntry)="saveEntry($event)" (projectSelected)="projectSelected($event)" [canMarkEntryAsWIP]="canMarkEntryAsWIP" #detailsFields>
</app-details-fields>
</div>
</div>
</div>
<div class="modal-body">
<app-details-fields
[entryToEdit]="entry"
(saveEntry)="saveEntry($event)"
(projectSelected)="projectSelected($event)"
[canMarkEntryAsWIP]="canMarkEntryAsWIP"
#detailsFields
>
</app-details-fields>
</div>
</div>
</div>
</div>

<app-dialog
*ngIf="showModal"
class="modal fade"
id="deleteModal"
tabindex="-1"
role="dialog"
aria-hidden="true"
[body]="message"
[title]="'Delete Entry'"
(closeModalEvent)="removeEntry()"
>
</app-dialog>
<app-dialog *ngIf="showModal" class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-hidden="true" [body]="message" [title]="'Delete Entry'" (closeModalEvent)="removeEntry()">
</app-dialog>
Loading