Skip to content
Snippets Groups Projects
Commit d0af3424 authored by Martin's avatar Martin
Browse files

OZG-6988 refactor postfach setting handling (as an example)

parent cb3016b2
No related tags found
No related merge requests found
Showing
with 150 additions and 197 deletions
......@@ -41,7 +41,6 @@ import { OAuthModule } from 'angular-oauth2-oidc';
import { HttpUnauthorizedInterceptor } from '@authentication';
import { ConfigurationsProviders } from 'libs/admin/configuration-shared/src/lib/configuration.providers';
import { OrganisationEinheitProviders } from 'libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.providers';
import { PostfachProviders } from 'libs/admin/postfach-shared/src/lib/postfach.providers';
import { SettingsProviders } from 'libs/admin/settings-shared/src/lib/settings.providers';
import { UserProviders } from 'libs/admin/user/src/lib/user.providers';
import { AppComponent } from './app/app.component';
......@@ -63,7 +62,6 @@ loadEnvironment(environment.environmentUrl).then((env) => {
bootstrapApplication(AppComponent, {
providers: [
ConfigurationsProviders,
PostfachProviders,
SettingsProviders,
OrganisationEinheitProviders,
UserProviders,
......
export * from './lib/postfach.model';
export * from './lib/postfach.service';
......@@ -21,21 +21,17 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { SettingsService } from '@admin-client/settings-shared';
import { ApiResourceService, ResourceRepository, ResourceServiceConfig } from '@alfa-client/tech-shared';
import { PostfachLinkRel } from './postfach.linkrel';
import { PostfachResource } from './postfach.model';
export class PostfachResourceService extends ApiResourceService<PostfachResource, PostfachResource> {}
// export class PostfachResourceService extends ApiResourceService<PostfachResource, PostfachResource> {}
export function createPostfachResourceService(repository: ResourceRepository, settingService: SettingsService) {
return new ApiResourceService(buildConfig(settingService), repository);
}
// export function createPostfachResourceService(repository: ResourceRepository, settingService: SettingsService) {
// return new ApiResourceService(buildConfig(settingService), repository);
// }
function buildConfig(settingService: SettingsService): ResourceServiceConfig<PostfachResource> {
return {
resource: settingService.getPostfach(),
getLinkRel: PostfachLinkRel.SELF,
edit: { linkRel: PostfachLinkRel.SELF },
};
}
// function buildConfig(settingService: SettingsService): ResourceServiceConfig<PostfachResource> {
// return {
// resource: settingService.getPostfach(),
// getLinkRel: PostfachLinkRel.SELF,
// edit: { linkRel: PostfachLinkRel.SELF },
// };
// }
......@@ -42,4 +42,9 @@ export declare type PostfachSettingsItem = {
settingBody: Postfach;
};
export declare type PostfachResource = Resource & PostfachSettingsItem;
export declare type PostfachResource = Resource & PostfachSettingsItem & SettingsItem;
export interface SettingsItem {
name: SettingName;
settingBody: any; //typisieren
}
import { SettingsService } from '@admin-client/settings-shared';
import { ResourceRepository } from '@alfa-client/tech-shared';
import { createPostfachResourceService, PostfachResourceService } from './postfach-resource.service';
export const PostfachProviders = [
SettingsService,
{
provide: PostfachResourceService,
useFactory: createPostfachResourceService,
deps: [ResourceRepository, SettingsService],
},
];
/*
* Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { SettingName } from '@admin-client/settings-shared';
import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
import { SnackBarService } from '@alfa-client/ui';
import { inject, Injectable } from '@angular/core';
import { Observable, startWith, tap } from 'rxjs';
import { PostfachResourceService } from './postfach-resource.service';
import { Postfach, PostfachResource, PostfachSettingsItem } from './postfach.model';
@Injectable()
export class PostfachService {
private postfachResourceService = inject(PostfachResourceService)
private snackbarService = inject(SnackBarService)
public get(): Observable<StateResource<PostfachResource>> {
return this.postfachResourceService.get();
}
public save(postfach: Postfach): Observable<StateResource<PostfachResource>> {
return this.postfachResourceService.save(this.buildPostfachSettingItem(postfach)).pipe(
tap((stateResource: StateResource<PostfachResource>) => this.showInfoAfterSave(stateResource)),
startWith(createEmptyStateResource<PostfachResource>(true)),
);
}
private showInfoAfterSave(stateResource: StateResource<PostfachResource>) {
if (!stateResource.loading) {
this.snackbarService.showInfo('Die Signatur wurde erfolgreich gespeichert.');
}
}
private buildPostfachSettingItem(postfach: Postfach): PostfachSettingsItem {
return {
name: SettingName.POSTFACH,
settingBody: postfach,
};
}
}
<h1 class="heading-1">Postfach</h1>
<admin-postfach-form [postfachStateResource]="postfachStateResource$ | async" />
<admin-postfach-form />
......@@ -21,11 +21,8 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { PostfachResource, PostfachService } from '@admin-client/postfach-shared';
import { StateResource } from '@alfa-client/tech-shared';
import { CommonModule } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Component } from '@angular/core';
import { PostfachFormComponent } from './postfach-form/postfach-form.component';
@Component({
......@@ -33,14 +30,5 @@ import { PostfachFormComponent } from './postfach-form/postfach-form.component';
templateUrl: './postfach-container.component.html',
standalone: true,
imports: [CommonModule, PostfachFormComponent],
providers: [PostfachService],
})
export class PostfachContainerComponent implements OnInit {
private postfachService = inject(PostfachService);
postfachStateResource$: Observable<StateResource<PostfachResource>>;
ngOnInit(): void {
this.postfachStateResource$ = this.postfachService.get();
}
}
export class PostfachContainerComponent {}
......@@ -23,43 +23,9 @@
unter der Lizenz sind dem Lizenztext zu entnehmen.
-->
<h1 class="heading-1">Postfach</h1>
<form class="form flex-col" [formGroup]="formService.form">
<!--
<h2 class="heading-2">Absender</h1>
<p id="absender-desc" class="p-1">Hinterlegen Sie Absenderinformationen zu Ihrem Postfach.</p>
<div
[formGroupName]="PostfachFormService.ASBSENDER_GROUP"
aria-describedby="absender-desc"
class="grid-col-1 mb-2 mt-2 grid w-96 gap-1"
>
<text-field
data-test-id="absender-name"
label="Name"
[formControlName]="PostfachFormService.NAME_FIELD"
></text-field>
<text-field
data-test-id="absender-anschrift"
label="Anschrift"
[formControlName]="PostfachFormService.ANSCHRIFT_FIELD"
></text-field>
<text-field
data-test-id="absender-dienst"
label="Dienst"
[formControlName]="PostfachFormService.DIENST_FIELD"
></text-field>
<text-field
data-test-id="absender-mandant"
label="Mandant"
[formControlName]="PostfachFormService.MANDANT_FIELD"
></text-field>
<text-field
data-test-id="absender-gemeindeschluessel"
label="Gemeindeschlüssel"
[formControlName]="PostfachFormService.GEMEINDESCHLUESSEL_FIELD"
></text-field>
</div>
<div class="h-20"></div>
-->
<admin-postfach-signatur class="mb-6 block" />
<ods-button-with-spinner
......@@ -68,13 +34,4 @@
[stateResource]="submitInProgress$ | async"
(clickEmitter)="submit()"
></ods-button-with-spinner>
@if (formService.isInvalid()) {
<span
data-test-id="invalid-empty-message-span"
class="m-2 text-red-500"
>
*Es müssen alle Felder ausgefüllt sein.
</span>
}
</form>
......@@ -21,10 +21,9 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { PostfachResource } from '@admin-client/postfach-shared';
import { createEmptyStateResource, isNotNil, StateResource } from '@alfa-client/tech-shared';
import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
import { CommonModule } from '@angular/common';
import { Component, inject, Input } from '@angular/core';
import { Component, inject } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Resource } from '@ngxp/rest';
import { ButtonWithSpinnerComponent } from '@ods/component';
......@@ -40,21 +39,9 @@ import { PostfachFormService } from './postfach.formservice';
imports: [CommonModule, FormsModule, ReactiveFormsModule, PostfachSignaturComponent, ButtonWithSpinnerComponent],
})
export class PostfachFormComponent {
public formService = inject(PostfachFormService);
public readonly formService = inject(PostfachFormService);
submitInProgress$: Observable<StateResource<Resource>> = of(createEmptyStateResource<Resource>());
@Input() set postfachStateResource(stateResource: StateResource<PostfachResource>) {
this.updatePostfachResource(stateResource.resource);
}
updatePostfachResource(postfachRessource: PostfachResource): void {
if (isNotNil(postfachRessource)) {
this.formService.patch(postfachRessource.settingBody);
}
}
protected readonly PostfachFormService = PostfachFormService;
public submitInProgress$: Observable<StateResource<Resource>> = of(createEmptyStateResource<Resource>());
public submit(): void {
this.submitInProgress$ = this.formService.submit();
......
......@@ -21,16 +21,18 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { Postfach, PostfachResource, PostfachService } from '@admin-client/postfach-shared';
import { AbstractFormService, EMPTY_STRING, StateResource } from '@alfa-client/tech-shared';
import { inject, Injectable } from '@angular/core';
import { FormControl, UntypedFormGroup } from '@angular/forms';
import { Postfach, PostfachResource } from '@admin-client/postfach-shared';
import { SettingName } from '@admin-client/settings-shared';
import { EMPTY_STRING, StateResource } from '@alfa-client/tech-shared';
import { Injectable } from '@angular/core';
import { FormBuilder, FormControl, UntypedFormGroup } from '@angular/forms';
import { isNil } from 'lodash-es';
import { Observable } from 'rxjs';
import { SettingFormService } from '../../../../../settings-shared/src/lib/settings-fom.service';
@Injectable()
export class PostfachFormService extends AbstractFormService {
private postfachService: PostfachService = inject(PostfachService);
export class PostfachFormService extends SettingFormService<PostfachResource> {
static readonly ITEM_NAME: SettingName = SettingName.POSTFACH;
public static readonly ASBSENDER_GROUP: string = 'absender';
public static readonly NAME_FIELD: string = 'name';
......@@ -41,6 +43,10 @@ export class PostfachFormService extends AbstractFormService {
public static readonly SIGNATUR_FIELD: string = 'signatur';
constructor(formBuilder: FormBuilder) {
super(formBuilder, PostfachFormService.ITEM_NAME);
}
protected initForm(): UntypedFormGroup {
return this.formBuilder.group({
[PostfachFormService.ASBSENDER_GROUP]: this.formBuilder.group({
......@@ -56,17 +62,13 @@ export class PostfachFormService extends AbstractFormService {
protected doSubmit(): Observable<StateResource<PostfachResource>> {
const value: Postfach = this.getFormValue();
if (this.shouldSkipAbsender(value)) {
if (this.shouldRemoveAbsender(value)) {
delete value.absender;
}
return this.postfachService.save(value);
}
private shouldSkipAbsender(postfach: Postfach): boolean {
return isNil(this.source?.absender) && Object.values(postfach.absender).every((v) => isNil(v) || v.length === 0);
return this.settingService.save(this.source, value, PostfachFormService.ITEM_NAME);
}
protected getPathPrefix(): string {
return 'settingBody';
private shouldRemoveAbsender(postfach: Postfach): boolean {
return isNil(this.source.absender) || Object.values(postfach.absender).every((v) => isNil(v) || v.length === 0);
}
}
import { SettingsItem } from '@admin-client/postfach-shared';
import { SettingName, SettingsService } from '@admin-client/settings-shared';
import { AbstractFormService, isLoaded, isNotNull, StateResource } from '@alfa-client/tech-shared';
import { inject, Injectable, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Subscription, tap } from 'rxjs';
@Injectable()
export abstract class SettingFormService<T extends SettingsItem> extends AbstractFormService implements OnInit, OnDestroy {
settingService: SettingsService = inject(SettingsService);
private sub: Subscription;
constructor(formBuilder: FormBuilder, name: SettingName) {
super(formBuilder);
console.info('SETTINGS FORMSERVICE: Constructor');
this.sub = this.settingService
.get(name)
.pipe(tap((stateResource: StateResource<T>) => this.handleSettingChange(stateResource)))
.subscribe();
}
handleSettingChange(stateResource: StateResource<T>) {
if (isLoaded(stateResource) && isNotNull(stateResource.resource)) {
this.patch(stateResource.resource.settingBody);
this.source = stateResource.resource;
}
}
ngOnInit(): void {
console.info('SETTINGS FORMSERVICE: ngOnInit');
}
ngOnDestroy(): void {
console.info('SETTINGS FORMSERVICE: ngOnDestrpy');
this.unsubscribe();
this.settingService.refresh();
}
unsubscribe(): void {
this.sub.unsubscribe();
}
protected getPathPrefix(): string {
return 'settingBody';
}
}
import { PostfachResource } from '@admin-client/postfach-shared';
import { StateResource } from '@alfa-client/tech-shared';
import { PostfachSettingsItem } from '@admin-client/postfach-shared';
import { createEmptyStateResource, createStateResource, ResourceRepository, StateResource } from '@alfa-client/tech-shared';
import { SnackBarService } from '@alfa-client/ui';
import { inject, Injectable } from '@angular/core';
import { map, Observable } from 'rxjs';
import { Resource } from '@ngxp/rest';
import { map, Observable, startWith, tap } from 'rxjs';
import { SettingListResourceService } from './settings-resource.service';
import { getPostfachResource } from './settings.util';
import { SettingName } from './settings.model';
import { getSettingItem } from './settings.util';
@Injectable()
export class SettingsService {
private settingListResourceService = inject(SettingListResourceService);
private repository: ResourceRepository = inject(ResourceRepository);
private snackbarService: SnackBarService = inject(SnackBarService);
public getPostfach(): Observable<StateResource<PostfachResource>> {
return this.settingListResourceService.getList().pipe(map(getPostfachResource));
public get<T>(name: SettingName): Observable<StateResource<T>> {
return this.settingListResourceService.getList().pipe(map((list) => getSettingItem<T>(list, name)));
}
//Objekt bauen, snackbar configuration/message ergänzen
public save<T extends Resource>(resource: Resource, toSave: unknown, name: SettingName): Observable<StateResource<T>> {
return this.repository
.save({
resource,
linkRel: 'self',
toSave: this.buildSettingItem(toSave, name),
})
.pipe(
map((res: T) => createStateResource<T>(res)),
tap((stRes: StateResource<T>) => this.showInfoAfterSave(stRes)),
startWith(createEmptyStateResource<T>(true)),
);
}
private showInfoAfterSave<T>(stateResource: StateResource<T>) {
if (!stateResource.loading) {
this.snackbarService.showInfo('Die Signatur wurde erfolgreich gespeichert.');
}
}
private buildSettingItem(settingBody: any, name: SettingName): PostfachSettingsItem {
return {
name: name,
settingBody: settingBody,
};
}
public refresh(): void {
this.settingListResourceService.refresh();
}
}
......@@ -21,7 +21,6 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { PostfachResource } from '@admin-client/postfach-shared';
import {
createEmptyStateResource,
createStateResource,
......@@ -32,14 +31,25 @@ import {
import { SettingListLinkRel } from './settings.linkrel';
import { SettingItemResource, SettingListResource, SettingName } from './settings.model';
export function getPostfachResource(settingsListResource: StateResource<SettingListResource>): StateResource<PostfachResource> {
// export function getPostfachResource<T>(settingsListResource: StateResource<SettingListResource>): StateResource<T> {
// const entries: SettingItemResource[] = getEmbeddedResources(settingsListResource, SettingListLinkRel.LIST);
// const postfachSettingItemResource: SettingItemResource = entries.find(isPostfachSettingItem);
// return isNotNil(postfachSettingItemResource) ?
// createStateResource(postfachSettingItemResource as T)
// : createEmptyStateResource();
// }
// function isPostfachSettingItem(item: SettingItemResource): boolean {
// return item.name === SettingName.POSTFACH;
// }
export function getSettingItem<T>(
settingsListResource: StateResource<SettingListResource>,
itemName: SettingName,
): StateResource<T> {
const entries: SettingItemResource[] = getEmbeddedResources(settingsListResource, SettingListLinkRel.LIST);
const postfachSettingItemResource: SettingItemResource = entries.find(isPostfachSettingItem);
const postfachSettingItemResource: SettingItemResource = entries.find((item) => item.name === itemName);
return isNotNil(postfachSettingItemResource) ?
createStateResource(postfachSettingItemResource as PostfachResource)
createStateResource(postfachSettingItemResource as T)
: createEmptyStateResource();
}
function isPostfachSettingItem(item: SettingItemResource): boolean {
return item.name === SettingName.POSTFACH;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment