Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,51 @@
<div class="container my-5" *ngIf="users; else dataLoading">
<div class="card">
<div class="card-body">
<!-- Filters Section -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build pipeline fails. Please analyze and fix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the build pipeline failures by resolving TypeScript compilation errors. The issues were unrelated to the main feature changes but were preventing the CI from passing. Specifically fixed:

  1. Missing override modifiers in API service stub methods
  2. Uninitialized properties in alert stub service

Build, lint, and TypeScript compilation now pass successfully. See commit 3e849c7.

<div class="mb-4">
<h5>Фильтры</h5>
<form [formGroup]="filterForm" (ngSubmit)="applyFilters()">
<div class="row">
<div class="col-md-4 mb-3">
<label for="email" class="form-label">Email</label>
<input
type="text"
class="form-control"
id="email"
formControlName="email"
placeholder="Поиск по email"
/>
</div>
<div class="col-md-4 mb-3">
<label for="unsubscribeMeFromAll" class="form-label"
>Отписка от всех емейлов</label
>
<select
class="form-select"
id="unsubscribeMeFromAll"
formControlName="unsubscribeMeFromAll"
>
<option [value]="null">Все</option>
<option [value]="true">Да</option>
<option [value]="false">Нет</option>
</select>
</div>
<div class="col-md-4 mb-3 d-flex align-items-end">
<button type="submit" class="btn btn-outline-dark me-2">
Применить
</button>
<button
type="button"
class="btn btn-outline-secondary"
(click)="resetFilters()"
>
Сброс
</button>
</div>
</div>
</form>
</div>

<div
class="table-responsive mb-3"
*ngIf="users.length > 0; else nothingToShow"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Component, OnDestroy, OnInit } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
import { ApplicationUser } from "@models/application-user";
import { UserRoleEnum } from "@models/enums";
import { ApplicationUserExtended } from "@models/extended";
import { defaultPageParams } from "@models/page-params";
import { PaginatedList } from "@models/paginated-list";
import { TitleService } from "@services/title.service";
import { UserAdminService } from "@services/user-admin.service";
import {
UserAdminService,
UserSearchParams,
} from "@services/user-admin.service";
import { untilDestroyed } from "@shared/subscriptions/until-destroyed";
import { UserRolesEditForm } from "./user-roles-edit-form";

Expand All @@ -23,12 +27,19 @@ export class UsersAdminPageComponent implements OnInit, OnDestroy {
source: PaginatedList<ApplicationUser> | 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;
Expand All @@ -40,8 +51,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));
Expand Down Expand Up @@ -77,4 +96,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);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { waitForAsync, ComponentFixture, TestBed } from "@angular/core/testing";

import { NoPermissionComponent } from "./no-permission.component";
import { mostUsedImports } from "@shared/test-utils";
import { mostUsedServices, testUtilStubs } from "@shared/test-utils";
import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";

describe("NoPermissionComponent", () => {
let component: NoPermissionComponent;
Expand All @@ -9,6 +12,9 @@ describe("NoPermissionComponent", () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [NoPermissionComponent],
imports: [...mostUsedImports],
providers: [...testUtilStubs, ...mostUsedServices],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
}));

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -9,6 +12,9 @@ describe("NotAuthorizedErrorComponent", () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [NotAuthorizedErrorComponent],
imports: [...mostUsedImports],
providers: [...testUtilStubs, ...mostUsedServices],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
}));

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -8,6 +11,9 @@ describe("NotFoundErrorComponent", () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [NotFoundErrorComponent],
imports: [...mostUsedImports],
providers: [...testUtilStubs, ...mostUsedServices],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
}));

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -9,6 +11,9 @@ describe("ServerUnavailableComponent", () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ServerUnavailableComponent],
imports: [...mostUsedImports],
providers: [...testUtilStubs, ...mostUsedServices],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
}));

Expand Down
13 changes: 11 additions & 2 deletions src/app/services/user-admin.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<UserRole>;
Expand All @@ -25,10 +30,14 @@ export class UserAdminService {
}

all(
pageParams: PageParams = defaultPageParams,
searchParams: UserSearchParams = {
...defaultPageParams,
email: null,
unsubscribeMeFromAll: null,
},
): Observable<PaginatedList<ApplicationUser>> {
return this.api.get<PaginatedList<ApplicationUser>>(
this.apiUrl + "?" + new ConvertObjectToHttpParams(pageParams).get(),
this.apiUrl + "?" + new ConvertObjectToHttpParams(searchParams).get(),
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Subject } from "rxjs";
import { Alert } from "../models/alert.model";

export class AlertStubService implements IAlertService {
readonly onAlert$: Subject<Alert>;
readonly onAlertsClear$: Subject<void>;
readonly onAlert$: Subject<Alert> = new Subject<Alert>();
readonly onAlertsClear$: Subject<void> = new Subject<void>();

success(message: string, keepAfterRouteChange: boolean): void {
console.log(message);
Expand Down
16 changes: 12 additions & 4 deletions src/app/shared/test-utils/api-service-stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,27 @@ export class ApiServiceStub extends ApiService {
super(new HttpClientStub() as HttpClient);
}

get<T>(url: string, options?: HttpOptions): Observable<T> {
override get<T>(url: string, options?: HttpOptions): Observable<T> {
throw Error("not implemented");
}

post<T>(url: string, body?: any, options?: HttpOptions): Observable<T> {
override post<T>(
url: string,
body?: any,
options?: HttpOptions,
): Observable<T> {
throw Error("not implemented");
}

put<T>(url: string, body: any, options?: HttpOptions): Observable<T> {
override put<T>(
url: string,
body: any,
options?: HttpOptions,
): Observable<T> {
throw Error("not implemented");
}

delete<T>(url: string, options?: HttpOptions): Observable<T> {
override delete<T>(url: string, options?: HttpOptions): Observable<T> {
throw Error("not implemented");
}
}
2 changes: 2 additions & 0 deletions src/app/shared/test-utils/models/test-application-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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;
Expand Down