From ebf351df62eecedc798f43a768e645d3d674891f Mon Sep 17 00:00:00 2001 From: Alexander Reifschneider <alexander.reifschneider@mgm-tp.com> Date: Fri, 28 Feb 2025 16:40:36 +0100 Subject: [PATCH 1/4] OZG-5977 Add styling --- ...rd-dokumente-hochladen-form.component.html | 2 +- .../binary-file-list-orientation.directive.ts | 2 +- .../multi-file-upload-editor.component.html | 6 ++- ...multi-file-upload-editor.component.spec.ts | 46 ++++++++++++++++++- .../multi-file-upload-editor.component.ts | 6 ++- .../multi-file-upload.component.html | 28 +++++------ .../single-file-upload-editor.component.ts | 5 +- .../file-upload-button.component.html | 15 +++--- .../file-upload-button.component.ts | 26 ++++++++++- 9 files changed, 105 insertions(+), 31 deletions(-) diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html index edd8aff832..007a02ec85 100644 --- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html +++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html @@ -23,7 +23,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div class="mt-4 flex flex-col gap-4"> +<div class="mt-4 flex max-w-72 flex-col gap-4"> @if (bescheidResource | hasLink: BescheidLinkRel.CREATE_DOCUMENT) { <alfa-bescheid-wizard-create-document-button-container [bescheidResource]="bescheidResource" diff --git a/alfa-client/libs/binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive.ts b/alfa-client/libs/binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive.ts index 3a1a42958a..956be5722c 100644 --- a/alfa-client/libs/binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive.ts +++ b/alfa-client/libs/binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive.ts @@ -1,7 +1,7 @@ import { Directive, ElementRef, Input } from '@angular/core'; export const _verticalClasses: string[] = ['flex', 'flex-col']; -export const _horizontalClasses: string[] = ['flex', 'flex-row', 'flex-wrap']; +export const _horizontalClasses: string[] = ['flex', 'flex-wrap', 'gap-2']; export enum BinaryFileListOrientation { HORIZONTAL = 'horizontal', diff --git a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.html b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.html index 1bfa1fb537..4024dc2de9 100644 --- a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.html +++ b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.html @@ -4,10 +4,12 @@ [attr.data-test-id]="(label | convertForDataTest) + '-file-upload-button'" [multi]="true" [isLoading]="isUploadInProgress$ | async" - class="relative w-72" + [variant]="uploadButtonVariant" data-test-id="binary-file-upload" > <ods-spinner-icon spinner size="medium" /> <ods-attachment-icon icon size="medium" /> - <p text class="text-center">{{ label }}</p> + @if (label) { + <p text data-test-id="upload-button-label" class="text-center">{{ label }}</p> + } </ods-file-upload-button> diff --git a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.spec.ts b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.spec.ts index dc42e69a0f..38303a464c 100644 --- a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.spec.ts @@ -1,11 +1,17 @@ import { BinaryFileService, FileUploadType, ToUploadFile } from '@alfa-client/binary-file-shared'; import { ConvertForDataTestPipe } from '@alfa-client/tech-shared'; -import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock } from '@alfa-client/test-utils'; +import { + existsAsHtmlElement, + getElementComponentFromFixtureByCss, + mock, + Mock, + notExistsAsHtmlElement, +} from '@alfa-client/test-utils'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { faker } from '@faker-js/faker/.'; import { expect } from '@jest/globals'; import { getUrl, Resource } from '@ngxp/rest'; -import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system'; +import { FileUploadButtonComponent, SpinnerIconComponent, UploadButtonVariants } from '@ods/system'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; @@ -23,6 +29,7 @@ describe('MultiFileUploadEditorComponent', () => { const uploadResource: Resource = createDummyResource([uploadLinkRel]); const buttonTestId: string = getDataTestIdOf('Ein_Label-file-upload-button'); + const buttonLabelTestId: string = getDataTestIdOf('upload-button-label'); let binaryFileService: Mock<BinaryFileService>; @@ -104,6 +111,24 @@ describe('MultiFileUploadEditorComponent', () => { } as ToUploadFile); }); }); + + describe('get uploadButtonVariant', () => { + it('should return "label"', () => { + component.label = 'test'; + + const result: UploadButtonVariants['variant'] = component.uploadButtonVariant; + + expect(result).toBe('label'); + }); + + it('should return "icon"', () => { + component.label = ''; + + const result: UploadButtonVariants['variant'] = component.uploadButtonVariant; + + expect(result).toBe('icon'); + }); + }); }); describe('template', () => { @@ -125,5 +150,22 @@ describe('MultiFileUploadEditorComponent', () => { expect(fileButtonComponent.isLoading).toEqual(true); }); }); + describe('upload button label', () => { + it('should show', () => { + component.label = 'test'; + + fixture.detectChanges(); + + existsAsHtmlElement(fixture, buttonLabelTestId); + }); + + it('should hide', () => { + component.label = ''; + + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, buttonLabelTestId); + }); + }); }); }); diff --git a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.ts b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.ts index 4c057b3f3d..2a96236120 100644 --- a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.ts +++ b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.ts @@ -5,7 +5,7 @@ import { AsyncPipe } from '@angular/common'; import { Component, HostListener, inject, Input, OnInit } from '@angular/core'; import { ControlContainer, FormGroupDirective, ReactiveFormsModule } from '@angular/forms'; import { getUrl, Resource } from '@ngxp/rest'; -import { AttachmentIconComponent, FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system'; +import { AttachmentIconComponent, FileUploadButtonComponent, SpinnerIconComponent, UploadButtonVariants } from '@ods/system'; import { uniqueId } from 'lodash-es'; import { Observable } from 'rxjs'; @@ -55,4 +55,8 @@ export class MultiFileUploadEditorComponent implements OnInit { }); } } + + get uploadButtonVariant(): UploadButtonVariants['variant'] { + return this.label ? 'label' : 'icon'; + } } diff --git a/alfa-client/libs/binary-file/src/lib/multi-file-upload/multi-file-upload.component.html b/alfa-client/libs/binary-file/src/lib/multi-file-upload/multi-file-upload.component.html index 184ac868f9..8efd002c00 100644 --- a/alfa-client/libs/binary-file/src/lib/multi-file-upload/multi-file-upload.component.html +++ b/alfa-client/libs/binary-file/src/lib/multi-file-upload/multi-file-upload.component.html @@ -1,13 +1,15 @@ -<ods-file-upload-list-container - [parentFormArrayName]="filesFormFieldName" - [fileUploadType]="fileUploadType" - [filesResource]="filesResource" - [filesLinkRel]="filesLinkRelation" - data-test-id="file-list" -></ods-file-upload-list-container> -<ods-multi-file-upload-editor - [fileUploadType]="fileUploadType" - [uploadResource]="uploadResource" - [uploadLinkRelation]="uploadLinkRelation" - data-test-id="multi-file-upload-editor" -></ods-multi-file-upload-editor> \ No newline at end of file +<div class="flex flex-col gap-2"> + <ods-file-upload-list-container + [parentFormArrayName]="filesFormFieldName" + [fileUploadType]="fileUploadType" + [filesResource]="filesResource" + [filesLinkRel]="filesLinkRelation" + data-test-id="file-list" + /> + <ods-multi-file-upload-editor + [fileUploadType]="fileUploadType" + [uploadResource]="uploadResource" + [uploadLinkRelation]="uploadLinkRelation" + data-test-id="multi-file-upload-editor" + /> +</div> diff --git a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts index a62e384fb3..7de4a0bf3f 100644 --- a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts +++ b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts @@ -24,7 +24,7 @@ import { ConvertForDataTestPipe, isNotNil } from '@alfa-client/tech-shared'; import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; -import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system'; +import { FileUploadButtonComponent } from '@ods/system'; import { uniqueId } from 'lodash-es'; import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component'; @@ -32,7 +32,8 @@ import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstra selector: 'ods-single-file-upload-editor', templateUrl: './single-file-upload-editor.component.html', standalone: true, - imports: [FileUploadButtonComponent, SpinnerIconComponent, ReactiveFormsModule, ConvertForDataTestPipe], + styles: [':host {@apply contents}'], + imports: [FileUploadButtonComponent, ReactiveFormsModule, ConvertForDataTestPipe], }) export class SingleFileUploadEditorComponent extends FormControlEditorAbstractComponent { @Input() label: string = ''; diff --git a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.html b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.html index dc2b6cef68..b65b88d5b0 100644 --- a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.html +++ b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.html @@ -34,14 +34,13 @@ [multiple]="multi" [attr.data-test-id]="(id | convertForDataTest) + '-file-upload-input'" /> -<label - [for]="id" - class="z-10 inline-flex w-full flex-grow items-center justify-start gap-4 break-words rounded-md bg-background-50 py-3 pl-6 pr-6 text-text hover:bg-background-100 focus:outline-none focus:ring-2 focus:ring-primary peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-ozgblue-800 peer-disabled:cursor-wait peer-disabled:hover:bg-background-50" - role="button" -> - <ng-content *ngIf="!isLoading" select="[icon]"></ng-content> - <ng-content *ngIf="isLoading" select="[spinner]"></ng-content> - <div class="flex-grow"> +<label [for]="id" [ngClass]="uploadButtonVariants({ variant })" role="button"> + @if (isLoading) { + <ng-content select="[spinner]"></ng-content> + } @else { + <ng-content select="[icon]"></ng-content> + } + <div class="flex-grow empty:hidden"> <ng-content select="[text]"></ng-content> </div> </label> diff --git a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts index 2371918f9c..b5048be11b 100644 --- a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts +++ b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts @@ -24,12 +24,33 @@ import { ConvertForDataTestPipe } from '@alfa-client/tech-shared'; import { CommonModule } from '@angular/common'; import { Component, ElementRef, Input, ViewChild } from '@angular/core'; +import { cva, VariantProps } from 'class-variance-authority'; + +export const uploadButtonVariants = cva( + [ + 'z-10 inline-flex flex-grow items-center justify-start gap-4 break-words rounded-md text-primary', + 'border border-transparent hover:bg-ghost-hover peer-focus-visible:border-background-200', + 'peer-focus-visible:outline peer-focus-visible:outline-focus peer-focus-visible:bg-ghost-hover peer-focus-visible:outline-offset-1', + ], + { + variants: { + variant: { + label: 'py-3 px-6 bg-background-50 w-full', + icon: 'p-2 w-fit', + }, + }, + defaultVariants: { + variant: 'label', + }, + }, +); +export type UploadButtonVariants = VariantProps<typeof uploadButtonVariants>; @Component({ selector: 'ods-file-upload-button', standalone: true, imports: [CommonModule, ConvertForDataTestPipe], - styles: [':host {@apply inline-flex}'], + styles: [':host {@apply relative}'], templateUrl: './file-upload-button.component.html', }) export class FileUploadButtonComponent { @@ -37,9 +58,12 @@ export class FileUploadButtonComponent { @Input() isLoading: boolean = false; @Input() accept: string = '*/*'; @Input() multi: boolean = false; + @Input() variant: UploadButtonVariants['variant']; @ViewChild('inputElement') inputElement: ElementRef = new ElementRef({}); + readonly uploadButtonVariants = uploadButtonVariants; + resetInput(): void { this.inputElement.nativeElement.value = ''; } -- GitLab From b8499321bb675ec86e560630159fcb54c3f6dcab Mon Sep 17 00:00:00 2001 From: Alexander Reifschneider <alexander.reifschneider@mgm-tp.com> Date: Mon, 3 Mar 2025 10:46:37 +0100 Subject: [PATCH 2/4] OZG-5977 hide file container on empty content --- .../binary-file-list-container.component.html | 11 +++---- ...nary-file-list-container.component.spec.ts | 31 +++++++++++++++---- .../binary-file-list-container.component.ts | 27 +++++++++++----- .../binary-file-list.component.html | 7 +---- .../binary-file-list.component.spec.ts | 11 +++---- .../binary-file-list.component.ts | 7 ++--- 6 files changed, 56 insertions(+), 38 deletions(-) diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html index cfa93fbc6b..a5d3d8ee19 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html @@ -23,9 +23,8 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ods-attachment-wrapper> - <alfa-binary-file-list - [binaryFileListStateResource]="binaryFileListStateResource$ | async" - [listOrientation]="listOrientation" - ></alfa-binary-file-list> -</ods-attachment-wrapper> +@if (binaryFileList) { + <ods-attachment-wrapper> + <alfa-binary-file-list [binaryFileList]="binaryFileList" [listOrientation]="listOrientation" /> + </ods-attachment-wrapper> +} diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts index e9473e9ee4..885d5d27a6 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts @@ -42,9 +42,11 @@ describe('BinaryFileListContainerComponent', () => { const binaryFileService: Mock<BinaryFileService> = mock(BinaryFileService); - const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource( - createBinaryFileResource(), - ); + const fileList: Resource[] = []; + const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource({ + ...createBinaryFileResource(), + _embedded: { ozgFileList: fileList }, + }); const resource: Resource = createDummyResource(); const linkRel: LinkRelationName = DummyLinkRel.DUMMY; @@ -81,14 +83,31 @@ describe('BinaryFileListContainerComponent', () => { expect(binaryFileService.getFiles).toHaveBeenCalledWith(resource, linkRel); }); + + it('should NOT set binaryFileList', () => { + component.binaryFileList = null; + binaryFileService.getFiles.mockReturnValue(of(createStateResource(null))); + + component.ngOnInit(); + + expect(component.binaryFileList).toBe(null); + }); + + it('should set binaryFileList', () => { + component.ngOnInit(); + + expect(component.binaryFileList).toBe(fileList); + }); }); describe('binary file list', () => { it('should be called with binary file state resource', () => { - const binaryFileListComponent: BinaryFileListComponent = - getMockComponent<BinaryFileListComponent>(fixture, BinaryFileListComponent); + const binaryFileListComponent: BinaryFileListComponent = getMockComponent<BinaryFileListComponent>( + fixture, + BinaryFileListComponent, + ); - expect(binaryFileListComponent.binaryFileListStateResource).toBe(binaryFileStateResource); + expect(binaryFileListComponent.binaryFileList).toBe(fileList); }); }); }); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.ts index b4dce3b40b..c5cc042d55 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.ts @@ -21,27 +21,38 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; -import { LinkRelationName, StateResource } from '@alfa-client/tech-shared'; -import { Component, Input, OnInit } from '@angular/core'; -import { Resource } from '@ngxp/rest'; -import { Observable } from 'rxjs'; +import { BinaryFile, BinaryFileListLinkRel, BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; +import { isNotNull, LinkRelationName, StateResource } from '@alfa-client/tech-shared'; +import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { getEmbeddedResource, Resource } from '@ngxp/rest'; +import { filter, Subscription } from 'rxjs'; import { BinaryFileListOrientation } from '../directive/binary-file-list-orientation/binary-file-list-orientation.directive'; @Component({ selector: 'alfa-binary-file-list-container', templateUrl: './binary-file-list-container.component.html', }) -export class BinaryFileListContainerComponent implements OnInit { +export class BinaryFileListContainerComponent implements OnInit, OnDestroy { @Input() resource: Resource; @Input() linkRel: LinkRelationName; @Input() listOrientation: BinaryFileListOrientation = BinaryFileListOrientation.HORIZONTAL; - public binaryFileListStateResource$: Observable<StateResource<BinaryFileListResource>>; + public binaryFileList: BinaryFile[]; + public readonly binaryFileListLinkRel = BinaryFileListLinkRel; + binaryFileListSubscription: Subscription; constructor(private service: BinaryFileService) {} ngOnInit(): void { - this.binaryFileListStateResource$ = this.service.getFiles(this.resource, this.linkRel); + this.binaryFileListSubscription = this.service + .getFiles(this.resource, this.linkRel) + .pipe(filter((stateResource) => isNotNull(stateResource.resource))) + .subscribe((stateResource: StateResource<BinaryFileListResource>) => { + this.binaryFileList = getEmbeddedResource(stateResource.resource, this.binaryFileListLinkRel.FILE_LIST); + }); + } + + ngOnDestroy() { + this.binaryFileListSubscription.unsubscribe(); } } diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html index 70054de869..33eab42685 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html @@ -24,10 +24,5 @@ --> <div [binaryFileListOrientation]="listOrientation"> - <alfa-binary-file2-container - *ngFor="let binaryFile of binaryFileListStateResource.resource | toEmbeddedResources: binaryFileListLinkRel.FILE_LIST" - [file]="binaryFile" - [deletable]="false" - > - </alfa-binary-file2-container> + <alfa-binary-file2-container *ngFor="let binaryFile of binaryFileList" [file]="binaryFile" [deletable]="false" /> </div> diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts index fbbc820600..c3206eec76 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts @@ -21,11 +21,11 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFileListResource, BinaryFileResource } from '@alfa-client/binary-file-shared'; -import { createStateResource, StateResource, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared'; +import { BinaryFileResource } from '@alfa-client/binary-file-shared'; +import { ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared'; import { getMockComponent } from '@alfa-client/test-utils'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { createBinaryFileListResource, createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; +import { createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; import { MockComponent, MockDirective } from 'ng-mocks'; import { BinaryFile2ContainerComponent } from '../../binary-file2-container/binary-file2-container.component'; import { BinaryFileListOrientationDirective } from '../../directive/binary-file-list-orientation/binary-file-list-orientation.directive'; @@ -36,9 +36,6 @@ describe('BinaryFileListComponent', () => { let fixture: ComponentFixture<BinaryFileListComponent>; const binaryFile: BinaryFileResource = createBinaryFileResource(); - const binaryFileListStateResource: StateResource<BinaryFileListResource> = createStateResource( - createBinaryFileListResource([binaryFile]), - ); beforeEach(async () => { await TestBed.configureTestingModule({ @@ -52,7 +49,7 @@ describe('BinaryFileListComponent', () => { fixture = TestBed.createComponent(BinaryFileListComponent); component = fixture.componentInstance; - component.binaryFileListStateResource = binaryFileListStateResource; + component.binaryFileList = [binaryFile]; fixture.detectChanges(); }); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.ts index f0ddb94034..7d7e50bb09 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.ts @@ -21,8 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFileListLinkRel, BinaryFileListResource } from '@alfa-client/binary-file-shared'; -import { StateResource } from '@alfa-client/tech-shared'; +import { BinaryFile } from '@alfa-client/binary-file-shared'; import { Component, Input } from '@angular/core'; import { BinaryFileListOrientation } from '../../directive/binary-file-list-orientation/binary-file-list-orientation.directive'; @@ -31,8 +30,6 @@ import { BinaryFileListOrientation } from '../../directive/binary-file-list-orie templateUrl: './binary-file-list.component.html', }) export class BinaryFileListComponent { - @Input() public binaryFileListStateResource: StateResource<BinaryFileListResource>; + @Input() public binaryFileList: BinaryFile[]; @Input() listOrientation: BinaryFileListOrientation = BinaryFileListOrientation.HORIZONTAL; - - public readonly binaryFileListLinkRel = BinaryFileListLinkRel; } -- GitLab From dd46632854d0a04bed851ef7b180d95d67b1af33 Mon Sep 17 00:00:00 2001 From: Alexander Reifschneider <alexander.reifschneider@mgm-tp.com> Date: Mon, 3 Mar 2025 11:51:48 +0100 Subject: [PATCH 3/4] Revert "OZG-5977 hide file container on empty content" This reverts commit b8499321bb675ec86e560630159fcb54c3f6dcab. --- .../binary-file-list-container.component.html | 11 ++++--- ...nary-file-list-container.component.spec.ts | 31 ++++--------------- .../binary-file-list-container.component.ts | 27 +++++----------- .../binary-file-list.component.html | 7 ++++- .../binary-file-list.component.spec.ts | 11 ++++--- .../binary-file-list.component.ts | 7 +++-- 6 files changed, 38 insertions(+), 56 deletions(-) diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html index a5d3d8ee19..cfa93fbc6b 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html @@ -23,8 +23,9 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -@if (binaryFileList) { - <ods-attachment-wrapper> - <alfa-binary-file-list [binaryFileList]="binaryFileList" [listOrientation]="listOrientation" /> - </ods-attachment-wrapper> -} +<ods-attachment-wrapper> + <alfa-binary-file-list + [binaryFileListStateResource]="binaryFileListStateResource$ | async" + [listOrientation]="listOrientation" + ></alfa-binary-file-list> +</ods-attachment-wrapper> diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts index 885d5d27a6..e9473e9ee4 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts @@ -42,11 +42,9 @@ describe('BinaryFileListContainerComponent', () => { const binaryFileService: Mock<BinaryFileService> = mock(BinaryFileService); - const fileList: Resource[] = []; - const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource({ - ...createBinaryFileResource(), - _embedded: { ozgFileList: fileList }, - }); + const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource( + createBinaryFileResource(), + ); const resource: Resource = createDummyResource(); const linkRel: LinkRelationName = DummyLinkRel.DUMMY; @@ -83,31 +81,14 @@ describe('BinaryFileListContainerComponent', () => { expect(binaryFileService.getFiles).toHaveBeenCalledWith(resource, linkRel); }); - - it('should NOT set binaryFileList', () => { - component.binaryFileList = null; - binaryFileService.getFiles.mockReturnValue(of(createStateResource(null))); - - component.ngOnInit(); - - expect(component.binaryFileList).toBe(null); - }); - - it('should set binaryFileList', () => { - component.ngOnInit(); - - expect(component.binaryFileList).toBe(fileList); - }); }); describe('binary file list', () => { it('should be called with binary file state resource', () => { - const binaryFileListComponent: BinaryFileListComponent = getMockComponent<BinaryFileListComponent>( - fixture, - BinaryFileListComponent, - ); + const binaryFileListComponent: BinaryFileListComponent = + getMockComponent<BinaryFileListComponent>(fixture, BinaryFileListComponent); - expect(binaryFileListComponent.binaryFileList).toBe(fileList); + expect(binaryFileListComponent.binaryFileListStateResource).toBe(binaryFileStateResource); }); }); }); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.ts index c5cc042d55..b4dce3b40b 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.ts @@ -21,38 +21,27 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFile, BinaryFileListLinkRel, BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; -import { isNotNull, LinkRelationName, StateResource } from '@alfa-client/tech-shared'; -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { getEmbeddedResource, Resource } from '@ngxp/rest'; -import { filter, Subscription } from 'rxjs'; +import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; +import { LinkRelationName, StateResource } from '@alfa-client/tech-shared'; +import { Component, Input, OnInit } from '@angular/core'; +import { Resource } from '@ngxp/rest'; +import { Observable } from 'rxjs'; import { BinaryFileListOrientation } from '../directive/binary-file-list-orientation/binary-file-list-orientation.directive'; @Component({ selector: 'alfa-binary-file-list-container', templateUrl: './binary-file-list-container.component.html', }) -export class BinaryFileListContainerComponent implements OnInit, OnDestroy { +export class BinaryFileListContainerComponent implements OnInit { @Input() resource: Resource; @Input() linkRel: LinkRelationName; @Input() listOrientation: BinaryFileListOrientation = BinaryFileListOrientation.HORIZONTAL; - public binaryFileList: BinaryFile[]; - public readonly binaryFileListLinkRel = BinaryFileListLinkRel; - binaryFileListSubscription: Subscription; + public binaryFileListStateResource$: Observable<StateResource<BinaryFileListResource>>; constructor(private service: BinaryFileService) {} ngOnInit(): void { - this.binaryFileListSubscription = this.service - .getFiles(this.resource, this.linkRel) - .pipe(filter((stateResource) => isNotNull(stateResource.resource))) - .subscribe((stateResource: StateResource<BinaryFileListResource>) => { - this.binaryFileList = getEmbeddedResource(stateResource.resource, this.binaryFileListLinkRel.FILE_LIST); - }); - } - - ngOnDestroy() { - this.binaryFileListSubscription.unsubscribe(); + this.binaryFileListStateResource$ = this.service.getFiles(this.resource, this.linkRel); } } diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html index 33eab42685..70054de869 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html @@ -24,5 +24,10 @@ --> <div [binaryFileListOrientation]="listOrientation"> - <alfa-binary-file2-container *ngFor="let binaryFile of binaryFileList" [file]="binaryFile" [deletable]="false" /> + <alfa-binary-file2-container + *ngFor="let binaryFile of binaryFileListStateResource.resource | toEmbeddedResources: binaryFileListLinkRel.FILE_LIST" + [file]="binaryFile" + [deletable]="false" + > + </alfa-binary-file2-container> </div> diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts index c3206eec76..fbbc820600 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts @@ -21,11 +21,11 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFileResource } from '@alfa-client/binary-file-shared'; -import { ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared'; +import { BinaryFileListResource, BinaryFileResource } from '@alfa-client/binary-file-shared'; +import { createStateResource, StateResource, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared'; import { getMockComponent } from '@alfa-client/test-utils'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; +import { createBinaryFileListResource, createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; import { MockComponent, MockDirective } from 'ng-mocks'; import { BinaryFile2ContainerComponent } from '../../binary-file2-container/binary-file2-container.component'; import { BinaryFileListOrientationDirective } from '../../directive/binary-file-list-orientation/binary-file-list-orientation.directive'; @@ -36,6 +36,9 @@ describe('BinaryFileListComponent', () => { let fixture: ComponentFixture<BinaryFileListComponent>; const binaryFile: BinaryFileResource = createBinaryFileResource(); + const binaryFileListStateResource: StateResource<BinaryFileListResource> = createStateResource( + createBinaryFileListResource([binaryFile]), + ); beforeEach(async () => { await TestBed.configureTestingModule({ @@ -49,7 +52,7 @@ describe('BinaryFileListComponent', () => { fixture = TestBed.createComponent(BinaryFileListComponent); component = fixture.componentInstance; - component.binaryFileList = [binaryFile]; + component.binaryFileListStateResource = binaryFileListStateResource; fixture.detectChanges(); }); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.ts index 7d7e50bb09..f0ddb94034 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.ts @@ -21,7 +21,8 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFile } from '@alfa-client/binary-file-shared'; +import { BinaryFileListLinkRel, BinaryFileListResource } from '@alfa-client/binary-file-shared'; +import { StateResource } from '@alfa-client/tech-shared'; import { Component, Input } from '@angular/core'; import { BinaryFileListOrientation } from '../../directive/binary-file-list-orientation/binary-file-list-orientation.directive'; @@ -30,6 +31,8 @@ import { BinaryFileListOrientation } from '../../directive/binary-file-list-orie templateUrl: './binary-file-list.component.html', }) export class BinaryFileListComponent { - @Input() public binaryFileList: BinaryFile[]; + @Input() public binaryFileListStateResource: StateResource<BinaryFileListResource>; @Input() listOrientation: BinaryFileListOrientation = BinaryFileListOrientation.HORIZONTAL; + + public readonly binaryFileListLinkRel = BinaryFileListLinkRel; } -- GitLab From efd1356af8df5c281e6d30635d04f3c6fd522206 Mon Sep 17 00:00:00 2001 From: Alexander Reifschneider <alexander.reifschneider@mgm-tp.com> Date: Mon, 3 Mar 2025 14:41:15 +0100 Subject: [PATCH 4/4] OZG-5977 move wrapper to binary file component --- .../binary-file-list-container.component.html | 10 +++--- ...nary-file-list-container.component.spec.ts | 18 ++++------- .../binary-file-list.component.html | 18 ++++++----- .../binary-file-list.component.spec.ts | 31 ++++++++++++++++--- 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html index cfa93fbc6b..de2d67af94 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html @@ -23,9 +23,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ods-attachment-wrapper> - <alfa-binary-file-list - [binaryFileListStateResource]="binaryFileListStateResource$ | async" - [listOrientation]="listOrientation" - ></alfa-binary-file-list> -</ods-attachment-wrapper> +<alfa-binary-file-list + [binaryFileListStateResource]="binaryFileListStateResource$ | async" + [listOrientation]="listOrientation" +></alfa-binary-file-list> diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts index e9473e9ee4..6cca0983e8 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts @@ -34,27 +34,19 @@ import { of } from 'rxjs'; import { BinaryFileListContainerComponent } from './binary-file-list-container.component'; import { BinaryFileListComponent } from './binary-file-list/binary-file-list.component'; -import { AttachmentWrapperComponent } from '@ods/system'; - describe('BinaryFileListContainerComponent', () => { let component: BinaryFileListContainerComponent; let fixture: ComponentFixture<BinaryFileListContainerComponent>; const binaryFileService: Mock<BinaryFileService> = mock(BinaryFileService); - const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource( - createBinaryFileResource(), - ); + const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource()); const resource: Resource = createDummyResource(); const linkRel: LinkRelationName = DummyLinkRel.DUMMY; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ - BinaryFileListContainerComponent, - MockComponent(BinaryFileListComponent), - MockComponent(AttachmentWrapperComponent), - ], + declarations: [BinaryFileListContainerComponent, MockComponent(BinaryFileListComponent)], providers: [ { provide: BinaryFileService, @@ -85,8 +77,10 @@ describe('BinaryFileListContainerComponent', () => { describe('binary file list', () => { it('should be called with binary file state resource', () => { - const binaryFileListComponent: BinaryFileListComponent = - getMockComponent<BinaryFileListComponent>(fixture, BinaryFileListComponent); + const binaryFileListComponent: BinaryFileListComponent = getMockComponent<BinaryFileListComponent>( + fixture, + BinaryFileListComponent, + ); expect(binaryFileListComponent.binaryFileListStateResource).toBe(binaryFileStateResource); }); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html index 70054de869..a4ee6adc69 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html @@ -23,11 +23,13 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div [binaryFileListOrientation]="listOrientation"> - <alfa-binary-file2-container - *ngFor="let binaryFile of binaryFileListStateResource.resource | toEmbeddedResources: binaryFileListLinkRel.FILE_LIST" - [file]="binaryFile" - [deletable]="false" - > - </alfa-binary-file2-container> -</div> +@if (binaryFileListStateResource.resource | toEmbeddedResources: binaryFileListLinkRel.FILE_LIST; as binaryFileList) { + @if (binaryFileList.length) { + <ods-attachment-wrapper data-test-id="binary-file-list-wrapper"> + <div [binaryFileListOrientation]="listOrientation"> + <alfa-binary-file2-container *ngFor="let binaryFile of binaryFileList" [file]="binaryFile" [deletable]="false"> + </alfa-binary-file2-container> + </div> + </ods-attachment-wrapper> + } +} diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts index fbbc820600..354a9d2be5 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts @@ -23,9 +23,11 @@ */ import { BinaryFileListResource, BinaryFileResource } from '@alfa-client/binary-file-shared'; import { createStateResource, StateResource, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared'; -import { getMockComponent } from '@alfa-client/test-utils'; +import { existsAsHtmlElement, getMockComponent, notExistsAsHtmlElement } from '@alfa-client/test-utils'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { AttachmentWrapperComponent } from '@ods/system'; import { createBinaryFileListResource, createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; +import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent, MockDirective } from 'ng-mocks'; import { BinaryFile2ContainerComponent } from '../../binary-file2-container/binary-file2-container.component'; import { BinaryFileListOrientationDirective } from '../../directive/binary-file-list-orientation/binary-file-list-orientation.directive'; @@ -36,9 +38,11 @@ describe('BinaryFileListComponent', () => { let fixture: ComponentFixture<BinaryFileListComponent>; const binaryFile: BinaryFileResource = createBinaryFileResource(); - const binaryFileListStateResource: StateResource<BinaryFileListResource> = createStateResource( - createBinaryFileListResource([binaryFile]), - ); + function getBinaryFileListStateResource(binaryFiles: BinaryFileResource[]): StateResource<BinaryFileListResource> { + return createStateResource(createBinaryFileListResource(binaryFiles)); + } + + const wrapperSelector: string = getDataTestIdOf('binary-file-list-wrapper'); beforeEach(async () => { await TestBed.configureTestingModule({ @@ -46,13 +50,14 @@ describe('BinaryFileListComponent', () => { BinaryFileListComponent, ToEmbeddedResourcesPipe, MockComponent(BinaryFile2ContainerComponent), + MockComponent(AttachmentWrapperComponent), MockDirective(BinaryFileListOrientationDirective), ], }).compileComponents(); fixture = TestBed.createComponent(BinaryFileListComponent); component = fixture.componentInstance; - component.binaryFileListStateResource = binaryFileListStateResource; + component.binaryFileListStateResource = getBinaryFileListStateResource([binaryFile]); fixture.detectChanges(); }); @@ -60,6 +65,22 @@ describe('BinaryFileListComponent', () => { expect(component).toBeTruthy(); }); + describe('template', () => { + describe('attachment wrapper', () => { + it('should show', () => { + existsAsHtmlElement(fixture, wrapperSelector); + }); + + it('should hide', () => { + component.binaryFileListStateResource = getBinaryFileListStateResource([]); + + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, wrapperSelector); + }); + }); + }); + describe('binary file container', () => { it('should be called with file', () => { const binaryFileContainerComponent: BinaryFile2ContainerComponent = getMockComponent<BinaryFile2ContainerComponent>( -- GitLab