Skip to content

Commit

Permalink
Merge pull request #8372 from ever-co/stage
Browse files Browse the repository at this point in the history
Stage
  • Loading branch information
evereq authored Oct 9, 2024
2 parents 8e79016 + 595a0b5 commit 8986d38
Show file tree
Hide file tree
Showing 246 changed files with 8,223 additions and 4,247 deletions.
2 changes: 2 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"Alexi",
"alish",
"Alish",
"Rahul",
"rahul",
"apicivo",
"apicw",
"apidemo",
Expand Down
2 changes: 0 additions & 2 deletions apps/gauzy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@
"@swimlane/ngx-charts": "^20.1.0",
"angular2-smart-table": "^3.2.0",
"angular2-toaster": "^11.0.1",
"bcrypt": "^5.1.0",
"bootstrap": "^4.3.1",
"brace": "^0.11.1",
"camelcase": "^6.3.0",
Expand Down Expand Up @@ -184,7 +183,6 @@
"@angular/cli": "^16.2.11",
"@angular/compiler-cli": "^16.2.12",
"@types/async": "^3.2.5",
"@types/bcrypt": "^5.0.0",
"@types/chart.js": "^2.9.37",
"@types/ckeditor": "^4.9.10",
"@types/d3-color": "^3.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import moment from 'moment-timezone';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { NbDialogService } from '@nebular/theme';
import { TranslateService } from '@ngx-translate/core';
import { DateRangePickerBuilderService, Store, TimesheetFilterService, TimesheetService } from '@gauzy/ui-core/core';
import {
ITimeLogFilters,
ITimeSlot,
IGetTimeSlotInput,
IScreenshotMap,
IScreenshot,
PermissionsEnum
PermissionsEnum,
ID
} from '@gauzy/contracts';
import { isEmpty, distinctUntilChange, isNotEmpty, toTimezone } from '@gauzy/ui-core/common';
import { DateRangePickerBuilderService, Store, TimesheetFilterService, TimesheetService } from '@gauzy/ui-core/core';
import {
BaseSelectorFilterComponent,
DeleteConfirmationComponent,
Expand Down Expand Up @@ -188,7 +189,7 @@ export class ScreenshotComponent extends BaseSelectorFilterComponent implements
*
* @param slotId The ID of the time slot to toggle selection for.
*/
toggleSelect(slotId?: string): void {
toggleSelect(slotId?: ID): void {
if (slotId) {
// Toggle the selection state of the time slot identified by slotId
this.selectedIds[slotId] = !this.selectedIds[slotId];
Expand Down Expand Up @@ -252,11 +253,17 @@ export class ScreenshotComponent extends BaseSelectorFilterComponent implements
const ids = Object.keys(this.selectedIds).filter((key) => this.selectedIds[key]);

// Construct request object with organization ID
const { id: organizationId } = this.organization;
const request = { ids, organizationId };
const { id: organizationId, tenantId } = this.organization;

// Call the deleteTimeSlots API with forceDelete set to true
const api$ = this._timesheetService.deleteTimeSlots({
ids,
organizationId,
tenantId
});

// Convert the promise to an observable and handle deletion
return from(this._timesheetService.deleteTimeSlots(request)).pipe(
return from(api$).pipe(
tap(() => this._deleteScreenshotGallery(ids)),
tap(() => this.screenshots$.next(true))
);
Expand All @@ -266,10 +273,6 @@ export class ScreenshotComponent extends BaseSelectorFilterComponent implements
.subscribe();
}

ngOnDestroy(): void {
this._galleryService.clearGallery();
}

/**
* Groups time slots by hour and prepares data for display.
* Also generates screenshot URLs and calculates employee work on the same time slots.
Expand Down Expand Up @@ -344,7 +347,7 @@ export class ScreenshotComponent extends BaseSelectorFilterComponent implements
*
* @param timeSlotIds An array of time slot IDs whose screenshots should be removed from the gallery.
*/
private _deleteScreenshotGallery(timeSlotIds: string[]) {
private _deleteScreenshotGallery(timeSlotIds: ID[]) {
if (isNotEmpty(this.originalTimeSlots)) {
// Extract all screenshots from time slots that match the provided time slot IDs
const screenshotsToRemove = this.originalTimeSlots
Expand All @@ -361,4 +364,8 @@ export class ScreenshotComponent extends BaseSelectorFilterComponent implements
this._galleryService.removeGalleryItems(screenshotsToRemove);
}
}

ngOnDestroy(): void {
this._galleryService.clearGallery();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import {
PermissionsEnum
} from '@gauzy/contracts';
import { distinctUntilChange } from '@gauzy/ui-core/common';
import { EmployeeStore, OrganizationProjectsService, Store, ToastrService } from '@gauzy/ui-core/core';
import {
EmployeeStore,
ErrorHandlingService,
OrganizationProjectsService,
Store,
ToastrService
} from '@gauzy/ui-core/core';
import { TranslationBaseComponent } from '@gauzy/ui-core/i18n';

@UntilDestroy({ checkProperties: true })
Expand Down Expand Up @@ -45,11 +51,12 @@ export class EditEmployeeProjectsComponent extends TranslationBaseComponent impl
public organization: IOrganization;

constructor(
private readonly organizationProjectsService: OrganizationProjectsService,
private readonly toastrService: ToastrService,
private readonly employeeStore: EmployeeStore,
public readonly translateService: TranslateService,
private readonly store: Store
private readonly _organizationProjectsService: OrganizationProjectsService,
private readonly _toastrService: ToastrService,
private readonly _employeeStore: EmployeeStore,
private readonly _store: Store,
private readonly _errorHandlingService: ErrorHandlingService
) {
super(translateService);
}
Expand All @@ -61,8 +68,8 @@ export class EditEmployeeProjectsComponent extends TranslationBaseComponent impl
untilDestroyed(this)
)
.subscribe();
const storeOrganization$ = this.store.selectedOrganization$;
const storeEmployee$ = this.employeeStore.selectedEmployee$;
const storeOrganization$ = this._store.selectedOrganization$;
const storeEmployee$ = this._employeeStore.selectedEmployee$;
combineLatest([storeOrganization$, storeEmployee$])
.pipe(
distinctUntilChange(),
Expand All @@ -77,79 +84,129 @@ export class EditEmployeeProjectsComponent extends TranslationBaseComponent impl
.subscribe();
}

ngOnDestroy(): void {}
/**
* Submits the form to update the employee's project association.
*
* If the `member` exists in the input, the method will either update or remove the employee's project assignment
* and provide feedback through a success or error toastr notification.
*
* @param input The input data containing information about the employee and the project.
* @param removed A flag indicating whether the employee was removed from or added to the project.
*/
async submitForm(input: IEditEntityByMemberInput, removed: boolean): Promise<void> {
if (!this.organization || !input.member) {
return;
}

const { id: organizationId, tenantId } = this.organization;

async submitForm(formInput: IEditEntityByMemberInput, removed: boolean) {
try {
if (formInput.member) {
await this.organizationProjectsService.updateByEmployee(formInput);
this.loadProjects();
this.toastrService.success(
removed ? 'TOASTR.MESSAGE.EMPLOYEE_PROJECT_REMOVED' : 'TOASTR.MESSAGE.EMPLOYEE_PROJECT_ADDED'
);
}
// Update the employee's project assignment
await this._organizationProjectsService.updateByEmployee({
addedProjectIds: input.addedEntityIds,
removedProjectIds: input.removedEntityIds,
member: input.member,
organizationId,
tenantId
});

// Show success message based on the action performed (added or removed)
const message = removed
? 'TOASTR.MESSAGE.EMPLOYEE_PROJECT_REMOVED'
: 'TOASTR.MESSAGE.EMPLOYEE_PROJECT_ADDED';
this._toastrService.success(message);
} catch (error) {
this.toastrService.danger('TOASTR.MESSAGE.EMPLOYEE_EDIT_ERROR');
// Show error message in case of failure
this._toastrService.danger('TOASTR.MESSAGE.EMPLOYEE_EDIT_ERROR');
} finally {
// Notify subscribers that the operation is complete
this.subject$.next(true);
}
}

/**
* Load organization & employee assigned projects
* Loads organization and employee assigned projects.
*
* This method loads the projects assigned to the selected employee and all organization projects,
* then filters out the employee's assigned projects from the full list of organization projects.
*/
private async loadProjects() {
private async loadProjects(): Promise<void> {
// Load employee projects and all organization projects
await this.loadSelectedEmployeeProjects();

// Get all organization projects
const organizationProjects = await this.getOrganizationProjects();

// Filter out employee's assigned projects from the organization projects list
this.organizationProjects = organizationProjects.filter(
(item: IOrganizationProject) =>
!this.employeeProjects.some((project: IOrganizationProject) => project.id === item.id)
(orgProject: IOrganizationProject) =>
!this.employeeProjects.some((empProject: IOrganizationProject) => empProject.id === orgProject.id)
);
}

/**
* Get selected employee projects
* Fetches projects assigned to the selected employee.
*
* This method loads the projects associated with the selected employee if the user has the necessary permissions
* and the organization is available.
*
* @returns
* @returns A Promise that resolves once the employee projects are loaded.
*/
private async loadSelectedEmployeeProjects() {
private async loadSelectedEmployeeProjects(): Promise<void> {
if (
!this.organization ||
!this.store.hasAnyPermission(PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_PROJECT_VIEW)
!this._store.hasAnyPermission(PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_PROJECT_VIEW)
) {
return;
}

const { tenantId } = this.store.user;
const { id: organizationId } = this.organization;
const { id: organizationId, tenantId } = this.organization;
const { id: selectedEmployeeId } = this.selectedEmployee;

this.employeeProjects = await this.organizationProjectsService.getAllByEmployee(selectedEmployeeId, {
organizationId,
tenantId
});
try {
// Fetch and assign employee projects to the component property
this.employeeProjects = await this._organizationProjectsService.getAllByEmployee(selectedEmployeeId, {
organizationId,
tenantId
});
} catch (error) {
console.error('Error loading selected employee projects:', error);
this._errorHandlingService.handleError(error);
}
}

/**
* Get organization projects
* Fetches all projects within the organization.
*
* @returns
* This method retrieves all projects in the organization if the user has the required permissions
* and the organization is available.
*
* @returns A Promise that resolves to an array of organization projects.
*/
private async getOrganizationProjects(): Promise<IOrganizationProject[]> {
if (
!this.organization ||
!this.store.hasAnyPermission(PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_PROJECT_VIEW)
!this._store.hasAnyPermission(PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_PROJECT_VIEW)
) {
return;
return [];
}

const { tenantId } = this.store.user;
const { id: organizationId } = this.organization;
const { id: organizationId, tenantId } = this.organization;

return (
await this.organizationProjectsService.getAll([], {
try {
// Fetch and return all organization projects
const result = await this._organizationProjectsService.getAll([], {
organizationId,
tenantId
})
).items;
});
return result.items;
} catch (error) {
console.error('Error fetching organization projects:', error);
// Handle errors
this._errorHandlingService.handleError(error);
return [];
}
}

ngOnDestroy(): void {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
<div class="mt-2 small">
<span *ngIf="log?.task; else noToDo" [nbTooltip]="log?.task?.title">
<strong>{{ 'TIMESHEET.TODO' | translate }}:</strong>
{{ log?.task?.title | truncate : 50 }}
{{ log?.task?.title | truncate : 40 }}
</span>
<ng-template #noToDo>
<span>{{ 'TIMESHEET.NO_TODO' | translate }}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
DateViewComponent,
DeleteConfirmationComponent,
EmployeesMergedTeamsComponent,
EmployeeWithLinksComponent,
PaginationFilterBaseComponent,
ProjectOrganizationComponent,
ProjectOrganizationEmployeesComponent,
Expand Down Expand Up @@ -247,6 +248,7 @@ export class ProjectListComponent extends PaginationFilterBaseComponent implemen
resultMap: (project: IOrganizationProject) => {
return Object.assign({}, project, {
...this.privatePublicProjectMapper(project),
managers: project.members.filter((member) => member.isManager).map((item) => item.employee),
employeesMergedTeams: [
project.members.map((member: IOrganizationProjectEmployee) => member.employee)
]
Expand Down Expand Up @@ -417,6 +419,17 @@ export class ProjectListComponent extends PaginationFilterBaseComponent implemen
instance.value = cell.getValue();
}
},
managers: {
title: this.getTranslation('ORGANIZATIONS_PAGE.EDIT.TEAMS_PAGE.MANAGERS'),
type: 'custom',
isFilterable: false,
renderComponent: EmployeeWithLinksComponent,
componentInitFunction: (instance: EmployeeWithLinksComponent, cell: Cell) => {
instance.rowData = cell.getRow().getData();
instance.value = cell.getRawValue();
}
},

employeesMergedTeams: {
title: this.getTranslation('ORGANIZATIONS_PAGE.EDIT.MEMBERS'),
type: 'custom',
Expand Down
Binary file added apps/gauzy/src/assets/images/avatars/rahul.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"config:prod": "yarn run config -- --environment=prod",
"start": "yarn build:package:all && yarn concurrently --raw --kill-others \"yarn start:api\" \"yarn start:gauzy\"",
"start:prod": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=12288 yarn build:package:all && yarn concurrently --raw --kill-others \"yarn start:api:prod\" \"yarn start:gauzy:prod\"",
"start:gauzy": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=12288 yarn run postinstall.web && yarn ng serve gauzy --open",
"start:gauzy": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=12288 yarn run postinstall.web && yarn build:package:ui-config && yarn ng serve gauzy --open",
"start:gauzy:forever": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=12288 yarn run config:dev && forever start node_modules/@angular/cli/bin/ng serve gauzy --disable-host-check --host 0.0.0.0",
"start:gauzy:pm2": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=12288 yarn build:package:all && yarn build:gauzy && yarn ts-node ./apps/gauzy/src/pm2bootstrap.ts",
"start:gauzy:prod": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=12288 yarn run config:prod && yarn ng serve gauzy --configuration production --disable-host-check --host 0.0.0.0 --prod",
Expand Down Expand Up @@ -331,7 +331,7 @@
"@ng-select/ng-select": "^11.2.0",
"angular2-smart-table": "^3.2.0",
"autoprefixer": "10.4.14",
"bcrypt": "^5.1.0",
"bcrypt": "^5.1.1",
"camelcase": "^6.3.0",
"dotenv": "^16.0.3",
"ffi-napi": "^4.0.3",
Expand Down Expand Up @@ -384,6 +384,7 @@
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^9.2.6",
"@semantic-release/npm": "^11.0.0",
"@types/bcrypt": "^5.0.2",
"@types/jest": "^29.4.4",
"@types/jsdom": "^21.1.6",
"@types/node": "^20.14.9",
Expand Down
4 changes: 2 additions & 2 deletions packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@nestjs/config": "^3.2.0",
"@nestjs/passport": "^10.0.3",
"axios": "^1.7.4",
"bcrypt": "^5.1.0",
"bcrypt": "^5.1.1",
"express": "^4.18.2",
"passport": "^0.6.0",
"passport-auth0": "^1.3.3",
Expand All @@ -59,7 +59,7 @@
"tslib": "^2.6.2"
},
"devDependencies": {
"@types/bcrypt": "^5.0.0",
"@types/bcrypt": "^5.0.2",
"@types/jest": "^29.4.4",
"@types/node": "^20.14.9",
"@types/passport": "^1.0.9",
Expand Down
Loading

0 comments on commit 8986d38

Please sign in to comment.