Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stage #8371

Merged
merged 83 commits into from
Oct 9, 2024
Merged

Stage #8371

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
0d42ed0
[Bug] Only the first task/project displayed(Group By Date)
samuelmbabhazi Oct 4, 2024
1e43c58
[Bug] Only the first task/project displayed(Group By Employee)
samuelmbabhazi Oct 4, 2024
0214d20
[Bug] Only the first task/project displayed(Group By Project)
samuelmbabhazi Oct 4, 2024
578e7dd
[Bug] Only the first task/project displayed(Group By Client)
samuelmbabhazi Oct 4, 2024
91ad306
fix: sub directory path for screenshots upload
rahul-rocket Oct 5, 2024
b163b46
feat: soft removal of screenshots based on parameters
rahul-rocket Oct 5, 2024
4e41f11
fix: screenshot force delete parameter parse
rahul-rocket Oct 5, 2024
7115ee1
fix(cspell): typo spelling :-)
rahul-rocket Oct 5, 2024
43c57a1
Merge pull request #8336 from ever-co/fix/screenshot-upload-directory…
rahul-rocket Oct 5, 2024
06e8117
Fix retrieve client
samuelmbabhazi Oct 5, 2024
fb79743
fix: missing employee & organizationId
rahul-rocket Oct 5, 2024
09172ef
fix(deepscan): removed unused import
rahul-rocket Oct 5, 2024
611f6f2
Merge pull request #8337 from ever-co/fix/missing-current-employeeId
rahul-rocket Oct 5, 2024
423a8ca
fix: quick refactor for soft removal entities
rahul-rocket Oct 5, 2024
e3e7bb7
fix(cspell): typo spelling :-)
rahul-rocket Oct 5, 2024
73abd35
Merge pull request #8338 from ever-co/fix/cspell
rahul-rocket Oct 5, 2024
10912d2
feat: organization sprint model members
GloireMutaliko21 Oct 7, 2024
127277d
fix: update employee total worked hours
rahul-rocket Oct 7, 2024
c6ae094
fix: improved time log related repository injection
rahul-rocket Oct 7, 2024
c1a486c
feat: organization sprint model status
GloireMutaliko21 Oct 7, 2024
e111f3d
fix: generate task max number for MySQL
rahul-rocket Oct 7, 2024
4f1476d
fix: fallback condition if project or projectId not found
rahul-rocket Oct 7, 2024
5ac458f
fix(cspell): typo spelling :-)
rahul-rocket Oct 7, 2024
71ad1e1
Merge pull request #8342 from ever-co/fix/total-worked-hours
rahul-rocket Oct 7, 2024
507464f
fix(deepscan): accessed without null check prior
rahul-rocket Oct 7, 2024
f103d9b
fix(cspell): typo spelling :-)
rahul-rocket Oct 7, 2024
d940882
Merge pull request #8343 from ever-co/fix/task-max-number
rahul-rocket Oct 7, 2024
693d1bd
Merge branch 'develop' into fix/#8271-only-the-first-task-per-projet-…
rahul-rocket Oct 7, 2024
71f0bde
feat: improve sprint entities and model
GloireMutaliko21 Oct 7, 2024
c84cda3
Merge pull request #8333 from ever-co/fix/#8271-only-the-first-task-p…
rahul-rocket Oct 7, 2024
4061405
fix: update projects by employee commands
rahul-rocket Oct 7, 2024
833c11c
fix(deepscan): removed unused import
rahul-rocket Oct 7, 2024
56f5e17
Merge pull request #8350 from ever-co/fix/add-organization-project-me…
rahul-rocket Oct 7, 2024
5497e4b
feat: organization sprint task history entity
GloireMutaliko21 Oct 7, 2024
143cf09
refactor: optimize code for time slots & logs
rahul-rocket Oct 7, 2024
61a83dd
fix(deepscan): removed unused import
rahul-rocket Oct 7, 2024
4985b98
Merge pull request #8352 from ever-co/fix/time-slot-log-optimization
rahul-rocket Oct 7, 2024
71449c5
fix: #8317 password reset request token alter column (MySQL)
rahul-rocket Oct 7, 2024
74c3f32
Merge pull request #8353 from ever-co/fix/#8317-password-reset-migration
rahul-rocket Oct 7, 2024
c140ac4
feat: create migrations for sprints and related entities
GloireMutaliko21 Oct 7, 2024
a0a7859
Merge branch 'develop' into feat/organization-sprint-entities-improve…
GloireMutaliko21 Oct 7, 2024
ec3933a
fix: MySQL indexing migration
GloireMutaliko21 Oct 7, 2024
32f59a4
fix(typos): typos error
GloireMutaliko21 Oct 7, 2024
077e2af
feat: create organization sprint service
GloireMutaliko21 Oct 8, 2024
1113505
feat: create sprint API
GloireMutaliko21 Oct 8, 2024
f27adda
fix: screenshots cascading for time-slots
rahul-rocket Oct 8, 2024
0ab78d7
Merge pull request #8356 from ever-co/fix/timeslot-screenshot-cascading
rahul-rocket Oct 8, 2024
3ea5a1f
feat: update organization sprint API
GloireMutaliko21 Oct 8, 2024
5a0b4a5
fix: #8329 soft delete for time slot & time logs
rahul-rocket Oct 8, 2024
7067626
fix: added my self to employee list :-)
rahul-rocket Oct 8, 2024
7856d11
fix: #8329 delete time slot with cascading
rahul-rocket Oct 8, 2024
ed93f24
fix: use common DTO for members and manageres base entities
GloireMutaliko21 Oct 8, 2024
8502638
fix: #8329 soft & hard deleting during update time log
rahul-rocket Oct 8, 2024
054114a
fix(cspell): typo spelling :-)
rahul-rocket Oct 8, 2024
9a496f7
Merge pull request #8359 from ever-co/fix/#8329-soft-delete-time-trac…
rahul-rocket Oct 8, 2024
b2892b1
feat: update task use sprints history if sprintId changed
GloireMutaliko21 Oct 8, 2024
88c8ba4
wip: time span handler
rahul-rocket Oct 8, 2024
e691c0f
feat: activate plugin after installation
adkif Oct 8, 2024
21d672f
Merge pull request #8363 from ever-co/fix/time-span-handler
rahul-rocket Oct 8, 2024
9430fd4
[Fix] #8329 Soft Delete (Time Tracking) (#8351)
rahul-rocket Oct 8, 2024
c91afc9
Merge pull request #8364 from ever-co/fix/plugin-activation-after-ins…
evereq Oct 8, 2024
7d1e15c
[Fix] Error when updating project: update of employees or managers
samuelmbabhazi Oct 9, 2024
8622d1a
[Fix] Error when updating project: update of employees or managers
samuelmbabhazi Oct 9, 2024
d8babc1
Merge pull request #8365 from ever-co/fix/8358-project-update
rahul-rocket Oct 9, 2024
e1ded3e
fix: #8347 changed "Select team" label to "Select Team"
rahul-rocket Oct 9, 2024
9e4d813
fix: uuid validation for member base entity DTO
rahul-rocket Oct 9, 2024
504f8fa
Merge pull request #8366 from ever-co/fix/#8347-change-label
rahul-rocket Oct 9, 2024
fe34e17
Merge pull request #8357 from ever-co/feat/organization-sprint-API-im…
GloireMutaliko21 Oct 9, 2024
5a261e3
fix: improvements and code consistence
GloireMutaliko21 Oct 9, 2024
82779f2
[Feature] Organization Project Managers
samuelmbabhazi Oct 7, 2024
49cd8c0
[Feature] Organization Project Managers
samuelmbabhazi Oct 7, 2024
8194e23
[Bug] Only the first task/project displayed(Group By Client)
samuelmbabhazi Oct 4, 2024
6efb783
Fix retrieve client
samuelmbabhazi Oct 5, 2024
7b550b1
fix: update projects by employee commands
rahul-rocket Oct 7, 2024
73efa8d
fix(deepscan): removed unused import
rahul-rocket Oct 7, 2024
47388d0
add column managers
samuelmbabhazi Oct 8, 2024
e532c67
fix update employee role
samuelmbabhazi Oct 9, 2024
c5ade17
fix(typos): typo errors
GloireMutaliko21 Oct 9, 2024
e077bcd
fix(typos): typo errors
GloireMutaliko21 Oct 9, 2024
76a0425
fix: estimate calculation task update
GloireMutaliko21 Oct 9, 2024
e3af4cf
Merge pull request #8368 from ever-co/fix/8263-project-manager
rahul-rocket Oct 9, 2024
64761fd
Merge pull request #8355 from ever-co/feat/organization-sprint-entiti…
rahul-rocket Oct 9, 2024
2e78d47
[Feat] Task views API (#8369)
GloireMutaliko21 Oct 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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 @@ -137,13 +137,6 @@
{{ log.duration | durationFormat }}
</div>
<div class="col-2">
<div class="">
{{
log.startedAt
| utcToTimezone : filters?.timeZone
| date : 'MMMM d, yyyy'
}}
</div>
<span class="start-timer">
{{
log.startedAt
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.
7 changes: 7 additions & 0 deletions packages/contracts/src/employee.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { IOrganizationProjectModule } from './organization-project-module.model'
import { CurrenciesEnum } from './currency.model';
import { IFavorite } from './favorite.model';
import { IComment } from './comment.model';
import { IOrganizationSprint } from './organization-sprint.model';

export interface IFindMembersInput extends IBasePerTenantAndOrganizationEntityModel {
organizationTeamId: ID;
Expand Down Expand Up @@ -79,6 +80,7 @@ export interface IEmployee extends IBasePerTenantAndOrganizationEntityModel, ITa
timesheets?: ITimesheet[];
tasks?: ITask[];
modules?: IOrganizationProjectModule[];
sprints?: IOrganizationSprint[];
assignedComments?: IComment[];
timeSlots?: ITimeSlot[];
contact?: IContact;
Expand Down Expand Up @@ -280,3 +282,8 @@ export interface IEmployeeStoreState {
export interface IEmployeeUpdateProfileStatus extends IBasePerTenantAndOrganizationEntityModel {
readonly isActive: boolean;
}

export interface IMemberEntityBased extends IBasePerTenantAndOrganizationEntityModel {
memberIds?: ID[]; // Members of the given entity
managerIds?: ID[]; // Managers of the given entity
}
1 change: 1 addition & 0 deletions packages/contracts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export * from './task-related-issue-type.model';
export * from './task-size.model';
export * from './task-status.model';
export * from './task-version.model';
export * from './task-view.model';
export * from './task.model';
export * from './daily-plan.model';
export * from './tenant.model';
Expand Down
Loading
Loading