diff --git a/.scripts/configure.ts b/.scripts/configure.ts
index ddc676d7deb..d9df0da12b5 100644
--- a/.scripts/configure.ts
+++ b/.scripts/configure.ts
@@ -78,6 +78,7 @@ if (!isDocker) {
API_BASE_URL: API_BASE_URL,
CLIENT_BASE_URL: CLIENT_BASE_URL,
+ COOKIE_DOMAIN: '${env.COOKIE_DOMAIN}',
PLATFORM_WEBSITE_URL: '${env.PLATFORM_WEBSITE_URL}',
PLATFORM_WEBSITE_DOWNLOAD_URL: '${env.PLATFORM_WEBSITE_DOWNLOAD_URL}',
@@ -221,6 +222,7 @@ if (!isDocker) {
API_BASE_URL: API_BASE_URL,
CLIENT_BASE_URL: CLIENT_BASE_URL,
+ COOKIE_DOMAIN: 'DOCKER_COOKIE_DOMAIN',
PLATFORM_WEBSITE_URL: 'DOCKER_PLATFORM_WEBSITE_URL',
PLATFORM_WEBSITE_DOWNLOAD_URL: 'DOCKER_PLATFORM_WEBSITE_DOWNLOAD_URL',
diff --git a/.scripts/env.ts b/.scripts/env.ts
index 4303ff0a472..d010c380ec7 100644
--- a/.scripts/env.ts
+++ b/.scripts/env.ts
@@ -10,6 +10,8 @@ export type Env = Readonly<{
// Set to true if build / runs in Docker
IS_DOCKER: boolean;
+ COOKIE_DOMAIN: string;
+
// Base URL of Gauzy UI website
CLIENT_BASE_URL: string;
@@ -140,6 +142,8 @@ export const env: Env = cleanEnv(
IS_DOCKER: bool({ default: false }),
+ COOKIE_DOMAIN: str({ default: '.gauzy.co' }),
+
CLIENT_BASE_URL: str({ default: 'http://localhost:4200' }),
API_BASE_URL: str({ default: 'http://localhost:3000' }),
diff --git a/apps/desktop-timer/src/assets/styles/gauzy/theme.gauzy-dark.ts b/apps/desktop-timer/src/assets/styles/gauzy/theme.gauzy-dark.ts
index 4ec88895401..9bf0e771154 100644
--- a/apps/desktop-timer/src/assets/styles/gauzy/theme.gauzy-dark.ts
+++ b/apps/desktop-timer/src/assets/styles/gauzy/theme.gauzy-dark.ts
@@ -45,18 +45,12 @@ const theme = {
export const GAUZY_DARK = {
name: 'gauzy-dark',
- base: 'dark',
+ base: 'dark',
variables: {
...theme,
temperature: {
- arcFill: [
- theme.primary,
- theme.primary,
- theme.primary,
- theme.primary,
- theme.primary
- ],
+ arcFill: Array(5).fill(theme.primary),
arcEmpty: theme.bg2,
thumbBg: theme.bg2,
thumbBorder: theme.primary
diff --git a/apps/desktop-timer/src/assets/styles/material/theme.material-light.ts b/apps/desktop-timer/src/assets/styles/material/theme.material-light.ts
index 41fd9732d98..bb2e166e089 100644
--- a/apps/desktop-timer/src/assets/styles/material/theme.material-light.ts
+++ b/apps/desktop-timer/src/assets/styles/material/theme.material-light.ts
@@ -1,4 +1,4 @@
-import { NbJSThemeOptions } from '@nebular/theme';
+import { NbJSThemeOptions, NbJSThemeVariable } from '@nebular/theme';
const palette = {
primary: '#6200ee',
@@ -47,20 +47,14 @@ export const baseTheme: NbJSThemeOptions = {
}
};
-const baseThemeVariables = baseTheme.variables;
+const baseThemeVariables = baseTheme.variables as NbJSThemeVariable;
export const MATERIAL_LIGHT_THEME = {
name: 'material-light',
base: 'default',
variables: {
temperature: {
- arcFill: [
- baseThemeVariables.primary,
- baseThemeVariables.primary,
- baseThemeVariables.primary,
- baseThemeVariables.primary,
- baseThemeVariables.primary
- ],
+ arcFill: Array(5).fill(baseThemeVariables.primary),
arcEmpty: baseThemeVariables.bg2,
thumbBg: baseThemeVariables.bg2,
thumbBorder: baseThemeVariables.primary
diff --git a/apps/desktop-timer/src/assets/styles/theme.dark.ts b/apps/desktop-timer/src/assets/styles/theme.dark.ts
index 983d147d3f4..63e247fa5b4 100644
--- a/apps/desktop-timer/src/assets/styles/theme.dark.ts
+++ b/apps/desktop-timer/src/assets/styles/theme.dark.ts
@@ -49,13 +49,7 @@ export const DARK_THEME = {
...theme,
temperature: {
- arcFill: [
- theme.primary,
- theme.primary,
- theme.primary,
- theme.primary,
- theme.primary
- ],
+ arcFill: Array(5).fill(theme.primary),
arcEmpty: theme.bg2,
thumbBg: theme.bg2,
thumbBorder: theme.primary
diff --git a/apps/desktop-timer/src/preload.ts b/apps/desktop-timer/src/preload.ts
index fd1459c8709..d918b204482 100644
--- a/apps/desktop-timer/src/preload.ts
+++ b/apps/desktop-timer/src/preload.ts
@@ -17,6 +17,10 @@ window.addEventListener('DOMContentLoaded', async () => {
titleBar.refreshMenu();
});
+ ipcRenderer.on('hide-menu', () => {
+ titleBar.dispose();
+ })
+
const overStyle = document.createElement('style');
overStyle.innerHTML = `
.cet-container {
diff --git a/apps/desktop/src/assets/styles/gauzy/theme.gauzy-dark.ts b/apps/desktop/src/assets/styles/gauzy/theme.gauzy-dark.ts
index 4ec88895401..9bf0e771154 100644
--- a/apps/desktop/src/assets/styles/gauzy/theme.gauzy-dark.ts
+++ b/apps/desktop/src/assets/styles/gauzy/theme.gauzy-dark.ts
@@ -45,18 +45,12 @@ const theme = {
export const GAUZY_DARK = {
name: 'gauzy-dark',
- base: 'dark',
+ base: 'dark',
variables: {
...theme,
temperature: {
- arcFill: [
- theme.primary,
- theme.primary,
- theme.primary,
- theme.primary,
- theme.primary
- ],
+ arcFill: Array(5).fill(theme.primary),
arcEmpty: theme.bg2,
thumbBg: theme.bg2,
thumbBorder: theme.primary
diff --git a/apps/desktop/src/assets/styles/material/theme.material-light.ts b/apps/desktop/src/assets/styles/material/theme.material-light.ts
index 41fd9732d98..bb2e166e089 100644
--- a/apps/desktop/src/assets/styles/material/theme.material-light.ts
+++ b/apps/desktop/src/assets/styles/material/theme.material-light.ts
@@ -1,4 +1,4 @@
-import { NbJSThemeOptions } from '@nebular/theme';
+import { NbJSThemeOptions, NbJSThemeVariable } from '@nebular/theme';
const palette = {
primary: '#6200ee',
@@ -47,20 +47,14 @@ export const baseTheme: NbJSThemeOptions = {
}
};
-const baseThemeVariables = baseTheme.variables;
+const baseThemeVariables = baseTheme.variables as NbJSThemeVariable;
export const MATERIAL_LIGHT_THEME = {
name: 'material-light',
base: 'default',
variables: {
temperature: {
- arcFill: [
- baseThemeVariables.primary,
- baseThemeVariables.primary,
- baseThemeVariables.primary,
- baseThemeVariables.primary,
- baseThemeVariables.primary
- ],
+ arcFill: Array(5).fill(baseThemeVariables.primary),
arcEmpty: baseThemeVariables.bg2,
thumbBg: baseThemeVariables.bg2,
thumbBorder: baseThemeVariables.primary
diff --git a/apps/desktop/src/assets/styles/theme.dark.ts b/apps/desktop/src/assets/styles/theme.dark.ts
index 983d147d3f4..63e247fa5b4 100644
--- a/apps/desktop/src/assets/styles/theme.dark.ts
+++ b/apps/desktop/src/assets/styles/theme.dark.ts
@@ -49,13 +49,7 @@ export const DARK_THEME = {
...theme,
temperature: {
- arcFill: [
- theme.primary,
- theme.primary,
- theme.primary,
- theme.primary,
- theme.primary
- ],
+ arcFill: Array(5).fill(theme.primary),
arcEmpty: theme.bg2,
thumbBg: theme.bg2,
thumbBorder: theme.primary
diff --git a/apps/desktop/src/preload/preload.ts b/apps/desktop/src/preload/preload.ts
index dbcec63fd7b..96f890c7c53 100644
--- a/apps/desktop/src/preload/preload.ts
+++ b/apps/desktop/src/preload/preload.ts
@@ -21,6 +21,10 @@ window.addEventListener('DOMContentLoaded', async () => {
titleBar.refreshMenu();
});
+ ipcRenderer.on('hide-menu', () => {
+ titleBar.dispose();
+ })
+
ipcRenderer.on('adjust_view', () => {
clearInterval(contentInterval);
const headerIcon = '/html/body/div[2]/ga-app/ngx-pages/ngx-one-column-layout/nb-layout/div[1]/div/div/nb-sidebar[1]/div/div/div';
diff --git a/apps/gauzy/package.json b/apps/gauzy/package.json
index dea89eb5772..76b6c7f4275 100644
--- a/apps/gauzy/package.json
+++ b/apps/gauzy/package.json
@@ -88,7 +88,7 @@
"@sentry/types": "^7.101.1",
"@sentry/utils": "^7.90.0",
"@swimlane/ngx-charts": "^20.1.0",
- "angular2-smart-table": "^3.2.0",
+ "angular2-smart-table": "^3.3.0",
"angular2-toaster": "^11.0.1",
"bootstrap": "^4.3.1",
"brace": "^0.11.1",
diff --git a/apps/gauzy/src/app/app.module.guard.ts b/apps/gauzy/src/app/app.module.guard.ts
index 915c37794ac..aef68709acf 100644
--- a/apps/gauzy/src/app/app.module.guard.ts
+++ b/apps/gauzy/src/app/app.module.guard.ts
@@ -1,10 +1,10 @@
import { Injectable } from '@angular/core';
-import { Router, CanActivate, ActivatedRouteSnapshot } from '@angular/router';
+import { Router, ActivatedRouteSnapshot } from '@angular/router';
import { environment } from '@gauzy/ui-config';
import { Store } from '@gauzy/ui-core/core';
@Injectable()
-export class AppModuleGuard implements CanActivate {
+export class AppModuleGuard {
constructor(private readonly router: Router, private readonly store: Store) {}
/**
diff --git a/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-profile.component.html b/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-profile.component.html
index b6d433df26f..4bb2915e29a 100644
--- a/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-profile.component.html
+++ b/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-profile.component.html
@@ -1 +1 @@
-
+
diff --git a/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-profile.component.ts b/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-profile.component.ts
index 4b364f4759b..bc67e42da33 100644
--- a/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-profile.component.ts
+++ b/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-profile.component.ts
@@ -1,20 +1,21 @@
import { Component, OnDestroy, OnInit, Output, EventEmitter } from '@angular/core';
-import { ActivatedRoute, Params } from '@angular/router';
+import { ActivatedRoute } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
-import { firstValueFrom, Subject } from 'rxjs';
-import { debounceTime, filter, tap } from 'rxjs/operators';
-import { NbRouteTab } from '@nebular/theme';
+import { debounceTime, filter, firstValueFrom, Subject, tap } from 'rxjs';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
-import { IEmployee, IEmployeeUpdateInput, IUserUpdateInput, PermissionsEnum } from '@gauzy/contracts';
-import { TranslationBaseComponent } from '@gauzy/ui-core/i18n';
+import { ID, IEmployee, IEmployeeUpdateInput, IUserUpdateInput, PermissionsEnum } from '@gauzy/contracts';
import {
EmployeesService,
EmployeeStore,
ErrorHandlingService,
+ PageTabRegistryConfig,
+ PageTabRegistryService,
+ PageTabsetRegistryId,
Store,
ToastrService,
UsersService
} from '@gauzy/ui-core/core';
+import { TranslationBaseComponent } from '@gauzy/ui-core/i18n';
@UntilDestroy({ checkProperties: true })
@Component({
@@ -24,10 +25,11 @@ import {
providers: [EmployeeStore]
})
export class EditEmployeeProfileComponent extends TranslationBaseComponent implements OnInit, OnDestroy {
- routeParams: Params;
+ public tabsetId: PageTabsetRegistryId = this._route.snapshot.data.tabsetId; // The identifier for the tabset
+ public employeeId: ID = this._route.snapshot.params.id;
+
selectedEmployee: IEmployee;
employeeName: string;
- tabs: NbRouteTab[] = [];
subject$: Subject = new Subject();
@Output() updatedImage = new EventEmitter();
@@ -40,7 +42,8 @@ export class EditEmployeeProfileComponent extends TranslationBaseComponent imple
private readonly _toastrService: ToastrService,
private readonly _employeeStore: EmployeeStore,
private readonly _errorHandlingService: ErrorHandlingService,
- private readonly _store: Store
+ private readonly _store: Store,
+ private readonly _pageTabRegistryService: PageTabRegistryService
) {
super(translateService);
}
@@ -56,8 +59,7 @@ export class EditEmployeeProfileComponent extends TranslationBaseComponent imple
this._route.params
.pipe(
filter((params) => !!params),
- tap((params) => (this.routeParams = params)),
- tap(() => this.loadTabs()),
+ tap(() => this._registerPageTabs()),
tap(() => this.subject$.next(true)),
untilDestroyed(this)
)
@@ -84,73 +86,167 @@ export class EditEmployeeProfileComponent extends TranslationBaseComponent imple
this._applyTranslationOnTabs();
}
+ /**
+ * Constructs a route URL for a specific tab in the 'edit-employee' view.
+ *
+ * This method dynamically generates the route URL based on the employee's ID
+ * and the tab passed as a parameter. It is used to navigate between
+ * different sections (tabs) of the employee edit page.
+ *
+ * @param {string} tab - The name of the tab for which to generate the route.
+ * @returns {string} - The complete route URL for the specified tab.
+ */
getRoute(tab: string): string {
- return `/pages/employees/edit/${this.routeParams.id}/${tab}`;
+ return `/pages/employees/edit/${this.employeeId}/${tab}`;
+ }
+
+ /**
+ * Registers custom tabs for the 'employee-edit' page.
+ * This method defines and registers the various tabs, their icons, routes, and titles.
+ */
+ private _registerPageTabs(): void {
+ const tabs: PageTabRegistryConfig[] = this._createTabsConfig();
+
+ // Register each tab using the page tab registry service
+ tabs.forEach((tab: PageTabRegistryConfig) => this._pageTabRegistryService.registerPageTab(tab));
}
- loadTabs() {
- this.tabs = [
+ /**
+ * Creates the configuration for the tabs used in the 'employee-edit' page.
+ * @returns An array of PageTabRegistryConfig objects.
+ */
+ private _createTabsConfig(): PageTabRegistryConfig[] {
+ return [
{
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.ACCOUNT'),
- icon: 'person-outline',
+ tabsetId: this.tabsetId,
+ tabId: 'account',
+ tabIcon: 'person-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.ACCOUNT'),
+ order: 0,
responsive: true,
route: this.getRoute('account')
},
{
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.NETWORKS'),
- icon: 'at-outline',
+ tabsetId: this.tabsetId,
+ tabId: 'networks',
+ tabIcon: 'at-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.NETWORKS'),
+ order: 1,
responsive: true,
route: this.getRoute('networks')
},
{
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.EMPLOYMENT'),
- icon: 'browser-outline',
+ tabsetId: this.tabsetId,
+ tabId: 'employment',
+ tabIcon: 'browser-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.EMPLOYMENT'),
+ order: 2,
responsive: true,
route: this.getRoute('employment')
},
{
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.HIRING'),
- icon: 'map-outline',
+ tabsetId: this.tabsetId,
+ tabId: 'hiring',
+ tabIcon: 'browser-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.HIRING'),
+ order: 3,
responsive: true,
route: this.getRoute('hiring')
},
{
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.LOCATION'),
- icon: 'pin-outline',
+ tabsetId: this.tabsetId,
+ tabId: 'location',
+ tabIcon: 'pin-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.LOCATION'),
+ order: 4,
responsive: true,
route: this.getRoute('location')
},
{
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.RATES'),
- icon: 'pricetags-outline',
+ tabsetId: this.tabsetId,
+ tabId: 'rates',
+ tabIcon: 'pricetags-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.RATES'),
+ order: 5,
responsive: true,
route: this.getRoute('rates')
},
- ...(this._store.hasAnyPermission(PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_PROJECT_VIEW)
- ? [
- {
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.PROJECTS'),
- icon: 'book-outline',
- responsive: true,
- route: this.getRoute('projects')
- }
- ]
- : []),
{
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.CONTACTS'),
- icon: 'book-open-outline',
+ tabsetId: this.tabsetId,
+ tabId: 'projects',
+ tabIcon: 'book-open-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.PROJECTS'),
+ order: 6,
+ responsive: true,
+ route: this.getRoute('projects'),
+ permissions: [PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_PROJECT_VIEW]
+ },
+ {
+ tabsetId: this.tabsetId,
+ tabId: 'contacts',
+ tabIcon: 'book-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.CONTACTS'),
+ order: 7,
responsive: true,
route: this.getRoute('contacts')
},
{
- title: this.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.SETTINGS'),
- icon: 'settings-outline',
+ tabsetId: this.tabsetId,
+ tabId: 'settings',
+ tabIcon: 'settings-outline',
+ tabsetType: 'route',
+ tabTitle: (_i18n) => _i18n.getTranslation('EMPLOYEES_PAGE.EDIT_EMPLOYEE.SETTINGS'),
+ order: 8,
responsive: true,
route: this.getRoute('settings')
}
];
}
+ /**
+ * Retrieves and sets the profile of the selected employee
+ *
+ * @returns
+ */
+ private async _getEmployeeProfile() {
+ try {
+ if (!this.employeeId) {
+ return;
+ }
+
+ // Fetch employee data from the service
+ const employee = await firstValueFrom(
+ this._employeeService.getEmployeeById(this.employeeId, [
+ 'user',
+ 'organizationDepartments',
+ 'organizationPosition',
+ 'organizationEmploymentTypes',
+ 'tags',
+ 'skills',
+ 'contact'
+ ])
+ );
+
+ // Set the selected employee in the store and component
+ this._employeeStore.selectedEmployee = this.selectedEmployee = employee;
+
+ // Set the employee name for display
+ this.employeeName = employee?.user?.name || employee?.user?.username || 'Unknown Employee';
+ } catch (error) {
+ // Handle errors gracefully
+ console.error('Error fetching employee profile:', error);
+ this._errorHandlingService.handleError(error);
+ }
+ }
+
/**
* Submit the employee form with updated data
*
@@ -218,44 +314,12 @@ export class EditEmployeeProfileComponent extends TranslationBaseComponent imple
}
/**
- * Retrieves and sets the profile of the selected employee
+ * Applies translations to the page tabs.
*/
- private async _getEmployeeProfile() {
- try {
- const { id } = this.routeParams;
- if (!id) {
- return;
- }
-
- // Fetch employee data from the service
- const employee = await firstValueFrom(
- this._employeeService.getEmployeeById(id, [
- 'user',
- 'organizationDepartments',
- 'organizationPosition',
- 'organizationEmploymentTypes',
- 'tags',
- 'skills',
- 'contact'
- ])
- );
-
- // Set the selected employee in the store and component
- this._employeeStore.selectedEmployee = this.selectedEmployee = employee;
-
- // Set the employee name for display
- this.employeeName = employee?.user?.name || employee?.user?.username || 'Unknown Employee';
- } catch (error) {
- // Handle errors gracefully
- console.error('Error fetching employee profile:', error);
- this._errorHandlingService.handleError(error);
- }
- }
-
private _applyTranslationOnTabs() {
this.translateService.onLangChange
.pipe(
- tap(() => this.loadTabs()),
+ tap(() => this._registerPageTabs()),
untilDestroyed(this)
)
.subscribe();
diff --git a/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-settings/edit-employee-other-settings.component.html b/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-settings/edit-employee-other-settings.component.html
index e0083798014..3c10456bc9b 100644
--- a/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-settings/edit-employee-other-settings.component.html
+++ b/apps/gauzy/src/app/pages/employees/edit-employee/edit-employee-profile/edit-employee-settings/edit-employee-other-settings.component.html
@@ -9,6 +9,11 @@