@acpaas-ui/ngx-forms 6.1.8 → 6.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +42 -0
- package/LICENSE.md +21 -0
- package/dist/README.md +23 -0
- package/dist/esm2020/lib/auto-complete/auto-complete.module.mjs +23 -0
- package/dist/esm2020/lib/auto-complete/components/auto-complete/auto-complete.component.mjs +265 -0
- package/dist/esm2020/lib/datepicker/components/datepicker/datepicker.component.mjs +232 -0
- package/dist/esm2020/lib/datepicker/datepicker.module.mjs +54 -0
- package/dist/esm2020/lib/range-slider/components/range-slider/range-slider.component.mjs +297 -0
- package/dist/esm2020/lib/range-slider/range-slider.module.mjs +19 -0
- package/dist/esm2020/lib/search-filter/components/search-filter/search-filter.component.mjs +149 -0
- package/dist/esm2020/lib/search-filter/search-filter.module.mjs +21 -0
- package/{esm2020 → dist/esm2020}/lib/shared/services/search.service.mjs +6 -6
- package/dist/esm2020/lib/timepicker/components/timepicker/timepicker.component.mjs +130 -0
- package/dist/esm2020/lib/timepicker/timepicker.module.mjs +21 -0
- package/dist/esm2020/lib/upload/components/upload/upload.component.mjs +69 -0
- package/dist/esm2020/lib/upload/components/upload-input/upload-input.component.mjs +39 -0
- package/dist/esm2020/lib/upload/components/upload-queue/upload-queue.component.mjs +42 -0
- package/dist/esm2020/lib/upload/components/upload-zone/upload-zone.component.mjs +143 -0
- package/dist/esm2020/lib/upload/components/validation-list/validation-list.component.mjs +33 -0
- package/dist/esm2020/lib/upload/services/validation-messages.service.mjs +29 -0
- package/dist/esm2020/lib/upload/upload.module.mjs +44 -0
- package/{fesm2015 → dist/fesm2015}/acpaas-ui-ngx-forms.mjs +141 -994
- package/dist/fesm2015/acpaas-ui-ngx-forms.mjs.map +1 -0
- package/dist/fesm2020/acpaas-ui-ngx-forms.mjs +1727 -0
- package/dist/fesm2020/acpaas-ui-ngx-forms.mjs.map +1 -0
- package/dist/package.json +44 -0
- package/karma.conf.js +38 -0
- package/ng-package.json +8 -0
- package/package.json +6 -30
- package/src/lib/auto-complete/README.md +148 -0
- package/src/lib/auto-complete/auto-complete.module.ts +15 -0
- package/src/lib/auto-complete/components/auto-complete/auto-complete.component.html +51 -0
- package/src/lib/auto-complete/components/auto-complete/auto-complete.component.scss +4 -0
- package/src/lib/auto-complete/components/auto-complete/auto-complete.component.spec.ts +378 -0
- package/src/lib/auto-complete/components/auto-complete/auto-complete.component.ts +281 -0
- package/src/lib/auto-complete/public-api.ts +2 -0
- package/src/lib/datepicker/README.md +110 -0
- package/src/lib/datepicker/components/datepicker/datepicker.component.html +47 -0
- package/src/lib/datepicker/components/datepicker/datepicker.component.scss +13 -0
- package/src/lib/datepicker/components/datepicker/datepicker.component.spec.ts +204 -0
- package/src/lib/datepicker/components/datepicker/datepicker.component.ts +251 -0
- package/src/lib/datepicker/datepicker.conf.ts +11 -0
- package/src/lib/datepicker/datepicker.module.ts +50 -0
- package/src/lib/datepicker/public-api.ts +8 -0
- package/src/lib/datepicker/types/datepicker.types.ts +8 -0
- package/src/lib/range-slider/README.md +56 -0
- package/src/lib/range-slider/components/range-slider/range-slider.component.html +46 -0
- package/src/lib/range-slider/components/range-slider/range-slider.component.scss +12 -0
- package/src/lib/range-slider/components/range-slider/range-slider.component.spec.ts +216 -0
- package/src/lib/range-slider/components/range-slider/range-slider.component.ts +301 -0
- package/src/lib/range-slider/public-api.ts +3 -0
- package/src/lib/range-slider/range-slider.module.ts +11 -0
- package/src/lib/range-slider/types/range-slider.types.ts +4 -0
- package/src/lib/search-filter/README.md +86 -0
- package/src/lib/search-filter/components/search-filter/search-filter.component.html +66 -0
- package/src/lib/search-filter/components/search-filter/search-filter.component.scss +23 -0
- package/src/lib/search-filter/components/search-filter/search-filter.component.spec.ts +264 -0
- package/src/lib/search-filter/components/search-filter/search-filter.component.ts +140 -0
- package/src/lib/search-filter/public-api.ts +3 -0
- package/src/lib/search-filter/search-filter.module.ts +13 -0
- package/src/lib/search-filter/types/search-filter.types.ts +4 -0
- package/src/lib/shared/services/search.service.spec.ts +78 -0
- package/src/lib/shared/services/search.service.ts +32 -0
- package/src/lib/shared/types/search.types.ts +6 -0
- package/src/lib/timepicker/README.md +84 -0
- package/src/lib/timepicker/classes/timepicker.validators.spec.ts +54 -0
- package/src/lib/timepicker/classes/timepicker.validators.ts +61 -0
- package/src/lib/timepicker/components/timepicker/timepicker.component.html +37 -0
- package/src/lib/timepicker/components/timepicker/timepicker.component.scss +3 -0
- package/src/lib/timepicker/components/timepicker/timepicker.component.spec.ts +161 -0
- package/src/lib/timepicker/components/timepicker/timepicker.component.ts +128 -0
- package/src/lib/timepicker/public-api.ts +4 -0
- package/src/lib/timepicker/timepicker.module.ts +13 -0
- package/src/lib/timepicker/types/timepicker.types.ts +5 -0
- package/src/lib/upload/README.md +283 -0
- package/src/lib/upload/classes/uploader.class.spec.ts +100 -0
- package/src/lib/upload/classes/uploader.class.ts +144 -0
- package/src/lib/upload/components/upload/upload.component.html +28 -0
- package/src/lib/upload/components/upload/upload.component.scss +3 -0
- package/src/lib/upload/components/upload/upload.component.spec.ts +117 -0
- package/src/lib/upload/components/upload/upload.component.ts +50 -0
- package/src/lib/upload/components/upload-input/upload-input.component.html +11 -0
- package/src/lib/upload/components/upload-input/upload-input.component.spec.ts +55 -0
- package/src/lib/upload/components/upload-input/upload-input.component.ts +35 -0
- package/src/lib/upload/components/upload-queue/upload-queue.component.html +16 -0
- package/src/lib/upload/components/upload-queue/upload-queue.component.spec.ts +99 -0
- package/src/lib/upload/components/upload-queue/upload-queue.component.ts +36 -0
- package/src/lib/upload/components/upload-zone/upload-zone.component.html +55 -0
- package/src/lib/upload/components/upload-zone/upload-zone.component.scss +3 -0
- package/src/lib/upload/components/upload-zone/upload-zone.component.spec.ts +144 -0
- package/src/lib/upload/components/upload-zone/upload-zone.component.ts +142 -0
- package/src/lib/upload/components/validation-list/validation-list.component.html +15 -0
- package/src/lib/upload/components/validation-list/validation-list.component.spec.ts +57 -0
- package/src/lib/upload/components/validation-list/validation-list.component.ts +29 -0
- package/src/lib/upload/public-api.ts +10 -0
- package/src/lib/upload/services/validation-messages.service.spec.ts +66 -0
- package/src/lib/upload/services/validation-messages.service.ts +27 -0
- package/src/lib/upload/types/upload.types.ts +20 -0
- package/src/lib/upload/upload.conf.ts +15 -0
- package/src/lib/upload/upload.module.ts +34 -0
- package/src/public-api.ts +6 -0
- package/src/test.ts +9 -0
- package/tsconfig.lib.json +26 -0
- package/tsconfig.spec.json +17 -0
- package/esm2020/lib/auto-complete/auto-complete.module.mjs +0 -24
- package/esm2020/lib/auto-complete/components/auto-complete/auto-complete.component.mjs +0 -347
- package/esm2020/lib/datepicker/components/datepicker/datepicker.component.mjs +0 -308
- package/esm2020/lib/datepicker/datepicker.module.mjs +0 -55
- package/esm2020/lib/range-slider/components/range-slider/range-slider.component.mjs +0 -349
- package/esm2020/lib/range-slider/range-slider.module.mjs +0 -20
- package/esm2020/lib/search-filter/components/search-filter/search-filter.component.mjs +0 -266
- package/esm2020/lib/search-filter/search-filter.module.mjs +0 -22
- package/esm2020/lib/timepicker/components/timepicker/timepicker.component.mjs +0 -243
- package/esm2020/lib/timepicker/timepicker.module.mjs +0 -22
- package/esm2020/lib/upload/components/upload/upload.component.mjs +0 -97
- package/esm2020/lib/upload/components/upload-input/upload-input.component.mjs +0 -56
- package/esm2020/lib/upload/components/upload-queue/upload-queue.component.mjs +0 -78
- package/esm2020/lib/upload/components/upload-zone/upload-zone.component.mjs +0 -252
- package/esm2020/lib/upload/components/validation-list/validation-list.component.mjs +0 -64
- package/esm2020/lib/upload/services/validation-messages.service.mjs +0 -29
- package/esm2020/lib/upload/upload.module.mjs +0 -45
- package/fesm2015/acpaas-ui-ngx-forms.mjs.map +0 -1
- package/fesm2020/acpaas-ui-ngx-forms.mjs +0 -2394
- package/fesm2020/acpaas-ui-ngx-forms.mjs.map +0 -1
- /package/{esm2020 → dist/esm2020}/acpaas-ui-ngx-forms.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/auto-complete/public-api.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/datepicker/datepicker.conf.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/datepicker/public-api.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/datepicker/types/datepicker.types.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/range-slider/public-api.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/range-slider/types/range-slider.types.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/search-filter/public-api.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/search-filter/types/search-filter.types.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/shared/types/search.types.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/timepicker/classes/timepicker.validators.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/timepicker/public-api.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/timepicker/types/timepicker.types.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/upload/classes/uploader.class.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/upload/public-api.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/upload/types/upload.types.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/lib/upload/upload.conf.mjs +0 -0
- /package/{esm2020 → dist/esm2020}/public-api.mjs +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{lib → dist/lib}/auto-complete/auto-complete.module.d.ts +0 -0
- /package/{lib → dist/lib}/auto-complete/components/auto-complete/auto-complete.component.d.ts +0 -0
- /package/{lib → dist/lib}/auto-complete/public-api.d.ts +0 -0
- /package/{lib → dist/lib}/datepicker/components/datepicker/datepicker.component.d.ts +0 -0
- /package/{lib → dist/lib}/datepicker/datepicker.conf.d.ts +0 -0
- /package/{lib → dist/lib}/datepicker/datepicker.module.d.ts +0 -0
- /package/{lib → dist/lib}/datepicker/public-api.d.ts +0 -0
- /package/{lib → dist/lib}/datepicker/types/datepicker.types.d.ts +0 -0
- /package/{lib → dist/lib}/range-slider/components/range-slider/range-slider.component.d.ts +0 -0
- /package/{lib → dist/lib}/range-slider/public-api.d.ts +0 -0
- /package/{lib → dist/lib}/range-slider/range-slider.module.d.ts +0 -0
- /package/{lib → dist/lib}/range-slider/types/range-slider.types.d.ts +0 -0
- /package/{lib → dist/lib}/search-filter/components/search-filter/search-filter.component.d.ts +0 -0
- /package/{lib → dist/lib}/search-filter/public-api.d.ts +0 -0
- /package/{lib → dist/lib}/search-filter/search-filter.module.d.ts +0 -0
- /package/{lib → dist/lib}/search-filter/types/search-filter.types.d.ts +0 -0
- /package/{lib → dist/lib}/shared/services/search.service.d.ts +0 -0
- /package/{lib → dist/lib}/shared/types/search.types.d.ts +0 -0
- /package/{lib → dist/lib}/timepicker/classes/timepicker.validators.d.ts +0 -0
- /package/{lib → dist/lib}/timepicker/components/timepicker/timepicker.component.d.ts +0 -0
- /package/{lib → dist/lib}/timepicker/public-api.d.ts +0 -0
- /package/{lib → dist/lib}/timepicker/timepicker.module.d.ts +0 -0
- /package/{lib → dist/lib}/timepicker/types/timepicker.types.d.ts +0 -0
- /package/{lib → dist/lib}/upload/classes/uploader.class.d.ts +0 -0
- /package/{lib → dist/lib}/upload/components/upload/upload.component.d.ts +0 -0
- /package/{lib → dist/lib}/upload/components/upload-input/upload-input.component.d.ts +0 -0
- /package/{lib → dist/lib}/upload/components/upload-queue/upload-queue.component.d.ts +0 -0
- /package/{lib → dist/lib}/upload/components/upload-zone/upload-zone.component.d.ts +0 -0
- /package/{lib → dist/lib}/upload/components/validation-list/validation-list.component.d.ts +0 -0
- /package/{lib → dist/lib}/upload/public-api.d.ts +0 -0
- /package/{lib → dist/lib}/upload/services/validation-messages.service.d.ts +0 -0
- /package/{lib → dist/lib}/upload/types/upload.types.d.ts +0 -0
- /package/{lib → dist/lib}/upload/upload.conf.d.ts +0 -0
- /package/{lib → dist/lib}/upload/upload.module.d.ts +0 -0
- /package/{public-api.d.ts → dist/public-api.d.ts} +0 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# @acpaas-ui/ngx-forms
|
|
2
|
+
|
|
3
|
+
The upload module provides a couple of upload components and an `Uploader` class.
|
|
4
|
+
|
|
5
|
+
- `<aui-upload>` component
|
|
6
|
+
- `<aui-upload-zone>` component
|
|
7
|
+
- `<aui-upload-queue>` component
|
|
8
|
+
- `<aui-validation-list>` component
|
|
9
|
+
- `Uploader` class (non-angular service)
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { UploadModule } from '@acpaas-ui/ngx-forms';
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Add a map with error messages for the validation
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
UploadModule.forChild({
|
|
21
|
+
INVALID_FILE_TYPE: 'Ongeldig bestandstype',
|
|
22
|
+
INVALID_FILE_SIZE: 'Ongeldige bestandsgrootte',
|
|
23
|
+
INVALID_MIME_TYPE: 'Ongeldig mime type',
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Documentation
|
|
28
|
+
|
|
29
|
+
Visit our [documentation site](https://antwerp-ui.digipolis.be/) for full how-to docs and guidelines
|
|
30
|
+
|
|
31
|
+
### API
|
|
32
|
+
|
|
33
|
+
#### `<aui-upload>`
|
|
34
|
+
|
|
35
|
+
This component wraps the `upload-zone`, `upload-queue` and `validation-list`, it is recommended to use this component instead of the individual `upload-zone` and `upload-queue` but it's not required.
|
|
36
|
+
|
|
37
|
+
| Name | Default value | Description |
|
|
38
|
+
| ------------------------------------------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
39
|
+
| `@Input() options: UploadOptions;` | `UPLOAD_OPTIONS_DEFAULT` | An instance of the UploadOptions interface that is part of the Uploader class. Its different options and there default values that are defined in `UPLOAD_OPTIONS_DEFAULT` are explained in detail below. |
|
|
40
|
+
| `@Input() data-id: string;` | `''` | An id that can be used in combination with a label's for attribute. |
|
|
41
|
+
| `@Input() ariaLabelRemove: string;` | `'Verwijder'` | The 'delete' text that is used for screenreaders. |
|
|
42
|
+
| `@Input() disabled: boolean;` | `false` | Optional attribute to set the upload and the upload zone disabled. |
|
|
43
|
+
| `@Input() multiple: boolean;` | `true` | Optional attribute to restrict the number of uploaded files to be selected. |
|
|
44
|
+
| `@Input() accept: boolean;` | `true` | Optional accept attribute to define the type of files that can be selected. |
|
|
45
|
+
| `@Output() selectUploadedFiles: EventEmitter<Object[]>` | - | On a successful upload, this will emit the response of the backend. This should be an array of objects with the uploaded filename and url. |
|
|
46
|
+
|
|
47
|
+
#### `<aui-upload-zone>`
|
|
48
|
+
|
|
49
|
+
This component provides the upload functionality.
|
|
50
|
+
|
|
51
|
+
| Name | Default value | Description |
|
|
52
|
+
| ------------------------------------------------------ | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
53
|
+
| `@Input() uploader: Uploader;` | - | An instance of the Uploader class. This class handles the validation and upload of a file. Its different options and there default values that are defined in `UPLOAD_OPTIONS_DEFAULT` are explained in detail below. |
|
|
54
|
+
| `@Input() multiple: boolean;` | `true` | Enable the HTML `multiple` attribute so the user can select multiple files to upload. |
|
|
55
|
+
| `@Input() id: string;` | `''` | An id that can be used in combination with a label's for attribute. |
|
|
56
|
+
| `@Input() ariaId: string;` | `[random id when no id was given]` | An id that can be used when you don't want a visible label. |
|
|
57
|
+
| `@Input() disabled: boolean;` | `false` | Optional attribute to set the upload zone disabled. |
|
|
58
|
+
| `@Input() multiple: boolean;` | `true` | Optional attribute to restrict the number of uploaded files to be selected. |
|
|
59
|
+
| `@Input() accept: boolean;` | `true` | Optional accept attribute to define the type of files that can be selected. |
|
|
60
|
+
| `@Output() uploadedFiles: EventEmitter<Object[]>;` | - | Emits an array of files that were uploaded. |
|
|
61
|
+
| `@Output() queuedFiles: EventEmitter<File[]>;` | - | Emits an array of file objects that have past the validation and are ready to be uploaded. |
|
|
62
|
+
| `@Output() invalidFiles: EventEmitter<InvalidFile[]>;` | - | Emits an array of invalid files and the reason why they are invalid. |
|
|
63
|
+
|
|
64
|
+
#### `<aui-upload-queue>`
|
|
65
|
+
|
|
66
|
+
This component provides a list of queued files.
|
|
67
|
+
|
|
68
|
+
| Name | Default value | Description |
|
|
69
|
+
| ------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
70
|
+
| `@Input() files: File[];` | - | An array of files. |
|
|
71
|
+
| `@Input() uploader: Uploader;` | - | An instance of the Uploader class. This class handles the validation and upload of a file. Its different options and there default values that are defined in `UPLOAD_OPTIONS_DEFAULT` are explained in detail below. |
|
|
72
|
+
| `@Input() ariaLabelRemove: string;` | `'Verwijder'` | The 'delete' text that is used for screenreaders. |
|
|
73
|
+
| `@Output() uploadedFiles: EventEmitter<Object[]>` | - | Emits an array of files that were uploaded. |
|
|
74
|
+
|
|
75
|
+
#### `<aui-validation-list>`
|
|
76
|
+
|
|
77
|
+
This component displays possible error messages.
|
|
78
|
+
|
|
79
|
+
| Name | Default value | Description |
|
|
80
|
+
| --------------------------------------- | ------------- | -------------------------------------------------------------- |
|
|
81
|
+
| `@Input() invalidFiles: InvalidFile[];` | `[]` | An array of invalid files and the reason why they are invalid. |
|
|
82
|
+
| `@Input() ariaLabelRemove: string;` | `'Verwijder'` | The 'delete' text that is used for screenreaders. |
|
|
83
|
+
|
|
84
|
+
#### `Uploader`
|
|
85
|
+
|
|
86
|
+
This class handles the validation and upload of a file.
|
|
87
|
+
|
|
88
|
+
##### `UploadOptions`
|
|
89
|
+
|
|
90
|
+
| Name | Default value | Description |
|
|
91
|
+
| ----------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
92
|
+
| `allowedMimeTypes: string[];` | `[]` | The MIME types that are allowed to be uploaded. |
|
|
93
|
+
| `allowedFileTypes: string[];` | `[]` | The file extensions that are allowed to be uploaded. |
|
|
94
|
+
| `autoUpload: boolean;` | `false` | Upload the file automatically without confirmation. |
|
|
95
|
+
| `maxFileSize: number;` | `0` | The maximum file size that is allowed. The value is expressed in Bytes. The value 0 equals infinite. |
|
|
96
|
+
| `queueLimit: number;` | `0` | The maximum number of files that can be selected at the same time. The value 0 equals infinite. |
|
|
97
|
+
| `type: string;` | `'drop'` | By default an upload has an `upload-zone` but with the option `'button'`, you can set it as an uploadbutton. |
|
|
98
|
+
| `url: string;` | `''` | The upload url. |
|
|
99
|
+
|
|
100
|
+
#### Example
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { UploadModule } from '@acpaas-ui/ngx-forms';
|
|
104
|
+
|
|
105
|
+
@NgModule({
|
|
106
|
+
imports: [
|
|
107
|
+
UploadModule
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
export class AppModule {};
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Basic upload**
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
public dropzone1: UploadOptions = {
|
|
118
|
+
allowedMimeTypes: ['image/jpeg'],
|
|
119
|
+
maxFileSize: 10000000,
|
|
120
|
+
queueLimit: 2,
|
|
121
|
+
type: 'drop',
|
|
122
|
+
url: 'api/upload',
|
|
123
|
+
};
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
```html
|
|
127
|
+
<aui-upload [options]="dropzone1" (selectUploadedFiles)="onUpload($event)">
|
|
128
|
+
<div class="m-upload__message">Drag your files here or click to upload</div>
|
|
129
|
+
<div class="m-upload__description">Optional description message</div>
|
|
130
|
+
</aui-upload>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Upload button**
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
public dropzone2: UploadOptions = {
|
|
137
|
+
type: 'button',
|
|
138
|
+
allowedFileTypes: ['.jpg', 'jpeg', 'png'],
|
|
139
|
+
autoUpload: true,
|
|
140
|
+
maxFileSize: 2000000,
|
|
141
|
+
url: 'api/upload',
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
```html
|
|
146
|
+
<div class="u-margin-bottom">
|
|
147
|
+
<aui-upload [options]="dropzone2" (selectUploadedFiles)="onUpload($event)">
|
|
148
|
+
<div class="m-upload__button">Select your files to upload</div>
|
|
149
|
+
</aui-upload>
|
|
150
|
+
</div>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Custom upload**
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { Uploader } from '@acpaas-ui/ngx-forms';
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
public files = [];
|
|
161
|
+
public invalidFiles: InvalidFile[] = [];
|
|
162
|
+
public queuedFiles: File[] = [];
|
|
163
|
+
public uploadedFiles: File[] = [];
|
|
164
|
+
// Pass created options into new instance of Uploader
|
|
165
|
+
public uploader = new Uploader({
|
|
166
|
+
allowedFileTypes: ['jpg', 'jpeg', 'png'],
|
|
167
|
+
type: 'drop',
|
|
168
|
+
url: 'api/upload',
|
|
169
|
+
});
|
|
170
|
+
public showError = false;
|
|
171
|
+
public fileName = '';
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
public onQueuedFiles(files: File[]) {
|
|
177
|
+
if (!files.length) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
this.queuedFiles = this.queuedFiles.concat(files);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public onUploadedFiles(files) {
|
|
184
|
+
this.uploadedFiles = this.uploadedFiles.concat(files);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public onInvalidFiles(errorFiles: InvalidFile[]) {
|
|
188
|
+
this.invalidFiles = errorFiles;
|
|
189
|
+
if (errorFiles.length > 0) {
|
|
190
|
+
this.fileName = this.invalidFiles[0]['file'].name;
|
|
191
|
+
this.showError = true;
|
|
192
|
+
this.invalidFiles = [];
|
|
193
|
+
} else {
|
|
194
|
+
this.showError = false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public reloadErrors() {
|
|
199
|
+
this.showError = false;
|
|
200
|
+
if (!this.queuedFiles.length) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Using the uploader url option
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
public uploadFiles(): void {
|
|
210
|
+
// Upload files returns an obervable
|
|
211
|
+
this.uploader.uploadFiles(this.queuedFiles).subscribe(
|
|
212
|
+
(response) => {
|
|
213
|
+
// Response has a progress property to use with a progress bar
|
|
214
|
+
if (response.progress) {
|
|
215
|
+
console.log('response.progress = ', response.progress);
|
|
216
|
+
}
|
|
217
|
+
// Response had a data property with an array of uploaded files: UploadedFile[]
|
|
218
|
+
if (response.data) {
|
|
219
|
+
console.log('response.data = ', response.data);
|
|
220
|
+
}
|
|
221
|
+
this.uploadedFiles = response.data;
|
|
222
|
+
},
|
|
223
|
+
(err) => {
|
|
224
|
+
console.log('HTTP Error', err);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Using a custom upload service
|
|
230
|
+
*/
|
|
231
|
+
|
|
232
|
+
// public uploadFiles(): void {
|
|
233
|
+
// if (!this.queuedFiles.length) {
|
|
234
|
+
// return;
|
|
235
|
+
// }
|
|
236
|
+
// this.customService.postFile(this.queuedFiles).subscribe(res => {
|
|
237
|
+
// this.result = res;
|
|
238
|
+
// }, (error) => {
|
|
239
|
+
// console.log(error);
|
|
240
|
+
// });
|
|
241
|
+
// }
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
```scss
|
|
245
|
+
::ng-deep .a-upload-queue__wrapper {
|
|
246
|
+
.a-button {
|
|
247
|
+
display: none;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
```html
|
|
253
|
+
<aui-upload-zone
|
|
254
|
+
[uploader]="uploader"
|
|
255
|
+
(queuedFiles)="onQueuedFiles($event)"
|
|
256
|
+
(uploadedFiles)="onUploadedFiles($event)"
|
|
257
|
+
(invalidFiles)="onInvalidFiles($event)"
|
|
258
|
+
>
|
|
259
|
+
<div class="m-upload__message">Drag your files here or click to upload</div>
|
|
260
|
+
<div class="m-upload__description">Maximum filesize: 10 MB, File extension: jpg, jpeg, png</div>
|
|
261
|
+
</aui-upload-zone>
|
|
262
|
+
<aui-upload-queue [files]="queuedFiles"></aui-upload-queue>
|
|
263
|
+
<div *ngIf="showError" class="u-margin-bottom">
|
|
264
|
+
<ul class="m-upload__files">
|
|
265
|
+
<li class="is-error">
|
|
266
|
+
<aui-icon name="ai-alert-triangle"></aui-icon>
|
|
267
|
+
<span class="m-upload__filename">{{ fileName }}</span>
|
|
268
|
+
<span class="m-upload__error">This file extension is not allowed.</span>
|
|
269
|
+
<button
|
|
270
|
+
type="button"
|
|
271
|
+
(click)="reloadErrors()"
|
|
272
|
+
class="m-upload__delete a-button a-button--text a-button--danger a-button--s has-icon"
|
|
273
|
+
>
|
|
274
|
+
<aui-icon name="ai-remove"></aui-icon>
|
|
275
|
+
</button>
|
|
276
|
+
</li>
|
|
277
|
+
</ul>
|
|
278
|
+
</div>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Contributing
|
|
282
|
+
|
|
283
|
+
Visit our [Contribution Guidelines](../../../../../CONTRIBUTING.md) for more information on how to contribute.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { UPLOAD_OPTIONS_DEFAULT } from '../upload.conf';
|
|
2
|
+
import { UploadOptions } from '../types/upload.types';
|
|
3
|
+
|
|
4
|
+
import { Uploader } from './uploader.class';
|
|
5
|
+
|
|
6
|
+
describe('Uploader', () => {
|
|
7
|
+
const uploadResponse = [
|
|
8
|
+
{
|
|
9
|
+
url: 'http://localhost/myfile',
|
|
10
|
+
name: 'myFile',
|
|
11
|
+
},
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {});
|
|
15
|
+
|
|
16
|
+
it('should have default options', () => {
|
|
17
|
+
const uploader = new Uploader();
|
|
18
|
+
expect(uploader.options).toEqual(UPLOAD_OPTIONS_DEFAULT);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should merge custom options with default options', () => {
|
|
22
|
+
const options: UploadOptions = {
|
|
23
|
+
type: 'button',
|
|
24
|
+
maxFileSize: 20000,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const uploader = new Uploader(options);
|
|
28
|
+
const result = Object.assign({}, UPLOAD_OPTIONS_DEFAULT, options);
|
|
29
|
+
expect(uploader.options).toEqual(result);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should validate file type', () => {
|
|
33
|
+
let result;
|
|
34
|
+
let f;
|
|
35
|
+
const date = new Date();
|
|
36
|
+
const uploader = new Uploader({
|
|
37
|
+
allowedFileTypes: ['jpg'],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
f = new File([''], 'filename.txt', { type: 'text/plain', lastModified: date.getTime() });
|
|
41
|
+
result = uploader.validateFiles([f]);
|
|
42
|
+
expect(result.validFiles.length).toEqual(0);
|
|
43
|
+
expect(result.invalidFiles.length).toEqual(1);
|
|
44
|
+
|
|
45
|
+
f = new File([''], 'filename.jpg', { type: 'image/jpeg', lastModified: date.getTime() });
|
|
46
|
+
result = uploader.validateFiles([f]);
|
|
47
|
+
expect(result.validFiles.length).toEqual(1);
|
|
48
|
+
expect(result.invalidFiles.length).toEqual(0);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should validate mime type', () => {
|
|
52
|
+
let result;
|
|
53
|
+
let f;
|
|
54
|
+
const date = new Date();
|
|
55
|
+
const uploader = new Uploader({
|
|
56
|
+
allowedMimeTypes: ['image/jpeg'],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
f = new File([''], 'filename.txt', { type: 'text/plain', lastModified: date.getTime() });
|
|
60
|
+
result = uploader.validateFiles([f]);
|
|
61
|
+
expect(result.validFiles.length).toEqual(0);
|
|
62
|
+
expect(result.invalidFiles.length).toEqual(1);
|
|
63
|
+
|
|
64
|
+
f = new File([''], 'filename.jpg', { type: 'image/jpeg', lastModified: date.getTime() });
|
|
65
|
+
result = uploader.validateFiles([f]);
|
|
66
|
+
expect(result.validFiles.length).toEqual(1);
|
|
67
|
+
expect(result.invalidFiles.length).toEqual(0);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should validate max file size', () => {
|
|
71
|
+
let result;
|
|
72
|
+
let f;
|
|
73
|
+
const date = new Date();
|
|
74
|
+
const uploader = new Uploader({
|
|
75
|
+
maxFileSize: 2,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
f = new File(['takesomespace'], 'filename.txt', { type: 'text/plain', lastModified: date.getTime() });
|
|
79
|
+
result = uploader.validateFiles([f]);
|
|
80
|
+
expect(result.validFiles.length).toEqual(0);
|
|
81
|
+
expect(result.invalidFiles.length).toEqual(1);
|
|
82
|
+
|
|
83
|
+
f = new File(['a'], 'filename.jpg', { type: 'image/jpeg', lastModified: date.getTime() });
|
|
84
|
+
result = uploader.validateFiles([f]);
|
|
85
|
+
expect(result.validFiles.length).toEqual(1);
|
|
86
|
+
expect(result.invalidFiles.length).toEqual(0);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should throw an error if no upload url is defined', () => {
|
|
90
|
+
const date = new Date();
|
|
91
|
+
const uploader = new Uploader({
|
|
92
|
+
maxFileSize: 2,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const f = new File(['takesomespace'], 'filename.txt', { type: 'text/plain', lastModified: date.getTime() });
|
|
96
|
+
expect(() => {
|
|
97
|
+
uploader.uploadFiles([f]);
|
|
98
|
+
}).toThrow(Error('Define the upload url.'));
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { UPLOAD_OPTIONS_DEFAULT } from '../upload.conf';
|
|
4
|
+
import { InvalidFile, UploadOptions } from '../types/upload.types';
|
|
5
|
+
|
|
6
|
+
export class Uploader {
|
|
7
|
+
public options: UploadOptions = UPLOAD_OPTIONS_DEFAULT;
|
|
8
|
+
|
|
9
|
+
constructor(options?: UploadOptions) {
|
|
10
|
+
this.setOptions(options);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public setOptions(options) {
|
|
14
|
+
this.options = Object.assign({}, this.options, options);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public uploadFiles(files: File[]): Observable<{ progress: number, data: object[] }> {
|
|
18
|
+
const formData: FormData = this.filesToFormData(files);
|
|
19
|
+
|
|
20
|
+
return new Observable(observer => {
|
|
21
|
+
const xhr = new XMLHttpRequest();
|
|
22
|
+
|
|
23
|
+
// Progress callback
|
|
24
|
+
xhr.upload.addEventListener('progress', (e) => {
|
|
25
|
+
if (e.lengthComputable) {
|
|
26
|
+
const percentComplete = e.loaded / e.total;
|
|
27
|
+
|
|
28
|
+
observer.next({
|
|
29
|
+
progress: percentComplete,
|
|
30
|
+
data: null,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Complete callback
|
|
36
|
+
xhr.onload = () => {
|
|
37
|
+
observer.next({
|
|
38
|
+
progress: 1,
|
|
39
|
+
data: xhr.response,
|
|
40
|
+
});
|
|
41
|
+
// observer.complete();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Do request
|
|
45
|
+
xhr.responseType = 'json';
|
|
46
|
+
xhr.open('post', this.options.url);
|
|
47
|
+
xhr.send(formData);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public validateFiles(files) {
|
|
52
|
+
const validFiles: File[] = [];
|
|
53
|
+
const invalidFiles: InvalidFile[] = [];
|
|
54
|
+
|
|
55
|
+
if (files.length > 0) {
|
|
56
|
+
|
|
57
|
+
for (const file of files) {
|
|
58
|
+
const errors = [];
|
|
59
|
+
|
|
60
|
+
if (!this.validateFileType(file)) {
|
|
61
|
+
errors.push('INVALID_FILE_TYPE');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!this.validateFileSize(file)) {
|
|
65
|
+
errors.push('INVALID_FILE_SIZE');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!this.validateMimeType(file)) {
|
|
69
|
+
errors.push('INVALID_MIME_TYPE');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (errors.length === 0) {
|
|
73
|
+
validFiles.push(file);
|
|
74
|
+
} else {
|
|
75
|
+
invalidFiles.push({
|
|
76
|
+
reasons: errors,
|
|
77
|
+
file,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
validFiles,
|
|
85
|
+
invalidFiles,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
protected filesToFormData(files: File[]): FormData {
|
|
90
|
+
const formData = new FormData();
|
|
91
|
+
|
|
92
|
+
if (!this.options.url || this.options.url === '') {
|
|
93
|
+
throw new Error('Define the upload url.');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (const file of files) {
|
|
97
|
+
formData.append('file', file);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return formData;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
protected getFileExtension(file: File): string {
|
|
104
|
+
return file.name.split('.')[file.name.split('.').length - 1];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
protected validateFileType(file: File): boolean {
|
|
108
|
+
const allowedFileTypes = this.options.allowedFileTypes;
|
|
109
|
+
const ext = this.getFileExtension(file);
|
|
110
|
+
|
|
111
|
+
// Filter defined?
|
|
112
|
+
if (!Array.isArray(allowedFileTypes) || allowedFileTypes.length === 0) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Make allowedFileTypes case insensitive
|
|
117
|
+
const toUpper = (x) => x.toUpperCase();
|
|
118
|
+
const allowedFileTypesToUpper = allowedFileTypes.map(toUpper);
|
|
119
|
+
|
|
120
|
+
return allowedFileTypesToUpper.lastIndexOf(ext.toUpperCase()) !== -1;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
protected validateFileSize(file: File): boolean {
|
|
124
|
+
const maxFileSize = this.options.maxFileSize;
|
|
125
|
+
|
|
126
|
+
// Filter defined?
|
|
127
|
+
if (!maxFileSize || maxFileSize === 0) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return maxFileSize > file.size;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
protected validateMimeType(file: File): boolean {
|
|
135
|
+
const allowedMimeTypes = this.options.allowedMimeTypes;
|
|
136
|
+
|
|
137
|
+
// Filter defined?
|
|
138
|
+
if (!Array.isArray(allowedMimeTypes) || allowedMimeTypes.length === 0) {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return allowedMimeTypes.lastIndexOf(file.type) !== -1;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<div class="m-upload aui-upload">
|
|
2
|
+
<aui-upload-zone
|
|
3
|
+
[id]="id"
|
|
4
|
+
[accept]="accept"
|
|
5
|
+
[capture]="capture"
|
|
6
|
+
[ariaId]="ariaId"
|
|
7
|
+
[disabled]="disabled"
|
|
8
|
+
[multiple]="multiple"
|
|
9
|
+
[uploader]="uploader"
|
|
10
|
+
(invalidFiles)="onInvalidFiles($event)"
|
|
11
|
+
(queuedFiles)="onQueuedFiles($event)"
|
|
12
|
+
(uploadedFiles)="onUploadedFiles($event)"
|
|
13
|
+
[label]="label"
|
|
14
|
+
[description]="description"
|
|
15
|
+
>
|
|
16
|
+
<div class="m-upload__button">
|
|
17
|
+
<ng-content select=".m-upload__button"></ng-content>
|
|
18
|
+
</div>
|
|
19
|
+
</aui-upload-zone>
|
|
20
|
+
<aui-validation-list [ariaLabelRemove]="ariaLabelRemove" [invalidFiles]="invalidFiles"></aui-validation-list>
|
|
21
|
+
<aui-upload-queue
|
|
22
|
+
(uploadedFiles)="onUploadedFiles($event)"
|
|
23
|
+
*ngIf="!options?.autoUpload"
|
|
24
|
+
[ariaLabelRemove]="ariaLabelRemove"
|
|
25
|
+
[files]="queuedFiles"
|
|
26
|
+
[uploader]="uploader"
|
|
27
|
+
></aui-upload-queue>
|
|
28
|
+
</div>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Component, DebugElement, Input } from '@angular/core';
|
|
2
|
+
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
3
|
+
import { By } from '@angular/platform-browser';
|
|
4
|
+
|
|
5
|
+
import { UploadComponent } from './upload.component';
|
|
6
|
+
import { InvalidFile } from '../../types/upload.types';
|
|
7
|
+
|
|
8
|
+
const mockUploadFiles = [
|
|
9
|
+
{
|
|
10
|
+
url: 'http://localhost/myfile.jpg',
|
|
11
|
+
name: 'myfile',
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const mockFile1 = new File(['file1'], 'filename1.txt', {
|
|
16
|
+
type: 'text/plain',
|
|
17
|
+
lastModified: new Date().getTime(),
|
|
18
|
+
});
|
|
19
|
+
const mockFile2 = new File(['file2'], 'filename2.txt', {
|
|
20
|
+
type: 'text/plain',
|
|
21
|
+
lastModified: new Date().getTime(),
|
|
22
|
+
});
|
|
23
|
+
const mockFileList = [mockFile1, mockFile2];
|
|
24
|
+
|
|
25
|
+
const mockInvalidFiles: InvalidFile[] = [
|
|
26
|
+
{
|
|
27
|
+
reasons: ['INVALID_FILE_TYPE'],
|
|
28
|
+
file: mockFile1,
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
@Component({
|
|
33
|
+
selector: 'aui-upload-zone',
|
|
34
|
+
template: '<div>aui-upload-zone</div>',
|
|
35
|
+
})
|
|
36
|
+
export class UploadZoneComponent {
|
|
37
|
+
@Input() uploader;
|
|
38
|
+
@Input() accept;
|
|
39
|
+
@Input() capture;
|
|
40
|
+
@Input() ariaId;
|
|
41
|
+
@Input() disabled = false;
|
|
42
|
+
@Input() multiple;
|
|
43
|
+
@Input() label;
|
|
44
|
+
@Input() description;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@Component({
|
|
48
|
+
selector: 'aui-upload-queue',
|
|
49
|
+
template: '<div>aui-upload-queue</div>',
|
|
50
|
+
})
|
|
51
|
+
export class UploadQueueComponent {
|
|
52
|
+
@Input() uploader;
|
|
53
|
+
@Input() files;
|
|
54
|
+
@Input() ariaLabelRemove;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Component({
|
|
58
|
+
selector: 'aui-validation-list',
|
|
59
|
+
template: '<div>aui-validation-list</div>',
|
|
60
|
+
})
|
|
61
|
+
export class ValidationListComponent {
|
|
62
|
+
@Input() invalidFiles;
|
|
63
|
+
@Input() ariaLabelRemove;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
describe('The Upload Component', () => {
|
|
67
|
+
let comp: UploadComponent;
|
|
68
|
+
let fixture: ComponentFixture<UploadComponent>;
|
|
69
|
+
let de: DebugElement;
|
|
70
|
+
let el: HTMLElement;
|
|
71
|
+
|
|
72
|
+
// waitForAsync beforeEach
|
|
73
|
+
beforeEach(waitForAsync(() => {
|
|
74
|
+
TestBed.configureTestingModule({
|
|
75
|
+
declarations: [
|
|
76
|
+
UploadComponent,
|
|
77
|
+
UploadZoneComponent,
|
|
78
|
+
UploadQueueComponent,
|
|
79
|
+
ValidationListComponent,
|
|
80
|
+
],
|
|
81
|
+
}).compileComponents(); // compile template and css
|
|
82
|
+
}));
|
|
83
|
+
|
|
84
|
+
// synchronous beforeEach
|
|
85
|
+
beforeEach(() => {
|
|
86
|
+
fixture = TestBed.createComponent(UploadComponent);
|
|
87
|
+
|
|
88
|
+
comp = fixture.componentInstance; // BannerComponent test instance
|
|
89
|
+
|
|
90
|
+
// query for the title <h1> by CSS element selector
|
|
91
|
+
de = fixture.debugElement.query(By.css('.m-upload'));
|
|
92
|
+
el = de.nativeElement;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should exist', () => {
|
|
96
|
+
fixture.detectChanges();
|
|
97
|
+
expect(el).not.toBeUndefined();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should emit uploaded files', () => {
|
|
101
|
+
spyOn(comp.selectUploadedFiles, 'emit');
|
|
102
|
+
comp.onUploadedFiles(mockUploadFiles);
|
|
103
|
+
expect(comp.selectUploadedFiles.emit).toHaveBeenCalledWith(mockUploadFiles);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should concat queued files', () => {
|
|
107
|
+
comp.queuedFiles = [mockFile1];
|
|
108
|
+
comp.onQueuedFiles(mockFileList);
|
|
109
|
+
const result = [mockFile1].concat(mockFileList);
|
|
110
|
+
expect(comp.queuedFiles).toEqual(result);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should set invalid files', () => {
|
|
114
|
+
comp.onInvalidFiles(mockInvalidFiles);
|
|
115
|
+
expect(comp.invalidFiles).toEqual(mockInvalidFiles);
|
|
116
|
+
});
|
|
117
|
+
});
|