Skip to content
Snippets Groups Projects
Commit 0eacadc3 authored by OZGCloud's avatar OZGCloud
Browse files

OZG-6731 multiple stateResources

parent 500624da
No related branches found
No related tags found
No related merge requests found
Showing
with 143 additions and 164 deletions
...@@ -13,10 +13,12 @@ ...@@ -13,10 +13,12 @@
label="Neue Organisationseinheit anlegen" label="Neue Organisationseinheit anlegen"
> >
</admin-secondary-button> </admin-secondary-button>
<ng-container *ngIf="deleteStateResource$ | async as deleteStateResource">
<admin-spinner <admin-spinner
data-test-id="organisationseinheit-spinner" data-test-id="organisationseinheit-spinner"
*ngIf="deleteInProgress$ | async" *ngIf="deleteStateResource.loading"
></admin-spinner> ></admin-spinner>
</ng-container>
<admin-organisationseinheit-list <admin-organisationseinheit-list
[organisationseinheitItems]="organisationseinheitItems" [organisationseinheitItems]="organisationseinheitItems"
......
import { StateResource } from '@alfa-client/tech-shared'; import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { Organisationseinheit } from '../../user/user.model'; import { Organisationseinheit } from '../../user/user.model';
...@@ -11,7 +11,8 @@ import { OrganisationseinheitFormComponent } from './organisationseinheit-form/o ...@@ -11,7 +11,8 @@ import { OrganisationseinheitFormComponent } from './organisationseinheit-form/o
}) })
export class OrganisationseinheitContainerComponent implements OnInit { export class OrganisationseinheitContainerComponent implements OnInit {
organisationseinheitItems$: Observable<StateResource<Organisationseinheit[]>>; organisationseinheitItems$: Observable<StateResource<Organisationseinheit[]>>;
deleteInProgress$: Observable<boolean> = of(false);
deleteStateResource$: Observable<StateResource<string>> = of(createEmptyStateResource<string>());
@ViewChild(OrganisationseinheitFormComponent) @ViewChild(OrganisationseinheitFormComponent)
private form!: OrganisationseinheitFormComponent; private form!: OrganisationseinheitFormComponent;
...@@ -31,6 +32,6 @@ export class OrganisationseinheitContainerComponent implements OnInit { ...@@ -31,6 +32,6 @@ export class OrganisationseinheitContainerComponent implements OnInit {
} }
public delete(organisationseinheit: Organisationseinheit): void { public delete(organisationseinheit: Organisationseinheit): void {
this.deleteInProgress$ = this.organisationseinheitService.delete(organisationseinheit.id); this.deleteStateResource$ = this.organisationseinheitService.delete(organisationseinheit.id);
} }
} }
<ng-container *ngIf="submitInProgress$ | async"></ng-container> <ng-container *ngIf="submitStateResource$ | async as submitStateResource">
<dialog #OrganisationseinheitDialog data-test-id="organisationseinheit-dialog" class="bg-gray-50"> <dialog #OrganisationseinheitDialog data-test-id="organisationseinheit-dialog" class="bg-gray-50">
<button <button
(click)="OrganisationseinheitDialog.close()" (click)="OrganisationseinheitDialog.close()"
...@@ -26,9 +26,10 @@ ...@@ -26,9 +26,10 @@
data-test-id="organisationseinheit-save-button" data-test-id="organisationseinheit-save-button"
class="justify-self-end" class="justify-self-end"
(clickEmitter)="submit()" (clickEmitter)="submit()"
[stateResource]="organisationseinheitItems" [stateResource]="submitStateResource"
text="Speichern" text="Speichern"
> >
</ods-button-with-spinner> </ods-button-with-spinner>
</form> </form>
</dialog> </dialog>
</ng-container>
...@@ -8,12 +8,7 @@ import { ...@@ -8,12 +8,7 @@ import {
} from '@alfa-client/test-utils'; } from '@alfa-client/test-utils';
import { DebugElement } from '@angular/core'; import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { import { AbstractControl, FormsModule, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
AbstractControl,
FormsModule,
ReactiveFormsModule,
UntypedFormGroup,
} from '@angular/forms';
import { ButtonWithSpinnerComponent } from '@ods/component'; import { ButtonWithSpinnerComponent } from '@ods/component';
import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
import { MockComponent, ngMocks } from 'ng-mocks'; import { MockComponent, ngMocks } from 'ng-mocks';
...@@ -30,9 +25,7 @@ describe('OrganisationseinheitFormComponent', () => { ...@@ -30,9 +25,7 @@ describe('OrganisationseinheitFormComponent', () => {
let fixture: ComponentFixture<OrganisationseinheitFormComponent>; let fixture: ComponentFixture<OrganisationseinheitFormComponent>;
let form: UntypedFormGroup; let form: UntypedFormGroup;
const organisationseinheitService: Mock<OrganisationseinheitService> = mock( const organisationseinheitService: Mock<OrganisationseinheitService> = mock(OrganisationseinheitService);
OrganisationseinheitService,
);
const saveButtonSelector: string = getDataTestIdOf('organisationseinheit-save-button'); const saveButtonSelector: string = getDataTestIdOf('organisationseinheit-save-button');
const closeButtonSelector: string = getDataTestIdOf('organisationseinheit-close-button'); const closeButtonSelector: string = getDataTestIdOf('organisationseinheit-close-button');
...@@ -64,34 +57,20 @@ describe('OrganisationseinheitFormComponent', () => { ...@@ -64,34 +57,20 @@ describe('OrganisationseinheitFormComponent', () => {
describe('form element', () => { describe('form element', () => {
const fields: string[][] = [ const fields: string[][] = [
[ [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, 'Name', 'organisationseinheit-name'],
OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD, 'OrganisationseinheitID', 'organisationseinheit-id'],
'Name',
'organisationseinheit-name',
],
[
OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD,
'OrganisationseinheitID',
'organisationseinheit-id',
],
]; ];
it.each(fields)( it.each(fields)('should have label for field "%s" with name "%s"', (fieldName: string, text: string, inputId: string) => {
'should have label for field "%s" with name "%s"',
(fieldName: string, text: string, inputId: string) => {
const textFieldElement = getElementFromFixture(fixture, getDataTestIdOf(inputId)); const textFieldElement = getElementFromFixture(fixture, getDataTestIdOf(inputId));
expect(textFieldElement.getAttribute('label')).toBe(text); expect(textFieldElement.getAttribute('label')).toBe(text);
}, });
);
it.each(fields)('should bind form for text-field "%s"', (fieldName, text, dataTestId) => { it.each(fields)('should bind form for text-field "%s"', (fieldName, text, dataTestId) => {
const fieldValue: string = `some text-field ${text}`; const fieldValue: string = `some text-field ${text}`;
const formControl: AbstractControl = form.get(fieldName); const formControl: AbstractControl = form.get(fieldName);
const textFieldComponent: DebugElement = getDebugElementFromFixtureByCss( const textFieldComponent: DebugElement = getDebugElementFromFixtureByCss(fixture, getDataTestIdOf(dataTestId));
fixture,
getDataTestIdOf(dataTestId),
);
ngMocks.change(textFieldComponent, fieldValue); ngMocks.change(textFieldComponent, fieldValue);
expect(formControl.value).toBe(fieldValue); expect(formControl.value).toBe(fieldValue);
}); });
...@@ -101,10 +80,7 @@ describe('OrganisationseinheitFormComponent', () => { ...@@ -101,10 +80,7 @@ describe('OrganisationseinheitFormComponent', () => {
let saveButtonComponent: ButtonWithSpinnerComponent; let saveButtonComponent: ButtonWithSpinnerComponent;
beforeEach(() => { beforeEach(() => {
saveButtonComponent = getDebugElementFromFixtureByCss( saveButtonComponent = getDebugElementFromFixtureByCss(fixture, saveButtonSelector).componentInstance;
fixture,
saveButtonSelector,
).componentInstance;
}); });
it('should call submit on click', () => { it('should call submit on click', () => {
...@@ -141,7 +117,7 @@ describe('OrganisationseinheitFormComponent', () => { ...@@ -141,7 +117,7 @@ describe('OrganisationseinheitFormComponent', () => {
component.formService.submit = () => throwError(() => new Error('some error')); component.formService.submit = () => throwError(() => new Error('some error'));
component.submit(); component.submit();
component.submitInProgress$.subscribe({ component.submitStateResource$.subscribe({
error: () => {}, error: () => {},
}); });
tick(); tick();
...@@ -153,7 +129,7 @@ describe('OrganisationseinheitFormComponent', () => { ...@@ -153,7 +129,7 @@ describe('OrganisationseinheitFormComponent', () => {
component.formService.submit = () => of(false); component.formService.submit = () => of(false);
component.submit(); component.submit();
component.submitInProgress$.subscribe(); component.submitStateResource$.subscribe();
tick(); tick();
expect(component.handleProgressChange).toHaveBeenCalled(); expect(component.handleProgressChange).toHaveBeenCalled();
......
import { StateResource, createStateResource } from '@alfa-client/tech-shared'; import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core'; import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core';
import { Observable, of, tap } from 'rxjs'; import { Observable, of, tap } from 'rxjs';
import { Organisationseinheit } from '../../../user/user.model'; import { Organisationseinheit } from '../../../user/user.model';
...@@ -21,7 +21,7 @@ export class OrganisationseinheitFormComponent implements AfterViewInit { ...@@ -21,7 +21,7 @@ export class OrganisationseinheitFormComponent implements AfterViewInit {
@ViewChild('OrganisationseinheitDialog') private dialogRef: ElementRef<HTMLDialogElement>; @ViewChild('OrganisationseinheitDialog') private dialogRef: ElementRef<HTMLDialogElement>;
dialog: HTMLDialogElement; dialog: HTMLDialogElement;
submitInProgress$: Observable<boolean> = of(false); submitStateResource$: Observable<StateResource<Organisationseinheit>> = of(createEmptyStateResource<Organisationseinheit>());
label: string; label: string;
...@@ -32,13 +32,13 @@ export class OrganisationseinheitFormComponent implements AfterViewInit { ...@@ -32,13 +32,13 @@ export class OrganisationseinheitFormComponent implements AfterViewInit {
} }
public submit() { public submit() {
this.submitInProgress$ = this.formService this.submitStateResource$ = this.formService
.submit() .submit()
.pipe(tap((progress: boolean) => this.handleProgressChange(progress))); .pipe(tap((stateResource: StateResource<Organisationseinheit>) => this.handleProgressChange(stateResource)));
} }
handleProgressChange(progress: boolean): void { handleProgressChange(stateResource: StateResource<Organisationseinheit>): void {
if (!progress) { if (!stateResource.loading) {
this.completeIfNoErrors(); this.completeIfNoErrors();
} }
} }
......
import { createStateResource, isNotNil, StateResource } from '@alfa-client/tech-shared'; import { createEmptyStateResource, createStateResource, isNotNil, StateResource } from '@alfa-client/tech-shared';
import { Injectable, Input } from '@angular/core'; import { Injectable, Input } from '@angular/core';
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { catchError, Observable, of } from 'rxjs'; import { catchError, Observable, of, tap } from 'rxjs';
import { import { Organisationseinheit, OrganisationseinheitError, OrganisationseinheitErrorType } from '../../../user/user.model';
Organisationseinheit,
OrganisationseinheitError,
OrganisationseinheitErrorType,
} from '../../../user/user.model';
import { getOrganisationseinheitErrorMessage } from '../../../user/user.util'; import { getOrganisationseinheitErrorMessage } from '../../../user/user.util';
import { OrganisationseinheitService } from '../../organisationseinheitService'; import { OrganisationseinheitService } from '../../organisationseinheitService';
...@@ -32,31 +28,32 @@ export class OrganisationseinheitFormservice { ...@@ -32,31 +28,32 @@ export class OrganisationseinheitFormservice {
}); });
} }
public submit(): Observable<boolean> { public submit(): Observable<StateResource<Organisationseinheit>> {
if (this.validate()) { if (this.validate()) {
return this.callService().pipe( return this.callService().pipe(
tap((state) => console.log(state)),
catchError((error: OrganisationseinheitError) => { catchError((error: OrganisationseinheitError) => {
this.handleError(error); this.handleError(error);
return of(false); return of(createEmptyStateResource<Organisationseinheit>());
}), }),
); );
} else { } else {
return of(false); return of(createEmptyStateResource<Organisationseinheit>());
} }
} }
callService(): Observable<boolean> { callService(): Observable<StateResource<Organisationseinheit>> {
return this.isPatch() ? this.save() : this.create(); return this.isPatch() ? this.save() : this.create();
} }
create(): Observable<boolean> { create(): Observable<StateResource<Organisationseinheit>> {
return this.organisationsEinheitService.create({ return this.organisationsEinheitService.create({
name: this.getName(), name: this.getName(),
organisationseinheitIds: this.getOrganisationseinheitIds(), organisationseinheitIds: this.getOrganisationseinheitIds(),
}); });
} }
save(): Observable<boolean> { save(): Observable<StateResource<Organisationseinheit>> {
return this.organisationsEinheitService.save({ return this.organisationsEinheitService.save({
...this.source, ...this.source,
name: this.getName(), name: this.getName(),
...@@ -79,9 +76,7 @@ export class OrganisationseinheitFormservice { ...@@ -79,9 +76,7 @@ export class OrganisationseinheitFormservice {
} }
private getName(): string { private getName(): string {
return this.getStringFromPotentiallyEmptyField( return this.getStringFromPotentiallyEmptyField(OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD);
OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD,
);
} }
private getOrganisationseinheitIds(): string[] { private getOrganisationseinheitIds(): string[] {
...@@ -126,8 +121,7 @@ export class OrganisationseinheitFormservice { ...@@ -126,8 +121,7 @@ export class OrganisationseinheitFormservice {
this.source = organisationseinheit; this.source = organisationseinheit;
this.form.patchValue({ this.form.patchValue({
[OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name, [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name,
[OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: organisationseinheit.organisationseinheitIds.join(', '),
organisationseinheit.organisationseinheitIds.join(', '),
}); });
} }
......
import { fakeAsync, tick } from '@angular/core/testing'; import { fakeAsync, tick } from '@angular/core/testing';
import faker from '@faker-js/faker'; import faker from '@faker-js/faker';
import { cold } from 'jest-marbles'; import { cold } from 'jest-marbles';
import { import { StateResource, createEmptyStateResource } from 'libs/tech-shared/src/lib/resource/resource.util';
StateResource,
createEmptyStateResource,
} from 'libs/tech-shared/src/lib/resource/resource.util';
import { createDummy } from 'libs/tech-shared/test/dummy'; import { createDummy } from 'libs/tech-shared/test/dummy';
import { singleCold } from 'libs/tech-shared/test/marbles'; import { singleCold } from 'libs/tech-shared/test/marbles';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
...@@ -30,7 +27,7 @@ describe('KeycloakResourceService', () => { ...@@ -30,7 +27,7 @@ describe('KeycloakResourceService', () => {
it('should return stateResource as observable', (done) => { it('should return stateResource as observable', (done) => {
service.get().subscribe((stateResource) => { service.get().subscribe((stateResource) => {
expect(stateResource).toBe(service.stateResource.value); expect(stateResource).toBe(service.listStateResource.value);
done(); done();
}); });
}); });
...@@ -68,7 +65,7 @@ describe('KeycloakResourceService', () => { ...@@ -68,7 +65,7 @@ describe('KeycloakResourceService', () => {
service.loadResource(); service.loadResource();
tick(); tick();
expect(service.stateResource.value.resource).toEqual(dummyItems); expect(service.listStateResource.value.resource).toEqual(dummyItems);
})); }));
}); });
...@@ -132,7 +129,7 @@ describe('KeycloakResourceService', () => { ...@@ -132,7 +129,7 @@ describe('KeycloakResourceService', () => {
it('should set loading', () => { it('should set loading', () => {
service.handleLoading(dummyAction); service.handleLoading(dummyAction);
expect(service.stateResource.value.loading).toBe(true); expect(service.listStateResource.value.loading).toBe(true);
}); });
it('should call refreshAfterFirstEmit', () => { it('should call refreshAfterFirstEmit', () => {
...@@ -154,12 +151,12 @@ describe('KeycloakResourceService', () => { ...@@ -154,12 +151,12 @@ describe('KeycloakResourceService', () => {
describe('refreshAfterFirstEmit', () => { describe('refreshAfterFirstEmit', () => {
it('should call refresh after first emit', fakeAsync(() => { it('should call refresh after first emit', fakeAsync(() => {
service.refresh = jest.fn(); service.refreshList = jest.fn();
service.refreshAfterFirstEmit(dummyAction).subscribe(); service.refreshAfterFirstEmit(dummyAction).subscribe();
tick(); tick();
expect(service.refresh).toHaveBeenCalled(); expect(service.refreshList).toHaveBeenCalled();
})); }));
}); });
...@@ -175,36 +172,36 @@ describe('KeycloakResourceService', () => { ...@@ -175,36 +172,36 @@ describe('KeycloakResourceService', () => {
it('should set loading in state to true without parameter', () => { it('should set loading in state to true without parameter', () => {
service.setLoading(); service.setLoading();
expect(service.stateResource.value.loading).toEqual(true); expect(service.listStateResource.value.loading).toEqual(true);
}); });
it('should set loading in state to false for parameter false', () => { it('should set loading in state to false for parameter false', () => {
service.setLoading(false); service.setLoading(false);
expect(service.stateResource.value.loading).toEqual(false); expect(service.listStateResource.value.loading).toEqual(false);
}); });
}); });
describe('refresh', () => { describe('refresh', () => {
it('should set reload in state to true', () => { it('should set reload in state to true', () => {
service.refresh(); service.refreshList();
expect(service.stateResource.value.reload).toBe(true); expect(service.listStateResource.value.reload).toBe(true);
}); });
it('should clear resource in state', () => { it('should clear resource in state', () => {
service.refresh(); service.refreshList();
expect(service.stateResource.value.resource).toBe(null); expect(service.listStateResource.value.resource).toBe(null);
}); });
}); });
describe('select resource', () => { describe('select resource', () => {
it('should return state resource', () => { it('should return state resource', () => {
const stateResource = createEmptyStateResource<unknown[]>(); const stateResource = createEmptyStateResource<unknown[]>();
service.stateResource.next(stateResource); service.listStateResource.next(stateResource);
const resource$: Observable<StateResource<unknown[]>> = service.selectResource(); const resource$: Observable<StateResource<unknown[]>> = service.selectListResource();
expect(resource$).toBeObservable(singleCold(stateResource)); expect(resource$).toBeObservable(singleCold(stateResource));
}); });
......
import { import { createEmptyStateResource, createStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared';
createEmptyStateResource, import { BehaviorSubject, first, Observable, startWith, switchMap, tap } from 'rxjs';
createStateResource,
doIfLoadingRequired,
StateResource,
} from '@alfa-client/tech-shared';
import { BehaviorSubject, first, map, Observable, startWith, tap } from 'rxjs';
export abstract class KeycloakResourceService<T> { export abstract class KeycloakResourceService<T> {
readonly stateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject( readonly listStateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject(createEmptyStateResource());
createEmptyStateResource(), readonly createStateResource: BehaviorSubject<StateResource<T>> = new BehaviorSubject(createEmptyStateResource());
); readonly deleteStateResource: BehaviorSubject<StateResource<string>> = new BehaviorSubject(createEmptyStateResource());
readonly saveStateResource: BehaviorSubject<StateResource<T>> = new BehaviorSubject(createEmptyStateResource());
public get() { public get() {
return this.stateResource return this.listStateResource.asObservable().pipe(tap((stateResource) => this.handleChanges(stateResource)));
.asObservable()
.pipe(tap((stateResource) => this.handleChanges(stateResource)));
} }
handleChanges(stateResource: StateResource<T[]>) { handleChanges(stateResource: StateResource<T[]>) {
...@@ -22,70 +16,84 @@ export abstract class KeycloakResourceService<T> { ...@@ -22,70 +16,84 @@ export abstract class KeycloakResourceService<T> {
} }
loadResource(): void { loadResource(): void {
this.setLoading(); this.setListLoading(this.listStateResource);
this.getItemsFromKeycloak() this.getItemsFromKeycloak()
.pipe(first()) .pipe(first())
.subscribe((items) => this.updateResource(items)); .subscribe((items) => this.updateResource(items));
} }
setListLoading(stateResource: BehaviorSubject<StateResource<unknown>>, loading: boolean = true): void {
stateResource.next({
...stateResource.value,
loading,
});
}
abstract getItemsFromKeycloak(): Observable<T[]>; abstract getItemsFromKeycloak(): Observable<T[]>;
private updateResource(items: T[]): void { private updateResource(items: T[]): void {
this.stateResource.next(createStateResource(items)); this.listStateResource.next(createStateResource(items));
} }
public create(item: Partial<T>): Observable<boolean> { public create(item: Partial<T>): Observable<StateResource<T>> {
return this.handleLoading(this.createInKeycloak(item)); this.createStateResource.next(createEmptyStateResource(true));
return this.createInKeycloak(item).pipe(
tap((item) => this.updateCreateStateResource(item)),
tap(() => this.refreshList()),
switchMap(() => this.createStateResource.asObservable()),
startWith(this.createStateResource.value),
);
}
updateCreateStateResource(item: T): void {
this.createStateResource.next(createStateResource(item));
} }
abstract createInKeycloak(item: Partial<T>): Observable<T>; abstract createInKeycloak(item: Partial<T>): Observable<T>;
public save(item: T): Observable<boolean> { public save(item: T): Observable<StateResource<T>> {
return this.handleLoading(this.saveInKeycloak(item)); this.saveStateResource.next(createEmptyStateResource(true));
}
abstract saveInKeycloak(item: T): Observable<void>; return this.saveInKeycloak(item).pipe(
tap(() => this.updateSaveStateResource(item)),
tap(() => this.refreshList()),
switchMap(() => this.saveStateResource.asObservable()),
startWith(this.saveStateResource.value),
);
}
public delete(id: string): Observable<boolean> { updateSaveStateResource(item: T): void {
return this.handleLoading(this.deleteInKeycloak(id)); this.saveStateResource.next(createStateResource(item));
} }
abstract deleteInKeycloak(id: string): Observable<void>; abstract saveInKeycloak(item: T): Observable<void>;
handleLoading(action: Observable<unknown>): Observable<boolean> { public delete(id: string): Observable<StateResource<string>> {
this.setLoading(); this.deleteStateResource.next(createEmptyStateResource(true));
return this.progress(this.refreshAfterFirstEmit(action));
}
refreshAfterFirstEmit(action: Observable<unknown>): Observable<unknown> { return this.deleteInKeycloak(id).pipe(
return action.pipe( tap(() => this.updateDeleteStateResource(id)),
first(), tap(() => this.refreshList()),
tap(() => this.refresh()), switchMap(() => this.deleteStateResource.asObservable()),
startWith(this.deleteStateResource.value),
); );
} }
progress(action: Observable<unknown>): Observable<boolean> { updateDeleteStateResource(id: string): void {
return action.pipe( this.deleteStateResource.next(createStateResource(id));
map(() => false),
startWith(true),
);
} }
setLoading(loading: boolean = true): void { abstract deleteInKeycloak(id: string): Observable<void>;
this.stateResource.next({
...this.stateResource.value,
loading,
});
}
refresh(): void { refreshList(): void {
this.stateResource.next({ this.listStateResource.next({
...createEmptyStateResource(), ...createEmptyStateResource(),
reload: true, reload: true,
}); });
} }
public selectResource(): Observable<StateResource<T[]>> { public selectListResource(): Observable<StateResource<T[]>> {
return this.stateResource.asObservable(); return this.listStateResource.asObservable();
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment