diff --git a/package.json b/package.json index 355e950e..b7882f1c 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "start": "ng serve -o", "build": "ng build", "build-prod": "ng build --configuration=production", + "serve-prod": "ng serve --configuration=production", "serve-staging": "ng serve --configuration=staging -o", "watch": "ng build --watch --configuration development", "test": "ng test", diff --git a/src/app/components/navbar/navbar.component.ts b/src/app/components/navbar/navbar.component.ts index 1cd590e6..12f3236b 100644 --- a/src/app/components/navbar/navbar.component.ts +++ b/src/app/components/navbar/navbar.component.ts @@ -142,7 +142,12 @@ export class NavbarComponent implements OnInit, OnDestroy { { title: "Опрос о пользе статистики", url: "/salaries/survey", - show: true, + show: hasCurrentUser, + }, + { + title: "Исторические данные", + url: "/salaries/historical-data", + show: hasCurrentUser, }, ], }, diff --git a/src/app/models/enums/developer-grade.enum.ts b/src/app/models/enums/developer-grade.enum.ts index 391a3e40..2b710840 100644 --- a/src/app/models/enums/developer-grade.enum.ts +++ b/src/app/models/enums/developer-grade.enum.ts @@ -25,7 +25,6 @@ export interface DeveloperGradeLabel { } export class DeveloperGradeEnum { - static readonly grades: Array = [ DeveloperGrade.Trainee, DeveloperGrade.Junior, @@ -41,40 +40,55 @@ export class DeveloperGradeEnum { cssText: "text-dark", }; - static readonly colorsByGrade: Map< - DeveloperGrade, - DeveloperGradeLabel - > = new Map([ - [DeveloperGrade.Trainee, { - label: "Trainee", - cssBackground: "bg-light", - cssText: "text-dark", - } - ], - [DeveloperGrade.Junior, { - label: "Junior", - cssBackground: "bg-success", - cssText: "", - }], - [DeveloperGrade.Middle, { - label: "Middle", - cssBackground: "bg-warning", - cssText: "text-dark", - }], - [DeveloperGrade.Senior, { - label: "Senior", - cssBackground: "bg-info", - cssText: "text-dark", - }], - [DeveloperGrade.Lead, { - label: "Lead", - cssBackground: "bg-primary", - cssText: "", - }], - [DeveloperGrade.Unknown, DeveloperGradeEnum.defaultColor], - ]); + static readonly colorsByGrade: Map = + new Map([ + [ + DeveloperGrade.Trainee, + { + label: "Trainee", + cssBackground: "bg-light", + cssText: "text-dark", + }, + ], + [ + DeveloperGrade.Junior, + { + label: "Junior", + cssBackground: "bg-success", + cssText: "text-light", + }, + ], + [ + DeveloperGrade.Middle, + { + label: "Middle", + cssBackground: "bg-warning", + cssText: "text-dark", + }, + ], + [ + DeveloperGrade.Senior, + { + label: "Senior", + cssBackground: "bg-info", + cssText: "text-dark", + }, + ], + [ + DeveloperGrade.Lead, + { + label: "Lead", + cssBackground: "bg-primary", + cssText: "text-light", + }, + ], + [DeveloperGrade.Unknown, DeveloperGradeEnum.defaultColor], + ]); static getColorData(grade: DeveloperGrade): DeveloperGradeLabel { - return DeveloperGradeEnum.colorsByGrade.get(grade) ?? DeveloperGradeEnum.defaultColor; + return ( + DeveloperGradeEnum.colorsByGrade.get(grade) ?? + DeveloperGradeEnum.defaultColor + ); } -} \ No newline at end of file +} diff --git a/src/app/models/salaries/salary.model.ts b/src/app/models/salaries/salary.model.ts index 61c25d45..74e9612e 100644 --- a/src/app/models/salaries/salary.model.ts +++ b/src/app/models/salaries/salary.model.ts @@ -4,18 +4,17 @@ import { Currency } from "./currency"; import { KazakhstanCity } from "./kazakhstan-city"; import { Gender } from "@models/enums/gender.enum"; -export interface UserSalaryAdminDto extends UserSalary { - id: string; - updatedAt: Date | null; -} - -export interface UserSalary { +export interface UserSalarySimple { value: number; quarter: number; year: number; currency: Currency; company: CompanyType; grade: DeveloperGrade | null; + createdAt: Date; +} + +export interface UserSalary extends UserSalarySimple { city: KazakhstanCity | null; gender: Gender | null; age: number | null; @@ -25,5 +24,9 @@ export interface UserSalary { skillId: number | null; workIndustryId: number | null; professionId: number | null; - createdAt: Date; +} + +export interface UserSalaryAdminDto extends UserSalary { + id: string; + updatedAt: Date | null; } diff --git a/src/app/modules/admin/components/background-jobs/background-jobs.component.html b/src/app/modules/admin/components/background-jobs/background-jobs.component.html index 81724f38..99d2f385 100644 --- a/src/app/modules/admin/components/background-jobs/background-jobs.component.html +++ b/src/app/modules/admin/components/background-jobs/background-jobs.component.html @@ -23,7 +23,7 @@ {{ item.currencyString }} {{ item.value }} kzt - {{ item.pubDate | date: "yyyy-MM-dd" }} + {{ item.pubDate | date : "yyyy-MM-dd" }} diff --git a/src/app/modules/admin/components/background-jobs/currency-item.ts b/src/app/modules/admin/components/background-jobs/currency-item.ts index 39e8e403..ad99cad2 100644 --- a/src/app/modules/admin/components/background-jobs/currency-item.ts +++ b/src/app/modules/admin/components/background-jobs/currency-item.ts @@ -1,16 +1,15 @@ import { CurrencyData, CurrencyType } from "@services/admin-tools.service"; export class CurrencyItem implements CurrencyData { + constructor(private readonly item: CurrencyData) { + this.value = item.value; + this.currency = item.currency; + this.currencyString = CurrencyType[item.currency]; + this.pubDate = item.pubDate; + } - constructor(private readonly item: CurrencyData) { - this.value = item.value; - this.currency = item.currency; - this.currencyString = CurrencyType[item.currency]; - this.pubDate = item.pubDate; - } - - readonly value: number; - readonly currency: CurrencyType; - readonly currencyString: string; - readonly pubDate: Date; -} \ No newline at end of file + readonly value: number; + readonly currency: CurrencyType; + readonly currencyString: string; + readonly pubDate: Date; +} diff --git a/src/app/modules/admin/components/interviews/interview-templates-admin-page/interview-templates-admin-page.component.html b/src/app/modules/admin/components/interviews/interview-templates-admin-page/interview-templates-admin-page.component.html index 0f0cfbba..63e4f917 100644 --- a/src/app/modules/admin/components/interviews/interview-templates-admin-page/interview-templates-admin-page.component.html +++ b/src/app/modules/admin/components/interviews/interview-templates-admin-page/interview-templates-admin-page.component.html @@ -28,7 +28,7 @@ [visibility]="item.isPublic" > - {{ item.updatedAt | date: "yyyy-MM-dd HH:mm" }} + {{ item.updatedAt | date : "yyyy-MM-dd HH:mm" }} - {{ item.value | number: "1.0-0" }} + {{ item.value | number : "1.0-0" }} {{ item.quarter }}.{{ item.year }} {{ item.age }} {{ item.gender }} {{ item.yearOfStartingWork }} {{ item.profession }} - + {{ item.company }} {{ item.city }} {{ item.skill }} {{ item.industry }} - {{ item.createdAt | date: "yyyy-MM-dd HH:mm" }} - {{ item.updatedAt | date: "yyyy-MM-dd HH:mm" }} + {{ item.createdAt | date : "yyyy-MM-dd HH:mm" }} + {{ item.updatedAt | date : "yyyy-MM-dd HH:mm" }} + + + +
+ {{ chart }} +
diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.scss b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.scss new file mode 100644 index 00000000..a43d2bc3 --- /dev/null +++ b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.scss @@ -0,0 +1,10 @@ +#canvas-historical-chart-by-grade { + min-height: 600px; +} + +#canvas-historical-chart-by-grade-container { + position: relative; + width: 100%; + height: 100%; + min-height: 600px; +} diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.spec.ts b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.spec.ts new file mode 100644 index 00000000..57dc319a --- /dev/null +++ b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.spec.ts @@ -0,0 +1,32 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; +import { ComponentFixture, TestBed } from "@angular/core/testing"; +import { + mostUsedImports, + mostUsedServices, + testUtilStubs, +} from "@shared/test-utils"; +import { HistoricalSalariesByGradeChartComponent } from "./historical-salaries-by-grade-chart.component"; + +describe("HistoricalSalariesByGradeChartComponent", () => { + let component: HistoricalSalariesByGradeChartComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HistoricalSalariesByGradeChartComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HistoricalSalariesByGradeChartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it("should create", () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.ts b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.ts new file mode 100644 index 00000000..0edc02d9 --- /dev/null +++ b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component.ts @@ -0,0 +1,55 @@ +import { Component, Input, OnInit } from "@angular/core"; +import { SalariesCountWeekByWeekChart } from "@services/historical-charts.service"; +import { HistoricalSalariesByGradeChartObject } from "./historical-salaries-by-grade-chart-object"; +import { DeveloperGrade, DeveloperGradeEnum } from "@models/enums"; + +interface GradeToggleButton { + label: string; + bgCss: string; + textCss: string; + toggle(): void; +} + +@Component({ + selector: "app-historical-salaries-by-grade-chart", + templateUrl: "./historical-salaries-by-grade-chart.component.html", + styleUrls: ["./historical-salaries-by-grade-chart.component.scss"], +}) +export class HistoricalSalariesByGradeChartComponent implements OnInit { + gradesButtons: Array = []; + + @Input() + data: SalariesCountWeekByWeekChart | null = null; + + chart: HistoricalSalariesByGradeChartObject | null = null; + + ngOnInit(): void { + if (this.data == null || !this.data.hasGradeItems) { + return; + } + + this.gradesButtons = [ + this.createGradeToggleButton(DeveloperGrade.Junior), + this.createGradeToggleButton(DeveloperGrade.Middle), + this.createGradeToggleButton(DeveloperGrade.Senior), + this.createGradeToggleButton(DeveloperGrade.Lead), + ]; + + this.chart = new HistoricalSalariesByGradeChartObject( + "canvas-historical-chart-by-grade", + this.data + ); + } + + private createGradeToggleButton(grade: DeveloperGrade): GradeToggleButton { + const color = DeveloperGradeEnum.getColorData(grade); + return { + label: color.label, + bgCss: color.cssBackground, + textCss: color.cssText, + toggle: () => { + this.chart?.toggle(grade); + }, + }; + } +} diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-charts-page.component.spec.ts b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-charts-page.component.spec.ts new file mode 100644 index 00000000..c3b80f7c --- /dev/null +++ b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-charts-page.component.spec.ts @@ -0,0 +1,32 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; +import { ComponentFixture, TestBed } from "@angular/core/testing"; +import { + mostUsedImports, + mostUsedServices, + testUtilStubs, +} from "@shared/test-utils"; +import { HistoricalSalariesChartComponent } from "./historical-charts-page.component"; + +describe("HistoricalSalariesChartComponent", () => { + let component: HistoricalSalariesChartComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HistoricalSalariesChartComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HistoricalSalariesChartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it("should create", () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-charts-page.component.ts b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-charts-page.component.ts new file mode 100644 index 00000000..25f99d56 --- /dev/null +++ b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-charts-page.component.ts @@ -0,0 +1,26 @@ +import { Component, Input, OnInit } from "@angular/core"; +import { SalariesCountWeekByWeekChart } from "@services/historical-charts.service"; +import { HistoricalSalariesChartObject } from "./historical-salaries-chart-object"; + +@Component({ + selector: "app-historical-salaries-chart", + templateUrl: "./historical-salaries-chart.component.html", + styleUrls: ["./historical-salaries-chart.component.scss"], +}) +export class HistoricalSalariesChartComponent implements OnInit { + @Input() + data: SalariesCountWeekByWeekChart | null = null; + + chart: HistoricalSalariesChartObject | null = null; + + ngOnInit(): void { + if (this.data == null) { + return; + } + + this.chart = new HistoricalSalariesChartObject( + "canvas-historical-chart", + this.data + ); + } +} diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart-object.ts b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart-object.ts new file mode 100644 index 00000000..a205bba4 --- /dev/null +++ b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart-object.ts @@ -0,0 +1,117 @@ +import { SalariesCountWeekByWeekChart } from "@services/historical-charts.service"; +import { Chart, ChartType, PointStyle } from "chart.js/auto"; +import { RandomRgbColor } from "../../random-rgb-color"; + +interface ChartDatasetType { + label: string; + data: Array; + borderWidth: number; + borderColor: string; + backgroundColor: string; + pointStyle: PointStyle; + yAxisID: "y" | "y1"; +} + +export class HistoricalSalariesChartObject extends Chart { + private readonly datasets: Array = []; + + constructor(canvasId: string, chartData: SalariesCountWeekByWeekChart) { + // По датасету на медиану и среднюю + const datasets: Array = [ + new DatasetItem( + "Количество анкет", + chartData.totalCountItems.map((x) => x.totalCount), + 4, + new RandomRgbColor(), + false as PointStyle, + "y1" + ), + new DatasetItem( + "Медиана, КЗ", + chartData.totalCountItems.map((x) => x.localMedian), + 2, + new RandomRgbColor(), + true as PointStyle, + "y" + ), + new DatasetItem( + "Средняя, КЗ", + chartData.totalCountItems.map((x) => x.localAverage), + 2, + new RandomRgbColor(), + true as PointStyle, + "y" + ), + new DatasetItem( + "Медиана, удаленка", + chartData.totalCountItems.map((x) => x.remoteMedian), + 2, + new RandomRgbColor(), + true as PointStyle, + "y" + ), + new DatasetItem( + "Средняя, удаленка", + chartData.totalCountItems.map((x) => x.remoteAverage), + 2, + new RandomRgbColor(), + true as PointStyle, + "y" + ), + ]; + + super(canvasId, { + type: "line" as ChartType, + data: { + labels: chartData.weekEnds.map((x) => x.toISOString().slice(0, 10)), + datasets: datasets, + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + beginAtZero: true, + position: "left", + }, + y1: { + beginAtZero: true, + position: "right", + }, + }, + elements: { + line: { + tension: 0.4, + }, + }, + plugins: { + legend: { + position: "bottom", + title: { + position: "start", + }, + }, + }, + }, + }); + + this.datasets = datasets; + } +} + +class DatasetItem implements ChartDatasetType { + constructor( + readonly label: string, + readonly data: number[], + readonly borderWidth: number, + readonly color: RandomRgbColor, + readonly pointStyle: PointStyle, + readonly yAxisID: "y1" | "y" + ) { + this.borderColor = color.toString(1); + this.backgroundColor = color.toString(0.5); + } + + readonly borderColor: string; + readonly backgroundColor: string; +} diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart.component.html b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart.component.html new file mode 100644 index 00000000..2ee5c346 --- /dev/null +++ b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart.component.html @@ -0,0 +1,7 @@ +
+ Изменение медианной и средней зарплат по времени +
+ +
+ {{ chart }} +
diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart.component.scss b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart.component.scss new file mode 100644 index 00000000..d7f25b1d --- /dev/null +++ b/src/app/modules/salaries/components/historical-charts-page/historical-salaries-chart/historical-salaries-chart.component.scss @@ -0,0 +1,10 @@ +#canvas-historical-chart { + min-height: 600px; +} + +#canvas-historical-chart-container { + position: relative; + width: 100%; + height: 100%; + min-height: 600px; +} diff --git a/src/app/modules/salaries/components/people-by-gender-chart/people-by-gender-chart.component.html b/src/app/modules/salaries/components/people-by-gender-chart/people-by-gender-chart.component.html index edea7c29..47921dc0 100644 --- a/src/app/modules/salaries/components/people-by-gender-chart/people-by-gender-chart.component.html +++ b/src/app/modules/salaries/components/people-by-gender-chart/people-by-gender-chart.component.html @@ -17,7 +17,7 @@ {{ item.label }} {{ item.value }} - {{ item.part | number: "1.3" }}% + {{ item.part | number : "1.3" }}% Всего @@ -44,7 +44,7 @@ {{ item.label }} {{ item.value }} - {{ item.part | number: "1.3" }}% + {{ item.part | number : "1.3" }}% Всего diff --git a/src/app/modules/salaries/components/people-by-grades-chart/people-by-grades-chart.component.ts b/src/app/modules/salaries/components/people-by-grades-chart/people-by-grades-chart.component.ts index af948020..1ba45779 100644 --- a/src/app/modules/salaries/components/people-by-grades-chart/people-by-grades-chart.component.ts +++ b/src/app/modules/salaries/components/people-by-grades-chart/people-by-grades-chart.component.ts @@ -19,7 +19,6 @@ interface ProgressBarData { styleUrl: "./people-by-grades-chart.component.scss", }) export class PeopleByGradesChartComponent implements OnInit { - readonly grades = DeveloperGradeEnum.grades; @Input() diff --git a/src/app/modules/salaries/components/salaries-chart/currency-select-box/currency-select-box.component.html b/src/app/modules/salaries/components/salaries-chart/currency-select-box/currency-select-box.component.html index 250c26df..fccbf314 100644 --- a/src/app/modules/salaries/components/salaries-chart/currency-select-box/currency-select-box.component.html +++ b/src/app/modules/salaries/components/salaries-chart/currency-select-box/currency-select-box.component.html @@ -1,15 +1,20 @@ -
- - - - +
+ + +
diff --git a/src/app/modules/salaries/components/salaries-chart/currency-select-box/currency-select-box.component.ts b/src/app/modules/salaries/components/salaries-chart/currency-select-box/currency-select-box.component.ts index 81330444..3215856f 100644 --- a/src/app/modules/salaries/components/salaries-chart/currency-select-box/currency-select-box.component.ts +++ b/src/app/modules/salaries/components/salaries-chart/currency-select-box/currency-select-box.component.ts @@ -10,7 +10,6 @@ import { GoogleAnalyticsService } from "ngx-google-analytics"; styleUrl: "./currency-select-box.component.scss", }) export class CurrencySelectBoxComponent implements OnInit { - @Input() chart: SalariesChart | null = null; @@ -22,45 +21,39 @@ export class CurrencySelectBoxComponent implements OnInit { currencies: Array | null = null; currencyDate: Date | null = null; - constructor( - private readonly gtag: GoogleAnalyticsService - ) {} + constructor(private readonly gtag: GoogleAnalyticsService) {} ngOnInit(): void { - if (!this.chart) { return; } this.currencies = this.chart.currencies; if (this.currencies.length === 0) { - this.currencies.push( - { - value: 1, - currency: CurrencyType.KZT, - currencyString: "тг", - pubDate: new Date(), - } - ); + this.currencies.push({ + value: 1, + currency: CurrencyType.KZT, + currencyString: "тг", + pubDate: new Date(), + }); } - this.currenciesAsItems = this.currencies - .map((x) => { - return { - value: CurrencyType[x.currency], - label: x.currency === CurrencyType.KZT + this.currenciesAsItems = this.currencies.map((x) => { + return { + value: CurrencyType[x.currency], + label: + x.currency === CurrencyType.KZT ? CurrencyType[x.currency] : `${CurrencyType[x.currency]} (${x.value} тг.)`, - item: x.currency, - }; - }); + item: x.currency, + }; + }); this.selectedCurrency = this.currenciesAsItems[0].item; this.currencyDate = this.currencies[0].pubDate; } onSelectionChange(e: SelectItem): void { - if (e == null) { // clear selection return; diff --git a/src/app/modules/salaries/components/salaries-chart/predefined-filter-info/predefined-info-block.component.ts b/src/app/modules/salaries/components/salaries-chart/predefined-filter-info/predefined-info-block.component.ts index 74020d2b..6b7db7e9 100644 --- a/src/app/modules/salaries/components/salaries-chart/predefined-filter-info/predefined-info-block.component.ts +++ b/src/app/modules/salaries/components/salaries-chart/predefined-filter-info/predefined-info-block.component.ts @@ -1,5 +1,5 @@ import { Component, Input } from "@angular/core"; -import { SalaryChartGlobalFiltersData } from "../salary-chart-global-filters/global-filters-form-group"; +import { SalaryChartGlobalFiltersData } from "../../shared/global-filters-form-group"; import { LabelEntityDto } from "@services/label-entity.model"; import { KazakhstanCityEnum } from "@models/salaries/kazakhstan-city"; import { DeveloperGrade } from "@models/enums"; diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-adding-chart/salaries-adding-chart.component.ts b/src/app/modules/salaries/components/salaries-chart/salaries-adding-chart/salaries-adding-chart.component.ts index 68b6ede7..e494c323 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-adding-chart/salaries-adding-chart.component.ts +++ b/src/app/modules/salaries/components/salaries-chart/salaries-adding-chart/salaries-adding-chart.component.ts @@ -5,7 +5,7 @@ import { } from "@services/user-salaries.service"; import { untilDestroyed } from "@shared/subscriptions/until-destroyed"; import { SalariesAddingChart } from "./salaries-adding-chart"; -import { SalaryChartGlobalFiltersData } from "../salary-chart-global-filters/global-filters-form-group"; +import { SalaryChartGlobalFiltersData } from "../../shared/global-filters-form-group"; @Component({ selector: "app-salaries-adding-chart", @@ -13,16 +13,13 @@ import { SalaryChartGlobalFiltersData } from "../salary-chart-global-filters/glo styleUrl: "./salaries-adding-chart.component.scss", }) export class SalariesAddingChartComponent implements OnInit, OnDestroy { - @Input() filter: SalaryChartGlobalFiltersData | null = null; data: SalariesAddingTrendChart | null = null; chart: SalariesAddingChart | null = null; - constructor( - private readonly service: UserSalariesService - ) {} + constructor(private readonly service: UserSalariesService) {} ngOnInit(): void { this.chart = null; @@ -35,7 +32,10 @@ export class SalariesAddingChartComponent implements OnInit, OnDestroy { .pipe(untilDestroyed(this)) .subscribe((x) => { this.data = x; - this.chart = new SalariesAddingChart("canvas-adding-trend-chart", this.data); + this.chart = new SalariesAddingChart( + "canvas-adding-trend-chart", + this.data + ); }); } diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-by-grade/salaries-by-grade-block.component.html b/src/app/modules/salaries/components/salaries-chart/salaries-by-grade/salaries-by-grade-block.component.html index ee9b88b0..302c9a52 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-by-grade/salaries-by-grade-block.component.html +++ b/src/app/modules/salaries/components/salaries-chart/salaries-by-grade/salaries-by-grade-block.component.html @@ -3,8 +3,8 @@ Грейд - Медианная, {{currentCurrencyLabel}} - Средняя, {{currentCurrencyLabel}} + Медианная, {{ currentCurrencyLabel }} + Средняя, {{ currentCurrencyLabel }} Кол-во анкет diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-by-grade/salaries-by-grade-block.component.ts b/src/app/modules/salaries/components/salaries-chart/salaries-by-grade/salaries-by-grade-block.component.ts index f6cc002d..f001c4d1 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-by-grade/salaries-by-grade-block.component.ts +++ b/src/app/modules/salaries/components/salaries-chart/salaries-by-grade/salaries-by-grade-block.component.ts @@ -31,7 +31,6 @@ export class SalariesByGradeBlockComponent implements OnInit, OnDestroy { currentCurrencyLabel: string | null = null; ngOnInit(): void { - if (this.chart == null) { this.items = []; return; @@ -50,7 +49,9 @@ export class SalariesByGradeBlockComponent implements OnInit, OnDestroy { } private recaulculate(): void { - const source = this.showLocal ? this.chart!.localSalariesByGrade : this.chart!.remoteSalariesByGrade; + const source = this.showLocal + ? this.chart!.localSalariesByGrade + : this.chart!.remoteSalariesByGrade; if (source == null) { this.items = []; return; @@ -66,8 +67,14 @@ export class SalariesByGradeBlockComponent implements OnInit, OnDestroy { hasData: x.hasData, averageSalary: x.averageSalary, medianSalary: x.medianSalary, - medianSalaryAsString: x.medianSalary != null ? formatNumber(x.medianSalary, "en-US", "1.0-2") : "", - averageSalaryAsString: x.averageSalary != null ? formatNumber(x.averageSalary, "en-US", "1.0-2") : "", + medianSalaryAsString: + x.medianSalary != null + ? formatNumber(x.medianSalary, "en-US", "1.0-2") + : "", + averageSalaryAsString: + x.averageSalary != null + ? formatNumber(x.averageSalary, "en-US", "1.0-2") + : "", }; }); } 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 1786f8a4..4b653f60 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 @@ -209,8 +209,7 @@ (filtersReset)="resetGlobalFilters()" (shareClicked)="share($event)" > - > +
@@ -334,7 +333,7 @@
+ >
diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.ts b/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.ts index d4b1a7e1..8c60eda0 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.ts +++ b/src/app/modules/salaries/components/salaries-chart/salaries-chart.component.ts @@ -8,9 +8,9 @@ import { AuthService } from "@shared/services/auth/auth.service"; import { CookieService } from "ngx-cookie-service"; import { StubSalariesChart } from "./stub-salaries-chart"; import { DeveloperGrade } from "@models/enums"; -import { SalaryChartGlobalFiltersData } from "./salary-chart-global-filters/global-filters-form-group"; +import { SalaryChartGlobalFiltersData } from "../shared/global-filters-form-group"; import { GoogleAnalyticsService } from "ngx-google-analytics"; -import { SalariesChartActivatedRoute } from "./salaries-activated-route"; +import { SalariesChartActivatedRoute } from "../shared/salaries-activated-route"; import { ApiBackendAbsoluteUrl, ClipboardCopier, diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-chart.ts b/src/app/modules/salaries/components/salaries-chart/salaries-chart.ts index 589d2a87..c816dd1e 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-chart.ts +++ b/src/app/modules/salaries/components/salaries-chart/salaries-chart.ts @@ -13,7 +13,6 @@ import { CurrencyData, CurrencyType } from "@services/admin-tools.service"; import { Subject } from "rxjs"; export class SalariesChart implements SalariesChartResponse { - private _averageSalary = 0; get averageSalary(): number { return this._averageSalary; @@ -54,17 +53,20 @@ export class SalariesChart implements SalariesChartResponse { return this._salariesByMoneyBarChart; } - private _salariesByMoneyBarChartForRemote: SalariesByMoneyBarChart | null = null; + private _salariesByMoneyBarChartForRemote: SalariesByMoneyBarChart | null = + null; get salariesByMoneyBarChartForRemote(): SalariesByMoneyBarChart | null { return this._salariesByMoneyBarChartForRemote; } - private _salariesPerProfessionForLocal: Array | null = null; + private _salariesPerProfessionForLocal: Array | null = + null; get salariesPerProfessionForLocal(): Array | null { return this._salariesPerProfessionForLocal; } - private _salariesPerProfessionForRemote: Array | null = null; + private _salariesPerProfessionForRemote: Array | null = + null; get salariesPerProfessionForRemote(): Array | null { return this._salariesPerProfessionForRemote; } @@ -83,7 +85,10 @@ export class SalariesChart implements SalariesChartResponse { readonly developersByExperienceYearsChartData: DevelopersByCategoryChartData | null; get hasRemoteSalaries(): boolean { - return this._salariesPerProfessionForRemote != null && this._salariesPerProfessionForRemote.length > 0 + return ( + this._salariesPerProfessionForRemote != null && + this._salariesPerProfessionForRemote.length > 0 + ); } readonly hasAuthentication: boolean; @@ -97,13 +102,13 @@ export class SalariesChart implements SalariesChartResponse { readonly rangeStart: Date; readonly rangeEnd: Date; - public readonly currentCurrencyChanged$: Subject = new Subject(); + public readonly currentCurrencyChanged$: Subject = + new Subject(); constructor( readonly data: SalariesChartResponse, readonly allProfessions: Array ) { - this.hasAuthentication = data.hasAuthentication; this.currencies = data.currencies; this.currentCurrency = this.getDefaultCurrency(); @@ -116,15 +121,19 @@ export class SalariesChart implements SalariesChartResponse { this.countOfRecords = data.totalCountInStats; this.developersByAgeChartData = data.developersByAgeChartData; - this.developersByExperienceYearsChartData = data.developersByExperienceYearsChartData; + this.developersByExperienceYearsChartData = + data.developersByExperienceYearsChartData; this.peopleByGradesChartDataForLocal = data.peopleByGradesChartDataForLocal; - this.peopleByGradesChartDataForRemote = data.peopleByGradesChartDataForRemote; + this.peopleByGradesChartDataForRemote = + data.peopleByGradesChartDataForRemote; this.recalculateData(data, allProfessions, this.currentCurrency); } public setCurrentCurrency(currencyType: CurrencyType): void { - this.currentCurrency = this.currencies.find((x) => x.currency === currencyType) ?? this.getDefaultCurrency(); + this.currentCurrency = + this.currencies.find((x) => x.currency === currencyType) ?? + this.getDefaultCurrency(); this.recalculateData(this.data, this.allProfessions, this.currentCurrency); this.currentCurrencyChanged$.next(this.currentCurrency); } @@ -142,13 +151,14 @@ export class SalariesChart implements SalariesChartResponse { } private getDefaultCurrency(): CurrencyData { - return this.currencies.find((x) => x.currency === CurrencyType.KZT) - ?? { - value: 1, - currency: CurrencyType.KZT, - currencyString: "тг", - pubDate: new Date(), - }; + return ( + this.currencies.find((x) => x.currency === CurrencyType.KZT) ?? { + value: 1, + currency: CurrencyType.KZT, + currencyString: "тг", + pubDate: new Date(), + } + ); } private recalculateData( @@ -156,7 +166,6 @@ export class SalariesChart implements SalariesChartResponse { allProfessions: Array, currentCurrency: CurrencyData ): void { - this._salaries = data.salaries.map((x) => { x.value = x.value / currentCurrency.value; return x; @@ -165,7 +174,8 @@ export class SalariesChart implements SalariesChartResponse { this._currentUserSalary = data.currentUserSalary; if (data.currentUserSalary != null) { this._currentUserSalary = { ...data.currentUserSalary }; - this._currentUserSalary!.value = data.currentUserSalary.value / currentCurrency.value; + this._currentUserSalary!.value = + data.currentUserSalary.value / currentCurrency.value; } this._averageSalary = data.averageSalary / currentCurrency.value; @@ -174,8 +184,14 @@ export class SalariesChart implements SalariesChartResponse { if (data.localSalariesByGrade != null) { this._localSalariesByGrade = data.localSalariesByGrade.map((x) => { const result = { ...x }; - result.averageSalary = x.averageSalary != null ? x.averageSalary / currentCurrency.value : null; - result.medianSalary = x.medianSalary != null ? x.medianSalary / currentCurrency.value : null; + result.averageSalary = + x.averageSalary != null + ? x.averageSalary / currentCurrency.value + : null; + result.medianSalary = + x.medianSalary != null + ? x.medianSalary / currentCurrency.value + : null; return result; }); } else { @@ -185,26 +201,38 @@ export class SalariesChart implements SalariesChartResponse { if (data.remoteSalariesByGrade != null) { this._remoteSalariesByGrade = data.remoteSalariesByGrade.map((x) => { const result = { ...x }; - result.averageSalary = x.averageSalary != null ? x.averageSalary / currentCurrency.value : null; - result.medianSalary = x.medianSalary != null ? x.medianSalary / currentCurrency.value : null; + result.averageSalary = + x.averageSalary != null + ? x.averageSalary / currentCurrency.value + : null; + result.medianSalary = + x.medianSalary != null + ? x.medianSalary / currentCurrency.value + : null; return result; }); } else { this._remoteSalariesByGrade = []; } - this._averageRemoteSalary = data.averageRemoteSalary != null - ? data.averageRemoteSalary / currentCurrency.value - : null; + this._averageRemoteSalary = + data.averageRemoteSalary != null + ? data.averageRemoteSalary / currentCurrency.value + : null; - this._medianRemoteSalary = data.medianRemoteSalary != null - ? data.medianRemoteSalary / currentCurrency.value - : null; + this._medianRemoteSalary = + data.medianRemoteSalary != null + ? data.medianRemoteSalary / currentCurrency.value + : null; this._salariesByMoneyBarChart = data.salariesByMoneyBarChart; - this._salariesByMoneyBarChartForRemote = data.salariesByMoneyBarChartForRemote; + this._salariesByMoneyBarChartForRemote = + data.salariesByMoneyBarChartForRemote; - const salariesPerProfession = SalariesPerProfession.from(this._salaries, allProfessions); + const salariesPerProfession = SalariesPerProfession.from( + this._salaries, + allProfessions + ); this._salariesPerProfessionForLocal = salariesPerProfession.local; this._salariesPerProfessionForRemote = salariesPerProfession.remote; diff --git a/src/app/modules/salaries/components/salaries-chart/salary-block-remote-value/salary-block-remote-value.component.ts b/src/app/modules/salaries/components/salaries-chart/salary-block-remote-value/salary-block-remote-value.component.ts index d992ed33..1f5af376 100644 --- a/src/app/modules/salaries/components/salaries-chart/salary-block-remote-value/salary-block-remote-value.component.ts +++ b/src/app/modules/salaries/components/salaries-chart/salary-block-remote-value/salary-block-remote-value.component.ts @@ -12,15 +12,18 @@ export class SalaryBlockRemoteValueComponent { source: SalariesChart | null = null; get median(): string { - return SalaryBlockRemoteValueComponent.formatNumber(this.source?.medianRemoteSalary); + return SalaryBlockRemoteValueComponent.formatNumber( + this.source?.medianRemoteSalary + ); } get average(): string { - return SalaryBlockRemoteValueComponent.formatNumber(this.source?.averageRemoteSalary); + return SalaryBlockRemoteValueComponent.formatNumber( + this.source?.averageRemoteSalary + ); } private static formatNumber(value: number | null | undefined): string { - if (value == null) { return ""; } diff --git a/src/app/modules/salaries/components/salaries-chart/salary-block-value/salary-block-value.component.html b/src/app/modules/salaries/components/salaries-chart/salary-block-value/salary-block-value.component.html index cb3496b8..edd4cf70 100644 --- a/src/app/modules/salaries/components/salaries-chart/salary-block-value/salary-block-value.component.html +++ b/src/app/modules/salaries/components/salaries-chart/salary-block-value/salary-block-value.component.html @@ -3,7 +3,7 @@
Медианная зарплата в местных компаниях
{{ median }} - {{currentCurrencyLabel}} + {{ currentCurrencyLabel }}
@@ -11,7 +11,7 @@
Средняя зарплата
{{ average }} - {{currentCurrencyLabel}} + {{ currentCurrencyLabel }}
@@ -19,7 +19,7 @@
Медианная на удаленке
{{ medianRemote }} - {{currentCurrencyLabel}} + {{ currentCurrencyLabel }}
@@ -27,7 +27,7 @@
Средняя на удаленке
{{ averageRemote }} - {{currentCurrencyLabel}} + {{ currentCurrencyLabel }}
diff --git a/src/app/modules/salaries/components/salaries-chart/salary-block-value/salary-block-value.component.ts b/src/app/modules/salaries/components/salaries-chart/salary-block-value/salary-block-value.component.ts index b27af83e..2b05ccab 100644 --- a/src/app/modules/salaries/components/salaries-chart/salary-block-value/salary-block-value.component.ts +++ b/src/app/modules/salaries/components/salaries-chart/salary-block-value/salary-block-value.component.ts @@ -37,15 +37,22 @@ export class SalaryBlockValueComponent implements OnInit, OnDestroy { return; } - this.median = SalaryBlockValueComponent.formatNumber(this.source.medianSalary); - this.average = SalaryBlockValueComponent.formatNumber(this.source.averageSalary); - this.medianRemote = SalaryBlockValueComponent.formatNumber(this.source.medianRemoteSalary); - this.averageRemote = SalaryBlockValueComponent.formatNumber(this.source.averageRemoteSalary); + this.median = SalaryBlockValueComponent.formatNumber( + this.source.medianSalary + ); + this.average = SalaryBlockValueComponent.formatNumber( + this.source.averageSalary + ); + this.medianRemote = SalaryBlockValueComponent.formatNumber( + this.source.medianRemoteSalary + ); + this.averageRemote = SalaryBlockValueComponent.formatNumber( + this.source.averageRemoteSalary + ); this.currentCurrencyLabel = this.source.getCurrentCurrencyLabel(); } private static formatNumber(value: number | null | undefined): string { - if (value == null) { return ""; } 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 index aa8ea640..9af43934 100644 --- 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 @@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core"; import { GlobalFiltersFormGroup, SalaryChartGlobalFiltersData, -} from "./global-filters-form-group"; +} from "../../shared/global-filters-form-group"; import { SelectItem } from "@shared/select-boxes/select-item"; import { KazakhstanCity, diff --git a/src/app/modules/salaries/components/salaries-paginated-table/salaries-paginated-table.component.html b/src/app/modules/salaries/components/salaries-paginated-table/salaries-paginated-table.component.html index a354b085..27319019 100644 --- a/src/app/modules/salaries/components/salaries-paginated-table/salaries-paginated-table.component.html +++ b/src/app/modules/salaries/components/salaries-paginated-table/salaries-paginated-table.component.html @@ -20,20 +20,22 @@ - {{ item.value | number: "1.0-0" }} + {{ item.value | number : "1.0-0" }} {{ item.quarter }}.{{ item.year }} {{ item.age }} {{ item.gender }} {{ item.yearOfStartingWork }} {{ item.profession }} - + {{ item.company }} {{ item.city }} {{ item.skill }} {{ item.industry }} - {{ item.createdAt | date: "yyyy-MM-dd HH:mm" }} + {{ item.createdAt | date : "yyyy-MM-dd HH:mm" }} diff --git a/src/app/modules/salaries/components/salaries-paginated-table/salaries-paginated-table.component.ts b/src/app/modules/salaries/components/salaries-paginated-table/salaries-paginated-table.component.ts index 60336ab4..7a0071a1 100644 --- a/src/app/modules/salaries/components/salaries-paginated-table/salaries-paginated-table.component.ts +++ b/src/app/modules/salaries/components/salaries-paginated-table/salaries-paginated-table.component.ts @@ -5,7 +5,7 @@ import { SelectBoxItemsResponse, UserSalariesService, } from "@services/user-salaries.service"; -import { SalaryChartGlobalFiltersData } from "../salaries-chart/salary-chart-global-filters/global-filters-form-group"; +import { SalaryChartGlobalFiltersData } from "../shared/global-filters-form-group"; import { untilDestroyed } from "@shared/subscriptions/until-destroyed"; import { SalaryTableRow } from "./salary-table-row"; import { LabelEntityDto } from "@services/label-entity.model"; diff --git a/src/app/modules/salaries/components/salaries-skills-chart/salaries-skills-chart.component.html b/src/app/modules/salaries/components/salaries-skills-chart/salaries-skills-chart.component.html index 32cfd60b..6fa8e17b 100644 --- a/src/app/modules/salaries/components/salaries-skills-chart/salaries-skills-chart.component.html +++ b/src/app/modules/salaries/components/salaries-skills-chart/salaries-skills-chart.component.html @@ -57,7 +57,7 @@ {{ item.title }} {{ item.value }} - {{ item.part | number: "1.3" }}% + {{ item.part | number : "1.3" }}% Всего анкет с данными diff --git a/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.html b/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.html index 50eff731..2f4f438b 100644 --- a/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.html +++ b/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.html @@ -1,21 +1,14 @@ - - \ No newline at end of file + diff --git a/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.scss b/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.scss index a1b36caa..7259cf35 100644 --- a/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.scss +++ b/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.scss @@ -1,7 +1,7 @@ .radiobutton-group { - cursor: pointer; + cursor: pointer; } .form-check-label { - cursor: pointer; + cursor: pointer; } diff --git a/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.ts b/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.ts index 0af805e0..8a264af1 100644 --- a/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.ts +++ b/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-block.component.ts @@ -10,7 +10,6 @@ import { GoogleAnalyticsService } from "ngx-google-analytics"; styleUrl: "./salaries-survey-block.component.scss", }) export class SalariesSurveyBlockComponent implements OnInit { - showThankYouBlock = false; formGroup: SalariesSurveyForm | null = null; diff --git a/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-form.ts b/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-form.ts index a1196645..fa2d7db7 100644 --- a/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-form.ts +++ b/src/app/modules/salaries/components/salaries-survey-block/salaries-survey-form.ts @@ -1,81 +1,90 @@ import { FormControl, FormGroup, Validators } from "@angular/forms"; -import { ExpectationReplyType, SalariesStatSurveyData, UsefulnessReplyType } from "@services/salaries-survey.service"; +import { + ExpectationReplyType, + SalariesStatSurveyData, + UsefulnessReplyType, +} from "@services/salaries-survey.service"; export interface CheckboxRadioOption { - value: TEnum; - label: string; + value: TEnum; + label: string; } export class SalariesSurveyForm extends FormGroup { + readonly usefullnessReplyOptions: Array< + CheckboxRadioOption + > = [ + { + label: "Да", + value: UsefulnessReplyType.Yes, + }, + { + label: "Нет", + value: UsefulnessReplyType.No, + }, + { + label: "Не знаю", + value: UsefulnessReplyType.NotSure, + }, + ]; - readonly usefullnessReplyOptions: Array> = [ - { - label: "Да", - value: UsefulnessReplyType.Yes, - }, - { - label: "Нет", - value: UsefulnessReplyType.No, - }, - { - label: "Не знаю", - value: UsefulnessReplyType.NotSure, - }, - ]; + readonly expectationReplyOptions: Array< + CheckboxRadioOption + > = [ + { + label: "Зарплаты такие, как и предполагал(а)", + value: ExpectationReplyType.Expected, + }, + { + label: "Я думал(а), что зарплаты меньше", + value: ExpectationReplyType.MoreThanExpected, + }, + { + label: "Я думал(а), что зарплаты выше", + value: ExpectationReplyType.LessThanExpected, + }, + ]; - readonly expectationReplyOptions: Array> = [ - { - label: "Зарплаты такие, как и предполагал(а)", - value: ExpectationReplyType.Expected, - }, - { - label: "Я думал(а), что зарплаты меньше", - value: ExpectationReplyType.MoreThanExpected, - }, - { - label: "Я думал(а), что зарплаты выше", - value: ExpectationReplyType.LessThanExpected, - }, - ]; + constructor() { + super({ + usefulnessReply: new FormControl(null, [Validators.required]), + expectationReply: new FormControl(null, [Validators.required]), + }); + } - constructor() { - super({ - usefulnessReply: new FormControl(null, [Validators.required]), - expectationReply: new FormControl(null, [Validators.required]), - }); - } + onCheckUsefulnessReply(data: any): void { + const value = data.target.value as UsefulnessReplyType; + this.get("usefulnessReply")?.setValue(value); + } - onCheckUsefulnessReply(data: any): void { - const value = data.target.value as UsefulnessReplyType; - this.get("usefulnessReply")?.setValue(value); - } + onCheckExpectationReply(data: any): void { + const value = data.target.value as ExpectationReplyType; + this.get("expectationReply")?.setValue(value); + } - onCheckExpectationReply(data: any): void { - const value = data.target.value as ExpectationReplyType; - this.get("expectationReply")?.setValue(value); + requestOrNull(): SalariesStatSurveyData | null { + if (!this.valid) { + this.markAllAsTouched(); + return null; } - requestOrNull(): SalariesStatSurveyData | null { - - if (!this.valid) { - this.markAllAsTouched(); - return null; - } - - const usefulnessReply = this.get("usefulnessReply")?.value; - const expectationReply = this.get("expectationReply")?.value; + const usefulnessReply = this.get("usefulnessReply")?.value; + const expectationReply = this.get("expectationReply")?.value; - if (usefulnessReply == null || - expectationReply == null) { - return null; - } + if (usefulnessReply == null || expectationReply == null) { + return null; + } - const usefulnessReplyAsEnum = Number(usefulnessReply) as UsefulnessReplyType; - const expectationReplyAsEnum = Number(expectationReply) as ExpectationReplyType; + const usefulnessReplyAsEnum = Number( + usefulnessReply + ) as UsefulnessReplyType; + const expectationReplyAsEnum = Number( + expectationReply + ) as ExpectationReplyType; - return { - usefulnessReply: usefulnessReplyAsEnum, - expectationReply: expectationReplyAsEnum, - }; - } -} \ No newline at end of file + return { + usefulnessReply: usefulnessReplyAsEnum, + expectationReply: expectationReplyAsEnum, + }; + } +} diff --git a/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.html b/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.html index b7f9e16d..897a0f8e 100644 --- a/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.html +++ b/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.html @@ -1,13 +1,10 @@ Опрос о пользе зарплатной статистики
-
-
-
Спасибо за обратную связь!
@@ -15,7 +12,8 @@ Вы уже оставили когда-то свое мнение о предоставленной статистике.
- Ниже представлена общая статистика по результатам опроса. Посмотрите, как много людей думают так же, как вы. + Ниже представлена общая статистика по результатам опроса. + Посмотрите, как много людей думают так же, как вы.
@@ -23,7 +21,7 @@ Кол-во ответов: {{ data.countOfRecords }}
- +
Полезность статистики
@@ -45,15 +43,17 @@
- - Значения: - + Значения: {{ item.label }} + class="ms-2 badge rounded-pill {{ item.cssBackground }} {{ + item.cssText + }}" + >{{ item.label }}
- +
Ожидания респондентов от статистики
@@ -75,33 +75,32 @@
- - Значения: - + Значения: {{ item.label }} + class="ms-2 px-3 badge rounded-pill {{ item.cssBackground }} {{ + item.cssText + }}" + >{{ item.label }}
-
- Нам важно мнение пользователей о предоставленной статистике. - Интересно взглянуть на то, как респонденты оценивают свою зарплату и какие ожидания у них относительно рынка труда в Казахстане. -
-
- Пожалуйста, примите участие в опросе. + Нам важно мнение пользователей о предоставленной статистике. Интересно + взглянуть на то, как респонденты оценивают свою зарплату и какие + ожидания у них относительно рынка труда в Казахстане.
+
Пожалуйста, примите участие в опросе.
+ >
- diff --git a/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.scss b/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.scss index 996b8c75..2c7e5c12 100644 --- a/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.scss +++ b/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.scss @@ -1,8 +1,8 @@ .progress-bar { - min-height: 30px; + min-height: 30px; } .progress { - min-height: 30px; - cursor: pointer; -} \ No newline at end of file + min-height: 30px; + cursor: pointer; +} diff --git a/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.ts b/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.ts index 18eabb6d..0b3cbcbf 100644 --- a/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.ts +++ b/src/app/modules/salaries/components/salaries-survey-page/salaries-survey-page.component.ts @@ -1,6 +1,13 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { Router } from "@angular/router"; -import { ExpectationReplyType, GetUserSalariesSurveyDataResponse, SalariesSurveyReplyDataItem, SalariesSurveyStatData, SurveyService, UsefulnessReplyType } from "@services/salaries-survey.service"; +import { + ExpectationReplyType, + GetUserSalariesSurveyDataResponse, + SalariesSurveyReplyDataItem, + SalariesSurveyStatData, + SurveyService, + UsefulnessReplyType, +} from "@services/salaries-survey.service"; import { TitleService } from "@services/title.service"; import { AuthService } from "@shared/services/auth/auth.service"; import { CookieService } from "ngx-cookie-service"; @@ -29,7 +36,6 @@ interface ProgressBarColorData { styleUrls: ["./salaries-survey-page.component.scss"], }) export class SalariesSurveyPageComponent implements OnInit, OnDestroy { - static readonly defaultColor: ProgressBarColorData = { label: "Нет данных", cssBackground: "bg-light", @@ -43,44 +49,60 @@ export class SalariesSurveyPageComponent implements OnInit, OnDestroy { UsefulnessReplyType, ProgressBarColorData > = new Map([ - [UsefulnessReplyType.Yes, { + [ + UsefulnessReplyType.Yes, + { label: "Да", cssBackground: "bg-success", cssText: "", - } + }, + ], + [ + UsefulnessReplyType.No, + { + label: "Нет", + cssBackground: "bg-warning", + cssText: "text-dark", + }, + ], + [ + UsefulnessReplyType.NotSure, + { + label: "Не уверен", + cssBackground: "bg-light border border-2", + cssText: "text-dark", + }, ], - [UsefulnessReplyType.No, { - label: "Нет", - cssBackground: "bg-warning", - cssText: "text-dark", - }], - [UsefulnessReplyType.NotSure, { - label: "Не уверен", - cssBackground: "bg-light border border-2", - cssText: "text-dark", - }], ]); static readonly colorsByExpectation: Map< ExpectationReplyType, ProgressBarColorData - > = new Map([ - [ExpectationReplyType.Expected, { + > = new Map([ + [ + ExpectationReplyType.Expected, + { label: "Ожидаемо", cssBackground: "bg-info", cssText: "text-dark", - } + }, + ], + [ + ExpectationReplyType.MoreThanExpected, + { + label: "Выше ожидаемого", + cssBackground: "bg-success", + cssText: "", + }, + ], + [ + ExpectationReplyType.LessThanExpected, + { + label: "Ниже ожидаемого", + cssBackground: "bg-warning", + cssText: "text-dark", + }, ], - [ExpectationReplyType.MoreThanExpected, { - label: "Выше ожидаемого", - cssBackground: "bg-success", - cssText: "", - }], - [ExpectationReplyType.LessThanExpected, { - label: "Ниже ожидаемого", - cssBackground: "bg-warning", - cssText: "text-dark", - }], ]); data: SalariesSurveyStatData | null = null; @@ -103,27 +125,41 @@ export class SalariesSurveyPageComponent implements OnInit, OnDestroy { titleService.setTitle("Опрос о пользе зарплатной статистики"); this.usefullnesLegendItems = [ - SalariesSurveyPageComponent.colorsByUsefulness.get(UsefulnessReplyType.Yes) ?? SalariesSurveyPageComponent.defaultColor, - SalariesSurveyPageComponent.colorsByUsefulness.get(UsefulnessReplyType.No) ?? SalariesSurveyPageComponent.defaultColor, - SalariesSurveyPageComponent.colorsByUsefulness.get(UsefulnessReplyType.NotSure) ?? SalariesSurveyPageComponent.defaultColor, + SalariesSurveyPageComponent.colorsByUsefulness.get( + UsefulnessReplyType.Yes + ) ?? SalariesSurveyPageComponent.defaultColor, + SalariesSurveyPageComponent.colorsByUsefulness.get( + UsefulnessReplyType.No + ) ?? SalariesSurveyPageComponent.defaultColor, + SalariesSurveyPageComponent.colorsByUsefulness.get( + UsefulnessReplyType.NotSure + ) ?? SalariesSurveyPageComponent.defaultColor, ]; this.expectationLegendItems = [ - SalariesSurveyPageComponent.colorsByExpectation.get(ExpectationReplyType.Expected) ?? SalariesSurveyPageComponent.defaultColor, - SalariesSurveyPageComponent.colorsByExpectation.get(ExpectationReplyType.MoreThanExpected) ?? SalariesSurveyPageComponent.defaultColor, - SalariesSurveyPageComponent.colorsByExpectation.get(ExpectationReplyType.LessThanExpected) ?? SalariesSurveyPageComponent.defaultColor, + SalariesSurveyPageComponent.colorsByExpectation.get( + ExpectationReplyType.Expected + ) ?? SalariesSurveyPageComponent.defaultColor, + SalariesSurveyPageComponent.colorsByExpectation.get( + ExpectationReplyType.MoreThanExpected + ) ?? SalariesSurveyPageComponent.defaultColor, + SalariesSurveyPageComponent.colorsByExpectation.get( + ExpectationReplyType.LessThanExpected + ) ?? SalariesSurveyPageComponent.defaultColor, ]; } - + ngOnInit(): void { - if (this.authService.isAuthenticated()) { - this.service.getUserSalariesSurveyDataResponse() + if (this.authService.isAuthenticated()) { + this.service + .getUserSalariesSurveyDataResponse() .pipe(untilDestroyed(this)) .subscribe((data) => { this.userData = data; if (data.hasRecentSurveyReply) { - this.service.getSalariesStatSurveyData() + this.service + .getSalariesStatSurveyData() .pipe(untilDestroyed(this)) .subscribe((x) => { this.data = x; @@ -134,7 +170,7 @@ export class SalariesSurveyPageComponent implements OnInit, OnDestroy { } }); - return; + return; } this.cookieService.set("url", this.router.url); @@ -162,7 +198,8 @@ export class SalariesSurveyPageComponent implements OnInit, OnDestroy { this.data.countOfRecords, this.showPercents, (replyType) => { - const colorData = SalariesSurveyPageComponent.colorsByUsefulness.get(replyType); + const colorData = + SalariesSurveyPageComponent.colorsByUsefulness.get(replyType); return colorData ?? SalariesSurveyPageComponent.defaultColor; } ); @@ -172,7 +209,8 @@ export class SalariesSurveyPageComponent implements OnInit, OnDestroy { this.data.countOfRecords, this.showPercents, (replyType) => { - const colorData = SalariesSurveyPageComponent.colorsByExpectation.get(replyType); + const colorData = + SalariesSurveyPageComponent.colorsByExpectation.get(replyType); return colorData ?? SalariesSurveyPageComponent.defaultColor; } ); @@ -184,29 +222,26 @@ export class SalariesSurveyPageComponent implements OnInit, OnDestroy { showPercents: boolean, giveColorData: (replyType: TEnum) => ProgressBarColorData ): Array { - var result: Array = []; - data - .forEach((item, index) => { - - const colorData = giveColorData(item.replyType); - const value = showPercents - ? formatNumber(item.data.partitionInPercent, "en-US", "1.0-2") + "%" - : formatNumber(item.data.countOfReplies, "en-US", "1.0-0"); - - const maxValue = showPercents - ? "100" - : formatNumber(totalCount, "en-US", "1.0-0"); - - result.push({ - color: colorData.cssBackground, - textColor: colorData.cssText, - value: value, - maxValue: maxValue, - width: item.data.partitionInPercent, - label: colorData.label, - }); + data.forEach((item, index) => { + const colorData = giveColorData(item.replyType); + const value = showPercents + ? formatNumber(item.data.partitionInPercent, "en-US", "1.0-2") + "%" + : formatNumber(item.data.countOfReplies, "en-US", "1.0-0"); + + const maxValue = showPercents + ? "100" + : formatNumber(totalCount, "en-US", "1.0-0"); + + result.push({ + color: colorData.cssBackground, + textColor: colorData.cssText, + value: value, + maxValue: maxValue, + width: item.data.partitionInPercent, + label: colorData.label, }); + }); return result; } 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/shared/global-filters-form-group.ts similarity index 96% rename from src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/global-filters-form-group.ts rename to src/app/modules/salaries/components/shared/global-filters-form-group.ts index d3f8f0e8..e19b59fd 100644 --- a/src/app/modules/salaries/components/salaries-chart/salary-chart-global-filters/global-filters-form-group.ts +++ b/src/app/modules/salaries/components/shared/global-filters-form-group.ts @@ -23,7 +23,6 @@ export class SalaryChartGlobalFiltersData { } equals(other: SalaryChartGlobalFiltersData): boolean { - // TODO mgorbatyuk: do more smart check that two arrays are not same return ( this.grade === other.grade && this.cities.length === other.cities.length && diff --git a/src/app/modules/salaries/components/salaries-chart/salaries-activated-route.ts b/src/app/modules/salaries/components/shared/salaries-activated-route.ts similarity index 96% rename from src/app/modules/salaries/components/salaries-chart/salaries-activated-route.ts rename to src/app/modules/salaries/components/shared/salaries-activated-route.ts index 8b1473fd..a5f2b6e0 100644 --- a/src/app/modules/salaries/components/salaries-chart/salaries-activated-route.ts +++ b/src/app/modules/salaries/components/shared/salaries-activated-route.ts @@ -1,7 +1,7 @@ import { DeveloperGrade } from "@models/enums"; import { ActivatedRouteExtended } from "@shared/routes/activated-route-extended"; import { Observable, map } from "rxjs"; -import { SalaryChartGlobalFiltersData } from "./salary-chart-global-filters/global-filters-form-group"; +import { SalaryChartGlobalFiltersData } from "./global-filters-form-group"; import { ActivatedRoute } from "@angular/router"; import { KazakhstanCity } from "@models/salaries/kazakhstan-city"; diff --git a/src/app/modules/salaries/components/work-industries-chart/work-industries-chart.component.html b/src/app/modules/salaries/components/work-industries-chart/work-industries-chart.component.html index b1223176..22eb35a7 100644 --- a/src/app/modules/salaries/components/work-industries-chart/work-industries-chart.component.html +++ b/src/app/modules/salaries/components/work-industries-chart/work-industries-chart.component.html @@ -56,7 +56,7 @@ {{ item.title }} {{ item.value }} - {{ item.part | number: "1.3" }}% + {{ item.part | number : "1.3" }}% Всего анкет с данными diff --git a/src/app/modules/salaries/salaries-routing.module.ts b/src/app/modules/salaries/salaries-routing.module.ts index a0df2abb..dc7ee2b4 100644 --- a/src/app/modules/salaries/salaries-routing.module.ts +++ b/src/app/modules/salaries/salaries-routing.module.ts @@ -2,6 +2,7 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; import { SalariesChartComponent } from "./components/salaries-chart/salaries-chart.component"; import { SalariesSurveyPageComponent } from "./components/salaries-survey-page/salaries-survey-page.component"; +import { HistoricalChartsPageComponent } from "./components/historical-charts-page/historical-charts-page.component"; const routes: Routes = [ { @@ -12,6 +13,10 @@ const routes: Routes = [ path: "survey", component: SalariesSurveyPageComponent, }, + { + path: "historical-data", + component: HistoricalChartsPageComponent, + }, ]; @NgModule({ diff --git a/src/app/modules/salaries/salaries.module.ts b/src/app/modules/salaries/salaries.module.ts index 7bc54f2e..70c5f964 100644 --- a/src/app/modules/salaries/salaries.module.ts +++ b/src/app/modules/salaries/salaries.module.ts @@ -27,6 +27,9 @@ import { SalariesSurveyBlockComponent } from "./components/salaries-survey-block import { SalariesSurveyPageComponent } from "./components/salaries-survey-page/salaries-survey-page.component"; import { SalariesAddingChartComponent } from "./components/salaries-chart/salaries-adding-chart/salaries-adding-chart.component"; import { CurrencySelectBoxComponent } from "./components/salaries-chart/currency-select-box/currency-select-box.component"; +import { HistoricalChartsPageComponent } from "./components/historical-charts-page/historical-charts-page.component"; +import { HistoricalSalariesChartComponent } from "./components/historical-charts-page/historical-salaries-chart/historical-charts-page.component"; +import { HistoricalSalariesByGradeChartComponent } from "./components/historical-charts-page/historical-salaries-by-grade-chart/historical-salaries-by-grade-chart.component"; @NgModule({ declarations: [ @@ -54,6 +57,9 @@ import { CurrencySelectBoxComponent } from "./components/salaries-chart/currency SalariesSurveyPageComponent, SalariesAddingChartComponent, CurrencySelectBoxComponent, + HistoricalChartsPageComponent, + HistoricalSalariesChartComponent, + HistoricalSalariesByGradeChartComponent, ], imports: [ CommonModule, diff --git a/src/app/services/historical-charts.service.ts b/src/app/services/historical-charts.service.ts new file mode 100644 index 00000000..7ae852b9 --- /dev/null +++ b/src/app/services/historical-charts.service.ts @@ -0,0 +1,61 @@ +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { ApiService } from "./api.service"; +import { ConvertObjectToHttpParams } from "@shared/value-objects/convert-object-to-http"; +import { DeveloperGrade } from "@models/enums"; +import { KazakhstanCity } from "@models/salaries/kazakhstan-city"; + +export interface SalariesCountWeekByWeekChartItem { + totalCount: number; + localMedian: number; + localAverage: number; + remoteMedian: number; + remoteAverage: number; +} + +export interface SalariesCountWeekByWeekChartGradeItem + extends SalariesCountWeekByWeekChartItem { + grade: DeveloperGrade; +} + +export interface SalariesCountWeekByWeekChart { + weekEnds: Array; + totalCountItems: Array; + gradeItems: Array; + hasGradeItems: boolean; +} + +export interface GetSalariesHistoricalChartResponse { + from: Date; + to: Date; + chartFrom: Date; + chartTo: Date; + + hasAuthentication: boolean; + shouldAddOwnSalary: boolean; + + salariesCountWeekByWeekChart: SalariesCountWeekByWeekChart | null; +} + +export interface SalariesChartFilterData { + grade: DeveloperGrade | null; + profsInclude: Array | null; + cities: Array | null; +} + +@Injectable() +export class HistoricalChartsService { + private readonly apiUrl: string; + + constructor(private readonly api: ApiService) { + this.apiUrl = `/api/historical-charts/`; + } + + salariesChart( + params: SalariesChartFilterData + ): Observable { + return this.api.get( + this.apiUrl + "salaries?" + new ConvertObjectToHttpParams(params).get() + ); + } +} diff --git a/src/app/services/index.ts b/src/app/services/index.ts index 52721b51..20f247c9 100644 --- a/src/app/services/index.ts +++ b/src/app/services/index.ts @@ -17,6 +17,7 @@ import { TelegramBotService } from "./telegram-bot.service"; import { SurveyService } from "./salaries-survey.service"; import { MetaTagService } from "./meta-tags.service"; import { AdminToolsService } from "./admin-tools.service"; +import { HistoricalChartsService } from "./historical-charts.service"; export * from "./authorization.service"; export * from "./api.service"; @@ -48,4 +49,5 @@ export const applicationServices = [ SurveyService, MetaTagService, AdminToolsService, + HistoricalChartsService, ]; diff --git a/src/app/services/meta-tags.service.ts b/src/app/services/meta-tags.service.ts index ce2dc3d9..60d85e01 100644 --- a/src/app/services/meta-tags.service.ts +++ b/src/app/services/meta-tags.service.ts @@ -4,49 +4,47 @@ import { environment } from "@environments/environment"; import { TitleService } from "@services/title.service"; @Injectable({ - providedIn: 'root' + providedIn: "root", }) export class MetaTagService { constructor( private readonly title: TitleService, - private readonly meta: Meta) {} - - updateChartMetaTags( - title: string, - description: string, - url: string): void { + private readonly meta: Meta + ) {} + updateChartMetaTags(title: string, description: string, url: string): void { this.title.setTitle(title); - url = url.startsWith('/') ? url : `/${url}`; + url = url.startsWith("/") ? url : `/${url}`; this.removeTags(); this.meta.addTags([ - { property: 'og:title', content: title }, - { name: 'twitter:title', content: title }, + { property: "og:title", content: title }, + { name: "twitter:title", content: title }, - { name: 'description', content: description }, - { property: 'og:description', content: description }, - { name: 'twitter:description', content: description }, + { name: "description", content: description }, + { property: "og:description", content: description }, + { name: "twitter:description", content: description }, - { property: 'og:url', content: environment.baseUrl + url }, + { property: "og:url", content: environment.baseUrl + url }, ]); } returnDefaultMetaTags(): void { this.removeTags(); - const title = 'Techinterview.space'; - const description = 'Зарплаты в IT в Казахстане. Цифры, графики, фильтр. Всё как все мы любим'; + const title = "Techinterview.space"; + const description = + "Зарплаты в IT в Казахстане. Цифры, графики, фильтр. Всё как все мы любим"; this.meta.addTags([ - { property: 'og:title', content: title }, - { name: 'twitter:title', content: title }, + { property: "og:title", content: title }, + { name: "twitter:title", content: title }, - { name: 'description', content: description }, - { property: 'og:description', content: description }, - { name: 'twitter:description', content: description }, + { name: "description", content: description }, + { property: "og:description", content: description }, + { name: "twitter:description", content: description }, - { property: 'og:url', content: environment.baseUrl }, + { property: "og:url", content: environment.baseUrl }, ]); } diff --git a/src/app/services/salaries-survey.service.ts b/src/app/services/salaries-survey.service.ts index 2acdadf5..a5c11e64 100644 --- a/src/app/services/salaries-survey.service.ts +++ b/src/app/services/salaries-survey.service.ts @@ -4,27 +4,27 @@ import { Observable } from "rxjs"; import { ApiService } from "./api.service"; export enum UsefulnessReplyType { - Undefined = 0, - Yes = 1, - No = 2, - NotSure = 3, + Undefined = 0, + Yes = 1, + No = 2, + NotSure = 3, } export enum ExpectationReplyType { - Undefined = 0, - Expected = 1, - MoreThanExpected = 2, - LessThanExpected = 3, + Undefined = 0, + Expected = 1, + MoreThanExpected = 2, + LessThanExpected = 3, } export interface SalariesStatSurveyData { - usefulnessReply: UsefulnessReplyType; - expectationReply: ExpectationReplyType; + usefulnessReply: UsefulnessReplyType; + expectationReply: ExpectationReplyType; } export interface SalariesStatSurveyReply extends SalariesStatSurveyData { - id: string; - createdAt: Date; + id: string; + createdAt: Date; } export interface SalariesSurveyStatDataItem { @@ -57,14 +57,21 @@ export class SurveyService { } getUserSalariesSurveyDataResponse(): Observable { - return this.api.get(this.apiUrl + 'salaries-user-stat-data'); + return this.api.get( + this.apiUrl + "salaries-user-stat-data" + ); } - salariesSatGapeReply(data: SalariesStatSurveyData): Observable { - return this.api.post(this.apiUrl + 'salaries-stat-page-reply', data); + salariesSatGapeReply( + data: SalariesStatSurveyData + ): Observable { + return this.api.post( + this.apiUrl + "salaries-stat-page-reply", + data + ); } getSalariesStatSurveyData(): Observable { - return this.api.get(this.apiUrl + 'salaries-stats'); + return this.api.get(this.apiUrl + "salaries-stats"); } } diff --git a/src/app/services/user-salaries.service.ts b/src/app/services/user-salaries.service.ts index 9ad4407d..6c3f5ed8 100644 --- a/src/app/services/user-salaries.service.ts +++ b/src/app/services/user-salaries.service.ts @@ -188,8 +188,9 @@ export class UserSalariesService { params: SalariesAddingTrendChartParams ): Observable { return this.api.get( - this.root + "salaries-adding-trend-chart?" + - new ConvertObjectToHttpParams(params).get() + this.root + + "salaries-adding-trend-chart?" + + new ConvertObjectToHttpParams(params).get() ); } diff --git a/src/app/shared/components/developer-grade-label/developer-grade-label.component.scss b/src/app/shared/components/developer-grade-label/developer-grade-label.component.scss index 5e020ca2..4663a802 100644 --- a/src/app/shared/components/developer-grade-label/developer-grade-label.component.scss +++ b/src/app/shared/components/developer-grade-label/developer-grade-label.component.scss @@ -1,7 +1,7 @@ .badge { - cursor: pointer; + cursor: pointer; - &:hover { - filter: brightness(85%); - } -} \ No newline at end of file + &:hover { + filter: brightness(85%); + } +} diff --git a/src/app/shared/test-utils/mock-google-analytics.service.ts b/src/app/shared/test-utils/mock-google-analytics.service.ts index 2a25e04d..af7252ad 100644 --- a/src/app/shared/test-utils/mock-google-analytics.service.ts +++ b/src/app/shared/test-utils/mock-google-analytics.service.ts @@ -3,7 +3,7 @@ import { GoogleAnalyticsService } from "ngx-google-analytics"; @Injectable() export class MockGoogleAnalyticsService extends GoogleAnalyticsService { - override gtag(...args: any[]): void { - return; - } + override gtag(...args: any[]): void { + return; + } } diff --git a/src/index.html b/src/index.html index f5cd23a9..d103b96e 100644 --- a/src/index.html +++ b/src/index.html @@ -10,36 +10,44 @@ + content="Зарплаты в IT в Казахстане. Цифры, графики, фильтр. Всё как все мы любим" + /> + content="Зарплаты в IT в Казахстане. Цифры, графики, фильтр. Всё как все мы любим" + /> + content="salaries, statistic, technical interview, interview, coding" + /> + content="Зарплаты в IT в Казахстане. Цифры, графики, фильтр. Всё как все мы любим" + /> + content="https://techinterview.fra1.cdn.digitaloceanspaces.com/images/main_charts_500.png" + /> + content="https://techinterview.fra1.cdn.digitaloceanspaces.com/images/main_charts_500.png" + /> + content="https://techinterview.fra1.cdn.digitaloceanspaces.com/images/main_charts_500.png" + /> + content="Зарплаты в IT в Казахстане. Цифры, графики, фильтр. Всё как все мы любим" + /> @@ -86,7 +94,8 @@ href="https://techhunter.kz" target="_blank" title="Портал вакансий в IT в Казахстане" - rel="noopener noreferrer"> + rel="noopener noreferrer" + > Вакансии на techhunter.kz diff --git a/src/test.ts b/src/test.ts index 93f0f52c..2bc904d3 100644 --- a/src/test.ts +++ b/src/test.ts @@ -25,7 +25,7 @@ getTestBed().initTestEnvironment( ); beforeAll(() => { - window.onbeforeunload = () => 'Oh no!'; + window.onbeforeunload = () => "Oh no!"; }); // Then we find all the tests. diff --git a/tsconfig.json b/tsconfig.json index a58ff37b..df635309 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,3 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "compileOnSave": false, "compilerOptions": {