diff --git a/src/app/components/admin-navbar/admin-navbar.component.ts b/src/app/components/admin-navbar/admin-navbar.component.ts index 1a7e4198..39f630e5 100644 --- a/src/app/components/admin-navbar/admin-navbar.component.ts +++ b/src/app/components/admin-navbar/admin-navbar.component.ts @@ -55,6 +55,10 @@ export class AdminNavbarComponent { title: 'All salaries', url: '/admin/salaries' }, + { + title: 'Salaries not in stats', + url: '/admin/salaries/not-in-stats' + }, { title: 'Salaries adding chart', url: '/admin/salaries/salaries-adding-trend-chart' diff --git a/src/app/models/salaries/user-profession.ts b/src/app/models/salaries/user-profession.ts index d815641a..7cd19f0d 100644 --- a/src/app/models/salaries/user-profession.ts +++ b/src/app/models/salaries/user-profession.ts @@ -52,4 +52,6 @@ export enum UserProfession { ProductManager = 25, ProductDesigner = 26, + + HrNonIt = 27, } diff --git a/src/app/modules/admin/admin-routing.module.ts b/src/app/modules/admin/admin-routing.module.ts index 0fdf865a..47e702f2 100644 --- a/src/app/modules/admin/admin-routing.module.ts +++ b/src/app/modules/admin/admin-routing.module.ts @@ -7,6 +7,7 @@ import { AllOrganizationsAdminComponent } from './components/organizations/all-o import { UsersAdminPageComponent } from './components/users/users-admin-page/users-admin-page.component'; import { SalariesAdminPageComponent } from './components/salaries/salaries-admin-page/salaries-admin-page.component'; import { SalariesAddingChartComponent } from './components/salaries/salaries-adding-chart/salaries-adding-chart.component'; +import { SalariesNotInStatsAdminPageComponent } from './components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component'; const routes: Routes = [ { path: '', component: AdminStartPageComponent }, @@ -15,6 +16,7 @@ const routes: Routes = [ { path: 'background-jobs', component: BackgroundJobsComponent }, { path: 'organizations', component: AllOrganizationsAdminComponent }, { path: 'salaries', component: SalariesAdminPageComponent }, + { path: 'salaries/not-in-stats', component: SalariesNotInStatsAdminPageComponent }, { path: 'salaries/salaries-adding-trend-chart', component: SalariesAddingChartComponent }, ]; diff --git a/src/app/modules/admin/admin.module.ts b/src/app/modules/admin/admin.module.ts index a117455a..1d66ce2e 100644 --- a/src/app/modules/admin/admin.module.ts +++ b/src/app/modules/admin/admin.module.ts @@ -13,6 +13,8 @@ import { AllOrganizationsAdminComponent } from './components/organizations/all-o import { AdminStartPageComponent } from './components/admin-start-page/admin-start-page.component'; import { SalariesAdminPageComponent } from './components/salaries/salaries-admin-page/salaries-admin-page.component'; import { SalariesAddingChartComponent } from './components/salaries/salaries-adding-chart/salaries-adding-chart.component'; +import { SalariesAdminPaginatedTableComponent } from './components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component'; +import { SalariesNotInStatsAdminPageComponent } from './components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component'; @NgModule({ declarations: [ @@ -25,7 +27,14 @@ import { SalariesAddingChartComponent } from './components/salaries/salaries-add AdminStartPageComponent, SalariesAdminPageComponent, SalariesAddingChartComponent, + SalariesAdminPaginatedTableComponent, + SalariesNotInStatsAdminPageComponent ], - imports: [CommonModule, SharedModule, AdminRoutingModule, FormsModule, ReactiveFormsModule] + imports: [ + CommonModule, + SharedModule, + AdminRoutingModule, + FormsModule, + ReactiveFormsModule] }) export class AdminModule {} diff --git a/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-admin-page.component.html b/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-admin-page.component.html index b96d7497..27e45c5b 100644 --- a/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-admin-page.component.html +++ b/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-admin-page.component.html @@ -4,75 +4,15 @@
-
-
- - -
+ -
- - -
- -
- - -
- -
-
- - -
-
-
- -
- - - - - - - - - - - - - - - - - - - - - -
ValuePeriodProfessionGradeCompanyCreated at
{{ item.value | number: '1.0-0' }}{{ item.quarter }}.{{ item.year }}{{ item.profession }}{{ item.grade }}{{ item.company }}{{ item.createdAt | date: 'yyyy-MM-dd' }} - -
-
- -
- -
@@ -82,13 +22,3 @@ - - -
-
-
There is no salaries.
-
-
-
- - \ No newline at end of file diff --git a/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-admin-page.component.ts b/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-admin-page.component.ts index 751c38c3..95723a19 100644 --- a/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-admin-page.component.ts +++ b/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-admin-page.component.ts @@ -3,13 +3,11 @@ import { defaultPageParams } from '@models/page-params'; import { PaginatedList } from '@models/paginated-list'; import { UserSalaryAdminDto } from '@models/salaries/salary.model'; import { TitleService } from '@services/title.service'; -import { UserSalariesService } from '@services/user-salaries.service'; +import { AdminAllSalariesQueryParams, UserSalariesService } from '@services/user-salaries.service'; import { untilDestroyed } from '@shared/subscriptions/until-destroyed'; -import { SalaryAdminItem } from './salary-admin-item'; -import { ConfirmMsg } from '@shared/components/dialogs/models/confirm-msg'; -import { DialogMessage } from '@shared/components/dialogs/models/dialog-message'; import { AlertService } from '@shared/components/alert/services/alert.service'; -import { SalariesTableFilter } from './salaries-table-filter'; +import { SalaryAdminItem } from '../salary-admin-item'; +import { SalariesTableFilter } from '../salaries-table-filter'; @Component({ templateUrl: './salaries-admin-page.component.html' @@ -18,33 +16,36 @@ export class SalariesAdminPageComponent implements OnInit, OnDestroy { salaries: Array | null = null; source: PaginatedList | null = null; - confirmDeletionMessage: DialogMessage | null = null; - readonly filter = new SalariesTableFilter(); + currentPage: number = 1; constructor( private readonly service: UserSalariesService, private readonly titleService: TitleService, - private readonly alert: AlertService) {} + private readonly alert: AlertService) { + titleService.setTitle('All salaries'); + } ngOnInit(): void { - this.loadData(); - this.titleService.setTitle('All salaries'); + this.salaries = null; + this.source = null; + this.loadData( + { + page: this.currentPage, + pageSize: defaultPageParams.pageSize, + ...this.filter + } + ); } - loadData(page = 1): void { + loadData(data: AdminAllSalariesQueryParams): void { this.salaries = null; this.source = null; + this.currentPage = data.page; this.service - .all({ - page, - pageSize: defaultPageParams.pageSize, - profession: this.filter.profession ?? null, - company: this.filter.company ?? null, - grade: this.filter.grade ?? null, - }) + .all(data) .pipe(untilDestroyed(this)) .subscribe((x) => { this.salaries = x.results.map((x) => new SalaryAdminItem(x)); @@ -56,27 +57,13 @@ export class SalariesAdminPageComponent implements OnInit, OnDestroy { // ignored } - openDeleteDialog(salary: SalaryAdminItem): void { - this.confirmDeletionMessage = new DialogMessage( - new ConfirmMsg( - 'Delete the salary record', - 'Are you sure to delete?', - () => { - this.service - .delete(salary.id) - .pipe(untilDestroyed(this)) - .subscribe(() => { - this.alert.success('Salary deleted'); - this.loadData(); - }); - } - ) - ); - } - - clearFilter(): void { - this.filter.profession = null; - this.filter.company = null; - this.loadData(); + deleteSalary(salary: SalaryAdminItem): void { + this.service + .delete(salary.id) + .pipe(untilDestroyed(this)) + .subscribe(() => { + this.alert.success('Salary deleted'); + this.ngOnInit(); + }); } } diff --git a/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.html b/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.html new file mode 100644 index 00000000..37d3bf6e --- /dev/null +++ b/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.html @@ -0,0 +1,95 @@ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
ValuePeriodProfessionGradeCompanyCreated at
{{ item.value | number: '1.0-0' }}{{ item.quarter }}.{{ item.year }}{{ item.profession }}{{ item.grade }}{{ item.company }}{{ item.createdAt | date: 'yyyy-MM-dd HH:mm' }} + + +
+
+ +
+ +
+ + +
+ +
+
+ + +
+
+
There is no salaries.
+
+
+
+ + \ No newline at end of file diff --git a/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.spec.ts b/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.spec.ts new file mode 100644 index 00000000..c364a0c0 --- /dev/null +++ b/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.spec.ts @@ -0,0 +1,28 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { mostUsedImports, testUtilStubs, mostUsedServices } from '@shared/test-utils'; +import { SalariesAdminPaginatedTableComponent } from './salaries-admin-paginated-table.component'; + +describe('SalariesAdminPaginatedTableComponent', () => { + let component: SalariesAdminPaginatedTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SalariesAdminPaginatedTableComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SalariesAdminPaginatedTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.ts b/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.ts new file mode 100644 index 00000000..7c64d6cc --- /dev/null +++ b/src/app/modules/admin/components/salaries/salaries-admin-paginated-table/salaries-admin-paginated-table.component.ts @@ -0,0 +1,86 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { defaultPageParams } from '@models/page-params'; +import { PaginatedList } from '@models/paginated-list'; +import { UserSalaryAdminDto } from '@models/salaries/salary.model'; +import { AdminAllSalariesQueryParams } from '@services/user-salaries.service'; +import { SalaryAdminItem } from '../salary-admin-item'; +import { ConfirmMsg } from '@shared/components/dialogs/models/confirm-msg'; +import { DialogMessage } from '@shared/components/dialogs/models/dialog-message'; +import { SalariesTableFilter } from '../salaries-table-filter'; + +@Component({ + selector: 'app-salaries-admin-paginated-table', + templateUrl: './salaries-admin-paginated-table.component.html' +}) +export class SalariesAdminPaginatedTableComponent { + + @Input() + salaries: Array | null = null; + + @Input() + source: PaginatedList | null = null; + + @Input() + filter: SalariesTableFilter | null = null; + + @Input() + showApproveButton = false; + + @Output() + loadDataRequested: EventEmitter = new EventEmitter(); + + @Output() + approveRequested: EventEmitter = new EventEmitter(); + + @Output() + deleteRequested: EventEmitter = new EventEmitter(); + + confirmDeletionMessage: DialogMessage | null = null; + + constructor() {} + + loadData(page = 1): void { + this.loadDataRequested.emit({ + page, + pageSize: defaultPageParams.pageSize, + profession: this.filter?.profession ?? null, + company: this.filter?.company ?? null, + grade: this.filter?.grade ?? null, + }); + } + + openDeleteDialog(salary: SalaryAdminItem): void { + this.confirmDeletionMessage = new DialogMessage( + new ConfirmMsg( + 'Delete the salary record', + 'Are you sure to delete?', + () => { + this.deleteRequested.emit(salary); + console.log('deleteRequested'); + } + ) + ); + } + + openApproveDialog(salary: SalaryAdminItem): void { + this.confirmDeletionMessage = new DialogMessage( + new ConfirmMsg( + 'Approve the salary record', + 'Are you sure to approve?', + () => { + this.approveRequested.emit(salary); + } + ) + ); + } + + clearFilter(): void { + if (this.filter) { + this.filter.profession = null; + this.filter.company = null; + this.filter.grade = null; + } + + this.loadData(); + } +} diff --git a/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.html b/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.html new file mode 100644 index 00000000..805cdd03 --- /dev/null +++ b/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.html @@ -0,0 +1,25 @@ +Salaries not in stats + +
+
+
+ + + +
+
+
+ + +
+ +
+
diff --git a/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.spec.ts b/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.spec.ts new file mode 100644 index 00000000..095d9a0d --- /dev/null +++ b/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.spec.ts @@ -0,0 +1,29 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { UserAdminService } from '@services/user-admin.service'; +import { mostUsedImports, testUtilStubs, mostUsedServices } from '@shared/test-utils'; +import { SalariesNotInStatsAdminPageComponent } from './salaries-not-in-stat-admin-page.component'; + +describe('SalariesNotInStatsAdminPageComponent', () => { + let component: SalariesNotInStatsAdminPageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SalariesNotInStatsAdminPageComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices, UserAdminService], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SalariesNotInStatsAdminPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.ts b/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.ts new file mode 100644 index 00000000..01c6c4e5 --- /dev/null +++ b/src/app/modules/admin/components/salaries/salaries-not-in-stat-admin-page/salaries-not-in-stat-admin-page.component.ts @@ -0,0 +1,79 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { defaultPageParams } from '@models/page-params'; +import { PaginatedList } from '@models/paginated-list'; +import { UserSalaryAdminDto } from '@models/salaries/salary.model'; +import { TitleService } from '@services/title.service'; +import { AdminAllSalariesQueryParams, UserSalariesService } from '@services/user-salaries.service'; +import { untilDestroyed } from '@shared/subscriptions/until-destroyed'; +import { AlertService } from '@shared/components/alert/services/alert.service'; +import { SalaryAdminItem } from '../salary-admin-item'; +import { SalariesTableFilter } from '../salaries-table-filter'; + +@Component({ + templateUrl: './salaries-not-in-stat-admin-page.component.html' +}) +export class SalariesNotInStatsAdminPageComponent implements OnInit, OnDestroy { + + salaries: Array | null = null; + source: PaginatedList | null = null; + readonly filter = new SalariesTableFilter(); + currentPage: number = 1; + + constructor( + private readonly service: UserSalariesService, + titleService: TitleService, + private readonly alert: AlertService) { + titleService.setTitle('Salaries not in stats'); + } + + ngOnInit(): void { + this.salaries = null; + this.source = null; + this.loadData( + { + page: this.currentPage, + pageSize: defaultPageParams.pageSize, + ...this.filter + } + ); + } + + loadData(data: AdminAllSalariesQueryParams): void { + + this.salaries = null; + this.source = null; + this.currentPage = data.page; + + this.service + .salariesNotInStats(data) + .pipe(untilDestroyed(this)) + .subscribe((x) => { + this.salaries = x.results.map((x) => new SalaryAdminItem(x)); + this.source = x; + }); + } + + ngOnDestroy(): void { + // ignored + } + + deleteSalary(salary: SalaryAdminItem): void { + this.service + .delete(salary.id) + .pipe(untilDestroyed(this)) + .subscribe(() => { + this.alert.success('Salary deleted'); + this.ngOnInit(); + }); + } + + approveSalary(salary: SalaryAdminItem): void { + this.service + .approve(salary.id) + .pipe(untilDestroyed(this)) + .subscribe(() => { + this.alert.success('Salary approved'); + this.ngOnInit(); + }); + } +} diff --git a/src/app/modules/admin/components/salaries/salaries-admin-page/salaries-table-filter.ts b/src/app/modules/admin/components/salaries/salaries-table-filter.ts similarity index 100% rename from src/app/modules/admin/components/salaries/salaries-admin-page/salaries-table-filter.ts rename to src/app/modules/admin/components/salaries/salaries-table-filter.ts diff --git a/src/app/modules/admin/components/salaries/salaries-admin-page/salary-admin-item.ts b/src/app/modules/admin/components/salaries/salary-admin-item.ts similarity index 100% rename from src/app/modules/admin/components/salaries/salaries-admin-page/salary-admin-item.ts rename to src/app/modules/admin/components/salaries/salary-admin-item.ts diff --git a/src/app/services/user-salaries.service.ts b/src/app/services/user-salaries.service.ts index d3953a74..82e9fa2d 100644 --- a/src/app/services/user-salaries.service.ts +++ b/src/app/services/user-salaries.service.ts @@ -97,6 +97,11 @@ export class UserSalariesService { this.root + 'all?' + new ConvertObjectToHttpParams(pageParams).get()); } + salariesNotInStats(pageParams: AdminAllSalariesQueryParams): Observable> { + return this.api.get>( + this.root + 'not-in-stats?' + new ConvertObjectToHttpParams(pageParams).get()); + } + addingSalariesaTrendAdminChart(): Observable { return this.api.get(this.root + 'salaries-adding-trend-chart'); } @@ -114,6 +119,10 @@ export class UserSalariesService { return this.api.post(this.root + id, data); } + approve(dataId: string): Observable { + return this.api.post(this.root + dataId + '/approve', {}); + } + delete(dataId: string): Observable { return this.api.delete(this.root + dataId); } diff --git a/src/app/shared/select-boxes/profession-select-item.ts b/src/app/shared/select-boxes/profession-select-item.ts index b0a11a1e..fc7fe113 100644 --- a/src/app/shared/select-boxes/profession-select-item.ts +++ b/src/app/shared/select-boxes/profession-select-item.ts @@ -24,6 +24,10 @@ export class ProfessionSelectItem implements SelectItem { this.label = 'UI/UX Designer'; break; + case UserProfession.HrNonIt: + this.label = 'HR (не из IT)'; + break; + default: this.label = new SplittedByWhitespacesString(UserProfession[item]).value; break;