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 072e44c9..b96d7497 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 @@ -27,12 +27,12 @@
- +
diff --git a/src/app/modules/home/components/auth-callback/auth-callback.component.ts b/src/app/modules/home/components/auth-callback/auth-callback.component.ts index f5222b2f..2488afb7 100644 --- a/src/app/modules/home/components/auth-callback/auth-callback.component.ts +++ b/src/app/modules/home/components/auth-callback/auth-callback.component.ts @@ -34,7 +34,6 @@ export class AuthCallbackComponent implements OnInit { this.cookieService.delete('url'); this.router.navigate([url]); } else { - console.log('Redirecting to /me'); this.router.navigate([this.urlToRedirectAfterLogin]); } }); diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.html b/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.html index adf53789..a42e92f3 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.html +++ b/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.html @@ -62,7 +62,6 @@ [title]="'На удаленке:'" [value]="salariesChart.averageRemoteSalary">
- @@ -88,6 +87,14 @@ TODO: в скором времени будет добавлена возможность фильтрации данных по специальностям, грейдам и фреймворкам/языкам программирования + +
+ + > +
= [ - "Junior", - "Middle", - "Senior", - "Lead", - ]; + gradeFilter: DeveloperGrade | null = null; constructor( private readonly service: UserSalariesService, @@ -50,9 +48,11 @@ export class SalariesChartComponent implements OnInit, OnDestroy { this.salariesChart = new StubSalariesChart(); } - load(): void { + load(data: SalaryChartGlobalFiltersData | null = null): void { this.salariesChart = null; - this.service.charts() + this.service.charts({ + grade: data?.grade ?? null, + }) .pipe(untilDestroyed(this)) .subscribe((x) => { if (x.shouldAddOwnSalary) { @@ -72,7 +72,6 @@ export class SalariesChartComponent implements OnInit, OnDestroy { return; } - console.log('Saving url to cookie', this.router.url); this.cookieService.set('url', this.router.url); this.authService.login(); } @@ -86,6 +85,27 @@ export class SalariesChartComponent implements OnInit, OnDestroy { this.load(); } + applyGlobalFilters(data: SalaryChartGlobalFiltersData): void { + + if (this.filterData.equals(data)) { + return; + } + + this.filterData = data; + this.load(data); + } + + resetGlobalFilters(): void { + + const newFilterData = new SalaryChartGlobalFiltersData(); + if (this.filterData.equals(newFilterData)) { + return; + } + + this.filterData = newFilterData; + this.load(); + } + ngOnDestroy(): void { // ignored } diff --git a/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/global-filters-form-group.ts b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/global-filters-form-group.ts new file mode 100644 index 00000000..12dfc2de --- /dev/null +++ b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/global-filters-form-group.ts @@ -0,0 +1,43 @@ +import { FormControl, FormGroup } from "@angular/forms"; +import { DeveloperGrade } from "@models/enums"; +import { DeveloperGradeSelectItem } from "@shared/select-boxes/developer-grade-select-item"; + +export class SalaryChartGlobalFiltersData { + grade: DeveloperGrade | null = null; + + constructor(grade: DeveloperGrade | null = null) { + if (grade === DeveloperGrade.Unknown) { + grade = null; + } + + this.grade = grade; + } + + equals(other: SalaryChartGlobalFiltersData): boolean { + return this.grade === other.grade; + } +} + +export class GlobalFiltersFormGroup extends FormGroup { + + readonly grades: Array = DeveloperGradeSelectItem.gradesSimpleOnly(); + + constructor(filterData: SalaryChartGlobalFiltersData | null) { + super({ + grade: new FormControl(filterData?.grade, []), + }); + } + + data(): SalaryChartGlobalFiltersData | null { + if (!this.valid) { + this.markAllAsTouched(); + return null; + } + + const grade = this.value.grade != null && this.value.grade !== 'null' + ? this.value.grade as DeveloperGrade + : null; + + return new SalaryChartGlobalFiltersData(grade); + } +} diff --git a/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.html b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.html new file mode 100644 index 00000000..630f0ec0 --- /dev/null +++ b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.html @@ -0,0 +1,22 @@ +
+
+
Глобальные фильтры
+
+
+ +
+ +
+
+ + +
+
+
+
+
\ No newline at end of file diff --git a/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.scss b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.spec.ts b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.spec.ts new file mode 100644 index 00000000..44429db9 --- /dev/null +++ b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.spec.ts @@ -0,0 +1,28 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { mostUsedImports, testUtilStubs, mostUsedServices } from '@shared/test-utils'; +import { SalaryChartGlobalFiltersComponent } from './salary-chart-global-filters.component'; + +describe('SalaryChartGlobalFiltersComponent', () => { + let component: SalaryChartGlobalFiltersComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SalaryChartGlobalFiltersComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SalaryChartGlobalFiltersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.ts b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.ts new file mode 100644 index 00000000..95202fec --- /dev/null +++ b/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component.ts @@ -0,0 +1,45 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { GlobalFiltersFormGroup, SalaryChartGlobalFiltersData } from './global-filters-form-group'; + +@Component({ + selector: 'app-salary-chart-global-filters', + templateUrl: './salary-chart-global-filters.component.html', + styleUrl: './salary-chart-global-filters.component.scss' +}) +export class SalaryChartGlobalFiltersComponent implements OnInit { + + @Input() + filterData: SalaryChartGlobalFiltersData | null = null; + + @Output() + readonly filtersApplied = new EventEmitter(); + + @Output() + readonly filtersReset = new EventEmitter(); + + form: GlobalFiltersFormGroup | null = null; + + ngOnInit(): void { + this.form = new GlobalFiltersFormGroup(this.filterData); + } + + apply(): void { + if (!this.form) { + return; + } + + const data = this.form.data(); + if (data) { + this.filtersApplied.emit(data); + } + } + + reset(): void { + if (!this.form) { + return; + } + + this.form.reset(); + this.filtersReset.emit(); + } +} diff --git a/src/app/modules/salaries/components/salaries-per-profession.ts b/src/app/modules/salaries/components/salaries-per-profession.ts index 6324e04a..4e1a171b 100644 --- a/src/app/modules/salaries/components/salaries-per-profession.ts +++ b/src/app/modules/salaries/components/salaries-per-profession.ts @@ -38,9 +38,6 @@ export class SalariesPerProfession { var uniqueProfessionsForLocal = [...new Set(localSalaries.map(x => x.profession))]; var uniqueProfessionsForRemote = [...new Set(remoteSalaries.map(x => x.profession))]; - console.log(uniqueProfessionsForLocal); - console.log(uniqueProfessionsForRemote); - const local = uniqueProfessionsForLocal.map(x => { const filteredSalaries = localSalaries.filter(salary => salary.profession == x); return new SalariesPerProfession(x, filteredSalaries); diff --git a/src/app/modules/salaries/salaries.module.ts b/src/app/modules/salaries/salaries.module.ts index 7cb7af17..5c95c7ff 100644 --- a/src/app/modules/salaries/salaries.module.ts +++ b/src/app/modules/salaries/salaries.module.ts @@ -9,6 +9,7 @@ import { AddSalaryComponent } from './components/add-salary/add-salary.component import { SalariesByGradesChartComponent } from './components/salaries-by-grades-chart/salaries-by-grades-chart.component'; import { SalaryBlockValueComponent } from './components/salaries-chart/salary-block-value/salary-block-value.component'; import { SalaryBlockRemoteValueComponent } from './components/salaries-chart/salary-block-remote-value/salary-block-remote-value.component'; +import { SalaryChartGlobalFiltersComponent } from './components/salaries-chart/salary-chart-global-filters/salary-chart-global-filters.component'; @NgModule({ declarations: [ @@ -17,6 +18,7 @@ import { SalaryBlockRemoteValueComponent } from './components/salaries-chart/sal SalariesByGradesChartComponent, SalaryBlockValueComponent, SalaryBlockRemoteValueComponent, + SalaryChartGlobalFiltersComponent, ], imports: [ CommonModule, diff --git a/src/app/services/user-salaries.service.ts b/src/app/services/user-salaries.service.ts index c97b82a2..46974013 100644 --- a/src/app/services/user-salaries.service.ts +++ b/src/app/services/user-salaries.service.ts @@ -71,6 +71,10 @@ export interface AdminAllSalariesQueryParams extends PageParams { grade: DeveloperGrade | null; } +export interface SalariesChartFilterData { + grade: DeveloperGrade | null; +} + @Injectable({ providedIn: 'root' }) @@ -83,8 +87,9 @@ export class UserSalariesService { this.root + 'all?' + new ConvertObjectToHttpParams(pageParams).get()); } - charts(): Observable { - return this.api.get(this.root + 'chart'); + charts(filters: SalariesChartFilterData): Observable { + return this.api.get( + this.root + 'chart?' + new ConvertObjectToHttpParams(filters).get()); } create(data: CreateUserSalaryRequest): Observable { diff --git a/src/app/shared/select-boxes/developer-grade-select-item.ts b/src/app/shared/select-boxes/developer-grade-select-item.ts index b4c34d6f..9a6e9464 100644 --- a/src/app/shared/select-boxes/developer-grade-select-item.ts +++ b/src/app/shared/select-boxes/developer-grade-select-item.ts @@ -8,12 +8,16 @@ export class DeveloperGradeSelectItem implements SelectItem { readonly label: string; readonly item: DeveloperGrade; - constructor(grade: DeveloperGrade) { + constructor(grade: DeveloperGrade, label: string | null = null) { this.value = grade.toString(); - this.label = new SplittedByWhitespacesString(DeveloperGrade[grade]).value; + this.label = label ?? new SplittedByWhitespacesString(DeveloperGrade[grade]).value; this.item = grade; } + static empty(label: string): DeveloperGradeSelectItem { + return new DeveloperGradeSelectItem(DeveloperGrade.Unknown, label); + } + static allGrades(): DeveloperGradeSelectItem[] { return EnumHelper.getValues(DeveloperGrade).map((grade) => new DeveloperGradeSelectItem(grade)); } diff --git a/src/app/shared/value-objects/convert-object-to-http.ts b/src/app/shared/value-objects/convert-object-to-http.ts index c626a98e..004d0839 100644 --- a/src/app/shared/value-objects/convert-object-to-http.ts +++ b/src/app/shared/value-objects/convert-object-to-http.ts @@ -19,7 +19,7 @@ export class ConvertObjectToHttpParams { continue; } - httpParams = httpParams.append(field, this.params[field]); + httpParams = httpParams.append(field, value); } return httpParams;