feature(filuppladdning): Informativ rapport med bilaga. (TV-874)

Merge in TEA/mina-sidor-fa-web from feature/TV-874-fe-lagg-till-mojlighet-att-lagga-upp-fil-och-synka-med-be to develop

Squashed commit of the following:

commit 2fdc27affebd4310fa432830ae4e2cf19a3669e9
Merge: 2706cd4e 609698eb
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Tue Nov 30 08:29:48 2021 +0100

    Merge branch 'develop' into feature/TV-874-fe-lagg-till-mojlighet-att-lagga-upp-fil-och-synka-med-be

commit 2706cd4e61b497b50d82518bdfd5e5c310dcc7aa
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Mon Nov 29 13:33:24 2021 +0100

    Added uploaded file to submitData

commit aa477af83df371e7701885aed7418a283fcf0a2d
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Mon Nov 29 10:12:34 2021 +0100

    Amends

commit 8c36a32e3d5f9c7d9530959d341d1ebf3e41be9d
Merge: b49a06f3 85f398ca
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Fri Nov 26 10:28:19 2021 +0100

    Merge branch 'develop' into feature/TV-874-fe-lagg-till-mojlighet-att-lagga-upp-fil-och-synka-med-be

commit b49a06f36616f2b49b62f66dfc53fb5ee7572273
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Wed Nov 24 09:39:42 2021 +0100

    Laddningssnurra för informativ rapport

commit 1fb6b51af5325a199b86630a12769ab3ac00f70c
Merge: c516a91b f0354d0a
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Mon Nov 22 14:17:14 2021 +0100

    - Merge branch 'develop' into feature/TV-874-fe-lagg-till-mojlighet-att-lagga-upp-fil-och-synka-med-be
    - Added label text to ui-select to prevent digi-core warning in console and added display:none; to hide it.

commit c516a91b8f2aabca7e2393f2ccb997447be5bedf
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Mon Nov 22 13:57:55 2021 +0100

    Prettier, changed in-parameter type.

commit d78e8e867ca3b632e86669af1780b5e5249eacd2
Merge: 1aa96b52 a0d10765
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Mon Nov 15 09:57:13 2021 +0100

    Merge branch 'develop' into feature/TV-874-fe-lagg-till-mojlighet-att-lagga-upp-fil-och-synka-med-be

commit 1aa96b5275115f0d60d0c0637b34bfc3174a4b34
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Fri Nov 12 11:20:51 2021 +0100

    - Reset package-lock.json
    - Changed type from unknown to file

commit abae56f4e3b9803552d2028f3c55184662181b22
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Fri Nov 12 11:13:35 2021 +0100

    File-upload

commit b1bc6f931a6fd043573a57cf489cf964796e2943
Merge: 5fe8cace 873b6a0c
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Wed Nov 10 12:49:57 2021 +0100

    Merge branch 'develop' into feature/TV-874-fe-lagg-till-mojlighet-att-lagga-upp-fil-och-synka-med-be

commit 5fe8cace262a75b75e4bebde6fa4c3effb11e39f
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Tue Nov 9 14:21:24 2021 +0100

    - Fortsatt utveckling av filuppladdaren
    - Byt alla af till ui, digi-ng referenser till digi-core/projektets
    - Ersätt digiNgFormValidatioMmesage till digi-cores
    - Validering (Måste ha fil) (funkar inte riktigt ännu då valideringens sker på alla kategorier eftersom den finns i modellen.

commit bda789b4451983ad69ab6c05a3bad1723b438c2d
Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se>
Date:   Mon Nov 1 16:40:16 2021 +0100

    File-upload
This commit is contained in:
Nikola Holst Nikolic
2021-11-30 08:33:55 +01:00
parent 609698eb4e
commit af4f6cbefc
12 changed files with 855 additions and 324 deletions

View File

@@ -0,0 +1,52 @@
<div class="ui-file-upload">
<digi-form-label
class="ui-file-upload__label"
[afFor]="uiId"
[afLabel]="uiLabel"
[afRequired]="uiRequired"
[afDescription]="uiLabelDescription"
[afAnnounceIfOptional]="uiAnnounceIfOptional"
></digi-form-label>
<digi-button
*ngIf="uiMultiple || files.length < 1"
af-variation="secondary"
[afAriaLabel]="uploadBtnAriaLabel"
(afOnClick)="fileInput.click()"
>
{{ uiUploadBtnText }}
<ui-icon [uiType]="iconType.PAPERCLIP" slot="icon"></ui-icon>
<input
#fileInput
(change)="onUploadFileHandler($event)"
[id]="uiId"
class="ui-file-upload__input"
[attr.multiple]="uiMultiple"
type="file"
[attr.accept]="uiAccept"
[attr.name]="uiName"
[attr.required]="uiRequired"
/>
</digi-button>
<digi-form-validation-message class="ui-file-upload__validation-message" *ngIf="uiInvalid" af-variation="error">
{{ this.uiInvalidMessage }}
</digi-form-validation-message>
<p class="ui-file-upload__status-message" #statusMessage aria-live="polite"></p>
<dl *ngIf="files.length" class="ui-file-upload__file-row-container">
<dt>
<h2 class="msfa__a11y-sr-only">Uppladdade filer</h2>
</dt>
<dd *ngFor="let file of files" class="ui-file-upload__file-row">
<p class="ui-file-upload__file-name">{{ file.name }}</p>
<digi-button
(afOnClick)="onRemoveFileHandler(file['id'])"
class="ui-file-upload__file-row-btn"
[afAriaLabel]="'Ta bort ' + file.name"
af-size="s"
af-variation="secondary"
>
<ui-icon size="m" class="ui-file-upload__icon-remove" [icon]="iconType.X" slot="icon"></ui-icon>
Ta bort
</digi-button>
</dd>
</dl>
</div>

View File

@@ -0,0 +1,61 @@
@import 'variables/gutters';
$ui__color--gray-20: #efefef;
.ui-file-upload {
&__label {
::ng-deep .digi-form-label {
margin-bottom: $digi--layout--gutter--s;
margin-top: $digi--layout--gutter--m;
}
}
&__file-row {
display: inline-flex;
width: 100%;
margin-bottom: $digi--layout--gutter;
}
&__input {
display: none;
}
&__file-row-container {
margin-bottom: 0;
margin-top: $digi--layout--gutter--l;
}
&__file-name {
font-family: var(--digi--typography--font-family);
flex: 1;
background-color: $ui__color--gray-20;
color: var(--digi--typography--color--text);
max-width: u(60);
padding: u(1);
font-weight: var(--digi--typography--font-weight--semibold);
margin-right: u(1.6);
margin-bottom: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&__status-message {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
&__icon-remove {
--digi--ui--width--icon: 100%;
}
&__validation-message {
display: block;
margin-top: var(--digi--layout--gutter--s);
}
}

View File

@@ -0,0 +1,190 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
Input,
Output,
ViewChild,
} from '@angular/core';
import { randomIdGenerator } from '@digi/core/dist/collection/global/utils/randomIdGenerator';
import { UiIconType } from '@ui/icon/icon-type.enum';
/**
* This component is used for uploading files. It restyles an input type file and emits events when a file is added or
* removed. It is up to the implementor to actually save the file to a backend.
*/
@Component({
selector: 'ui-file-upload',
templateUrl: './file-upload.component.html',
styleUrls: ['./file-upload.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FileUploadComponent {
iconType = UiIconType;
/**
* Label for button
*/
@Input() uiUploadBtnText = 'Välj filer';
/**
* If multiple file upload
*/
@Input() uiMultiple = false;
/**
* UiHeader is used to set the header to the component
*/
@Input() uiLabel?: string;
/**
* If invalid
*/
@Input() uiInvalid = false;
/**
* UiText is used to set the information text
*/
@Input() uiLabelDescription?: string;
/**
* ID for the input
*/
@Input() uiId: string = randomIdGenerator('ui-fileupload');
/**
* uiSecondary is to set outlined or contained variant on the button.
* Defaults to true.
*/
@Input() uiSecondary = false;
/**
* Maps directly to the input field's accept attribute. Use this to limit accepted file types.
*/
@Input() uiAccept?: string;
/**
* Maps directly to the input field's name attribute.
*/
@Input() uiName?: string;
/**
* Is this a required form field?
*/
@Input() uiRequired = false;
/**
* Max file size allowed in kb
*/
@Input() uiMaxFileSize: number;
/**
* Normally a required field is visually and semantically emphasized.
* This flips that and emphasizes the field if it is not required.
* Set this to true if your form contains more required fields than not.
*/
@Input() uiAnnounceIfOptional = false;
/**
* Invalid message
*/
@Input() uiInvalidMessage?: string;
/**
* UiOnUploadFiles is a function which emits all selected files.
*/
@Output() uiOnUploadFiles: EventEmitter<File[]> = new EventEmitter<File[]>();
/**
* UiOnRemoveFile emits when the selected file is successfully removed.
* Emits the updated array with files.
*/
@Output() uiOnRemoveFile: EventEmitter<File> = new EventEmitter<File>();
/**
* @ignore
*/
@ViewChild('fileInput') fileInput: HTMLInputElement;
/**
* @ignore
*/
@ViewChild('statusMessage') statusMessage: ElementRef;
/**
* @ignore
*/
files: File[] = [];
constructor(private changeDetector: ChangeDetectorRef) {}
/**
* @ignore
*/
onUploadFileHandler(event: any): void {
if (!event.target.files) {
return;
}
if (this.uiMaxFileSize) {
if (this.convertBytesToKb(2, event.target.files[0].size) > this.uiMaxFileSize) {
this.uiInvalid = true;
this.uiInvalidMessage = `
Filen överskrider max tillåten storlek på
${this.convertKbToMb(this.uiMaxFileSize)} MB
`;
return;
} else {
this.uiInvalid = false;
this.uiInvalidMessage = '';
}
}
this.files = [...this.files, ...event.target.files];
this.files.forEach(file => (file['id'] = randomIdGenerator('file')));
this.uiOnUploadFiles.emit(this.files);
const fileName = event.target.files[0] ? event.target.files[0].name : '';
this.updateStatusMessage('add', fileName);
}
convertBytesToKb(decimals: number, fileSize: number): number {
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const i = Math.floor(Math.log(fileSize) / Math.log(k));
return parseFloat((fileSize / Math.pow(k, i)).toFixed(dm));
}
convertKbToMb(size: number): string {
return (size / 1024).toFixed(2);
}
/**
* @ignore
*/
onRemoveFileHandler(id: string) {
const index = this.files.findIndex(file => file['id'] === id);
if (index === -1) {
return;
}
const fileToRemove = this.files[index];
this.files = [...this.files.slice(0, index), ...this.files.slice(index + 1)];
this.uiOnRemoveFile.emit(fileToRemove);
this.changeDetector.detectChanges();
this.updateStatusMessage('remove');
}
/**
* @ignore
*/
updateStatusMessage(type: string, fileName: string = '') {
const statusMessage = this.statusMessage.nativeElement;
statusMessage.textContent = '';
setTimeout(() => {
switch (type) {
case 'remove':
statusMessage.textContent =
this.files.length > 0 ? 'Fil borttagen' : 'Fil borttagen. Du har inga filer uppladdade';
break;
case 'add':
statusMessage.textContent = `Fil uppladdad ${fileName}`;
break;
default:
statusMessage.textContent = '';
}
}, 50);
}
/**
* @ignore
*/
get uploadBtnAriaLabel() {
return this.files.length > 0 && this.uiMultiple ? 'Välj ny fil' : 'Välj fil';
}
}

View File

@@ -0,0 +1,15 @@
import { CommonModule } from '@angular/common';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FileUploadComponent } from './file-upload.component';
import { UiIconModule } from '@ui/icon/icon.module';
const COMPONENTS = [FileUploadComponent];
const MODULES = [CommonModule];
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
imports: [...MODULES, UiIconModule],
declarations: [...COMPONENTS],
exports: [...COMPONENTS],
})
export class UiFileUploadModule {}

View File

@@ -22,4 +22,5 @@ export enum UiIconType {
EYE = 'eye',
EYESLASH = 'eyeslash',
ARCHIVE = 'archive',
PAPERCLIP = 'paperclip'
}

View File

@@ -99,5 +99,6 @@
<digi-icon-eye *ngSwitchCase="iconType.EYE" [ngClass]="iconClass"></digi-icon-eye>
<digi-icon-eye-slash *ngSwitchCase="iconType.EYESLASH" [ngClass]="iconClass"></digi-icon-eye-slash>
<digi-icon-archive *ngSwitchCase="iconType.ARCHIVE" [ngClass]="iconClass"></digi-icon-archive>
<digi-icon-paperclip *ngSwitchCase="iconType.PAPERCLIP" [ngClass]="iconClass"></digi-icon-paperclip>
</ng-container>
</ng-template>