diff --git a/apps/desktop/package.json b/apps/desktop/package.json
index 3a66fc54cc2..c5370df3f7c 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -43,7 +43,6 @@
"@gauzy/contracts": "^0.1.0",
"@gauzy/desktop-ui-lib": "^0.1.0",
"@gauzy/ui-config": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@grpc/grpc-js": "^1.6.7",
"@nebular/auth": "^12.0.0",
"@nebular/bootstrap": "^9.1.0-rc.6",
diff --git a/apps/desktop/src/index.ts b/apps/desktop/src/index.ts
index 5a4b90ece56..0b765566938 100644
--- a/apps/desktop/src/index.ts
+++ b/apps/desktop/src/index.ts
@@ -5,10 +5,10 @@ import log from 'electron-log';
console.log = log.log;
Object.assign(console, log.functions);
-import * as path from 'path';
-import { app, BrowserWindow, ipcMain, Menu, shell, MenuItemConstructorOptions, dialog, nativeTheme } from 'electron';
import * as remoteMain from '@electron/remote/main';
import { setupTitlebar } from 'custom-electron-titlebar/main';
+import { BrowserWindow, Menu, MenuItemConstructorOptions, app, dialog, ipcMain, nativeTheme, shell } from 'electron';
+import * as path from 'path';
import { environment } from './environments/environment';
@@ -29,6 +29,7 @@ import {
AppError,
AppMenu,
DesktopServer,
+ DesktopThemeListener,
DesktopUpdater,
DialogErrorHandler,
ErrorEventManager,
@@ -43,8 +44,7 @@ import {
ipcMainHandler,
ipcTimer,
removeMainListener,
- removeTimerListener,
- DesktopThemeListener
+ removeTimerListener
} from '@gauzy/desktop-libs';
import {
AlwaysOn,
@@ -57,10 +57,10 @@ import {
createTimeTrackerWindow,
createUpdaterWindow
} from '@gauzy/desktop-window';
-import { initSentry } from './sentry';
+import * as Sentry from '@sentry/electron';
import { fork } from 'child_process';
import { autoUpdater } from 'electron-updater';
-import * as Sentry from '@sentry/electron';
+import { initSentry } from './sentry';
// the folder where all app data will be stored (e.g. sqlite DB, settings, cache, etc)
// C:\Users\USERNAME\AppData\Roaming\gauzy-desktop
@@ -535,7 +535,7 @@ app.on('ready', async () => {
timeTrackerWindow,
settingsWindow,
updaterWindow,
- imageViewWindow: imageView,
+ imageViewerWindow: imageView,
gauzyWindow,
splashScreenWindow: splashScreen.browserWindow,
alwaysOnWindow: alwaysOn.browserWindow
diff --git a/apps/desktop/src/package.json b/apps/desktop/src/package.json
index 525acd156ee..f5452aa0e7f 100644
--- a/apps/desktop/src/package.json
+++ b/apps/desktop/src/package.json
@@ -29,6 +29,7 @@
"../../../packages/config",
"../../../packages/contracts",
"../../../packages/ui-config",
+ "../../../packages/ui-core",
"../../../packages/plugin",
"../../../packages/plugins/integration-ai",
"../../../packages/plugins/integration-hubstaff",
diff --git a/apps/gauzy/package.json b/apps/gauzy/package.json
index 5d41c85beb5..584846b9852 100644
--- a/apps/gauzy/package.json
+++ b/apps/gauzy/package.json
@@ -68,7 +68,6 @@
"@gauzy/plugin-onboarding-ui": "^0.1.0",
"@gauzy/plugin-public-layout-ui": "^0.1.0",
"@gauzy/ui-config": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@jitsu/js": "^1.8.2",
"@kurkle/color": "^0.2.0",
"@nebular/auth": "^12.0.0",
diff --git a/apps/gauzy/src/app/pages/dashboard/dashboard.module.ts b/apps/gauzy/src/app/pages/dashboard/dashboard.module.ts
index 081f2109e83..4200f5f303b 100644
--- a/apps/gauzy/src/app/pages/dashboard/dashboard.module.ts
+++ b/apps/gauzy/src/app/pages/dashboard/dashboard.module.ts
@@ -1,31 +1,45 @@
import { NgModule } from '@angular/core';
import {
NbAlertModule,
+ NbBadgeModule,
NbButtonModule,
NbCardModule,
NbDialogModule,
NbIconModule,
NbInputModule,
+ NbListModule,
+ NbPopoverModule,
+ NbProgressBarModule,
NbRouteTabsetModule,
NbSelectModule,
NbSpinnerModule,
+ NbToggleModule,
NbTooltipModule,
NbTreeGridModule
} from '@nebular/theme';
import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { NgChartsModule } from 'ng2-charts';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { NgxPermissionsModule } from 'ngx-permissions';
-import { TranslateModule } from '@ngx-translate/core';
+import { SwiperModule } from 'swiper/angular';
import {
+ ActivityItemModule,
+ CounterPointModule,
DynamicTabsModule,
+ GalleryModule,
InfoBlockModule,
LineChartModule,
NoDataMessageModule,
ProfitHistoryModule,
RecordsHistoryModule,
+ ScreenshotsItemModule,
SharedModule,
SingleStatisticModule,
TableComponentsModule,
+ TimezoneFilterModule,
+ WidgetLayoutModule,
+ WindowLayoutModule,
WorkInProgressModule
} from '@gauzy/ui-core/shared';
import { DashboardRoutingModule } from './dashboard-routing.module';
@@ -34,22 +48,32 @@ import { DataEntryShortcutsComponent } from './data-entry-shortcuts/data-entry-s
import { HumanResourcesComponent } from './human-resources/human-resources.component';
import { AccountingComponent } from './accounting/accounting.component';
import { ProjectManagementComponent } from './project-management/project-management.component';
-import { EmployeeChartsModule } from './human-resources/employee-charts/employee-charts.module';
-import { TimeTrackingModule } from './time-tracking/time-tracking.module';
import { ProjectManagementDetailsComponent } from './project-management/project-management-details/project-management-details.component';
-import { TeamModule } from './team/team.module';
+import { TimeTrackingComponent } from './time-tracking/time-tracking.component';
+import {
+ EmployeeChartsComponent,
+ EmployeeDoughnutChartComponent,
+ EmployeeHorizontalBarChartComponent,
+ EmployeeStackedBarChartComponent
+} from './employee-charts';
+import { AllTeamComponent, ChartComponent, TeamCardComponent, TeamComponent, TeamMemberComponent } from './team';
// NB Modules
const NB_MODULES = [
NbAlertModule,
+ NbBadgeModule,
NbButtonModule,
NbCardModule,
NbDialogModule.forChild(),
NbIconModule,
NbInputModule,
+ NbListModule,
+ NbPopoverModule,
+ NbProgressBarModule,
NbRouteTabsetModule,
NbSelectModule,
NbSpinnerModule,
+ NbToggleModule,
NbTooltipModule,
NbTreeGridModule
];
@@ -60,9 +84,31 @@ const THIRD_PARTY_MODULES = [
LineChartModule,
NgSelectModule,
NgxPermissionsModule.forChild(),
+ NgChartsModule,
+ SwiperModule,
TranslateModule.forChild()
];
+// Components
+const COMPONENTS = [
+ DashboardComponent,
+ DataEntryShortcutsComponent,
+ AccountingComponent,
+ HumanResourcesComponent,
+ ProjectManagementComponent,
+ ProjectManagementDetailsComponent,
+ TimeTrackingComponent,
+ EmployeeChartsComponent,
+ EmployeeHorizontalBarChartComponent,
+ EmployeeStackedBarChartComponent,
+ EmployeeDoughnutChartComponent,
+ TeamComponent,
+ TeamCardComponent,
+ TeamMemberComponent,
+ ChartComponent,
+ AllTeamComponent
+];
+
@NgModule({
imports: [
DashboardRoutingModule,
@@ -71,26 +117,21 @@ const THIRD_PARTY_MODULES = [
// Feature Modules
RecordsHistoryModule,
ProfitHistoryModule,
- EmployeeChartsModule,
SingleStatisticModule,
InfoBlockModule,
- TimeTrackingModule,
- TeamModule,
- // Shared Modules
SharedModule,
TableComponentsModule,
NoDataMessageModule,
WorkInProgressModule,
- // Custom Modules
- DynamicTabsModule
+ ActivityItemModule,
+ CounterPointModule,
+ DynamicTabsModule,
+ GalleryModule,
+ ScreenshotsItemModule,
+ TimezoneFilterModule,
+ WidgetLayoutModule,
+ WindowLayoutModule
],
- declarations: [
- DashboardComponent,
- AccountingComponent,
- HumanResourcesComponent,
- DataEntryShortcutsComponent,
- ProjectManagementComponent,
- ProjectManagementDetailsComponent
- ]
+ declarations: [...COMPONENTS]
})
export class DashboardModule {}
diff --git a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.component.html b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-charts.component.html
similarity index 100%
rename from apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.component.html
rename to apps/gauzy/src/app/pages/dashboard/employee-charts/employee-charts.component.html
diff --git a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.component.scss b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-charts.component.scss
similarity index 100%
rename from apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.component.scss
rename to apps/gauzy/src/app/pages/dashboard/employee-charts/employee-charts.component.scss
diff --git a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.component.ts b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-charts.component.ts
similarity index 96%
rename from apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.component.ts
rename to apps/gauzy/src/app/pages/dashboard/employee-charts/employee-charts.component.ts
index 6a951aab8f3..383922edd8f 100644
--- a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-charts.component.ts
@@ -16,9 +16,7 @@ export class EmployeeChartsComponent implements OnInit {
selectedChart = EmployeeChartEnum.BAR;
EmployeeChartEnum: typeof EmployeeChartEnum = EmployeeChartEnum;
- @Input() employeeStatistics: IMonthAggregatedEmployeeStatistics[];
-
- constructor() {}
+ @Input() employeeStatistics: IMonthAggregatedEmployeeStatistics[] = [];
ngOnInit() {}
}
diff --git a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-doughnut-chart/employee-doughnut-chart.component.ts b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-doughnut-chart/employee-doughnut-chart.component.ts
similarity index 100%
rename from apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-doughnut-chart/employee-doughnut-chart.component.ts
rename to apps/gauzy/src/app/pages/dashboard/employee-charts/employee-doughnut-chart/employee-doughnut-chart.component.ts
diff --git a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-horizontal-bar-chart/employee-horizontal-bar-chart.component.ts b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-horizontal-bar-chart/employee-horizontal-bar-chart.component.ts
similarity index 100%
rename from apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-horizontal-bar-chart/employee-horizontal-bar-chart.component.ts
rename to apps/gauzy/src/app/pages/dashboard/employee-charts/employee-horizontal-bar-chart/employee-horizontal-bar-chart.component.ts
index 4af862bbf2d..42841a07bda 100644
--- a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-horizontal-bar-chart/employee-horizontal-bar-chart.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-horizontal-bar-chart/employee-horizontal-bar-chart.component.ts
@@ -7,11 +7,11 @@ import { debounceTime, filter, tap } from 'rxjs/operators';
import { BaseChartDirective } from 'ng2-charts';
import { ChartConfiguration, ChartType } from 'chart.js';
import { environment } from '@gauzy/ui-config';
-import { TranslationBaseComponent } from '@gauzy/ui-core/i18n';
import { CurrencyPosition, IMonthAggregatedEmployeeStatistics, IOrganization } from '@gauzy/contracts';
import { distinctUntilChange } from '@gauzy/ui-core/common';
-import { CurrencyPositionPipe } from '@gauzy/ui-core/shared';
import { Store, months } from '@gauzy/ui-core/core';
+import { TranslationBaseComponent } from '@gauzy/ui-core/i18n';
+import { CurrencyPositionPipe } from '@gauzy/ui-core/shared';
@UntilDestroy({ checkProperties: true })
@Component({
diff --git a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-stacked-bar-chart/employee-stacked-bar-chart.component.ts b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-stacked-bar-chart/employee-stacked-bar-chart.component.ts
similarity index 100%
rename from apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-stacked-bar-chart/employee-stacked-bar-chart.component.ts
rename to apps/gauzy/src/app/pages/dashboard/employee-charts/employee-stacked-bar-chart/employee-stacked-bar-chart.component.ts
index 487b7c39b88..d4aa1c52bb2 100644
--- a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-stacked-bar-chart/employee-stacked-bar-chart.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/employee-charts/employee-stacked-bar-chart/employee-stacked-bar-chart.component.ts
@@ -2,8 +2,8 @@ import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { TranslateService } from '@ngx-translate/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
-import { monthNames } from '@gauzy/ui-core/core';
import { IMonthAggregatedEmployeeStatistics } from '@gauzy/contracts';
+import { monthNames } from '@gauzy/ui-core/core';
import { TranslationBaseComponent } from '@gauzy/ui-core/i18n';
@UntilDestroy()
diff --git a/apps/gauzy/src/app/pages/dashboard/employee-charts/index.ts b/apps/gauzy/src/app/pages/dashboard/employee-charts/index.ts
new file mode 100644
index 00000000000..2dd3ef3d92d
--- /dev/null
+++ b/apps/gauzy/src/app/pages/dashboard/employee-charts/index.ts
@@ -0,0 +1,4 @@
+export * from './employee-charts.component';
+export * from './employee-stacked-bar-chart/employee-stacked-bar-chart.component';
+export * from './employee-doughnut-chart/employee-doughnut-chart.component';
+export * from './employee-horizontal-bar-chart/employee-horizontal-bar-chart.component';
diff --git a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.module.ts b/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.module.ts
deleted file mode 100644
index 248f22afd26..00000000000
--- a/apps/gauzy/src/app/pages/dashboard/human-resources/employee-charts/employee-charts.module.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { NbIconModule, NbSelectModule } from '@nebular/theme';
-import { NgChartsModule } from 'ng2-charts';
-import { TranslateModule } from '@ngx-translate/core';
-import { EmployeeChartsComponent } from './employee-charts.component';
-import { EmployeeDoughnutChartComponent } from './employee-doughnut-chart/employee-doughnut-chart.component';
-import { EmployeeHorizontalBarChartComponent } from './employee-horizontal-bar-chart/employee-horizontal-bar-chart.component';
-import { EmployeeStackedBarChartComponent } from './employee-stacked-bar-chart/employee-stacked-bar-chart.component';
-
-@NgModule({
- imports: [CommonModule, NgChartsModule, NbIconModule, NbSelectModule, TranslateModule.forChild()],
- exports: [EmployeeChartsComponent],
- declarations: [
- EmployeeChartsComponent,
- EmployeeHorizontalBarChartComponent,
- EmployeeStackedBarChartComponent,
- EmployeeDoughnutChartComponent
- ]
-})
-export class EmployeeChartsModule {}
diff --git a/apps/gauzy/src/app/pages/dashboard/project-management/project-management-details/project-management-details.component.html b/apps/gauzy/src/app/pages/dashboard/project-management/project-management-details/project-management-details.component.html
index 4b4e93b946c..a8ddebd7cb2 100644
--- a/apps/gauzy/src/app/pages/dashboard/project-management/project-management-details/project-management-details.component.html
+++ b/apps/gauzy/src/app/pages/dashboard/project-management/project-management-details/project-management-details.component.html
@@ -39,9 +39,7 @@
-
+
@@ -51,10 +49,7 @@
-
+
{{ 'DASHBOARD_PAGE.MOST_VIEW_PROJECTS' | translate }}
@@ -72,15 +67,11 @@
@@ -101,10 +92,7 @@
>
{{ 'BUTTONS.VIEW_ALL' | translate }}
-
+
diff --git a/apps/gauzy/src/app/pages/dashboard/project-management/project-management-details/project-management-details.component.ts b/apps/gauzy/src/app/pages/dashboard/project-management/project-management-details/project-management-details.component.ts
index 30d1181641a..15a6a928799 100644
--- a/apps/gauzy/src/app/pages/dashboard/project-management/project-management-details/project-management-details.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/project-management/project-management-details/project-management-details.component.ts
@@ -1,14 +1,14 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
+import { Router } from '@angular/router';
import { combineLatest, debounceTime, filter, first, firstValueFrom, Subject } from 'rxjs';
import { tap } from 'rxjs/operators';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService } from '@ngx-translate/core';
-import { pluck } from 'underscore';
import { NbDialogService } from '@nebular/theme';
-import { ErrorHandlingService, ServerDataSource, Store, TasksService } from '@gauzy/ui-core/core';
+import { pluck } from 'underscore';
import {
+ ID,
IOrganization,
IOrganizationProject,
ISelectedEmployee,
@@ -16,6 +16,7 @@ import {
PermissionsEnum,
TaskStatusEnum
} from '@gauzy/contracts';
+import { ErrorHandlingService, ServerDataSource, Store, TasksService } from '@gauzy/ui-core/core';
import { API_PREFIX, distinctUntilChange } from '@gauzy/ui-core/common';
import { AddTaskDialogComponent, PaginationFilterBaseComponent } from '@gauzy/ui-core/shared';
import { MyTaskDialogComponent } from '../../../tasks/components/my-task-dialog/my-task-dialog.component';
@@ -30,8 +31,8 @@ export class ProjectManagementDetailsComponent extends PaginationFilterBaseCompo
private _smartTableSource: ServerDataSource;
private _tasks: ITask[] = [];
private _selectedEmployee: ISelectedEmployee;
- public selectedEmployeeId: ISelectedEmployee['id'];
- private selectedProjectId: IOrganizationProject['id'];
+ public selectedEmployeeId: ID;
+ private selectedProjectId: ID;
private _organization: IOrganization;
private _task$: Subject
= this.subject$;
private _projects: IOrganizationProject[] = [];
@@ -101,26 +102,14 @@ export class ProjectManagementDetailsComponent extends PaginationFilterBaseCompo
this._smartTableSource = new ServerDataSource(this._httpClient, {
...(this.selectedEmployeeId
- ? {
- endPoint: `${API_PREFIX}/tasks/employee`
- }
- : {
- endPoint: `${API_PREFIX}/tasks/pagination`
- }),
+ ? { endPoint: `${API_PREFIX}/tasks/employee` }
+ : { endPoint: `${API_PREFIX}/tasks/pagination` }),
relations: ['project', 'tags'],
where: {
organizationId,
tenantId,
- ...(this.selectedEmployeeId
- ? {
- employeeId: this.selectedEmployeeId
- }
- : {}),
- ...(this.selectedProjectId
- ? {
- projectId: this.selectedProjectId
- }
- : {}),
+ ...(this.selectedEmployeeId ? { employeeId: this.selectedEmployeeId } : {}),
+ ...(this.selectedProjectId ? { projectId: this.selectedProjectId } : {}),
...(this.filters.where ? this.filters.where : {})
}
});
diff --git a/apps/gauzy/src/app/pages/dashboard/project-management/project-management.component.html b/apps/gauzy/src/app/pages/dashboard/project-management/project-management.component.html
index 698dfbe4ffd..420e0e27e96 100644
--- a/apps/gauzy/src/app/pages/dashboard/project-management/project-management.component.html
+++ b/apps/gauzy/src/app/pages/dashboard/project-management/project-management.component.html
@@ -5,9 +5,7 @@
{{ 'DASHBOARD_PAGE.PROJECT_MANAGEMENT' | translate }}
-
+
- {{organization?.statistics?.countWorking}}
+ {{ organization?.statistics?.countWorking }}
-
/{{organization?.statistics?.countTeams}}
+
/{{ organization?.statistics?.countTeams }}
@@ -27,9 +27,9 @@
{{ 'TIMESHEET.MEMBERS_WORKED' | translate }}
- {{organization?.statistics?.counts?.employeesCount || 0}}
+ {{ organization?.statistics?.counts?.employeesCount || 0 }}
-
/{{organization?.statistics?.counts?.employeesCountTotal || 0}}
+
/{{ organization?.statistics?.counts?.employeesCountTotal || 0 }}
{{ 'TIMESHEET.PROJECTS_WORKED' | translate }}
- {{organization?.statistics?.counts?.projectsCount || 0}}
+ {{ organization?.statistics?.counts?.projectsCount || 0 }}
-
/{{projectCount}}
+
/{{ projectCount }}
{{ 'TIMESHEET.PROJECTS_WORKED' | translate }}
[value]="organization?.statistics?.counts?.projectsCount"
>
-
@@ -66,7 +65,7 @@ {{ 'TIMESHEET.WORKED_FOR_DAY' | translate }}
- {{organization?.statistics?.counts?.weekActivities || 0}}
+ {{ organization?.statistics?.counts?.weekActivities || 0 }}
%
@@ -74,7 +73,7 @@ {{ 'TIMESHEET.WORKED_FOR_DAY' | translate }}
@@ -85,29 +84,39 @@
{{ 'TIMESHEET.WORKED_FOR_DAY' | translate }}
-
{{team?.statistics?.countWorking}}
-
/{{team?.statistics?.countWorking + team?.statistics.countNotWorking}}
+
{{ team?.statistics?.countWorking }}
+
/{{ team?.statistics?.countWorking + team?.statistics.countNotWorking }}
-
{{team?.name}}
+
{{ team?.name }}
+ status="success"
+ [text]="
+ ('DASHBOARD_PAGE.CHARTS.WORKING_NOW' | translate) + ' ' + team?.statistics?.countOnline
+ "
+ >
+ status="warning"
+ [text]="
+ ('DASHBOARD_PAGE.CHARTS.WORKING_TODAY' | translate) +
+ ' ' +
+ (team?.statistics?.countWorking - team?.statistics?.countOnline).toString()
+ "
+ >
+ status="danger"
+ [text]="
+ ('DASHBOARD_PAGE.CHARTS.NOT_WORKING' | translate) +
+ ' ' +
+ team?.statistics?.countNotWorking
+ "
+ >
@@ -118,9 +127,8 @@
{{ 'TIMESHEET.WORKED_FOR_DAY' | translate }}
-
-
+
+
diff --git a/apps/gauzy/src/app/pages/dashboard/team/all-team/all-team.component.ts b/apps/gauzy/src/app/pages/dashboard/team/all-team/all-team.component.ts
index 2288f17a312..df7b0c1e580 100644
--- a/apps/gauzy/src/app/pages/dashboard/team/all-team/all-team.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/team/all-team/all-team.component.ts
@@ -1,7 +1,6 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { UntilDestroy } from '@ngneat/until-destroy';
-import { Store } from '@gauzy/ui-core/core';
-import { OrganizationProjectsService } from '@gauzy/ui-core/core';
+import { OrganizationProjectsService, Store } from '@gauzy/ui-core/core';
@UntilDestroy({ checkProperties: true })
@Component({
diff --git a/apps/gauzy/src/app/pages/dashboard/team/chart/chart.component.ts b/apps/gauzy/src/app/pages/dashboard/team/chart/chart.component.ts
index 5ce74085fcc..dc00d560f7f 100644
--- a/apps/gauzy/src/app/pages/dashboard/team/chart/chart.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/team/chart/chart.component.ts
@@ -7,7 +7,7 @@ import { TranslationBaseComponent } from '@gauzy/ui-core/i18n';
@UntilDestroy({ checkProperties: true })
@Component({
- selector: 'gauzy-chart',
+ selector: 'gz-doughnut-chart',
templateUrl: './chart.component.html',
styleUrls: ['./chart.component.scss']
})
@@ -23,13 +23,14 @@ export class ChartComponent extends TranslationBaseComponent implements OnInit,
}
private get _labels() {
+ // Retrieve the statistics
+ const { countOnline, countWorking, countNotWorking } = this.statistics;
+ // Build the labels
return {
labels: [
- `${this.getTranslation('DASHBOARD_PAGE.CHARTS.WORKING_NOW')}: ${this.statistics.countOnline}`,
- `${this.getTranslation('DASHBOARD_PAGE.CHARTS.WORKING')}: ${
- this.statistics.countWorking - this.statistics.countOnline
- }`,
- `${this.getTranslation('DASHBOARD_PAGE.CHARTS.NOT_WORKING')}: ${this.statistics.countNotWorking}`
+ `${this.getTranslation('DASHBOARD_PAGE.CHARTS.WORKING_NOW')}: ${countOnline}`,
+ `${this.getTranslation('DASHBOARD_PAGE.CHARTS.WORKING')}: ${countWorking - countOnline}`,
+ `${this.getTranslation('DASHBOARD_PAGE.CHARTS.NOT_WORKING')}: ${countNotWorking}`
]
};
}
diff --git a/apps/gauzy/src/app/pages/dashboard/team/index.ts b/apps/gauzy/src/app/pages/dashboard/team/index.ts
new file mode 100644
index 00000000000..6fa5cbe50a1
--- /dev/null
+++ b/apps/gauzy/src/app/pages/dashboard/team/index.ts
@@ -0,0 +1,5 @@
+export * from './all-team/all-team.component';
+export * from './team-card/team-card.component';
+export * from './team-member/team-member.component';
+export * from './team.component';
+export * from './chart/chart.component';
diff --git a/apps/gauzy/src/app/pages/dashboard/team/team-card/team-card.component.ts b/apps/gauzy/src/app/pages/dashboard/team/team-card/team-card.component.ts
index 3dcbe4de865..82c7ee03305 100644
--- a/apps/gauzy/src/app/pages/dashboard/team/team-card/team-card.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/team/team-card/team-card.component.ts
@@ -1,46 +1,33 @@
import { Component, Input, OnInit } from '@angular/core';
-import { IEmployee, IOrganizationTeam, RolesEnum } from "@gauzy/contracts";
+import { IEmployee, IOrganizationTeam, RolesEnum } from '@gauzy/contracts';
@Component({
- selector: 'gauzy-team-card',
- templateUrl: './team-card.component.html',
- styleUrls: ['./team-card.component.scss']
+ selector: 'gauzy-team-card',
+ templateUrl: './team-card.component.html',
+ styleUrls: ['./team-card.component.scss']
})
export class TeamCardComponent implements OnInit {
- constructor() {
- }
-
- private _managers: IEmployee[];
-
- get managers(): IEmployee[] {
- return this._team.members
- .filter(
- (member) =>
- member.role &&
- member.role.name === RolesEnum.MANAGER
- )
- .map((item) => item.employee);
- }
-
- private _members: IEmployee[];
-
- get members(): IEmployee[] {
- return this._team.members
- .filter((member) => !member.role)
- .map((item) => item.employee);
- }
-
- private _team: IOrganizationTeam | any;
-
- public get team(): IOrganizationTeam | any {
- return this._team;
- }
-
- @Input()
- public set team(value: IOrganizationTeam | any) {
- this._team = value;
- };
-
- ngOnInit(): void {
- }
+ constructor() {}
+
+ _managers: IEmployee[];
+ get managers(): IEmployee[] {
+ return this._team.members
+ .filter((member) => member.role && member.role.name === RolesEnum.MANAGER)
+ .map((item) => item.employee);
+ }
+
+ _members: IEmployee[];
+ get members(): IEmployee[] {
+ return this._team.members.filter((member) => !member.role).map((item) => item.employee);
+ }
+
+ private _team: IOrganizationTeam | any;
+ public get team(): IOrganizationTeam | any {
+ return this._team;
+ }
+ @Input() public set team(value: IOrganizationTeam | any) {
+ this._team = value;
+ }
+
+ ngOnInit(): void {}
}
diff --git a/apps/gauzy/src/app/pages/dashboard/team/team-member/team-member.component.ts b/apps/gauzy/src/app/pages/dashboard/team/team-member/team-member.component.ts
index f92f22c24a8..72038de7285 100644
--- a/apps/gauzy/src/app/pages/dashboard/team/team-member/team-member.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/team/team-member/team-member.component.ts
@@ -1,7 +1,7 @@
import { Component, Input, OnInit } from '@angular/core';
+import * as moment from 'moment';
import { IOrganizationTeamEmployee } from '@gauzy/contracts';
import { progressStatus } from '@gauzy/ui-core/common';
-import * as moment from 'moment';
@Component({
selector: 'gauzy-team-member',
@@ -9,10 +9,6 @@ import * as moment from 'moment';
styleUrls: ['./team-member.component.scss']
})
export class TeamMemberComponent implements OnInit {
- constructor() {
- this._isClassic = false;
- }
-
private _member: IOrganizationTeamEmployee | any;
public get member(): IOrganizationTeamEmployee | any {
@@ -49,5 +45,9 @@ export class TeamMemberComponent implements OnInit {
return moment.duration(duration, 'seconds').humanize();
}
+ constructor() {
+ this._isClassic = false;
+ }
+
ngOnInit(): void {}
}
diff --git a/apps/gauzy/src/app/pages/dashboard/team/team.component.html b/apps/gauzy/src/app/pages/dashboard/team/team.component.html
index 77fb7fd78e9..b5034381cfd 100644
--- a/apps/gauzy/src/app/pages/dashboard/team/team.component.html
+++ b/apps/gauzy/src/app/pages/dashboard/team/team.component.html
@@ -1,14 +1,20 @@
-
-
@@ -36,28 +42,28 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
diff --git a/apps/gauzy/src/app/pages/dashboard/team/team.component.ts b/apps/gauzy/src/app/pages/dashboard/team/team.component.ts
index 6789b255b49..69cd2b2e021 100644
--- a/apps/gauzy/src/app/pages/dashboard/team/team.component.ts
+++ b/apps/gauzy/src/app/pages/dashboard/team/team.component.ts
@@ -3,12 +3,6 @@ import * as moment from 'moment';
import { combineLatest, debounceTime, tap } from 'rxjs';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService } from '@ngx-translate/core';
-import {
- DateRangePickerBuilderService,
- OrganizationTeamsService,
- TimesheetService,
- TimesheetStatisticsService
-} from '@gauzy/ui-core/core';
import {
IGetCountsStatistics,
IGetTimeLogReportInput,
@@ -18,7 +12,14 @@ import {
ITimeLog,
ReportGroupFilterEnum
} from '@gauzy/contracts';
-import { Store } from '@gauzy/ui-core/core';
+import {
+ DateRangePickerBuilderService,
+ ErrorHandlingService,
+ OrganizationTeamsService,
+ Store,
+ TimesheetService,
+ TimesheetStatisticsService
+} from '@gauzy/ui-core/core';
import { BaseSelectorFilterComponent, TimeZoneService } from '@gauzy/ui-core/shared';
@UntilDestroy({ checkProperties: true })
@@ -35,13 +36,14 @@ export class TeamComponent extends BaseSelectorFilterComponent implements OnInit
private _selectedOrganizationTeam: IOrganizationTeam;
constructor(
- private readonly _organizationTeamsService: OrganizationTeamsService,
- private readonly _timesheetStatisticsService: TimesheetStatisticsService,
- private readonly _timesheetService: TimesheetService,
protected readonly translateService: TranslateService,
protected readonly dateRangePickerBuilderService: DateRangePickerBuilderService,
protected readonly store: Store,
- protected readonly timeZoneService: TimeZoneService
+ protected readonly timeZoneService: TimeZoneService,
+ private readonly _organizationTeamsService: OrganizationTeamsService,
+ private readonly _timesheetStatisticsService: TimesheetStatisticsService,
+ private readonly _timesheetService: TimesheetService,
+ private readonly _errorHandlingService: ErrorHandlingService
) {
super(store, translateService, dateRangePickerBuilderService, timeZoneService);
this._selectedTeam = {
@@ -160,8 +162,8 @@ export class TeamComponent extends BaseSelectorFilterComponent implements OnInit
if (!this.organization) {
return;
}
- const { id: organizationId } = this.organization;
- const { tenantId } = this.store.user;
+ const { id: organizationId, tenantId } = this.organization;
+
this.isLoading = true;
this._organizationTeamsService
.getAll(['members', 'members.role', 'members.employee', 'members.employee.user'], {
@@ -188,8 +190,8 @@ export class TeamComponent extends BaseSelectorFilterComponent implements OnInit
this._dailyLogs = await this._timesheetService.getDailyReport(request);
await this.teamMapper();
} catch (error) {
- console.log(error);
- } finally {
+ console.log('Error while loading logs', error);
+ this._errorHandlingService.handleError(error);
}
}
diff --git a/apps/gauzy/src/app/pages/dashboard/team/team.module.ts b/apps/gauzy/src/app/pages/dashboard/team/team.module.ts
deleted file mode 100644
index 334a6ecd398..00000000000
--- a/apps/gauzy/src/app/pages/dashboard/team/team.module.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { NgModule } from '@angular/core';
-import {
- NbBadgeModule,
- NbButtonModule,
- NbCardModule,
- NbIconModule,
- NbProgressBarModule,
- NbSpinnerModule
-} from '@nebular/theme';
-import { NgChartsModule } from 'ng2-charts';
-import { TranslateModule } from '@ngx-translate/core';
-import { CounterPointModule, NoDataMessageModule, SharedModule } from '@gauzy/ui-core/shared';
-import { TeamComponent } from './team.component';
-import { TeamCardComponent } from './team-card/team-card.component';
-import { TeamMemberComponent } from './team-member/team-member.component';
-import { ChartComponent } from './chart/chart.component';
-import { AllTeamComponent } from './all-team/all-team.component';
-
-@NgModule({
- declarations: [TeamComponent, TeamCardComponent, TeamMemberComponent, ChartComponent, AllTeamComponent],
- imports: [
- NbBadgeModule,
- NbButtonModule,
- NbCardModule,
- NbIconModule,
- NbProgressBarModule,
- NbSpinnerModule,
- NgChartsModule,
- SharedModule,
- TranslateModule.forChild(),
- CounterPointModule,
- NoDataMessageModule
- ]
-})
-export class TeamModule {}
diff --git a/apps/gauzy/src/app/pages/dashboard/time-tracking/time-tracking.module.ts b/apps/gauzy/src/app/pages/dashboard/time-tracking/time-tracking.module.ts
deleted file mode 100644
index 23a37a064f4..00000000000
--- a/apps/gauzy/src/app/pages/dashboard/time-tracking/time-tracking.module.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { NgModule } from '@angular/core';
-import {
- NbCardModule,
- NbSpinnerModule,
- NbListModule,
- NbProgressBarModule,
- NbBadgeModule,
- NbToggleModule,
- NbIconModule,
- NbButtonModule,
- NbPopoverModule
-} from '@nebular/theme';
-import { NgChartsModule } from 'ng2-charts';
-import { NgxPermissionsModule } from 'ngx-permissions';
-import { TranslateModule } from '@ngx-translate/core';
-import { SwiperModule } from 'swiper/angular';
-import { TimeTrackingComponent } from './time-tracking.component';
-import {
- ActivityItemModule,
- CounterPointModule,
- GalleryModule,
- ScreenshotsItemModule,
- SharedModule,
- TimezoneFilterModule,
- WidgetLayoutModule,
- WindowLayoutModule
-} from '@gauzy/ui-core/shared';
-
-@NgModule({
- imports: [
- SharedModule,
- NbCardModule,
- NbButtonModule,
- NbSpinnerModule,
- NbListModule,
- NbProgressBarModule,
- NbToggleModule,
- NbIconModule,
- NbBadgeModule,
- NbPopoverModule,
- ScreenshotsItemModule,
- ActivityItemModule,
- NgChartsModule,
- TranslateModule.forChild(),
- GalleryModule,
- CounterPointModule,
- WidgetLayoutModule,
- WindowLayoutModule,
- SwiperModule,
- TimezoneFilterModule,
- NgxPermissionsModule.forChild()
- ],
- declarations: [TimeTrackingComponent],
- exports: [TimeTrackingComponent]
-})
-export class TimeTrackingModule {}
diff --git a/apps/server/package.json b/apps/server/package.json
index f7bab33daa1..37503e345b0 100644
--- a/apps/server/package.json
+++ b/apps/server/package.json
@@ -42,7 +42,6 @@
"@electron/remote": "^2.0.8",
"@gauzy/desktop-ui-lib": "^0.1.0",
"@gauzy/ui-config": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@grpc/grpc-js": "^1.6.7",
"@nebular/auth": "^12.0.0",
"@nebular/bootstrap": "^9.1.0-rc.6",
diff --git a/apps/server/src/package.json b/apps/server/src/package.json
index 33b18c7e3ff..8e762b94898 100755
--- a/apps/server/src/package.json
+++ b/apps/server/src/package.json
@@ -30,6 +30,7 @@
"../../../packages/config",
"../../../packages/contracts",
"../../../packages/ui-config",
+ "../../../packages/ui-core",
"../../../packages/plugin",
"../../../packages/plugins/integration-ai",
"../../../packages/plugins/integration-hubstaff",
diff --git a/packages/core/src/time-tracking/time-log/commands/handlers/schedule-time-log-entries.handler.ts b/packages/core/src/time-tracking/time-log/commands/handlers/schedule-time-log-entries.handler.ts
index cae7152815a..e252dcdfe21 100644
--- a/packages/core/src/time-tracking/time-log/commands/handlers/schedule-time-log-entries.handler.ts
+++ b/packages/core/src/time-tracking/time-log/commands/handlers/schedule-time-log-entries.handler.ts
@@ -1,11 +1,9 @@
import { ICommandHandler, CommandHandler } from '@nestjs/cqrs';
-import { InjectRepository } from '@nestjs/typeorm';
import { Brackets, SelectQueryBuilder, WhereExpressionBuilder } from 'typeorm';
import * as moment from 'moment';
-import { isEmpty, isNotEmpty } from "@gauzy/common";
-import { DatabaseTypeEnum, getConfig } from '@gauzy/config';
-import { prepareSQLQuery as p } from './../../../../database/database.helper';
+import { isEmpty, isNotEmpty } from '@gauzy/common';
import { ITimeLog } from '@gauzy/contracts';
+import { prepareSQLQuery as p } from './../../../../database/database.helper';
import { TimeLog } from './../../time-log.entity';
import { ScheduleTimeLogEntriesCommand } from '../schedule-time-log-entries.command';
import { RequestContext } from './../../../../core/context';
@@ -13,25 +11,31 @@ import { TypeOrmTimeLogRepository } from '../../repository/type-orm-time-log.rep
@CommandHandler(ScheduleTimeLogEntriesCommand)
export class ScheduleTimeLogEntriesHandler implements ICommandHandler {
+ constructor(private readonly typeOrmTimeLogRepository: TypeOrmTimeLogRepository) {}
- constructor(
- @InjectRepository(TimeLog)
- private readonly typeOrmTimeLogRepository: TypeOrmTimeLogRepository,
- ) { }
-
- public async execute(command: ScheduleTimeLogEntriesCommand) {
+ /**
+ * Schedule TimeLog Entries
+ *
+ * @param command
+ * @returns
+ */
+ public async execute(command: ScheduleTimeLogEntriesCommand): Promise {
const { timeLog } = command;
let timeLogs: ITimeLog[] = [];
+
+ // Query the timeLogs
+ const query = this.typeOrmTimeLogRepository.createQueryBuilder('time_log');
+ query.setFindOptions({
+ relations: { timeSlots: true }
+ });
+
if (timeLog) {
+ // Get the tenantId
+ const tenantId = RequestContext.currentTenantId() || timeLog.tenantId;
+
+ // Get the organizationId
const { organizationId, employeeId } = timeLog;
- const tenantId = RequestContext.currentTenantId();
- const query = this.typeOrmTimeLogRepository.createQueryBuilder('time_log');
- query.setFindOptions({
- relations: {
- timeSlots: true
- }
- });
query.where((qb: SelectQueryBuilder) => {
qb.andWhere(
new Brackets((web: WhereExpressionBuilder) => {
@@ -57,14 +61,7 @@ export class ScheduleTimeLogEntriesHandler implements ICommandHandler) => {
qb.andWhere(
new Brackets((web: WhereExpressionBuilder) => {
@@ -79,54 +76,56 @@ export class ScheduleTimeLogEntriesHandler implements ICommandHandler 10
- ) {
- console.log('Schedule Time Log Entry Updated StoppedAt Using StartedAt', timeLog.startedAt);
- await this.typeOrmTimeLogRepository.save({
- id: timeLog.id,
- stoppedAt: moment(timeLog.startedAt).add(10, 'seconds').toDate()
- });
- } else if (isNotEmpty(timeLog.timeSlots)) {
- let stoppedAt: any;
- let slotDifference: any;
-
- const duration = timeLog.timeSlots.reduce(
- (sum: number, current: any) => sum + current.duration, 0
- );
- /**
- * Adjust stopped date as per database selection
- */
- switch (getConfig().dbConnectionOptions.type) {
- case DatabaseTypeEnum.sqlite:
- case DatabaseTypeEnum.betterSqlite3:
- stoppedAt = moment.utc(timeLog.startedAt).add(duration, 'seconds').format('YYYY-MM-DD HH:mm:ss.SSS');
- slotDifference = moment.utc(moment()).diff(stoppedAt, 'minutes');
- break;
- case DatabaseTypeEnum.postgres:
- case DatabaseTypeEnum.mysql:
- stoppedAt = moment(timeLog.startedAt).add(duration, 'seconds').toDate();
- slotDifference = moment().diff(moment.utc(stoppedAt), 'minutes');
- break;
- default:
- throw Error(`cannot format startedAt, slotDifference due to unsupported database type: ${getConfig().dbConnectionOptions.type}`);
+ const { timeSlots } = timeLog;
+
+ // Calculate the minutes difference
+ const minutes = moment().diff(moment.utc(timeLog.startedAt), 'minutes');
+
+ // Handle case where there are no time slots
+ if (isEmpty(timeLog.timeSlots)) {
+ // If the minutes difference is greater than 10, update the stoppedAt date
+ if (minutes > 10) {
+ console.log('Schedule Time Log Entry Updated StoppedAt Using StartedAt', timeLog.startedAt);
+
+ // Calculate the stoppedAt date
+ const stoppedAt = moment.utc(timeLog.startedAt).add(10, 'seconds').toDate();
+
+ // Calculate the stoppedAt date
+ await this.typeOrmTimeLogRepository.save({
+ id: timeLog.id,
+ stoppedAt
+ });
}
+ }
+ // Handle case where there are time slots
+ else if (isNotEmpty(timeLog.timeSlots)) {
+ // Calculate the duration
+ const duration = timeSlots.reduce((sum, { duration }) => sum + duration, 0);
+
+ // Calculate the stoppedAt date
+ const stoppedAt = moment.utc(timeLog.startedAt).add(duration, 'seconds').toDate();
+
+ // Calculate the minutes difference
+ const minutes = moment.utc().diff(moment.utc(stoppedAt), 'minutes');
console.log('Schedule Time Log Entry Updated StoppedAt Using StoppedAt', stoppedAt);
- if (slotDifference > 10) {
+
+ // If the minutes difference is greater than 10, update the stoppedAt date
+ if (minutes > 10) {
await this.typeOrmTimeLogRepository.save({
id: timeLog.id,
- stoppedAt: stoppedAt
+ stoppedAt
});
}
}
+
/**
* Stop previous pending timer anyway.
* If we have any pending TimeLog entry
diff --git a/packages/core/src/time-tracking/time-log/commands/schedule-time-log-entries.command.ts b/packages/core/src/time-tracking/time-log/commands/schedule-time-log-entries.command.ts
index d81a17b07cb..650295cd6da 100644
--- a/packages/core/src/time-tracking/time-log/commands/schedule-time-log-entries.command.ts
+++ b/packages/core/src/time-tracking/time-log/commands/schedule-time-log-entries.command.ts
@@ -4,7 +4,5 @@ import { ITimeLog } from '@gauzy/contracts';
export class ScheduleTimeLogEntriesCommand implements ICommand {
static readonly type = 'Adjust [TimeLog] Entries';
- constructor(
- public readonly timeLog?: ITimeLog
- ) {}
-}
\ No newline at end of file
+ constructor(public readonly timeLog?: ITimeLog) {}
+}
diff --git a/packages/core/src/time-tracking/time-log/commands/time-log-update.command.ts b/packages/core/src/time-tracking/time-log/commands/time-log-update.command.ts
index e47579dc5b9..5e2cbf3a86f 100644
--- a/packages/core/src/time-tracking/time-log/commands/time-log-update.command.ts
+++ b/packages/core/src/time-tracking/time-log/commands/time-log-update.command.ts
@@ -1,4 +1,5 @@
import { ICommand } from '@nestjs/cqrs';
+import { ID } from '@gauzy/contracts';
import { TimeLog } from './../time-log.entity';
export class TimeLogUpdateCommand implements ICommand {
@@ -6,7 +7,7 @@ export class TimeLogUpdateCommand implements ICommand {
constructor(
public readonly input: Partial,
- public readonly id: TimeLog['id'] | TimeLog,
+ public readonly id: ID | TimeLog,
public readonly manualTimeSlot?: boolean | null
- ) { }
+ ) {}
}
diff --git a/packages/core/src/time-tracking/timer/timer.service.ts b/packages/core/src/time-tracking/timer/timer.service.ts
index aa93d3c7944..3480f03928f 100644
--- a/packages/core/src/time-tracking/timer/timer.service.ts
+++ b/packages/core/src/time-tracking/timer/timer.service.ts
@@ -1,9 +1,4 @@
-import {
- Injectable,
- NotFoundException,
- ForbiddenException,
- BadRequestException,
-} from '@nestjs/common';
+import { Injectable, NotFoundException, ForbiddenException, BadRequestException } from '@nestjs/common';
import { CommandBus } from '@nestjs/cqrs';
import { IsNull, Between, Not, In } from 'typeorm';
import * as moment from 'moment';
@@ -18,7 +13,7 @@ import {
PermissionsEnum,
ITimeSlot,
IEmployee,
- IEmployeeFindInput,
+ IEmployeeFindInput
} from '@gauzy/contracts';
import { isNotEmpty } from '@gauzy/common';
import { TimeLog } from '../../core/entities/internal';
@@ -38,7 +33,7 @@ import {
IGetConflictTimeLogCommand,
ScheduleTimeLogEntriesCommand,
TimeLogCreateCommand,
- TimeLogUpdateCommand,
+ TimeLogUpdateCommand
} from '../time-log/commands';
import { MikroOrmTimeLogRepository, TypeOrmTimeLogRepository } from '../time-log/repository';
import { TypeOrmEmployeeRepository, MikroOrmEmployeeRepository } from '../../employee/repository';
@@ -49,7 +44,6 @@ const ormType: MultiORM = getORMType();
@Injectable()
export class TimerService {
-
protected ormType: MultiORM = ormType;
constructor(
@@ -58,7 +52,7 @@ export class TimerService {
readonly typeOrmEmployeeRepository: TypeOrmEmployeeRepository,
readonly mikroOrmEmployeeRepository: MikroOrmEmployeeRepository,
readonly commandBus: CommandBus
- ) { }
+ ) {}
/**
* Fetches an employee based on the provided query.
@@ -66,7 +60,8 @@ export class TimerService {
* @param query - The query parameters to find the employee.
* @returns A Promise resolving to the employee entity or null.
*/
- async fetchEmployee(query: IEmployeeFindInput): Promise { // Replace 'Employee' with your actual Employee entity type
+ async fetchEmployee(query: IEmployeeFindInput): Promise {
+ // Replace 'Employee' with your actual Employee entity type
switch (this.ormType) {
case MultiORMEnum.MikroORM:
return await this.mikroOrmEmployeeRepository.findOneByOptions(query);
@@ -94,7 +89,7 @@ export class TimerService {
if (!!permission && isNotEmpty(request.employeeId)) {
const { employeeId } = request;
- employee = await this.fetchEmployee({ id: employeeId, tenantId, organizationId, });
+ employee = await this.fetchEmployee({ id: employeeId, tenantId, organizationId });
} else {
const userId = RequestContext.currentUserId();
employee = await this.fetchEmployee({ userId, tenantId, organizationId });
@@ -146,7 +141,10 @@ export class TimerService {
const parseMikroOrmOptions = parseTypeORMFindToMikroOrm(lastLogQueryParamsMikroOrm);
// Get today's last log (running or completed)
- lastLog = await this.mikroOrmTimeLogRepository.findOne(parseMikroOrmOptions.where, parseMikroOrmOptions.mikroOptions) as TimeLog;
+ lastLog = (await this.mikroOrmTimeLogRepository.findOne(
+ parseMikroOrmOptions.where,
+ parseMikroOrmOptions.mikroOptions
+ )) as TimeLog;
break;
case MultiORMEnum.TypeORM:
@@ -167,7 +165,7 @@ export class TimerService {
const status: ITimerStatus = {
duration: 0,
running: false,
- lastLog: null,
+ lastLog: null
};
// Calculate completed timelogs duration
@@ -198,11 +196,13 @@ export class TimerService {
moment.utc(request.startedAt).toDate()
);
const { organizationId, source, logType } = request;
+
/**
- * If source, logType not found in request then reject the request.
+ * If source or logType is not found in the request, reject the request.
*/
const c1 = Object.values(TimeLogSourceEnum).includes(source);
const c2 = Object.values(TimeLogType).includes(logType);
+
if (!c1 || !c2) {
throw new BadRequestException();
}
@@ -212,13 +212,12 @@ export class TimerService {
const employee = await this.typeOrmEmployeeRepository.findOneBy({
userId,
- tenantId,
+ tenantId
});
if (!employee) {
- throw new NotFoundException(
- "We couldn't find the employee you were looking for."
- );
+ throw new NotFoundException("We couldn't find the employee you were looking for.");
}
+
const { id: employeeId } = employee;
const lastLog = await this.getLastRunningLog(request);
@@ -231,29 +230,26 @@ export class TimerService {
* It will manage to create proper entires in database
*/
console.log('Schedule Time Log Entries Command', lastLog);
- await this.commandBus.execute(
- new ScheduleTimeLogEntriesCommand(lastLog)
- );
+ await this.commandBus.execute(new ScheduleTimeLogEntriesCommand(lastLog));
}
- await this.typeOrmEmployeeRepository.update({ id: employeeId }, {
- isOnline: true, // Employee status (Online/Offline)
- isTrackingTime: true, // Employee time tracking status
- });
+ await this.typeOrmEmployeeRepository.update(
+ { id: employeeId },
+ {
+ isOnline: true, // Employee status (Online/Offline)
+ isTrackingTime: true // Employee time tracking status
+ }
+ );
- const {
- projectId,
- taskId,
- organizationContactId,
- organizationTeamId,
- description,
- isBillable,
- version,
- } = request;
+ // Get the request parameters
+ const { projectId, taskId, organizationContactId, organizationTeamId } = request;
+ const { description, isBillable, version } = request;
+ // Get the current date
const now = moment.utc().toDate();
const startedAt = request.startedAt ? moment.utc(request.startedAt).toDate() : now;
+ // Create the timeLog
return await this.commandBus.execute(
new TimeLogCreateCommand({
organizationId,
@@ -271,7 +267,7 @@ export class TimerService {
description: description || null,
isBillable: isBillable || false,
version: version || null,
- isRunning: true,
+ isRunning: true
})
);
}
@@ -287,24 +283,32 @@ export class TimerService {
'----------------------------------Stopped Timer Date----------------------------------',
moment.utc(request.stoppedAt).toDate()
);
- const { organizationId } = request;
- const tenantId = RequestContext.currentTenantId() || request.tenantId;
+ // Get the user ID
const userId = RequestContext.currentUserId();
+ // Get the tenant ID
+ const tenantId = RequestContext.currentTenantId() || request.tenantId;
+ // Get the employee
const employee = await this.typeOrmEmployeeRepository.findOneBy({
userId,
- tenantId,
+ tenantId
});
if (!employee) {
throw new NotFoundException("We couldn't find the employee you were looking for.");
}
+ // Get the employee ID
const { id: employeeId } = employee;
- await this.typeOrmEmployeeRepository.update({ id: employeeId }, {
- isOnline: false, // Employee status (Online/Offline)
- isTrackingTime: false, // Employee time tracking status
- });
+
+ // Update the employee
+ await this.typeOrmEmployeeRepository.update(
+ { id: employeeId },
+ {
+ isOnline: false, // Employee status (Online/Offline)
+ isTrackingTime: false // Employee time tracking status
+ }
+ );
let lastLog = await this.getLastRunningLog(request);
if (!lastLog) {
@@ -313,12 +317,15 @@ export class TimerService {
* So, we have to first create start timer entry in database, then update stop timer entry.
* It will manage to create proper entires in database
*/
- await this.startTimer(request);
- lastLog = await this.getLastRunningLog(request);
+ lastLog = await this.startTimer(request);
}
+ // Get the organization ID
+ const organizationId = request.organizationTeamId || employee.organizationId;
+
+ // Get the current date and set the initial stoppedAt date
const now = moment.utc().toDate();
- const stoppedAt = request.stoppedAt ? moment.utc(request.stoppedAt).toDate() : now;
+ let stoppedAt = moment.utc(request.stoppedAt ?? now).toDate();
/** Function that performs the date range validation */
try {
@@ -327,11 +334,12 @@ export class TimerService {
throw new BadRequestException(error);
}
+ // Update the lastLog
lastLog = await this.commandBus.execute(
new TimeLogUpdateCommand(
{
stoppedAt,
- isRunning: false,
+ isRunning: false
},
lastLog.id,
request.manualTimeSlot
@@ -340,6 +348,7 @@ export class TimerService {
console.log('Stop Timer Time Log', { lastLog });
try {
+ // Get conflicts time logs
const conflicts = await this.commandBus.execute(
new IGetConflictTimeLogCommand({
ignoreId: lastLog.id,
@@ -347,45 +356,38 @@ export class TimerService {
endDate: lastLog.stoppedAt,
employeeId: lastLog.employeeId,
organizationId: organizationId || lastLog.organizationId,
- tenantId,
+ tenantId
})
);
+
console.log('Get Conflicts Time Logs', conflicts, {
ignoreId: lastLog.id,
startDate: lastLog.startedAt,
endDate: lastLog.stoppedAt,
employeeId: lastLog.employeeId,
- organizationId:
- request.organizationId || lastLog.organizationId,
- tenantId,
+ organizationId: request.organizationId || lastLog.organizationId,
+ tenantId
});
+
+ // If there are conflicts, delete them
if (isNotEmpty(conflicts)) {
const times: IDateRange = {
start: new Date(lastLog.startedAt),
- end: new Date(lastLog.stoppedAt),
+ end: new Date(lastLog.stoppedAt)
};
- if (isNotEmpty(conflicts)) {
- await Promise.all(
- await conflicts.map(async (timeLog: ITimeLog) => {
- const { timeSlots = [] } = timeLog;
- timeSlots.map(async (timeSlot: ITimeSlot) => {
- await this.commandBus.execute(
- new DeleteTimeSpanCommand(
- times,
- timeLog,
- timeSlot
- )
- );
- });
- })
- );
- }
+
+ // Delete conflicts
+ await Promise.all(
+ await conflicts.flatMap((timeLog: ITimeLog) => {
+ const { timeSlots = [] } = timeLog;
+ timeSlots.map(async (timeSlot: ITimeSlot) => {
+ await this.commandBus.execute(new DeleteTimeSpanCommand(times, timeLog, timeSlot));
+ });
+ })
+ );
}
} catch (error) {
- console.error(
- 'Error while deleting time span during conflicts timelogs',
- error
- );
+ console.error('Error while deleting time span during conflicts timelogs', error);
}
return lastLog;
@@ -412,38 +414,45 @@ export class TimerService {
* @param request
* @returns
*/
- private async getLastRunningLog(request: ITimerToggleInput) {
+ private async getLastRunningLog(request: ITimerToggleInput): Promise {
const userId = RequestContext.currentUserId();
const tenantId = RequestContext.currentTenantId();
+ // Replace 'Employee' with your actual Employee entity type
const employee = await this.typeOrmEmployeeRepository.findOne({
- where: {
- userId,
- tenantId,
- },
- relations: {
- user: true,
- },
+ where: { userId, tenantId },
+ relations: { user: true }
});
+
+ // If employee is not found, throw a NotFoundException
if (!employee) {
throw new NotFoundException("We couldn't find the employee you were looking for.");
}
+
+ // Employee time tracking status
if (!employee.isTrackingEnabled) {
throw new ForbiddenException(`The time tracking functionality has been disabled for you.`);
}
+
+ // Get the employee ID
const { id: employeeId } = employee;
+
+ // Get the organization ID
+ const organizationId = request.organizationTeamId || employee.organizationId;
+
+ // Return the last running log
return await this.typeOrmTimeLogRepository.findOne({
where: {
stoppedAt: Not(IsNull()),
employeeId,
tenantId,
- organizationId: request.organizationId,
- isRunning: true,
+ organizationId,
+ isRunning: true
},
order: {
startedAt: 'DESC',
- createdAt: 'DESC',
- },
+ createdAt: 'DESC'
+ }
});
}
@@ -454,7 +463,6 @@ export class TimerService {
* @returns The timer status for the employee.
*/
public async getTimerWorkedStatus(request: ITimerStatusInput): Promise {
-
const tenantId = RequestContext.currentTenantId() || request.tenantId;
const { organizationId, organizationTeamId, source } = request;
@@ -466,7 +474,9 @@ export class TimerService {
// Check if the current user has any of the specified permissions
if (RequestContext.hasAnyPermission(permissions)) {
// If yes, set employeeIds based on request.employeeIds or request.employeeId
- employeeIds = request.employeeIds ? request.employeeIds.filter(Boolean) : [request.employeeId].filter(Boolean);
+ employeeIds = request.employeeIds
+ ? request.employeeIds.filter(Boolean)
+ : [request.employeeId].filter(Boolean);
} else {
// EMPLOYEE have the ability to see only their own timer status
const employeeId = RequestContext.currentEmployeeId();
@@ -480,9 +490,7 @@ export class TimerService {
const knex = this.mikroOrmTimeLogRepository.getKnex();
// Construct your SQL query using knex
- let sqlQuery = knex('time_log').select(
- knex.raw('DISTINCT ON ("time_log"."employeeId") *')
- );
+ let sqlQuery = knex('time_log').select(knex.raw('DISTINCT ON ("time_log"."employeeId") *'));
// Builds an SQL query with specific where clauses.
sqlQuery.whereNotNull('startedAt');
@@ -495,8 +503,12 @@ export class TimerService {
isArchived: false
});
- if (source) { sqlQuery = sqlQuery.andWhere({ source }); }
- if (organizationTeamId) { sqlQuery = sqlQuery.andWhere({ organizationTeamId }); }
+ if (source) {
+ sqlQuery = sqlQuery.andWhere({ source });
+ }
+ if (organizationTeamId) {
+ sqlQuery = sqlQuery.andWhere({ organizationTeamId });
+ }
// Adds ordering to the SQL query.
sqlQuery = sqlQuery.orderBy([
@@ -526,7 +538,7 @@ export class TimerService {
const query = this.typeOrmTimeLogRepository.createQueryBuilder('time_log');
// query.innerJoin(`${query.alias}.timeSlots`, 'timeSlots');
query.setFindOptions({
- ...(request['relations'] ? { relations: request['relations'] } : {}),
+ ...(request['relations'] ? { relations: request['relations'] } : {})
});
query.where({
startedAt: Not(IsNull()),
@@ -537,7 +549,7 @@ export class TimerService {
isActive: true,
isArchived: false,
...(isNotEmpty(source) ? { source } : {}),
- ...(isNotEmpty(organizationTeamId) ? { organizationTeamId } : {}),
+ ...(isNotEmpty(organizationTeamId) ? { organizationTeamId } : {})
});
query.orderBy(p(`"${query.alias}"."employeeId"`), 'ASC'); // Adjust ORDER BY to match the SELECT list
query.addOrderBy(p(`"${query.alias}"."startedAt"`), 'DESC');
@@ -551,12 +563,21 @@ export class TimerService {
}
/** Transform an array of ITimeLog objects into an array of ITimerStatus objects. */
- const statistics: ITimerStatus[] = lastLogs.map((lastLog: ITimeLog) => ({
- duration: lastLog?.duration || 0,
- running: lastLog?.isRunning || false,
- lastLog: lastLog || null,
- timerStatus: lastLog?.isRunning ? 'running' : moment(lastLog?.stoppedAt).diff(new Date(), 'day') > 0 ? 'idle' : 'pause',
- }));
+ const statistics: ITimerStatus[] = lastLogs.map((lastLog: ITimeLog) => {
+ const duration = lastLog?.duration ?? 0;
+ const running = lastLog?.isRunning ?? false;
+ const stoppedAt = lastLog?.stoppedAt ? moment(lastLog.stoppedAt) : moment().subtract(1, 'day'); // Default to 1 day ago if stoppedAt is not present
+
+ // Calculate the timer status
+ const timerStatus = running ? 'running' : moment().diff(stoppedAt, 'days') > 0 ? 'idle' : 'pause';
+
+ return {
+ duration,
+ running,
+ lastLog: lastLog ?? null,
+ timerStatus
+ };
+ });
/**
* @returns An array of ITimerStatus objects.
diff --git a/packages/plugins/job-employee-ui/package.json b/packages/plugins/job-employee-ui/package.json
index a642b237315..7a5cd6c74c2 100644
--- a/packages/plugins/job-employee-ui/package.json
+++ b/packages/plugins/job-employee-ui/package.json
@@ -40,7 +40,6 @@
"@angular/forms": "^16.2.12",
"@angular/router": "^16.2.12",
"@gauzy/contracts": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@nebular/theme": "^12.0.0",
"@ngneat/until-destroy": "^9.2.0",
"@ngx-translate/core": "^15.0.0",
diff --git a/packages/plugins/job-proposal-ui/package.json b/packages/plugins/job-proposal-ui/package.json
index f38e6b4a0dc..4df54349620 100644
--- a/packages/plugins/job-proposal-ui/package.json
+++ b/packages/plugins/job-proposal-ui/package.json
@@ -41,7 +41,6 @@
"@angular/platform-browser": "^16.2.12",
"@angular/router": "^16.2.12",
"@gauzy/contracts": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@nebular/theme": "^12.0.0",
"@ng-select/ng-select": "^11.2.0",
"@ngneat/until-destroy": "^9.2.0",
diff --git a/packages/plugins/job-search-ui/package.json b/packages/plugins/job-search-ui/package.json
index 6cd4434065e..d69f015cf3f 100644
--- a/packages/plugins/job-search-ui/package.json
+++ b/packages/plugins/job-search-ui/package.json
@@ -41,7 +41,6 @@
"@angular/forms": "^16.2.12",
"@angular/router": "^16.2.12",
"@gauzy/contracts": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@nebular/theme": "^12.0.0",
"@ngneat/until-destroy": "^9.2.0",
"@ngx-translate/core": "^15.0.0",
diff --git a/packages/plugins/legal-ui/package.json b/packages/plugins/legal-ui/package.json
index f4ed44a5c3e..608a002610e 100644
--- a/packages/plugins/legal-ui/package.json
+++ b/packages/plugins/legal-ui/package.json
@@ -36,7 +36,6 @@
},
"dependencies": {
"@angular/router": "^16.2.12",
- "@gauzy/ui-core": "^0.1.0",
"@nebular/auth": "^12.0.0",
"@ngx-translate/core": "^15.0.0",
"tslib": "^2.6.2"
diff --git a/packages/plugins/maintenance-ui/package.json b/packages/plugins/maintenance-ui/package.json
index 49928573d18..42778d58a16 100644
--- a/packages/plugins/maintenance-ui/package.json
+++ b/packages/plugins/maintenance-ui/package.json
@@ -32,7 +32,6 @@
"@angular/router": "^16.2.12",
"@gauzy/contracts": "^0.1.0",
"@gauzy/ui-config": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@nebular/theme": "^12.0.0",
"@ngx-translate/core": "^15.0.0",
"tslib": "^2.6.2"
diff --git a/packages/plugins/onboarding-ui/package.json b/packages/plugins/onboarding-ui/package.json
index 9d477606d16..4d2766e3b64 100644
--- a/packages/plugins/onboarding-ui/package.json
+++ b/packages/plugins/onboarding-ui/package.json
@@ -37,7 +37,6 @@
"dependencies": {
"@angular/router": "^16.2.12",
"@gauzy/contracts": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@nebular/theme": "^12.0.0",
"@ngneat/until-destroy": "^9.2.0",
"@ngx-translate/core": "^15.0.0",
diff --git a/packages/plugins/public-layout-ui/package.json b/packages/plugins/public-layout-ui/package.json
index 557dfab7f00..4c3cfb9ea15 100644
--- a/packages/plugins/public-layout-ui/package.json
+++ b/packages/plugins/public-layout-ui/package.json
@@ -33,7 +33,6 @@
"@angular/router": "^16.2.12",
"@fullcalendar/angular": "~6.1.10",
"@gauzy/contracts": "^0.1.0",
- "@gauzy/ui-core": "^0.1.0",
"@nebular/theme": "^12.0.0",
"@ng-select/ng-select": "^11.2.0",
"@ngneat/until-destroy": "^9.2.0",
diff --git a/tsconfig.json b/tsconfig.json
index 298183d2ded..e0900849ec6 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -11,8 +11,8 @@
"@gauzy/desktop-window": ["./packages/desktop-window/src/index.ts"],
"@gauzy/plugin-job-employee-ui": ["./packages/plugins/job-employee-ui/src/index.ts"],
"@gauzy/plugin-job-matching-ui": ["./packages/plugins/job-matching-ui/src/index.ts"],
- "@gauzy/plugin-job-search-ui": ["./packages/plugins/job-search-ui/src/index.ts"],
"@gauzy/plugin-job-proposal-ui": ["./packages/plugins/job-proposal-ui/src/index.ts"],
+ "@gauzy/plugin-job-search-ui": ["./packages/plugins/job-search-ui/src/index.ts"],
"@gauzy/plugin-legal-ui": ["./packages/plugins/legal-ui/src/index.ts"],
"@gauzy/plugin-maintenance-ui": ["./packages/plugins/maintenance-ui/src/index.ts"],
"@gauzy/plugin-onboarding-ui": ["./packages/plugins/onboarding-ui/src/index.ts"],