@es.framework/ng.ui.core 2.0.58
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/README.md +3 -0
- package/attachments/README.md +3 -0
- package/base-crud/README.md +3 -0
- package/breadcrumb/README.md +3 -0
- package/checkbox/README.md +3 -0
- package/collapsible/README.md +3 -0
- package/color-picker/README.md +3 -0
- package/column-settings-popover/README.md +3 -0
- package/custom-switch/README.md +3 -0
- package/datepicker/README.md +3 -0
- package/deactivation-reason/README.md +3 -0
- package/excel-import/README.md +3 -0
- package/fesm2022/es.framework-ng.ui.core-attachments.mjs +217 -0
- package/fesm2022/es.framework-ng.ui.core-attachments.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-base-crud.mjs +370 -0
- package/fesm2022/es.framework-ng.ui.core-base-crud.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-breadcrumb.mjs +145 -0
- package/fesm2022/es.framework-ng.ui.core-breadcrumb.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-checkbox.mjs +131 -0
- package/fesm2022/es.framework-ng.ui.core-checkbox.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-collapsible.mjs +90 -0
- package/fesm2022/es.framework-ng.ui.core-collapsible.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-color-picker.mjs +87 -0
- package/fesm2022/es.framework-ng.ui.core-color-picker.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-column-settings-popover.mjs +183 -0
- package/fesm2022/es.framework-ng.ui.core-column-settings-popover.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-custom-switch.mjs +119 -0
- package/fesm2022/es.framework-ng.ui.core-custom-switch.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-datepicker.mjs +519 -0
- package/fesm2022/es.framework-ng.ui.core-datepicker.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-deactivation-reason.mjs +144 -0
- package/fesm2022/es.framework-ng.ui.core-deactivation-reason.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-excel-import.mjs +566 -0
- package/fesm2022/es.framework-ng.ui.core-excel-import.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-filter-templates.mjs +386 -0
- package/fesm2022/es.framework-ng.ui.core-filter-templates.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-form-button.mjs +62 -0
- package/fesm2022/es.framework-ng.ui.core-form-button.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-form-field.mjs +155 -0
- package/fesm2022/es.framework-ng.ui.core-form-field.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-form-template.mjs +37 -0
- package/fesm2022/es.framework-ng.ui.core-form-template.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-avatar-image.mjs +132 -0
- package/fesm2022/es.framework-ng.ui.core-formly-avatar-image.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-avatar-label.mjs +89 -0
- package/fesm2022/es.framework-ng.ui.core-formly-avatar-label.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-button-selector.mjs +195 -0
- package/fesm2022/es.framework-ng.ui.core-formly-button-selector.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-button.mjs +73 -0
- package/fesm2022/es.framework-ng.ui.core-formly-button.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-presets.mjs +201 -0
- package/fesm2022/es.framework-ng.ui.core-formly-presets.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-prime-icon-picker.mjs +542 -0
- package/fesm2022/es.framework-ng.ui.core-formly-prime-icon-picker.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-split-button.mjs +62 -0
- package/fesm2022/es.framework-ng.ui.core-formly-split-button.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-ui-all.mjs +422 -0
- package/fesm2022/es.framework-ng.ui.core-formly-ui-all.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-ui.mjs +48 -0
- package/fesm2022/es.framework-ng.ui.core-formly-ui.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-formly-username-with-domain.mjs +85 -0
- package/fesm2022/es.framework-ng.ui.core-formly-username-with-domain.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-assets.mjs +22 -0
- package/fesm2022/es.framework-ng.ui.core-generic-assets.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-autocomplete.mjs +173 -0
- package/fesm2022/es.framework-ng.ui.core-generic-autocomplete.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-button.mjs +150 -0
- package/fesm2022/es.framework-ng.ui.core-generic-button.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-card.mjs +218 -0
- package/fesm2022/es.framework-ng.ui.core-generic-card.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-crud-table.mjs +929 -0
- package/fesm2022/es.framework-ng.ui.core-generic-crud-table.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-dialog.mjs +321 -0
- package/fesm2022/es.framework-ng.ui.core-generic-dialog.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-errormessage.mjs +35 -0
- package/fesm2022/es.framework-ng.ui.core-generic-errormessage.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-formly-fields.mjs +63 -0
- package/fesm2022/es.framework-ng.ui.core-generic-formly-fields.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-loadingspinner.mjs +34 -0
- package/fesm2022/es.framework-ng.ui.core-generic-loadingspinner.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-report-tabs.mjs +196 -0
- package/fesm2022/es.framework-ng.ui.core-generic-report-tabs.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-report.mjs +556 -0
- package/fesm2022/es.framework-ng.ui.core-generic-report.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-search-advanced.mjs +2995 -0
- package/fesm2022/es.framework-ng.ui.core-generic-search-advanced.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-search.mjs +103 -0
- package/fesm2022/es.framework-ng.ui.core-generic-search.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-selector.mjs +684 -0
- package/fesm2022/es.framework-ng.ui.core-generic-selector.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-table.mjs +388 -0
- package/fesm2022/es.framework-ng.ui.core-generic-table.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-generic-view.mjs +465 -0
- package/fesm2022/es.framework-ng.ui.core-generic-view.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-header-wrapper.mjs +31 -0
- package/fesm2022/es.framework-ng.ui.core-header-wrapper.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-icon-picker.mjs +205 -0
- package/fesm2022/es.framework-ng.ui.core-icon-picker.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-input-switch.mjs +102 -0
- package/fesm2022/es.framework-ng.ui.core-input-switch.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-input-with-icon.mjs +67 -0
- package/fesm2022/es.framework-ng.ui.core-input-with-icon.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-input.mjs +250 -0
- package/fesm2022/es.framework-ng.ui.core-input.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-label-type.mjs +184 -0
- package/fesm2022/es.framework-ng.ui.core-label-type.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-loading-skeletons.mjs +66 -0
- package/fesm2022/es.framework-ng.ui.core-loading-skeletons.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-odata-query-builder.mjs +307 -0
- package/fesm2022/es.framework-ng.ui.core-odata-query-builder.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-query-type.mjs +162 -0
- package/fesm2022/es.framework-ng.ui.core-query-type.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-radio.mjs +120 -0
- package/fesm2022/es.framework-ng.ui.core-radio.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-repeat.mjs +290 -0
- package/fesm2022/es.framework-ng.ui.core-repeat.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-select.mjs +179 -0
- package/fesm2022/es.framework-ng.ui.core-select.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-sidebar-cards.mjs +52 -0
- package/fesm2022/es.framework-ng.ui.core-sidebar-cards.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-sidebar-toggles.mjs +53 -0
- package/fesm2022/es.framework-ng.ui.core-sidebar-toggles.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-tabs.mjs +57 -0
- package/fesm2022/es.framework-ng.ui.core-tabs.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-tag-type.mjs +209 -0
- package/fesm2022/es.framework-ng.ui.core-tag-type.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-text-editor.mjs +58 -0
- package/fesm2022/es.framework-ng.ui.core-text-editor.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-textarea.mjs +93 -0
- package/fesm2022/es.framework-ng.ui.core-textarea.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core-wrappers.mjs +245 -0
- package/fesm2022/es.framework-ng.ui.core-wrappers.mjs.map +1 -0
- package/fesm2022/es.framework-ng.ui.core.mjs +20 -0
- package/fesm2022/es.framework-ng.ui.core.mjs.map +1 -0
- package/filter-templates/README.md +3 -0
- package/form-button/README.md +3 -0
- package/form-field/README.md +3 -0
- package/form-template/README.md +3 -0
- package/formly-avatar-image/README.md +3 -0
- package/formly-avatar-label/README.md +3 -0
- package/formly-button/README.md +3 -0
- package/formly-button-selector/README.md +3 -0
- package/formly-presets/README.md +3 -0
- package/formly-prime-icon-picker/README.md +3 -0
- package/formly-split-button/README.md +3 -0
- package/formly-ui/README.md +3 -0
- package/formly-ui-all/README.md +3 -0
- package/formly-username-with-domain/README.md +3 -0
- package/generic-assets/README.md +3 -0
- package/generic-autocomplete/README.md +3 -0
- package/generic-button/README.md +3 -0
- package/generic-card/README.md +3 -0
- package/generic-crud-table/README.md +3 -0
- package/generic-dialog/README.md +3 -0
- package/generic-errormessage/README.md +3 -0
- package/generic-formly-fields/README.md +3 -0
- package/generic-loadingspinner/README.md +3 -0
- package/generic-report/README.md +3 -0
- package/generic-report-tabs/README.md +0 -0
- package/generic-search/README.md +3 -0
- package/generic-search-advanced/README.md +3 -0
- package/generic-selector/README.md +3 -0
- package/generic-table/README.md +3 -0
- package/generic-view/README.md +3 -0
- package/header-wrapper/README.md +3 -0
- package/icon-picker/README.md +3 -0
- package/input/README.md +3 -0
- package/input-switch/README.md +3 -0
- package/input-with-icon/README.md +3 -0
- package/label-type/README.md +3 -0
- package/loading-skeletons/README.md +3 -0
- package/odata-query-builder/README.md +3 -0
- package/package.json +264 -0
- package/query-type/README.md +3 -0
- package/radio/README.md +3 -0
- package/repeat/README.md +3 -0
- package/select/README.md +3 -0
- package/sidebar-cards/README.md +3 -0
- package/sidebar-toggles/README.md +3 -0
- package/styles.css +2 -0
- package/tabs/README.md +3 -0
- package/tag-type/README.md +3 -0
- package/text-editor/README.md +3 -0
- package/textarea/README.md +3 -0
- package/types/es.framework-ng.ui.core-attachments.d.ts +38 -0
- package/types/es.framework-ng.ui.core-base-crud.d.ts +74 -0
- package/types/es.framework-ng.ui.core-breadcrumb.d.ts +17 -0
- package/types/es.framework-ng.ui.core-checkbox.d.ts +33 -0
- package/types/es.framework-ng.ui.core-collapsible.d.ts +18 -0
- package/types/es.framework-ng.ui.core-color-picker.d.ts +16 -0
- package/types/es.framework-ng.ui.core-column-settings-popover.d.ts +46 -0
- package/types/es.framework-ng.ui.core-custom-switch.d.ts +19 -0
- package/types/es.framework-ng.ui.core-datepicker.d.ts +23 -0
- package/types/es.framework-ng.ui.core-deactivation-reason.d.ts +32 -0
- package/types/es.framework-ng.ui.core-excel-import.d.ts +69 -0
- package/types/es.framework-ng.ui.core-filter-templates.d.ts +57 -0
- package/types/es.framework-ng.ui.core-form-button.d.ts +17 -0
- package/types/es.framework-ng.ui.core-form-field.d.ts +30 -0
- package/types/es.framework-ng.ui.core-form-template.d.ts +16 -0
- package/types/es.framework-ng.ui.core-formly-avatar-image.d.ts +18 -0
- package/types/es.framework-ng.ui.core-formly-avatar-label.d.ts +36 -0
- package/types/es.framework-ng.ui.core-formly-button-selector.d.ts +35 -0
- package/types/es.framework-ng.ui.core-formly-button.d.ts +20 -0
- package/types/es.framework-ng.ui.core-formly-presets.d.ts +37 -0
- package/types/es.framework-ng.ui.core-formly-prime-icon-picker.d.ts +45 -0
- package/types/es.framework-ng.ui.core-formly-split-button.d.ts +23 -0
- package/types/es.framework-ng.ui.core-formly-ui-all.d.ts +40 -0
- package/types/es.framework-ng.ui.core-formly-ui.d.ts +13 -0
- package/types/es.framework-ng.ui.core-formly-username-with-domain.d.ts +19 -0
- package/types/es.framework-ng.ui.core-generic-assets.d.ts +10 -0
- package/types/es.framework-ng.ui.core-generic-autocomplete.d.ts +41 -0
- package/types/es.framework-ng.ui.core-generic-button.d.ts +39 -0
- package/types/es.framework-ng.ui.core-generic-card.d.ts +93 -0
- package/types/es.framework-ng.ui.core-generic-crud-table.d.ts +293 -0
- package/types/es.framework-ng.ui.core-generic-dialog.d.ts +93 -0
- package/types/es.framework-ng.ui.core-generic-errormessage.d.ts +17 -0
- package/types/es.framework-ng.ui.core-generic-formly-fields.d.ts +26 -0
- package/types/es.framework-ng.ui.core-generic-loadingspinner.d.ts +16 -0
- package/types/es.framework-ng.ui.core-generic-report-tabs.d.ts +21 -0
- package/types/es.framework-ng.ui.core-generic-report.d.ts +121 -0
- package/types/es.framework-ng.ui.core-generic-search-advanced.d.ts +305 -0
- package/types/es.framework-ng.ui.core-generic-search.d.ts +36 -0
- package/types/es.framework-ng.ui.core-generic-selector.d.ts +99 -0
- package/types/es.framework-ng.ui.core-generic-table.d.ts +84 -0
- package/types/es.framework-ng.ui.core-generic-view.d.ts +97 -0
- package/types/es.framework-ng.ui.core-header-wrapper.d.ts +15 -0
- package/types/es.framework-ng.ui.core-icon-picker.d.ts +30 -0
- package/types/es.framework-ng.ui.core-input-switch.d.ts +16 -0
- package/types/es.framework-ng.ui.core-input-with-icon.d.ts +17 -0
- package/types/es.framework-ng.ui.core-input.d.ts +47 -0
- package/types/es.framework-ng.ui.core-label-type.d.ts +38 -0
- package/types/es.framework-ng.ui.core-loading-skeletons.d.ts +17 -0
- package/types/es.framework-ng.ui.core-odata-query-builder.d.ts +87 -0
- package/types/es.framework-ng.ui.core-query-type.d.ts +37 -0
- package/types/es.framework-ng.ui.core-radio.d.ts +38 -0
- package/types/es.framework-ng.ui.core-repeat.d.ts +31 -0
- package/types/es.framework-ng.ui.core-select.d.ts +42 -0
- package/types/es.framework-ng.ui.core-sidebar-cards.d.ts +25 -0
- package/types/es.framework-ng.ui.core-sidebar-toggles.d.ts +25 -0
- package/types/es.framework-ng.ui.core-tabs.d.ts +17 -0
- package/types/es.framework-ng.ui.core-tag-type.d.ts +34 -0
- package/types/es.framework-ng.ui.core-text-editor.d.ts +16 -0
- package/types/es.framework-ng.ui.core-textarea.d.ts +36 -0
- package/types/es.framework-ng.ui.core-wrappers.d.ts +36 -0
- package/types/es.framework-ng.ui.core.d.ts +8 -0
- package/wrappers/README.md +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { NgModule, inject, Component } from '@angular/core';
|
|
3
|
+
import * as i2 from '@angular/common';
|
|
4
|
+
import { CommonModule } from '@angular/common';
|
|
5
|
+
import * as i3 from '@angular/forms';
|
|
6
|
+
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
7
|
+
import { FieldType } from '@ngx-formly/core';
|
|
8
|
+
import * as i4 from 'primeng/fileupload';
|
|
9
|
+
import { FileUploadModule } from 'primeng/fileupload';
|
|
10
|
+
import * as i5 from 'primeng/button';
|
|
11
|
+
import { ButtonModule } from 'primeng/button';
|
|
12
|
+
import * as i1 from 'primeng/api';
|
|
13
|
+
import { MessageService } from 'primeng/api';
|
|
14
|
+
import * as i6 from 'primeng/inputtext';
|
|
15
|
+
import { InputTextModule } from 'primeng/inputtext';
|
|
16
|
+
import { AttachmentDto } from '@es.framework/ng.core/models';
|
|
17
|
+
import { EnvironmentService } from '@es.framework/ng.core/services';
|
|
18
|
+
|
|
19
|
+
class AttachmentsModule {
|
|
20
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AttachmentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
21
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.3", ngImport: i0, type: AttachmentsModule, imports: [CommonModule] });
|
|
22
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AttachmentsModule, imports: [CommonModule] });
|
|
23
|
+
}
|
|
24
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AttachmentsModule, decorators: [{
|
|
25
|
+
type: NgModule,
|
|
26
|
+
args: [{
|
|
27
|
+
imports: [CommonModule],
|
|
28
|
+
}]
|
|
29
|
+
}] });
|
|
30
|
+
|
|
31
|
+
class AttachmentTypeComponent extends FieldType {
|
|
32
|
+
messageService;
|
|
33
|
+
defaultAcceptTypes = '.pdf,application/pdf,image/*,.txt,text/plain,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel';
|
|
34
|
+
maxFileSize = 1 * 1024 * 1024; // 1 MB
|
|
35
|
+
tenantId = 0;
|
|
36
|
+
env = inject(EnvironmentService);
|
|
37
|
+
constructor(messageService) {
|
|
38
|
+
super();
|
|
39
|
+
this.messageService = messageService;
|
|
40
|
+
}
|
|
41
|
+
get url() {
|
|
42
|
+
return this.env.getEnvironment().apis.default.url + (this.props['apiUrl'] ?? '/api/files');
|
|
43
|
+
}
|
|
44
|
+
get attachments() {
|
|
45
|
+
return Array.isArray(this.formControl.value)
|
|
46
|
+
? this.formControl.value
|
|
47
|
+
: (this.formControl.value ? [this.formControl.value] : []);
|
|
48
|
+
}
|
|
49
|
+
set attachments(value) {
|
|
50
|
+
if (this.props['multiple']) {
|
|
51
|
+
this.formControl.setValue(value);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.formControl.setValue(value?.[0] || null);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
get attachment() {
|
|
58
|
+
return Array.isArray(this.formControl.value)
|
|
59
|
+
? (this.formControl.value[0] || null)
|
|
60
|
+
: this.formControl.value || null;
|
|
61
|
+
}
|
|
62
|
+
set attachment(value) {
|
|
63
|
+
if (this.props['multiple']) {
|
|
64
|
+
const arr = Array.isArray(this.formControl.value)
|
|
65
|
+
? [...this.formControl.value]
|
|
66
|
+
: (this.formControl.value ? [this.formControl.value] : []);
|
|
67
|
+
if (value)
|
|
68
|
+
arr.push(value);
|
|
69
|
+
this.formControl.setValue(arr);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this.formControl.setValue(value);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async onUpload(event) {
|
|
76
|
+
const files = event.files;
|
|
77
|
+
const isMultiple = this.props['multiple'] ?? true;
|
|
78
|
+
const allowedTypes = this.props['accept'] || '';
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
if (file.size > this.maxFileSize) {
|
|
81
|
+
this.messageService.add({
|
|
82
|
+
severity: 'error',
|
|
83
|
+
summary: 'خطأ',
|
|
84
|
+
detail: `الملف "${file.name}" يتجاوز الحد الأقصى (1MB)`,
|
|
85
|
+
});
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (allowedTypes && !this.isFileTypeAllowed(file, allowedTypes)) {
|
|
89
|
+
this.messageService.add({
|
|
90
|
+
severity: 'error',
|
|
91
|
+
summary: 'نوع الملف غير مسموح',
|
|
92
|
+
detail: `الملف "${file.name}" ليس من الأنواع المسموحة`,
|
|
93
|
+
});
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (isMultiple && this.attachments.some(a => a.fileName === file.name)) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const base64 = await this.fileToBase64(file);
|
|
100
|
+
const attachment = new AttachmentDto();
|
|
101
|
+
attachment.fileName = file.name;
|
|
102
|
+
attachment.mimeType = file.type;
|
|
103
|
+
attachment.base64 = base64;
|
|
104
|
+
if (isMultiple) {
|
|
105
|
+
this.attachments = [...this.attachments, attachment];
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
this.attachment = attachment;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
remove(index) {
|
|
113
|
+
const copy = [...this.attachments];
|
|
114
|
+
copy.splice(index, 1);
|
|
115
|
+
this.attachments = copy;
|
|
116
|
+
}
|
|
117
|
+
choose(event, callback) {
|
|
118
|
+
callback();
|
|
119
|
+
}
|
|
120
|
+
fileToBase64(file) {
|
|
121
|
+
return new Promise((resolve, reject) => {
|
|
122
|
+
const reader = new FileReader();
|
|
123
|
+
reader.readAsDataURL(file);
|
|
124
|
+
reader.onload = () => resolve(reader.result.split(',')[1]);
|
|
125
|
+
reader.onerror = err => reject(err);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
isFileTypeAllowed(file, allowedTypes) {
|
|
129
|
+
const accepted = allowedTypes.split(',').map(t => t.trim());
|
|
130
|
+
return accepted.some(type => {
|
|
131
|
+
if (type === '*/*')
|
|
132
|
+
return true;
|
|
133
|
+
if (type.endsWith('/*')) {
|
|
134
|
+
return file.type.startsWith(type.split('/')[0] + '/');
|
|
135
|
+
}
|
|
136
|
+
return file.type === type;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
getFileLabel(mime) {
|
|
140
|
+
if (!mime)
|
|
141
|
+
return 'FILE';
|
|
142
|
+
if (mime.includes('pdf'))
|
|
143
|
+
return 'PDF';
|
|
144
|
+
if (mime.includes('excel') || mime.includes('spreadsheet'))
|
|
145
|
+
return 'XLS';
|
|
146
|
+
if (mime.includes('word'))
|
|
147
|
+
return 'DOC';
|
|
148
|
+
if (mime.includes('image'))
|
|
149
|
+
return 'IMG';
|
|
150
|
+
if (mime.includes('zip'))
|
|
151
|
+
return 'ZIP';
|
|
152
|
+
if (mime.includes('csv'))
|
|
153
|
+
return 'CSV';
|
|
154
|
+
if (mime.includes('text'))
|
|
155
|
+
return 'TXT';
|
|
156
|
+
return 'FILE';
|
|
157
|
+
}
|
|
158
|
+
getLabelClass(mime) {
|
|
159
|
+
if (mime.includes('pdf'))
|
|
160
|
+
return 'bg-red-600 text-white';
|
|
161
|
+
if (mime.includes('excel'))
|
|
162
|
+
return 'bg-green-600 text-white';
|
|
163
|
+
if (mime.includes('word'))
|
|
164
|
+
return 'bg-blue-600 text-white';
|
|
165
|
+
if (mime.includes('image'))
|
|
166
|
+
return 'bg-yellow-500 text-white';
|
|
167
|
+
if (mime.includes('zip'))
|
|
168
|
+
return 'bg-pink-600 text-white';
|
|
169
|
+
return 'bg-gray-400 text-white';
|
|
170
|
+
}
|
|
171
|
+
getIconColor(mime) {
|
|
172
|
+
if (mime.includes('pdf'))
|
|
173
|
+
return 'text-red-400';
|
|
174
|
+
if (mime.includes('excel'))
|
|
175
|
+
return 'text-green-500';
|
|
176
|
+
if (mime.includes('word'))
|
|
177
|
+
return 'text-blue-500';
|
|
178
|
+
if (mime.includes('image'))
|
|
179
|
+
return 'text-yellow-500';
|
|
180
|
+
if (mime.includes('zip'))
|
|
181
|
+
return 'text-pink-500';
|
|
182
|
+
return 'text-gray-400';
|
|
183
|
+
}
|
|
184
|
+
getFileIcon(mime) {
|
|
185
|
+
if (mime.includes('pdf'))
|
|
186
|
+
return 'pi pi-file-pdf';
|
|
187
|
+
if (mime.includes('excel') || mime.includes('spreadsheet'))
|
|
188
|
+
return 'pi pi-file-excel';
|
|
189
|
+
if (mime.includes('word'))
|
|
190
|
+
return 'pi pi-file-word';
|
|
191
|
+
if (mime.includes('image'))
|
|
192
|
+
return 'pi pi-image';
|
|
193
|
+
if (mime.includes('zip'))
|
|
194
|
+
return 'pi pi-file-zip';
|
|
195
|
+
return 'pi pi-file';
|
|
196
|
+
}
|
|
197
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AttachmentTypeComponent, deps: [{ token: i1.MessageService }], target: i0.ɵɵFactoryTarget.Component });
|
|
198
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: AttachmentTypeComponent, isStandalone: true, selector: "attachment-type", providers: [MessageService], usesInheritance: true, ngImport: i0, template: "<p-fileUpload\n name=\"file\"\n [customUpload]=\"true\"\n [auto]=\"true\"\n [multiple]=\"props['multiple'] !== false\"\n [maxFileSize]=\"maxFileSize\"\n [accept]=\"props['accept'] || defaultAcceptTypes\"\n (uploadHandler)=\"onUpload($event)\"\n chooseLabel=\"\u0627\u0633\u062D\u0628 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0623\u0648 \u0627\u0646\u0642\u0631 \u0644\u0644\u0625\u0631\u0641\u0627\u0642\"\n class=\"w-full\"\n >\n <!-- Header Template -->\n <ng-template pTemplate=\"header\" let-chooseCallback=\"chooseCallback\">\n <div class=\"flex flex-wrap justify-content-between align-items-center flex-1 gap-2\">\n <div class=\"flex gap-2\">\n <p-button\n (click)=\"choose($event, chooseCallback)\"\n icon=\"pi pi-plus\"\n [rounded]=\"true\"\n [outlined]=\"true\"\n styleClass=\"border border-green-600 text-green-600 hover:bg-green-100 bg-white shadow-sm !rounded-full\"\n ></p-button>\n </div>\n </div>\n </ng-template>\n\n <!-- Content Template -->\n <ng-template pTemplate=\"content\">\n <!-- Multi mode -->\n <div class=\"p-2 flex flex-wrap gap-4\">\n @for (file of attachments; track file; let i = $index) {\n <div\n style=\"height: 7rem;\"\n class=\"relative w-24 h-28 bg-white border rounded-lg shadow-sm flex flex-col items-center justify-center\"\n >\n <!-- File type label -->\n <div\n class=\"absolute top-0 left-0 px-2 py-0.5 text-[10px] font-bold uppercase rounded-br-md shadow-sm text-white\"\n [ngClass]=\"getLabelClass(file.mimeType)\"\n >\n {{ getFileLabel(file.mimeType) }}\n </div>\n <!-- Remove button -->\n <button\n style=\"top: 3px;right: 3px;\"\n type=\"button\"\n class=\"absolute top-1 right-1 text-red-500 hover:text-red-700\"\n (click)=\"remove(i)\"\n title=\"\u062D\u0630\u0641\"\n >\n <i class=\"pi pi-times text-xs\"></i>\n </button>\n <!-- Center icon -->\n <i\n [class]=\"getFileIcon(file.mimeType)\"\n [ngClass]=\"getIconColor(file.mimeType)\"\n class=\"!text-4xl text-center mt-5\"\n ></i>\n <!-- File name -->\n <div style=\"max-width: 85%;\" class=\"mt-1 text-[11px] text-gray-600 truncate max-w-[85%] text-center\">\n <div class=\"truncate\">{{ file.fileName }}</div>\n </div>\n <!-- Download icon -->\n @if (file.binaryObjectId) {\n <a\n style=\"bottom: 3px;right: 3px;\"\n class=\"absolute bottom-1 right-1 text-gray-400 hover:text-blue-500\"\n [href]=\"url+'/' + file.binaryObjectId\"\n target=\"_blank\"\n download\n title=\"\u062A\u062D\u0645\u064A\u0644\"\n >\n <i class=\"pi pi-download text-xs\"></i>\n </a>\n }\n </div>\n }\n </div>\n\n <!-- Single mode -->\n @if (props['multiple'] === false && attachment) {\n <div>\n <div class=\"flex items-center justify-between p-2 border-b\">\n <span>{{ attachment.fileName }}</span>\n <p-button\n type=\"button\"\n icon=\"pi pi-times\"\n class=\"p-button-rounded p-button-text text-red-600\"\n (click)=\"remove(0)\"\n ></p-button>\n </div>\n <!-- Caption input if allowed -->\n @if (props['allowCaption']) {\n <div class=\"mt-1\">\n <input\n pInputText\n type=\"text\"\n class=\"w-full border rounded px-2 py-1 text-sm\"\n placeholder=\"\u0623\u0636\u0641 \u0648\u0635\u0641\u0627\u064B\"\n (change)=\"attachment = attachment\"\n [(ngModel)]=\"attachment.caption\"\n />\n </div>\n }\n </div>\n }\n </ng-template>\n\n <!-- Empty Template -->\n <ng-template pTemplate=\"empty\">\n @if ((props['multiple'] !== false && (!attachments || attachments.length === 0)) ||\n (props['multiple'] === false && !attachment)) {\n <div\n class=\"border-2 border-dashed rounded-md p-4 bg-gray-50 hover:bg-gray-100 transition flex align-items-center justify-content-center flex-column\"\n >\n <i class=\"pi pi-cloud-upload border-2 rounded p-5 text-8xl text-400 border-400\"></i>\n <p class=\"mt-4 mb-0\">\u0627\u0633\u062D\u0628 \u0648\u0623\u0641\u0644\u0650\u062A \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0647\u0646\u0627 \u0644\u0644\u062A\u062D\u0645\u064A\u0644.</p>\n </div>\n }\n </ng-template>\n</p-fileUpload>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i4.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "directive", type: i1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i5.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i6.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }] });
|
|
199
|
+
}
|
|
200
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AttachmentTypeComponent, decorators: [{
|
|
201
|
+
type: Component,
|
|
202
|
+
args: [{ selector: 'attachment-type', standalone: true, imports: [
|
|
203
|
+
CommonModule,
|
|
204
|
+
ReactiveFormsModule,
|
|
205
|
+
FormsModule,
|
|
206
|
+
FileUploadModule,
|
|
207
|
+
ButtonModule,
|
|
208
|
+
InputTextModule
|
|
209
|
+
], providers: [MessageService], template: "<p-fileUpload\n name=\"file\"\n [customUpload]=\"true\"\n [auto]=\"true\"\n [multiple]=\"props['multiple'] !== false\"\n [maxFileSize]=\"maxFileSize\"\n [accept]=\"props['accept'] || defaultAcceptTypes\"\n (uploadHandler)=\"onUpload($event)\"\n chooseLabel=\"\u0627\u0633\u062D\u0628 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0623\u0648 \u0627\u0646\u0642\u0631 \u0644\u0644\u0625\u0631\u0641\u0627\u0642\"\n class=\"w-full\"\n >\n <!-- Header Template -->\n <ng-template pTemplate=\"header\" let-chooseCallback=\"chooseCallback\">\n <div class=\"flex flex-wrap justify-content-between align-items-center flex-1 gap-2\">\n <div class=\"flex gap-2\">\n <p-button\n (click)=\"choose($event, chooseCallback)\"\n icon=\"pi pi-plus\"\n [rounded]=\"true\"\n [outlined]=\"true\"\n styleClass=\"border border-green-600 text-green-600 hover:bg-green-100 bg-white shadow-sm !rounded-full\"\n ></p-button>\n </div>\n </div>\n </ng-template>\n\n <!-- Content Template -->\n <ng-template pTemplate=\"content\">\n <!-- Multi mode -->\n <div class=\"p-2 flex flex-wrap gap-4\">\n @for (file of attachments; track file; let i = $index) {\n <div\n style=\"height: 7rem;\"\n class=\"relative w-24 h-28 bg-white border rounded-lg shadow-sm flex flex-col items-center justify-center\"\n >\n <!-- File type label -->\n <div\n class=\"absolute top-0 left-0 px-2 py-0.5 text-[10px] font-bold uppercase rounded-br-md shadow-sm text-white\"\n [ngClass]=\"getLabelClass(file.mimeType)\"\n >\n {{ getFileLabel(file.mimeType) }}\n </div>\n <!-- Remove button -->\n <button\n style=\"top: 3px;right: 3px;\"\n type=\"button\"\n class=\"absolute top-1 right-1 text-red-500 hover:text-red-700\"\n (click)=\"remove(i)\"\n title=\"\u062D\u0630\u0641\"\n >\n <i class=\"pi pi-times text-xs\"></i>\n </button>\n <!-- Center icon -->\n <i\n [class]=\"getFileIcon(file.mimeType)\"\n [ngClass]=\"getIconColor(file.mimeType)\"\n class=\"!text-4xl text-center mt-5\"\n ></i>\n <!-- File name -->\n <div style=\"max-width: 85%;\" class=\"mt-1 text-[11px] text-gray-600 truncate max-w-[85%] text-center\">\n <div class=\"truncate\">{{ file.fileName }}</div>\n </div>\n <!-- Download icon -->\n @if (file.binaryObjectId) {\n <a\n style=\"bottom: 3px;right: 3px;\"\n class=\"absolute bottom-1 right-1 text-gray-400 hover:text-blue-500\"\n [href]=\"url+'/' + file.binaryObjectId\"\n target=\"_blank\"\n download\n title=\"\u062A\u062D\u0645\u064A\u0644\"\n >\n <i class=\"pi pi-download text-xs\"></i>\n </a>\n }\n </div>\n }\n </div>\n\n <!-- Single mode -->\n @if (props['multiple'] === false && attachment) {\n <div>\n <div class=\"flex items-center justify-between p-2 border-b\">\n <span>{{ attachment.fileName }}</span>\n <p-button\n type=\"button\"\n icon=\"pi pi-times\"\n class=\"p-button-rounded p-button-text text-red-600\"\n (click)=\"remove(0)\"\n ></p-button>\n </div>\n <!-- Caption input if allowed -->\n @if (props['allowCaption']) {\n <div class=\"mt-1\">\n <input\n pInputText\n type=\"text\"\n class=\"w-full border rounded px-2 py-1 text-sm\"\n placeholder=\"\u0623\u0636\u0641 \u0648\u0635\u0641\u0627\u064B\"\n (change)=\"attachment = attachment\"\n [(ngModel)]=\"attachment.caption\"\n />\n </div>\n }\n </div>\n }\n </ng-template>\n\n <!-- Empty Template -->\n <ng-template pTemplate=\"empty\">\n @if ((props['multiple'] !== false && (!attachments || attachments.length === 0)) ||\n (props['multiple'] === false && !attachment)) {\n <div\n class=\"border-2 border-dashed rounded-md p-4 bg-gray-50 hover:bg-gray-100 transition flex align-items-center justify-content-center flex-column\"\n >\n <i class=\"pi pi-cloud-upload border-2 rounded p-5 text-8xl text-400 border-400\"></i>\n <p class=\"mt-4 mb-0\">\u0627\u0633\u062D\u0628 \u0648\u0623\u0641\u0644\u0650\u062A \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0647\u0646\u0627 \u0644\u0644\u062A\u062D\u0645\u064A\u0644.</p>\n </div>\n }\n </ng-template>\n</p-fileUpload>\n" }]
|
|
210
|
+
}], ctorParameters: () => [{ type: i1.MessageService }] });
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Generated bundle index. Do not edit.
|
|
214
|
+
*/
|
|
215
|
+
|
|
216
|
+
export { AttachmentTypeComponent, AttachmentsModule };
|
|
217
|
+
//# sourceMappingURL=es.framework-ng.ui.core-attachments.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"es.framework-ng.ui.core-attachments.mjs","sources":["../../../../libs/ng.ui.core/attachments/src/lib/attachments-module.ts","../../../../libs/ng.ui.core/attachments/src/lib/attachment-type.ts","../../../../libs/ng.ui.core/attachments/src/lib/attachment-type.html","../../../../libs/ng.ui.core/attachments/src/es.framework-ng.ui.core-attachments.ts"],"sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\n@NgModule({\n imports: [CommonModule],\n})\nexport class AttachmentsModule {}\n","import { Component, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ReactiveFormsModule, FormsModule } from '@angular/forms';\n\nimport { FieldType } from '@ngx-formly/core';\n\nimport { FileUploadModule } from 'primeng/fileupload';\nimport { ButtonModule } from 'primeng/button';\nimport { MessageService } from 'primeng/api';\n\nimport { InputTextModule } from 'primeng/inputtext';\nimport { AttachmentDto } from '@es.framework/ng.core/models';\nimport { EnvironmentService } from '@es.framework/ng.core/services';\n\n\n@Component({\n selector: 'attachment-type',\n standalone: true,\n imports: [\n CommonModule,\n ReactiveFormsModule,\n FormsModule,\n FileUploadModule,\n ButtonModule,\n InputTextModule\n ],\n providers: [MessageService],\n templateUrl: './attachment-type.html',\n})\nexport class AttachmentTypeComponent extends FieldType {\n defaultAcceptTypes = '.pdf,application/pdf,image/*,.txt,text/plain,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel';\n\n maxFileSize = 1 * 1024 * 1024; // 1 MB\n tenantId = 0;\n private env = inject(EnvironmentService);\n\n constructor(private messageService: MessageService) {\n super();\n\n }\n get url():string{\n return this.env.getEnvironment().apis.default.url + (this.props['apiUrl'] ?? '/api/files');\n }\n get attachments(): AttachmentDto[] {\n return Array.isArray(this.formControl.value)\n ? this.formControl.value\n : (this.formControl.value ? [this.formControl.value] : []);\n }\n\n set attachments(value: AttachmentDto[]) {\n if (this.props['multiple']) {\n this.formControl.setValue(value);\n } else {\n this.formControl.setValue(value?.[0] || null);\n }\n }\n\n get attachment(): AttachmentDto | null {\n return Array.isArray(this.formControl.value)\n ? (this.formControl.value[0] || null)\n : this.formControl.value || null;\n }\n\n\n set attachment(value: AttachmentDto | null) {\n if (this.props['multiple']) {\n const arr = Array.isArray(this.formControl.value)\n ? [...this.formControl.value]\n : (this.formControl.value ? [this.formControl.value] : []);\n if (value) arr.push(value);\n this.formControl.setValue(arr);\n } else {\n this.formControl.setValue(value);\n }\n }\n\n async onUpload(event: any) {\n const files: File[] = event.files;\n const isMultiple = this.props['multiple'] ?? true;\n const allowedTypes = (this.props['accept'] as string) || '';\n\n for (const file of files) {\n if (file.size > this.maxFileSize) {\n this.messageService.add({\n severity: 'error',\n summary: 'خطأ',\n detail: `الملف \"${file.name}\" يتجاوز الحد الأقصى (1MB)`,\n });\n continue;\n }\n\n if (allowedTypes && !this.isFileTypeAllowed(file, allowedTypes)) {\n this.messageService.add({\n severity: 'error',\n summary: 'نوع الملف غير مسموح',\n detail: `الملف \"${file.name}\" ليس من الأنواع المسموحة`,\n });\n continue;\n }\n\n if (isMultiple && this.attachments.some(a => a.fileName === file.name)) {\n continue;\n }\n\n const base64 = await this.fileToBase64(file);\n const attachment = new AttachmentDto();\n attachment.fileName = file.name;\n attachment.mimeType = file.type;\n attachment.base64 = base64;\n\n if (isMultiple) {\n this.attachments = [...this.attachments, attachment];\n } else {\n this.attachment = attachment;\n }\n }\n }\n\n remove(index: number) {\n const copy = [...this.attachments];\n copy.splice(index, 1);\n this.attachments = copy;\n }\n\n choose(event: any, callback: any) {\n callback();\n }\n\n private fileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.readAsDataURL(file);\n reader.onload = () => resolve((reader.result as string).split(',')[1]);\n reader.onerror = err => reject(err);\n });\n }\n\n private isFileTypeAllowed(file: File, allowedTypes: string): boolean {\n const accepted = allowedTypes.split(',').map(t => t.trim());\n return accepted.some(type => {\n if (type === '*/*') return true;\n if (type.endsWith('/*')) {\n return file.type.startsWith(type.split('/')[0] + '/');\n }\n return file.type === type;\n });\n }\n\n getFileLabel(mime: string): string {\n if (!mime) return 'FILE';\n if (mime.includes('pdf')) return 'PDF';\n if (mime.includes('excel') || mime.includes('spreadsheet')) return 'XLS';\n if (mime.includes('word')) return 'DOC';\n if (mime.includes('image')) return 'IMG';\n if (mime.includes('zip')) return 'ZIP';\n if (mime.includes('csv')) return 'CSV';\n if (mime.includes('text')) return 'TXT';\n return 'FILE';\n }\n\n getLabelClass(mime: string): string {\n if (mime.includes('pdf')) return 'bg-red-600 text-white';\n if (mime.includes('excel')) return 'bg-green-600 text-white';\n if (mime.includes('word')) return 'bg-blue-600 text-white';\n if (mime.includes('image')) return 'bg-yellow-500 text-white';\n if (mime.includes('zip')) return 'bg-pink-600 text-white';\n return 'bg-gray-400 text-white';\n }\n\n getIconColor(mime: string): string {\n if (mime.includes('pdf')) return 'text-red-400';\n if (mime.includes('excel')) return 'text-green-500';\n if (mime.includes('word')) return 'text-blue-500';\n if (mime.includes('image')) return 'text-yellow-500';\n if (mime.includes('zip')) return 'text-pink-500';\n return 'text-gray-400';\n }\n\n getFileIcon(mime: string): string {\n if (mime.includes('pdf')) return 'pi pi-file-pdf';\n if (mime.includes('excel') || mime.includes('spreadsheet')) return 'pi pi-file-excel';\n if (mime.includes('word')) return 'pi pi-file-word';\n if (mime.includes('image')) return 'pi pi-image';\n if (mime.includes('zip')) return 'pi pi-file-zip';\n return 'pi pi-file';\n }\n}\n","<p-fileUpload\n name=\"file\"\n [customUpload]=\"true\"\n [auto]=\"true\"\n [multiple]=\"props['multiple'] !== false\"\n [maxFileSize]=\"maxFileSize\"\n [accept]=\"props['accept'] || defaultAcceptTypes\"\n (uploadHandler)=\"onUpload($event)\"\n chooseLabel=\"اسحب الملفات أو انقر للإرفاق\"\n class=\"w-full\"\n >\n <!-- Header Template -->\n <ng-template pTemplate=\"header\" let-chooseCallback=\"chooseCallback\">\n <div class=\"flex flex-wrap justify-content-between align-items-center flex-1 gap-2\">\n <div class=\"flex gap-2\">\n <p-button\n (click)=\"choose($event, chooseCallback)\"\n icon=\"pi pi-plus\"\n [rounded]=\"true\"\n [outlined]=\"true\"\n styleClass=\"border border-green-600 text-green-600 hover:bg-green-100 bg-white shadow-sm !rounded-full\"\n ></p-button>\n </div>\n </div>\n </ng-template>\n\n <!-- Content Template -->\n <ng-template pTemplate=\"content\">\n <!-- Multi mode -->\n <div class=\"p-2 flex flex-wrap gap-4\">\n @for (file of attachments; track file; let i = $index) {\n <div\n style=\"height: 7rem;\"\n class=\"relative w-24 h-28 bg-white border rounded-lg shadow-sm flex flex-col items-center justify-center\"\n >\n <!-- File type label -->\n <div\n class=\"absolute top-0 left-0 px-2 py-0.5 text-[10px] font-bold uppercase rounded-br-md shadow-sm text-white\"\n [ngClass]=\"getLabelClass(file.mimeType)\"\n >\n {{ getFileLabel(file.mimeType) }}\n </div>\n <!-- Remove button -->\n <button\n style=\"top: 3px;right: 3px;\"\n type=\"button\"\n class=\"absolute top-1 right-1 text-red-500 hover:text-red-700\"\n (click)=\"remove(i)\"\n title=\"حذف\"\n >\n <i class=\"pi pi-times text-xs\"></i>\n </button>\n <!-- Center icon -->\n <i\n [class]=\"getFileIcon(file.mimeType)\"\n [ngClass]=\"getIconColor(file.mimeType)\"\n class=\"!text-4xl text-center mt-5\"\n ></i>\n <!-- File name -->\n <div style=\"max-width: 85%;\" class=\"mt-1 text-[11px] text-gray-600 truncate max-w-[85%] text-center\">\n <div class=\"truncate\">{{ file.fileName }}</div>\n </div>\n <!-- Download icon -->\n @if (file.binaryObjectId) {\n <a\n style=\"bottom: 3px;right: 3px;\"\n class=\"absolute bottom-1 right-1 text-gray-400 hover:text-blue-500\"\n [href]=\"url+'/' + file.binaryObjectId\"\n target=\"_blank\"\n download\n title=\"تحميل\"\n >\n <i class=\"pi pi-download text-xs\"></i>\n </a>\n }\n </div>\n }\n </div>\n\n <!-- Single mode -->\n @if (props['multiple'] === false && attachment) {\n <div>\n <div class=\"flex items-center justify-between p-2 border-b\">\n <span>{{ attachment.fileName }}</span>\n <p-button\n type=\"button\"\n icon=\"pi pi-times\"\n class=\"p-button-rounded p-button-text text-red-600\"\n (click)=\"remove(0)\"\n ></p-button>\n </div>\n <!-- Caption input if allowed -->\n @if (props['allowCaption']) {\n <div class=\"mt-1\">\n <input\n pInputText\n type=\"text\"\n class=\"w-full border rounded px-2 py-1 text-sm\"\n placeholder=\"أضف وصفاً\"\n (change)=\"attachment = attachment\"\n [(ngModel)]=\"attachment.caption\"\n />\n </div>\n }\n </div>\n }\n </ng-template>\n\n <!-- Empty Template -->\n <ng-template pTemplate=\"empty\">\n @if ((props['multiple'] !== false && (!attachments || attachments.length === 0)) ||\n (props['multiple'] === false && !attachment)) {\n <div\n class=\"border-2 border-dashed rounded-md p-4 bg-gray-50 hover:bg-gray-100 transition flex align-items-center justify-content-center flex-column\"\n >\n <i class=\"pi pi-cloud-upload border-2 rounded p-5 text-8xl text-400 border-400\"></i>\n <p class=\"mt-4 mb-0\">اسحب وأفلِت الملفات هنا للتحميل.</p>\n </div>\n }\n </ng-template>\n</p-fileUpload>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|