From a3568bc58065e3b0848b1017d215ad22fd34ec50 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Jun 2025 11:39:31 +0000 Subject: [PATCH 1/4] Initial plan for issue From dc30ac61cd17a285ce326db4c5017fd7ef856a15 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Jun 2025 11:48:52 +0000 Subject: [PATCH 2/4] Add email search and unsubscribe filter to Users admin page Co-authored-by: maximgorbatyuk <13348685+maximgorbatyuk@users.noreply.github.com> --- .../users-admin-page.component.html | 31 +++++++++++++++++ .../users-admin-page.component.ts | 34 +++++++++++++++++-- src/app/services/user-admin.service.ts | 9 +++-- .../models/test-application-user.ts | 2 ++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/app/modules/admin/components/users/users-admin-page/users-admin-page.component.html b/src/app/modules/admin/components/users/users-admin-page/users-admin-page.component.html index 5b1bc080..f04b134f 100644 --- a/src/app/modules/admin/components/users/users-admin-page/users-admin-page.component.html +++ b/src/app/modules/admin/components/users/users-admin-page/users-admin-page.component.html @@ -3,6 +3,37 @@
+ +
+
Фильтры
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
| null = null; userRolesForm: UserRolesEditForm | null = null; + filterForm: FormGroup; readonly options = UserRoleEnum.options(); constructor( private readonly service: UserAdminService, private readonly titleService: TitleService, - ) {} + private readonly fb: FormBuilder, + ) { + this.filterForm = this.fb.group({ + email: [''], + unsubscribeMeFromAll: [null] + }); + } ngOnInit(): void { this.userRolesForm = null; @@ -40,8 +48,16 @@ export class UsersAdminPageComponent implements OnInit, OnDestroy { this.users = null; this.source = null; + const formValue = this.filterForm.value; + const searchParams: UserSearchParams = { + ...defaultPageParams, + page, + email: formValue.email || null, + unsubscribeMeFromAll: formValue.unsubscribeMeFromAll + }; + this.service - .all({ ...defaultPageParams, page }) + .all(searchParams) .pipe(untilDestroyed(this)) .subscribe((users) => { this.users = users.results.map((x) => new ApplicationUserExtended(x)); @@ -77,4 +93,16 @@ export class UsersAdminPageComponent implements OnInit, OnDestroy { this.loadData(); }); } + + applyFilters(): void { + this.loadData(1); + } + + resetFilters(): void { + this.filterForm.reset({ + email: '', + unsubscribeMeFromAll: null + }); + this.loadData(1); + } } diff --git a/src/app/services/user-admin.service.ts b/src/app/services/user-admin.service.ts index add7f889..ca912541 100644 --- a/src/app/services/user-admin.service.ts +++ b/src/app/services/user-admin.service.ts @@ -7,6 +7,11 @@ import { ConvertObjectToHttpParams } from "@shared/value-objects/convert-object- import { Observable } from "rxjs"; import { ApiService } from "./api.service"; +export interface UserSearchParams extends PageParams { + email: string | null; + unsubscribeMeFromAll: boolean | null; +} + export interface UpdateUserRolesRequest { id: number; roles: Array; @@ -25,10 +30,10 @@ export class UserAdminService { } all( - pageParams: PageParams = defaultPageParams, + searchParams: UserSearchParams = { ...defaultPageParams, email: null, unsubscribeMeFromAll: null }, ): Observable> { return this.api.get>( - this.apiUrl + "?" + new ConvertObjectToHttpParams(pageParams).get(), + this.apiUrl + "?" + new ConvertObjectToHttpParams(searchParams).get(), ); } diff --git a/src/app/shared/test-utils/models/test-application-user.ts b/src/app/shared/test-utils/models/test-application-user.ts index 9db94324..24ebf959 100644 --- a/src/app/shared/test-utils/models/test-application-user.ts +++ b/src/app/shared/test-utils/models/test-application-user.ts @@ -10,6 +10,7 @@ export class TestApplicationUser implements ApplicationUser { this.email = "j.smith@gmail.com"; this.roles = [role]; this.emailConfirmed = true; + this.unsubscribeMeFromAll = false; this.identityId = id; this.deletedAt = null; this.createdAt = new Date(); @@ -25,6 +26,7 @@ export class TestApplicationUser implements ApplicationUser { lastName: string | null; roles: UserRole[]; emailConfirmed: boolean; + unsubscribeMeFromAll: boolean; identityId: number | null; deletedAt: Date | null; id: number; From 3e849c790ba8de88b08dfd3ed258c5b96f31a470 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Jun 2025 12:01:14 +0000 Subject: [PATCH 3/4] Fix TypeScript compilation errors to resolve build pipeline failures Co-authored-by: maximgorbatyuk <13348685+maximgorbatyuk@users.noreply.github.com> --- .../components/alert/services/alert.stub.service.ts | 4 ++-- src/app/shared/test-utils/api-service-stub.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/shared/components/alert/services/alert.stub.service.ts b/src/app/shared/components/alert/services/alert.stub.service.ts index 1b83bcbc..c65bcb41 100644 --- a/src/app/shared/components/alert/services/alert.stub.service.ts +++ b/src/app/shared/components/alert/services/alert.stub.service.ts @@ -3,8 +3,8 @@ import { Subject } from "rxjs"; import { Alert } from "../models/alert.model"; export class AlertStubService implements IAlertService { - readonly onAlert$: Subject; - readonly onAlertsClear$: Subject; + readonly onAlert$: Subject = new Subject(); + readonly onAlertsClear$: Subject = new Subject(); success(message: string, keepAfterRouteChange: boolean): void { console.log(message); diff --git a/src/app/shared/test-utils/api-service-stub.ts b/src/app/shared/test-utils/api-service-stub.ts index cd54613f..6a0516df 100644 --- a/src/app/shared/test-utils/api-service-stub.ts +++ b/src/app/shared/test-utils/api-service-stub.ts @@ -8,19 +8,19 @@ export class ApiServiceStub extends ApiService { super(new HttpClientStub() as HttpClient); } - get(url: string, options?: HttpOptions): Observable { + override get(url: string, options?: HttpOptions): Observable { throw Error("not implemented"); } - post(url: string, body?: any, options?: HttpOptions): Observable { + override post(url: string, body?: any, options?: HttpOptions): Observable { throw Error("not implemented"); } - put(url: string, body: any, options?: HttpOptions): Observable { + override put(url: string, body: any, options?: HttpOptions): Observable { throw Error("not implemented"); } - delete(url: string, options?: HttpOptions): Observable { + override delete(url: string, options?: HttpOptions): Observable { throw Error("not implemented"); } } From f3e5e5fa755272f6276d12ee9e037ea041f1d467 Mon Sep 17 00:00:00 2001 From: "maxim.gorbatyuk" Date: Mon, 16 Jun 2025 17:21:59 +0500 Subject: [PATCH 4/4] Test fix + prettier --- .../users-admin-page.component.html | 24 +++++++++++++++---- .../users-admin-page.component.ts | 15 +++++++----- .../no-permission.component.spec.ts | 6 +++++ .../not-authorized-error.component.spec.ts | 6 +++++ .../not-found-error.component.spec.ts | 6 +++++ .../server-unavailable.component.spec.ts | 7 +++++- src/app/services/user-admin.service.ts | 6 ++++- src/app/shared/test-utils/api-service-stub.ts | 12 ++++++++-- 8 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/app/modules/admin/components/users/users-admin-page/users-admin-page.component.html b/src/app/modules/admin/components/users/users-admin-page/users-admin-page.component.html index f04b134f..2f68b46d 100644 --- a/src/app/modules/admin/components/users/users-admin-page/users-admin-page.component.html +++ b/src/app/modules/admin/components/users/users-admin-page/users-admin-page.component.html @@ -19,21 +19,35 @@
Фильтры
/>
- -
- - + +
- +
{ let component: NoPermissionComponent; @@ -9,6 +12,9 @@ describe("NoPermissionComponent", () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [NoPermissionComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices], + schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); })); diff --git a/src/app/modules/home/components/not-authorized-error/not-authorized-error.component.spec.ts b/src/app/modules/home/components/not-authorized-error/not-authorized-error.component.spec.ts index 98412fac..2acfb363 100644 --- a/src/app/modules/home/components/not-authorized-error/not-authorized-error.component.spec.ts +++ b/src/app/modules/home/components/not-authorized-error/not-authorized-error.component.spec.ts @@ -1,6 +1,9 @@ import { waitForAsync, ComponentFixture, TestBed } from "@angular/core/testing"; import { NotAuthorizedErrorComponent } from "./not-authorized-error.component"; +import { mostUsedImports } from "@shared/test-utils"; +import { mostUsedServices, testUtilStubs } from "@shared/test-utils"; +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; describe("NotAuthorizedErrorComponent", () => { let component: NotAuthorizedErrorComponent; @@ -9,6 +12,9 @@ describe("NotAuthorizedErrorComponent", () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [NotAuthorizedErrorComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices], + schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); })); diff --git a/src/app/modules/home/components/not-found-error/not-found-error.component.spec.ts b/src/app/modules/home/components/not-found-error/not-found-error.component.spec.ts index 0d66cafa..0752cd39 100644 --- a/src/app/modules/home/components/not-found-error/not-found-error.component.spec.ts +++ b/src/app/modules/home/components/not-found-error/not-found-error.component.spec.ts @@ -1,5 +1,8 @@ import { waitForAsync, ComponentFixture, TestBed } from "@angular/core/testing"; import { NotFoundErrorComponent } from "./not-found-error.component"; +import { mostUsedImports } from "@shared/test-utils"; +import { mostUsedServices, testUtilStubs } from "@shared/test-utils"; +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; describe("NotFoundErrorComponent", () => { let component: NotFoundErrorComponent; @@ -8,6 +11,9 @@ describe("NotFoundErrorComponent", () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [NotFoundErrorComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices], + schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); })); diff --git a/src/app/modules/home/components/server-unavailable/server-unavailable.component.spec.ts b/src/app/modules/home/components/server-unavailable/server-unavailable.component.spec.ts index bf70e004..30ecf0ef 100644 --- a/src/app/modules/home/components/server-unavailable/server-unavailable.component.spec.ts +++ b/src/app/modules/home/components/server-unavailable/server-unavailable.component.spec.ts @@ -1,6 +1,8 @@ import { waitForAsync, ComponentFixture, TestBed } from "@angular/core/testing"; - import { ServerUnavailableComponent } from "./server-unavailable.component"; +import { mostUsedImports } from "@shared/test-utils"; +import { mostUsedServices, testUtilStubs } from "@shared/test-utils"; +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; describe("ServerUnavailableComponent", () => { let component: ServerUnavailableComponent; @@ -9,6 +11,9 @@ describe("ServerUnavailableComponent", () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ServerUnavailableComponent], + imports: [...mostUsedImports], + providers: [...testUtilStubs, ...mostUsedServices], + schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); })); diff --git a/src/app/services/user-admin.service.ts b/src/app/services/user-admin.service.ts index ca912541..6b9dda5d 100644 --- a/src/app/services/user-admin.service.ts +++ b/src/app/services/user-admin.service.ts @@ -30,7 +30,11 @@ export class UserAdminService { } all( - searchParams: UserSearchParams = { ...defaultPageParams, email: null, unsubscribeMeFromAll: null }, + searchParams: UserSearchParams = { + ...defaultPageParams, + email: null, + unsubscribeMeFromAll: null, + }, ): Observable> { return this.api.get>( this.apiUrl + "?" + new ConvertObjectToHttpParams(searchParams).get(), diff --git a/src/app/shared/test-utils/api-service-stub.ts b/src/app/shared/test-utils/api-service-stub.ts index 6a0516df..ff19bec3 100644 --- a/src/app/shared/test-utils/api-service-stub.ts +++ b/src/app/shared/test-utils/api-service-stub.ts @@ -12,11 +12,19 @@ export class ApiServiceStub extends ApiService { throw Error("not implemented"); } - override post(url: string, body?: any, options?: HttpOptions): Observable { + override post( + url: string, + body?: any, + options?: HttpOptions, + ): Observable { throw Error("not implemented"); } - override put(url: string, body: any, options?: HttpOptions): Observable { + override put( + url: string, + body: any, + options?: HttpOptions, + ): Observable { throw Error("not implemented"); }