@corp-products/ui-components 3.6.8 → 3.6.9
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { ViewEncapsulation, Component, Input, ChangeDetectionStrategy, model, inject, Pipe, EventEmitter, Output, Injectable, Renderer2, ChangeDetectorRef, signal, effect, HostListener, ViewChild, InjectionToken, Injector, createComponent, ViewContainerRef, ApplicationRef, EnvironmentInjector, DestroyRef } from '@angular/core';
|
|
2
|
+
import { ViewEncapsulation, Component, Input, ChangeDetectionStrategy, model, inject, Pipe, EventEmitter, Output, Injectable, Renderer2, ChangeDetectorRef, signal, effect, HostListener, ViewChild, input, computed, InjectionToken, Injector, createComponent, ViewContainerRef, ApplicationRef, EnvironmentInjector, DestroyRef } from '@angular/core';
|
|
3
3
|
import * as i1 from 'primeng/button';
|
|
4
4
|
import { Button, ButtonModule, ButtonStyle } from 'primeng/button';
|
|
5
5
|
import * as i1$1 from '@angular/common';
|
|
@@ -870,6 +870,7 @@ var FormFieldTypeEnum;
|
|
|
870
870
|
FormFieldTypeEnum["SWITCH"] = "switch";
|
|
871
871
|
FormFieldTypeEnum["AUTO_COMPLETE"] = "auto-complete";
|
|
872
872
|
FormFieldTypeEnum["HIJRI_DATE_PICKER"] = "hijri-date";
|
|
873
|
+
FormFieldTypeEnum["UPLOAD_FILE"] = "upload-file";
|
|
873
874
|
})(FormFieldTypeEnum || (FormFieldTypeEnum = {}));
|
|
874
875
|
|
|
875
876
|
const WEEKDAYS = {
|
|
@@ -1532,6 +1533,320 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
1532
1533
|
args: ['document:click', ['$event']]
|
|
1533
1534
|
}] } });
|
|
1534
1535
|
|
|
1536
|
+
/**
|
|
1537
|
+
* Transforms file size from bytes to readable format (B, KB, MB, GB, TB).
|
|
1538
|
+
*
|
|
1539
|
+
* Usage:
|
|
1540
|
+
* {{ fileSize | fileSize }} // Default: auto unit, 2 decimals
|
|
1541
|
+
* {{ fileSize | fileSize:0 }} // Auto unit, 0 decimals
|
|
1542
|
+
* {{ fileSize | fileSize:2:'MB' }} // Force MB, 2 decimals
|
|
1543
|
+
*
|
|
1544
|
+
* @param value - File size in bytes
|
|
1545
|
+
* @param decimals - Number of decimal places (default: 2)
|
|
1546
|
+
* @param unit - Unit: 'B', 'KB', 'MB', 'GB', 'TB' (default: auto)
|
|
1547
|
+
*/
|
|
1548
|
+
class FileSizePipe {
|
|
1549
|
+
units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
1550
|
+
k = 1024;
|
|
1551
|
+
transform(bytes, decimals = 2, unit) {
|
|
1552
|
+
if (bytes === null || bytes === undefined || isNaN(bytes)) {
|
|
1553
|
+
return '0 B';
|
|
1554
|
+
}
|
|
1555
|
+
if (bytes === 0) {
|
|
1556
|
+
return '0 B';
|
|
1557
|
+
}
|
|
1558
|
+
// If a specific unit is requested
|
|
1559
|
+
if (unit) {
|
|
1560
|
+
const unitIndex = this.units.indexOf(unit);
|
|
1561
|
+
if (unitIndex === -1) {
|
|
1562
|
+
return this.autoFormat(bytes, decimals);
|
|
1563
|
+
}
|
|
1564
|
+
const divisor = Math.pow(this.k, unitIndex);
|
|
1565
|
+
const value = bytes / divisor;
|
|
1566
|
+
return `${this.formatNumber(value, decimals)} ${unit}`;
|
|
1567
|
+
}
|
|
1568
|
+
// Auto-detect the best unit
|
|
1569
|
+
return this.autoFormat(bytes, decimals);
|
|
1570
|
+
}
|
|
1571
|
+
autoFormat(bytes, decimals) {
|
|
1572
|
+
const i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(this.k));
|
|
1573
|
+
const unitIndex = Math.min(i, this.units.length - 1);
|
|
1574
|
+
const value = bytes / Math.pow(this.k, unitIndex);
|
|
1575
|
+
return `${this.formatNumber(value, decimals)} ${this.units[unitIndex]}`;
|
|
1576
|
+
}
|
|
1577
|
+
formatNumber(value, decimals) {
|
|
1578
|
+
return parseFloat(value.toFixed(decimals)).toString();
|
|
1579
|
+
}
|
|
1580
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FileSizePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1581
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: FileSizePipe, isStandalone: true, name: "fileSize" });
|
|
1582
|
+
}
|
|
1583
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FileSizePipe, decorators: [{
|
|
1584
|
+
type: Pipe,
|
|
1585
|
+
args: [{
|
|
1586
|
+
name: 'fileSize',
|
|
1587
|
+
standalone: true,
|
|
1588
|
+
}]
|
|
1589
|
+
}] });
|
|
1590
|
+
|
|
1591
|
+
var UploadStatus;
|
|
1592
|
+
(function (UploadStatus) {
|
|
1593
|
+
UploadStatus["PENDING"] = "pending";
|
|
1594
|
+
UploadStatus["UPLOADING"] = "uploading";
|
|
1595
|
+
UploadStatus["SUCCESS"] = "success";
|
|
1596
|
+
UploadStatus["FAILED"] = "failed";
|
|
1597
|
+
})(UploadStatus || (UploadStatus = {}));
|
|
1598
|
+
|
|
1599
|
+
class FileManagementComponent {
|
|
1600
|
+
// Inputs
|
|
1601
|
+
existingFiles = input([], ...(ngDevMode ? [{ debugName: "existingFiles" }] : []));
|
|
1602
|
+
acceptedTypes = input('*', ...(ngDevMode ? [{ debugName: "acceptedTypes" }] : []));
|
|
1603
|
+
maxFileSize = input(10485760, ...(ngDevMode ? [{ debugName: "maxFileSize" }] : [])); //250 MB
|
|
1604
|
+
maxConcurrentUploads = input(3, ...(ngDevMode ? [{ debugName: "maxConcurrentUploads" }] : []));
|
|
1605
|
+
showTable = input(true, ...(ngDevMode ? [{ debugName: "showTable" }] : []));
|
|
1606
|
+
showDropZone = input(true, ...(ngDevMode ? [{ debugName: "showDropZone" }] : []));
|
|
1607
|
+
allowPreview = input(true, ...(ngDevMode ? [{ debugName: "allowPreview" }] : []));
|
|
1608
|
+
permissonKey = input('', ...(ngDevMode ? [{ debugName: "permissonKey" }] : []));
|
|
1609
|
+
allowedActions = input([], ...(ngDevMode ? [{ debugName: "allowedActions" }] : []));
|
|
1610
|
+
uploadedFile = signal([], ...(ngDevMode ? [{ debugName: "uploadedFile" }] : []));
|
|
1611
|
+
// Outputs
|
|
1612
|
+
filesUploaded = new EventEmitter();
|
|
1613
|
+
fileDeleted = new EventEmitter();
|
|
1614
|
+
filePreview = new EventEmitter();
|
|
1615
|
+
fileDownload = new EventEmitter();
|
|
1616
|
+
uploadError = new EventEmitter();
|
|
1617
|
+
newFilesChange = new EventEmitter();
|
|
1618
|
+
fileInput;
|
|
1619
|
+
destroy$ = new Subject();
|
|
1620
|
+
// State - separate new uploads from existing files
|
|
1621
|
+
isDragOver = signal(false, ...(ngDevMode ? [{ debugName: "isDragOver" }] : []));
|
|
1622
|
+
newFiles = signal([], ...(ngDevMode ? [{ debugName: "newFiles" }] : [])); // Files being uploaded or newly uploaded
|
|
1623
|
+
uploadedResponses = [];
|
|
1624
|
+
// Combined files list for the table (existing + new)
|
|
1625
|
+
allFiles = computed(() => {
|
|
1626
|
+
const existing = this.existingFiles().map((f) => ({
|
|
1627
|
+
...f,
|
|
1628
|
+
status: undefined, // Don't show status for existing files
|
|
1629
|
+
isNew: false,
|
|
1630
|
+
}));
|
|
1631
|
+
const newOnes = this.newFiles();
|
|
1632
|
+
return [...newOnes, ...existing];
|
|
1633
|
+
}, ...(ngDevMode ? [{ debugName: "allFiles" }] : []));
|
|
1634
|
+
// Get only successfully uploaded new file IDs
|
|
1635
|
+
uploadedNewFileIds = computed(() => {
|
|
1636
|
+
return this.newFiles()
|
|
1637
|
+
.filter((f) => f.status === UploadStatus.SUCCESS && f.id && !f.id.startsWith('temp-'))
|
|
1638
|
+
.map((f) => f.id);
|
|
1639
|
+
}, ...(ngDevMode ? [{ debugName: "uploadedNewFileIds" }] : []));
|
|
1640
|
+
// Formatted accepted file types for display
|
|
1641
|
+
formattedAcceptedTypes = computed(() => {
|
|
1642
|
+
const accepted = this.acceptedTypes();
|
|
1643
|
+
if (accepted === '*' || accepted === '*/*')
|
|
1644
|
+
return '';
|
|
1645
|
+
return accepted
|
|
1646
|
+
.split(',')
|
|
1647
|
+
.map((type) => type.trim().replace('.', '').toUpperCase())
|
|
1648
|
+
.join(', ');
|
|
1649
|
+
}, ...(ngDevMode ? [{ debugName: "formattedAcceptedTypes" }] : []));
|
|
1650
|
+
// Table configuration
|
|
1651
|
+
constructor() {
|
|
1652
|
+
// Emit when new files change
|
|
1653
|
+
effect(() => {
|
|
1654
|
+
const newFilesList = this.newFiles();
|
|
1655
|
+
this.newFilesChange.emit(newFilesList);
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
ngOnDestroy() {
|
|
1659
|
+
this.destroy$.next();
|
|
1660
|
+
this.destroy$.complete();
|
|
1661
|
+
}
|
|
1662
|
+
// Drag & Drop handlers
|
|
1663
|
+
onDragOver(event) {
|
|
1664
|
+
event.preventDefault();
|
|
1665
|
+
event.stopPropagation();
|
|
1666
|
+
this.isDragOver.set(true);
|
|
1667
|
+
}
|
|
1668
|
+
onDragLeave(event) {
|
|
1669
|
+
event.preventDefault();
|
|
1670
|
+
event.stopPropagation();
|
|
1671
|
+
this.isDragOver.set(false);
|
|
1672
|
+
}
|
|
1673
|
+
onDrop(event) {
|
|
1674
|
+
event.preventDefault();
|
|
1675
|
+
event.stopPropagation();
|
|
1676
|
+
this.isDragOver.set(false);
|
|
1677
|
+
const droppedFiles = event.dataTransfer?.files;
|
|
1678
|
+
if (droppedFiles) {
|
|
1679
|
+
this.handleFiles(Array.from(droppedFiles));
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
// Browse button handler
|
|
1683
|
+
onBrowseClick() {
|
|
1684
|
+
this.fileInput.nativeElement.click();
|
|
1685
|
+
}
|
|
1686
|
+
onFileInputChange(event) {
|
|
1687
|
+
const input = event.target;
|
|
1688
|
+
if (input.files) {
|
|
1689
|
+
this.handleFiles(Array.from(input.files));
|
|
1690
|
+
// Reset input to allow selecting the same file again
|
|
1691
|
+
input.value = '';
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
// Public method to trigger file selection from parent
|
|
1695
|
+
triggerFileInput() {
|
|
1696
|
+
this.fileInput?.nativeElement?.click();
|
|
1697
|
+
}
|
|
1698
|
+
// Public method to append file selection from parent
|
|
1699
|
+
appendFileFromParent(file) {
|
|
1700
|
+
this.handleFiles([file]);
|
|
1701
|
+
}
|
|
1702
|
+
// Public method to upload files programmatically from parent
|
|
1703
|
+
uploadFilesFromParent(files) {
|
|
1704
|
+
this.handleFiles(files);
|
|
1705
|
+
}
|
|
1706
|
+
// Public method to get new uploaded file IDs
|
|
1707
|
+
getUploadedFileIds() {
|
|
1708
|
+
return this.uploadedNewFileIds();
|
|
1709
|
+
}
|
|
1710
|
+
// Public method to clear new files (after save)
|
|
1711
|
+
clearNewFiles() {
|
|
1712
|
+
this.newFiles.set([]);
|
|
1713
|
+
this.uploadedResponses = [];
|
|
1714
|
+
}
|
|
1715
|
+
// Public method to remove a new file by ID
|
|
1716
|
+
removeNewFile(fileId) {
|
|
1717
|
+
this.newFiles.update((files) => files.filter((f) => f.id !== fileId));
|
|
1718
|
+
}
|
|
1719
|
+
// Check if there are pending/uploading files
|
|
1720
|
+
// File handling
|
|
1721
|
+
handleFiles(filesToProcess) {
|
|
1722
|
+
const validFiles = [];
|
|
1723
|
+
for (const file of filesToProcess) {
|
|
1724
|
+
// Validate file size
|
|
1725
|
+
if (file.size > this.maxFileSize()) {
|
|
1726
|
+
this.uploadError.emit({
|
|
1727
|
+
file,
|
|
1728
|
+
error: `File ${file.name} exceeds maximum size of ${this.formatFileSize(this.maxFileSize())}`,
|
|
1729
|
+
});
|
|
1730
|
+
continue;
|
|
1731
|
+
}
|
|
1732
|
+
// Validate file type
|
|
1733
|
+
// if (!this.isValidFileType(file)) {
|
|
1734
|
+
// this.uploadError.emit({
|
|
1735
|
+
// file,
|
|
1736
|
+
// error: `File type not allowed: ${file.type}`,
|
|
1737
|
+
// });
|
|
1738
|
+
// continue;
|
|
1739
|
+
// }
|
|
1740
|
+
validFiles.push(file);
|
|
1741
|
+
}
|
|
1742
|
+
if (validFiles.length > 0) {
|
|
1743
|
+
// this.uploadFiles(validFiles);
|
|
1744
|
+
this.uploadedFile.set(validFiles);
|
|
1745
|
+
this.filesUploaded.emit(validFiles);
|
|
1746
|
+
console.log('uploadedFile', this.uploadedFile());
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
deleteFile() {
|
|
1750
|
+
this.uploadedFile.set([]);
|
|
1751
|
+
this.filesUploaded.emit([]);
|
|
1752
|
+
}
|
|
1753
|
+
isValidFileType(file) {
|
|
1754
|
+
const accepted = this.acceptedTypes();
|
|
1755
|
+
if (accepted === '*' || accepted === '*/*')
|
|
1756
|
+
return true;
|
|
1757
|
+
const acceptedTypes = accepted.split(',').map((t) => t.trim().toLowerCase());
|
|
1758
|
+
const fileType = file.type.toLowerCase();
|
|
1759
|
+
const fileExt = '.' + file.name.split('.').pop()?.toLowerCase();
|
|
1760
|
+
return acceptedTypes.some((type) => {
|
|
1761
|
+
if (type.startsWith('.')) {
|
|
1762
|
+
return fileExt === type;
|
|
1763
|
+
}
|
|
1764
|
+
if (type.endsWith('/*')) {
|
|
1765
|
+
return fileType.startsWith(type.replace('/*', '/'));
|
|
1766
|
+
}
|
|
1767
|
+
return fileType === type;
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
updateFileFromAttachment(attachment) {
|
|
1771
|
+
this.newFiles.update((currentFiles) => {
|
|
1772
|
+
return currentFiles.map((file) => {
|
|
1773
|
+
// Match by file name and size
|
|
1774
|
+
if (file.fileName === attachment.nameFile && file.size === attachment.size) {
|
|
1775
|
+
const updatedFile = {
|
|
1776
|
+
...file,
|
|
1777
|
+
progress: attachment.status?.percentage ?? 0,
|
|
1778
|
+
error: attachment.errorMessage,
|
|
1779
|
+
};
|
|
1780
|
+
// If upload succeeded, update with response data from serverResponse
|
|
1781
|
+
if (attachment.uploadStatus === UploadStatus.SUCCESS && attachment.serverResponse) {
|
|
1782
|
+
const serverData = attachment.serverResponse;
|
|
1783
|
+
const responseFile = {
|
|
1784
|
+
id: attachment.id || serverData?.id || file.id,
|
|
1785
|
+
fileName: serverData?.fileName || attachment.nameFile,
|
|
1786
|
+
size: serverData?.size || attachment.size,
|
|
1787
|
+
mimeType: serverData?.mimeType || file.mimeType,
|
|
1788
|
+
};
|
|
1789
|
+
this.uploadedResponses.push(responseFile);
|
|
1790
|
+
return {
|
|
1791
|
+
...updatedFile,
|
|
1792
|
+
id: responseFile.id,
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1795
|
+
return updatedFile;
|
|
1796
|
+
}
|
|
1797
|
+
return file;
|
|
1798
|
+
});
|
|
1799
|
+
});
|
|
1800
|
+
}
|
|
1801
|
+
// Actions
|
|
1802
|
+
onDeleteFile(file) {
|
|
1803
|
+
const isNewFile = file.isNew;
|
|
1804
|
+
this.fileDeleted.emit({ fileId: file.id, isNew: !!isNewFile });
|
|
1805
|
+
if (isNewFile) {
|
|
1806
|
+
// Remove from newFiles list immediately for new uploads
|
|
1807
|
+
this.newFiles.update((files) => files.filter((f) => f.id !== file.id));
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
onPreviewFile(file) {
|
|
1811
|
+
this.filePreview.emit(file);
|
|
1812
|
+
}
|
|
1813
|
+
removeFileFromList(fileId) {
|
|
1814
|
+
this.newFiles.update((current) => current.filter((f) => f.id !== fileId));
|
|
1815
|
+
}
|
|
1816
|
+
generateTempId(file) {
|
|
1817
|
+
return `temp-${file.name}-${file.size}-${Date.now()}`;
|
|
1818
|
+
}
|
|
1819
|
+
formatFileSize(bytes) {
|
|
1820
|
+
if (bytes === 0)
|
|
1821
|
+
return '0 B';
|
|
1822
|
+
const k = 1024;
|
|
1823
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
1824
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
1825
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
1826
|
+
}
|
|
1827
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FileManagementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1828
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: FileManagementComponent, isStandalone: true, selector: "app-file-management", inputs: { existingFiles: { classPropertyName: "existingFiles", publicName: "existingFiles", isSignal: true, isRequired: false, transformFunction: null }, acceptedTypes: { classPropertyName: "acceptedTypes", publicName: "acceptedTypes", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, maxConcurrentUploads: { classPropertyName: "maxConcurrentUploads", publicName: "maxConcurrentUploads", isSignal: true, isRequired: false, transformFunction: null }, showTable: { classPropertyName: "showTable", publicName: "showTable", isSignal: true, isRequired: false, transformFunction: null }, showDropZone: { classPropertyName: "showDropZone", publicName: "showDropZone", isSignal: true, isRequired: false, transformFunction: null }, allowPreview: { classPropertyName: "allowPreview", publicName: "allowPreview", isSignal: true, isRequired: false, transformFunction: null }, permissonKey: { classPropertyName: "permissonKey", publicName: "permissonKey", isSignal: true, isRequired: false, transformFunction: null }, allowedActions: { classPropertyName: "allowedActions", publicName: "allowedActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesUploaded: "filesUploaded", fileDeleted: "fileDeleted", filePreview: "filePreview", fileDownload: "fileDownload", uploadError: "uploadError", newFilesChange: "newFilesChange" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"file-management\">\r\n <!-- Drop Zone -->\r\n @if (showDropZone()) {\r\n <div\r\n class=\"drop-zone upload-container\"\r\n [class.drag-over]=\"isDragOver()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <div class=\"drop-zone-content\">\r\n <p class=\"drop-text\">{{ 'file.drag_drop_files' | translate }}</p>\r\n <p-button\r\n [label]=\"'file.browse' | translate\"\r\n severity=\"danger\"\r\n [outlined]=\"true\"\r\n (onClick)=\"onBrowseClick()\"\r\n />\r\n <p class=\"drop-hint text-xs text-gray-500 mt-2\">\r\n {{ 'file.max_size_hint' | translate }}: {{ maxFileSize() | fileSize: 2 : 'MB' }}\r\n </p>\r\n @if (formattedAcceptedTypes()) {\r\n <p class=\"accepted-types text-xs text-gray-400\">\r\n {{ 'file.accepted_types' | translate }}: {{ formattedAcceptedTypes() }}\r\n </p>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Hidden file input (always present for programmatic access) -->\r\n <input\r\n #fileInput\r\n type=\"file\"\r\n [accept]=\"acceptedTypes()\"\r\n multiple\r\n hidden\r\n (change)=\"onFileInputChange($event)\"\r\n />\r\n\r\n @if(uploadedFile().length) {\r\n @for(file of uploadedFile() ; track file) {\r\n <div class=\"uploaded-files \" >\r\n <p>{{file.name}}</p>\r\n <i class=\"pi pi-trash\" style=\"font-size: 1.5rem; color: #f00\" (click)=\"deleteFile()\"></i>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Files Table -->\r\n\r\n</div>\r\n", styles: [".file-management{width:100%}.drop-zone{@apply cursor-pointer rounded-l border-2 border-dashed border-gray-300 p-8 bg-purple-light3 text-center transition-all duration-200 ease-in-out;}.drop-zone.drag-over{@apply border-purple-200 bg-purple-light;}.drop-zone-content{@apply flex flex-col items-center gap-2;}.drop-icon{font-size:3rem;color:var(--gray-400, #9ca3af);margin-bottom:.5rem}.drop-text{font-size:1rem;color:var(--gray-700, #374151);margin:0}.drop-or{font-size:.875rem;color:var(--gray-500, #6b7280);margin:.25rem 0}.drop-hint{margin-top:.75rem}.files-table{border:1px solid var(--gray-200, #e5e7eb);border-radius:8px;overflow:hidden}:host-context([dir=rtl]) .drop-zone-content{direction:rtl}.uploaded-files{background-color:#f3f3f7;border:1px solid #DFE0E6;display:flex;justify-content:space-between;align-items:center;padding:15px;margin-bottom:10px}.uploaded-files .pi-trash{cursor:pointer}.uploaded-files p{margin-block-start:0;margin-block-end:0}.upload-container{background-color:#f3f3f7;padding:15px;border:1px dashed #DFE0E6;margin-bottom:15px;display:flex;justify-content:center;align-items:center;border-radius:2px}.upload-container .drop-zone-content{display:flex;align-items:center;flex-direction:column}.upload-container .drop-zone-content .drop-text{margin-bottom:10px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1.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: TooltipModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: FileSizePipe, name: "fileSize" }] });
|
|
1829
|
+
}
|
|
1830
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FileManagementComponent, decorators: [{
|
|
1831
|
+
type: Component,
|
|
1832
|
+
args: [{ selector: 'app-file-management', imports: [CommonModule, TranslatePipe, ButtonModule, TooltipModule, FileSizePipe], template: "<div class=\"file-management\">\r\n <!-- Drop Zone -->\r\n @if (showDropZone()) {\r\n <div\r\n class=\"drop-zone upload-container\"\r\n [class.drag-over]=\"isDragOver()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <div class=\"drop-zone-content\">\r\n <p class=\"drop-text\">{{ 'file.drag_drop_files' | translate }}</p>\r\n <p-button\r\n [label]=\"'file.browse' | translate\"\r\n severity=\"danger\"\r\n [outlined]=\"true\"\r\n (onClick)=\"onBrowseClick()\"\r\n />\r\n <p class=\"drop-hint text-xs text-gray-500 mt-2\">\r\n {{ 'file.max_size_hint' | translate }}: {{ maxFileSize() | fileSize: 2 : 'MB' }}\r\n </p>\r\n @if (formattedAcceptedTypes()) {\r\n <p class=\"accepted-types text-xs text-gray-400\">\r\n {{ 'file.accepted_types' | translate }}: {{ formattedAcceptedTypes() }}\r\n </p>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Hidden file input (always present for programmatic access) -->\r\n <input\r\n #fileInput\r\n type=\"file\"\r\n [accept]=\"acceptedTypes()\"\r\n multiple\r\n hidden\r\n (change)=\"onFileInputChange($event)\"\r\n />\r\n\r\n @if(uploadedFile().length) {\r\n @for(file of uploadedFile() ; track file) {\r\n <div class=\"uploaded-files \" >\r\n <p>{{file.name}}</p>\r\n <i class=\"pi pi-trash\" style=\"font-size: 1.5rem; color: #f00\" (click)=\"deleteFile()\"></i>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Files Table -->\r\n\r\n</div>\r\n", styles: [".file-management{width:100%}.drop-zone{@apply cursor-pointer rounded-l border-2 border-dashed border-gray-300 p-8 bg-purple-light3 text-center transition-all duration-200 ease-in-out;}.drop-zone.drag-over{@apply border-purple-200 bg-purple-light;}.drop-zone-content{@apply flex flex-col items-center gap-2;}.drop-icon{font-size:3rem;color:var(--gray-400, #9ca3af);margin-bottom:.5rem}.drop-text{font-size:1rem;color:var(--gray-700, #374151);margin:0}.drop-or{font-size:.875rem;color:var(--gray-500, #6b7280);margin:.25rem 0}.drop-hint{margin-top:.75rem}.files-table{border:1px solid var(--gray-200, #e5e7eb);border-radius:8px;overflow:hidden}:host-context([dir=rtl]) .drop-zone-content{direction:rtl}.uploaded-files{background-color:#f3f3f7;border:1px solid #DFE0E6;display:flex;justify-content:space-between;align-items:center;padding:15px;margin-bottom:10px}.uploaded-files .pi-trash{cursor:pointer}.uploaded-files p{margin-block-start:0;margin-block-end:0}.upload-container{background-color:#f3f3f7;padding:15px;border:1px dashed #DFE0E6;margin-bottom:15px;display:flex;justify-content:center;align-items:center;border-radius:2px}.upload-container .drop-zone-content{display:flex;align-items:center;flex-direction:column}.upload-container .drop-zone-content .drop-text{margin-bottom:10px}\n"] }]
|
|
1833
|
+
}], ctorParameters: () => [], propDecorators: { existingFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "existingFiles", required: false }] }], acceptedTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "acceptedTypes", required: false }] }], maxFileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSize", required: false }] }], maxConcurrentUploads: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxConcurrentUploads", required: false }] }], showTable: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTable", required: false }] }], showDropZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDropZone", required: false }] }], allowPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowPreview", required: false }] }], permissonKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "permissonKey", required: false }] }], allowedActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowedActions", required: false }] }], filesUploaded: [{
|
|
1834
|
+
type: Output
|
|
1835
|
+
}], fileDeleted: [{
|
|
1836
|
+
type: Output
|
|
1837
|
+
}], filePreview: [{
|
|
1838
|
+
type: Output
|
|
1839
|
+
}], fileDownload: [{
|
|
1840
|
+
type: Output
|
|
1841
|
+
}], uploadError: [{
|
|
1842
|
+
type: Output
|
|
1843
|
+
}], newFilesChange: [{
|
|
1844
|
+
type: Output
|
|
1845
|
+
}], fileInput: [{
|
|
1846
|
+
type: ViewChild,
|
|
1847
|
+
args: ['fileInput']
|
|
1848
|
+
}] } });
|
|
1849
|
+
|
|
1535
1850
|
class LocalizedLabelPipe {
|
|
1536
1851
|
translateService = inject(TranslateService);
|
|
1537
1852
|
transform(label) {
|
|
@@ -1562,6 +1877,8 @@ class DynamicFormComponent {
|
|
|
1562
1877
|
switchChange = new EventEmitter();
|
|
1563
1878
|
autoCompleteSearch = new EventEmitter();
|
|
1564
1879
|
autoCompleteSelect = new EventEmitter();
|
|
1880
|
+
popUpFilesUploaded = new EventEmitter();
|
|
1881
|
+
fileDeleted = new EventEmitter();
|
|
1565
1882
|
inputsNames = [];
|
|
1566
1883
|
formGroup;
|
|
1567
1884
|
inputsMap;
|
|
@@ -1572,8 +1889,14 @@ class DynamicFormComponent {
|
|
|
1572
1889
|
this.inputsMap = this.dynamicFormData?.inputsMap;
|
|
1573
1890
|
this.inputsNames = Object.keys(this.inputsMap || {});
|
|
1574
1891
|
}
|
|
1892
|
+
onFilesUploaded(file) {
|
|
1893
|
+
this.popUpFilesUploaded.emit(file);
|
|
1894
|
+
}
|
|
1895
|
+
onFileDeleted(file) {
|
|
1896
|
+
this.fileDeleted.emit(file);
|
|
1897
|
+
}
|
|
1575
1898
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1576
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DynamicFormComponent, isStandalone: true, selector: "app-dynamic-form", inputs: { dynamicFormData: "dynamicFormData" }, outputs: { selectButtonChange: "selectButtonChange", selectChange: "selectChange", switchChange: "switchChange", autoCompleteSearch: "autoCompleteSearch", autoCompleteSelect: "autoCompleteSelect" }, ngImport: i0, template: "<form [formGroup]=\"formGroup\" class=\"dynamic-form\">\r\n <div class=\"grid grid-cols-12 gap-x-2\">\r\n @for (inputName of inputsNames; track $index) {\r\n <div [ngClass]=\"inputsMap[inputName].rowSize\">\r\n @switch (inputsMap[inputName].fieldType) {\r\n @case (fieldType.HIJRI_DATE_PICKER) {\r\n
|
|
1899
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DynamicFormComponent, isStandalone: true, selector: "app-dynamic-form", inputs: { dynamicFormData: "dynamicFormData" }, outputs: { selectButtonChange: "selectButtonChange", selectChange: "selectChange", switchChange: "switchChange", autoCompleteSearch: "autoCompleteSearch", autoCompleteSelect: "autoCompleteSelect", popUpFilesUploaded: "popUpFilesUploaded", fileDeleted: "fileDeleted" }, ngImport: i0, template: "<form [formGroup]=\"formGroup\" class=\"dynamic-form\">\r\n <div class=\"grid grid-cols-12 gap-x-2\">\r\n @for (inputName of inputsNames; track $index) {\r\n <div [ngClass]=\"inputsMap[inputName].rowSize\">\r\n @switch (inputsMap[inputName].fieldType) {\r\n @case (fieldType.HIJRI_DATE_PICKER) {\r\n <app-dual-calendar [control]=\"getFormControl(inputName, formGroup)\"></app-dual-calendar>\r\n }\r\n\r\n @case (fieldType.DATE_PICKER) {\r\n <stc-date-picker [minDate]=\"inputsMap[inputName]?.dateRange?.min\" [maxDate]=\"inputsMap[inputName]?.dateRange?.max\"\r\n [id]=\"inputsMap[inputName].inputId\" [control]=\"getFormControl(inputName, formGroup)\" [name]=\"inputName\"\r\n [label]=\"inputsMap[inputName].label\" [placeholder]=\"inputsMap[inputName].placeholder || ''\"\r\n [hint]=\"inputsMap[inputName].hint\"\r\n [readonly]=\"inputsMap[inputName].readonly || dynamicFormData.isReadOnlyForm || false\"\r\n [disabled]=\"inputsMap[inputName].disabled || false\" [variant]=\"inputsMap[inputName].variant || 'over'\"\r\n [showIcon]=\"inputsMap[inputName].showIcon !== false\" [isTimeOnly]=\"inputsMap[inputName].isTimeOnly || false\" />\r\n }\r\n @case (fieldType.SELECT_BUTTON) {\r\n <stc-select-button [control]=\"getFormControl(inputName, formGroup)\" [id]=\"inputsMap[inputName].inputId\"\r\n [name]=\"inputName\" [label]=\"inputsMap[inputName].label\"\r\n [options]=\"inputsMap[inputName].selectButtonOptions || []\"\r\n (onChange)=\"selectButtonChange.emit({ name: inputName, value: $event })\" />\r\n }\r\n @case (fieldType.INPUT) {\r\n <stc-input [control]=\"getFormControl(inputName, formGroup)\" [id]=\"inputsMap[inputName].inputId\" [name]=\"inputName\"\r\n [label]=\"inputsMap[inputName].label\" [placeholder]=\"inputsMap[inputName].placeholder || ''\"\r\n [hint]=\"inputsMap[inputName].hint\"\r\n [readonly]=\"inputsMap[inputName].readonly || dynamicFormData.isReadOnlyForm || false\"\r\n [disabled]=\"inputsMap[inputName].disabled || false\" [type]=\"inputsMap[inputName].inputType || 'text'\"\r\n [contentType]=\"inputsMap[inputName].contentType || 'text'\" [rows]=\"inputsMap[inputName].rows || 2\"\r\n [cols]=\"inputsMap[inputName].cols || 20\" [autoResize]=\"inputsMap[inputName].autoResize ?? false\"\r\n [prefix]=\"inputsMap[inputName].prefix || ''\" [size]=\"inputsMap[inputName].size || 'small'\"\r\n [variant]=\"inputsMap[inputName].variant || 'over'\">\r\n @if(inputsMap[inputName].maxLength){\r\n <span class=\"text-xs text-gray-700\">\r\n {{ (getFormControl(inputName, formGroup).value?.length || 0) }}\r\n <span> / {{ inputsMap[inputName].maxLength}}</span>\r\n </span>\r\n }\r\n </stc-input>\r\n }\r\n @case (fieldType.SELECT) {\r\n <stc-select [control]=\"getFormControl(inputName, formGroup)\" [id]=\"inputsMap[inputName].inputId\"\r\n [name]=\"inputName\" [label]=\"inputsMap[inputName].label\" [placeholder]=\"inputsMap[inputName].placeholder || ''\"\r\n [hint]=\"inputsMap[inputName].hint\"\r\n [readonly]=\"inputsMap[inputName].readonly || dynamicFormData.isReadOnlyForm || false\"\r\n [disabled]=\"inputsMap[inputName].disabled || false\" [options]=\"inputsMap[inputName].selectOptions || []\"\r\n [optionLabel]=\"inputsMap[inputName]?.translatable\r\n ? ((inputsMap[inputName]?.optionLabel || 'label') | localizedLabel)\r\n : (inputsMap[inputName]?.optionLabel || 'label')\"\r\n [filter]=\"inputsMap[inputName].filter || false\"\r\n [multiple]=\"inputsMap[inputName].multiple || false\" [showClear]=\"inputsMap[inputName].showClear || false\"\r\n [checkmark]=\"inputsMap[inputName].checkmark ?? true\" [filterBy]=\"inputsMap[inputName].filterBy || ''\"\r\n [selectedItemsLabel]=\"inputsMap[inputName].selectedItemsLabel || ''\"\r\n [size]=\"inputsMap[inputName].size || 'small'\" [variant]=\"inputsMap[inputName].variant || 'over'\"\r\n (change)=\"selectChange.emit({ name: inputName, event: $event })\" />\r\n }\r\n @case (fieldType.SWITCH) {\r\n <stc-switch [label]=\"inputsMap[inputName].label\" [key]=\"inputName\"\r\n [checked]=\"getFormControl(inputName, formGroup).value\"\r\n (onChange)=\"getFormControl(inputName, formGroup).setValue(typeof $event === 'string' ? ($event === 'true') : $event); switchChange.emit({ name: inputName, value: (typeof $event === 'string' ? ($event === 'true') : $event) })\" />\r\n }\r\n @case (fieldType.AUTO_COMPLETE) {\r\n <stc-auto-complete [control]=\"getFormControl(inputName, formGroup)\" [id]=\"inputsMap[inputName].inputId\"\r\n [name]=\"inputName\" [label]=\"inputsMap[inputName].label\" [placeholder]=\"inputsMap[inputName].placeholder || ''\"\r\n [hint]=\"inputsMap[inputName].hint\"\r\n [readonly]=\"inputsMap[inputName].readonly || dynamicFormData.isReadOnlyForm || false\"\r\n [disabled]=\"inputsMap[inputName].disabled || false\" [items]=\"inputsMap[inputName].autoCompleteItems || []\"\r\n [minLengthToSearch]=\"inputsMap[inputName].minLengthToSearch || 2\" [delay]=\"inputsMap[inputName].delay || 300\"\r\n (onSearch)=\"autoCompleteSearch.emit({ name: inputName, query: $event })\"\r\n (selectOption)=\"autoCompleteSelect.emit({ name: inputName, event: $event })\"\r\n [variant]=\"inputsMap[inputName].variant || 'over'\" />\r\n }\r\n @case(fieldType.UPLOAD_FILE) {\r\n <app-file-management #fileManager #groupFileManager [maxFileSize]=\"262144000\" [maxConcurrentUploads]=\"1\"\r\n [allowPreview]=\"true\" (filesUploaded)=\"onFilesUploaded($event)\" (fileDeleted)=\"onFileDeleted($event)\" />\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n\r\n\r\n </div>\r\n <div class=\"col-span-12\">\r\n <small class=\"p-error text-red-700\">\r\n @for (error of formGroup.errors | validationErrors: dynamicFormData.formValidationErrorsKeys;\r\n track error) {\r\n {{ error }}\r\n }\r\n </small>\r\n </div>\r\n</form>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DatePickerComponent, selector: "stc-date-picker", inputs: ["showIcon", "showClear", "basicInput", "isTimeOnly", "minDate", "maxDate", "hourFormat", "selectionMode", "variant", "withoutTime"], outputs: ["onAfterClearDate"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: SelectButtonComponent, selector: "stc-select-button", inputs: ["options", "title"], outputs: ["onChange"] }, { kind: "component", type: DualCalendarComponent, selector: "app-dual-calendar", inputs: ["control", "label", "name", "withTime", "isDatePickerShow", "currentLang", "isShown"], outputs: ["gregorianUTC", "onClose"] }, { kind: "component", type: InputComponent, selector: "stc-input", inputs: ["type", "contentType", "size", "prefix", "rows", "cols", "autoResize", "basicInput", "noStyle", "canClear", "hideOptionalLabel", "inputDirection", "variant", "defaultColor", "iconClass", "iconPosition"] }, { kind: "component", type: FileManagementComponent, selector: "app-file-management", inputs: ["existingFiles", "acceptedTypes", "maxFileSize", "maxConcurrentUploads", "showTable", "showDropZone", "allowPreview", "permissonKey", "allowedActions"], outputs: ["filesUploaded", "fileDeleted", "filePreview", "fileDownload", "uploadError", "newFilesChange"] }, { kind: "component", type: SelectComponent, selector: "stc-select", inputs: ["selectedItemTemplate", "optionTemplate", "options", "optionLabel", "optionValue", "emptyMessage", "checkmark", "showClear", "editable", "filter", "multiple", "filterBy", "selectAllLabel", "dataKey", "size", "selectedItemsLabel", "basicInput", "variant", "defaultColor"], outputs: ["change"] }, { kind: "component", type: AutoCompleteComponent, selector: "stc-auto-complete", inputs: ["selectedItemTemplate", "items", "minLengthToSearch", "delay", "basicInput", "typeAhead", "variant"], outputs: ["onSearch", "selectOption"] }, { kind: "component", type: SwitchComponent, selector: "stc-switch", inputs: ["label", "key", "checked"], outputs: ["onChange"] }, { kind: "pipe", type: ValidationErrorsPipe, name: "validationErrors" }, { kind: "pipe", type: LocalizedLabelPipe, name: "localizedLabel" }] });
|
|
1577
1900
|
}
|
|
1578
1901
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DynamicFormComponent, decorators: [{
|
|
1579
1902
|
type: Component,
|
|
@@ -1586,11 +1909,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
1586
1909
|
SelectButtonComponent,
|
|
1587
1910
|
DualCalendarComponent,
|
|
1588
1911
|
InputComponent,
|
|
1912
|
+
FileManagementComponent,
|
|
1589
1913
|
SelectComponent,
|
|
1590
1914
|
AutoCompleteComponent,
|
|
1591
1915
|
SwitchComponent,
|
|
1592
1916
|
LocalizedLabelPipe
|
|
1593
|
-
], template: "<form [formGroup]=\"formGroup\" class=\"dynamic-form\">\r\n <div class=\"grid grid-cols-12 gap-x-2\">\r\n @for (inputName of inputsNames; track $index) {\r\n <div [ngClass]=\"inputsMap[inputName].rowSize\">\r\n @switch (inputsMap[inputName].fieldType) {\r\n @case (fieldType.HIJRI_DATE_PICKER) {\r\n
|
|
1917
|
+
], template: "<form [formGroup]=\"formGroup\" class=\"dynamic-form\">\r\n <div class=\"grid grid-cols-12 gap-x-2\">\r\n @for (inputName of inputsNames; track $index) {\r\n <div [ngClass]=\"inputsMap[inputName].rowSize\">\r\n @switch (inputsMap[inputName].fieldType) {\r\n @case (fieldType.HIJRI_DATE_PICKER) {\r\n <app-dual-calendar [control]=\"getFormControl(inputName, formGroup)\"></app-dual-calendar>\r\n }\r\n\r\n @case (fieldType.DATE_PICKER) {\r\n <stc-date-picker [minDate]=\"inputsMap[inputName]?.dateRange?.min\" [maxDate]=\"inputsMap[inputName]?.dateRange?.max\"\r\n [id]=\"inputsMap[inputName].inputId\" [control]=\"getFormControl(inputName, formGroup)\" [name]=\"inputName\"\r\n [label]=\"inputsMap[inputName].label\" [placeholder]=\"inputsMap[inputName].placeholder || ''\"\r\n [hint]=\"inputsMap[inputName].hint\"\r\n [readonly]=\"inputsMap[inputName].readonly || dynamicFormData.isReadOnlyForm || false\"\r\n [disabled]=\"inputsMap[inputName].disabled || false\" [variant]=\"inputsMap[inputName].variant || 'over'\"\r\n [showIcon]=\"inputsMap[inputName].showIcon !== false\" [isTimeOnly]=\"inputsMap[inputName].isTimeOnly || false\" />\r\n }\r\n @case (fieldType.SELECT_BUTTON) {\r\n <stc-select-button [control]=\"getFormControl(inputName, formGroup)\" [id]=\"inputsMap[inputName].inputId\"\r\n [name]=\"inputName\" [label]=\"inputsMap[inputName].label\"\r\n [options]=\"inputsMap[inputName].selectButtonOptions || []\"\r\n (onChange)=\"selectButtonChange.emit({ name: inputName, value: $event })\" />\r\n }\r\n @case (fieldType.INPUT) {\r\n <stc-input [control]=\"getFormControl(inputName, formGroup)\" [id]=\"inputsMap[inputName].inputId\" [name]=\"inputName\"\r\n [label]=\"inputsMap[inputName].label\" [placeholder]=\"inputsMap[inputName].placeholder || ''\"\r\n [hint]=\"inputsMap[inputName].hint\"\r\n [readonly]=\"inputsMap[inputName].readonly || dynamicFormData.isReadOnlyForm || false\"\r\n [disabled]=\"inputsMap[inputName].disabled || false\" [type]=\"inputsMap[inputName].inputType || 'text'\"\r\n [contentType]=\"inputsMap[inputName].contentType || 'text'\" [rows]=\"inputsMap[inputName].rows || 2\"\r\n [cols]=\"inputsMap[inputName].cols || 20\" [autoResize]=\"inputsMap[inputName].autoResize ?? false\"\r\n [prefix]=\"inputsMap[inputName].prefix || ''\" [size]=\"inputsMap[inputName].size || 'small'\"\r\n [variant]=\"inputsMap[inputName].variant || 'over'\">\r\n @if(inputsMap[inputName].maxLength){\r\n <span class=\"text-xs text-gray-700\">\r\n {{ (getFormControl(inputName, formGroup).value?.length || 0) }}\r\n <span> / {{ inputsMap[inputName].maxLength}}</span>\r\n </span>\r\n }\r\n </stc-input>\r\n }\r\n @case (fieldType.SELECT) {\r\n <stc-select [control]=\"getFormControl(inputName, formGroup)\" [id]=\"inputsMap[inputName].inputId\"\r\n [name]=\"inputName\" [label]=\"inputsMap[inputName].label\" [placeholder]=\"inputsMap[inputName].placeholder || ''\"\r\n [hint]=\"inputsMap[inputName].hint\"\r\n [readonly]=\"inputsMap[inputName].readonly || dynamicFormData.isReadOnlyForm || false\"\r\n [disabled]=\"inputsMap[inputName].disabled || false\" [options]=\"inputsMap[inputName].selectOptions || []\"\r\n [optionLabel]=\"inputsMap[inputName]?.translatable\r\n ? ((inputsMap[inputName]?.optionLabel || 'label') | localizedLabel)\r\n : (inputsMap[inputName]?.optionLabel || 'label')\"\r\n [filter]=\"inputsMap[inputName].filter || false\"\r\n [multiple]=\"inputsMap[inputName].multiple || false\" [showClear]=\"inputsMap[inputName].showClear || false\"\r\n [checkmark]=\"inputsMap[inputName].checkmark ?? true\" [filterBy]=\"inputsMap[inputName].filterBy || ''\"\r\n [selectedItemsLabel]=\"inputsMap[inputName].selectedItemsLabel || ''\"\r\n [size]=\"inputsMap[inputName].size || 'small'\" [variant]=\"inputsMap[inputName].variant || 'over'\"\r\n (change)=\"selectChange.emit({ name: inputName, event: $event })\" />\r\n }\r\n @case (fieldType.SWITCH) {\r\n <stc-switch [label]=\"inputsMap[inputName].label\" [key]=\"inputName\"\r\n [checked]=\"getFormControl(inputName, formGroup).value\"\r\n (onChange)=\"getFormControl(inputName, formGroup).setValue(typeof $event === 'string' ? ($event === 'true') : $event); switchChange.emit({ name: inputName, value: (typeof $event === 'string' ? ($event === 'true') : $event) })\" />\r\n }\r\n @case (fieldType.AUTO_COMPLETE) {\r\n <stc-auto-complete [control]=\"getFormControl(inputName, formGroup)\" [id]=\"inputsMap[inputName].inputId\"\r\n [name]=\"inputName\" [label]=\"inputsMap[inputName].label\" [placeholder]=\"inputsMap[inputName].placeholder || ''\"\r\n [hint]=\"inputsMap[inputName].hint\"\r\n [readonly]=\"inputsMap[inputName].readonly || dynamicFormData.isReadOnlyForm || false\"\r\n [disabled]=\"inputsMap[inputName].disabled || false\" [items]=\"inputsMap[inputName].autoCompleteItems || []\"\r\n [minLengthToSearch]=\"inputsMap[inputName].minLengthToSearch || 2\" [delay]=\"inputsMap[inputName].delay || 300\"\r\n (onSearch)=\"autoCompleteSearch.emit({ name: inputName, query: $event })\"\r\n (selectOption)=\"autoCompleteSelect.emit({ name: inputName, event: $event })\"\r\n [variant]=\"inputsMap[inputName].variant || 'over'\" />\r\n }\r\n @case(fieldType.UPLOAD_FILE) {\r\n <app-file-management #fileManager #groupFileManager [maxFileSize]=\"262144000\" [maxConcurrentUploads]=\"1\"\r\n [allowPreview]=\"true\" (filesUploaded)=\"onFilesUploaded($event)\" (fileDeleted)=\"onFileDeleted($event)\" />\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n\r\n\r\n </div>\r\n <div class=\"col-span-12\">\r\n <small class=\"p-error text-red-700\">\r\n @for (error of formGroup.errors | validationErrors: dynamicFormData.formValidationErrorsKeys;\r\n track error) {\r\n {{ error }}\r\n }\r\n </small>\r\n </div>\r\n</form>\r\n" }]
|
|
1594
1918
|
}], propDecorators: { dynamicFormData: [{
|
|
1595
1919
|
type: Input,
|
|
1596
1920
|
args: [{ required: true }]
|
|
@@ -1604,6 +1928,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
1604
1928
|
type: Output
|
|
1605
1929
|
}], autoCompleteSelect: [{
|
|
1606
1930
|
type: Output
|
|
1931
|
+
}], popUpFilesUploaded: [{
|
|
1932
|
+
type: Output
|
|
1933
|
+
}], fileDeleted: [{
|
|
1934
|
+
type: Output
|
|
1607
1935
|
}] } });
|
|
1608
1936
|
|
|
1609
1937
|
class ConfirmationDialogComponent extends DynamicDialogRef {
|
|
@@ -1613,6 +1941,7 @@ class ConfirmationDialogComponent extends DynamicDialogRef {
|
|
|
1613
1941
|
_ref = inject(DynamicDialogRef);
|
|
1614
1942
|
_subscription = new Subscription();
|
|
1615
1943
|
dialogFormData;
|
|
1944
|
+
uploadedFile;
|
|
1616
1945
|
ngOnDestroy() {
|
|
1617
1946
|
this._subscription.unsubscribe();
|
|
1618
1947
|
}
|
|
@@ -1629,13 +1958,23 @@ class ConfirmationDialogComponent extends DynamicDialogRef {
|
|
|
1629
1958
|
// we should pass submitted data when using form dialog
|
|
1630
1959
|
// const submitData = { submitted: true, data: this.dialogFormData?.formGroup?.value };
|
|
1631
1960
|
// this._ref.close(this.dynamicDialogConfig.data.inputForm ? submitData : true);
|
|
1632
|
-
this.
|
|
1961
|
+
if (this.uploadedFile) {
|
|
1962
|
+
this._ref.close({ isSubmitted: true, file: this.uploadedFile });
|
|
1963
|
+
}
|
|
1964
|
+
else {
|
|
1965
|
+
this._ref.close(true);
|
|
1966
|
+
}
|
|
1633
1967
|
}
|
|
1634
1968
|
close() {
|
|
1635
1969
|
this._ref.close(false);
|
|
1636
1970
|
}
|
|
1971
|
+
onPopFilesUploaded(file) {
|
|
1972
|
+
this.uploadedFile = file;
|
|
1973
|
+
}
|
|
1974
|
+
onFileDeleted(file) {
|
|
1975
|
+
}
|
|
1637
1976
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationDialogComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1638
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfirmationDialogComponent, isStandalone: true, selector: "app-confirm-dialog", providers: [DialogService, DynamicDialogStyle], usesInheritance: true, ngImport: i0, template: "@if (dynamicDialogConfig.data) {\r\n<div class=\"confirmation-dialog\">\r\n <div class=\"dialog-wrapper\">\r\n @if (dynamicDialogConfig.data) {\r\n <div class=\"confirmation-dialog__content my-4\">\r\n @if (dynamicDialogConfig.data.dialogIcon) {\r\n <em [class]=\"dynamicDialogConfig.data.dialogIcon\"></em>\r\n }\r\n <p class=\"confirmation-dialog__message text-xl mb-2\">\r\n {{ dynamicDialogConfig.data.message }}\r\n </p>\r\n @if (dynamicDialogConfig.data.hint) {\r\n <p class=\"confirmation-dialog__hint font-normal text-base\">\r\n {{ dynamicDialogConfig.data.hint }}\r\n </p>\r\n }\r\n @if (dynamicDialogConfig.data.inputForm) {\r\n <app-dynamic-form [dynamicFormData]=\"dialogFormData\"></app-dynamic-form>\r\n }\r\n </div>\r\n }\r\n <div class=\"confirmation-dialog__actions flex gap-2 mt-4\">\r\n <app-button [title]=\"dynamicDialogConfig.data?.confirmLabel || ('actions.confirm' | translate)\"\r\n [disabled]=\"!!(dialogFormData && dialogFormData.formGroup?.invalid)\" [severity]=\"'primary'\"\r\n [id]=\"dynamicDialogConfig.data.confirmBtnId\" [icon]=\"dynamicDialogConfig.data.confirmBtnIcon || ''\"\r\n [label]=\"dynamicDialogConfig.data.confirmBtnLabel\"\r\n [iconPos]=\"dynamicDialogConfig.data.confirmBtnPosition || 'left'\" [styleClass]=\"'confirmation-btn'\"\r\n (click)=\"submit()\" />\r\n <app-button [title]=\"dynamicDialogConfig.data?.closeLabel || ('actions.cancel' | translate)\"\r\n [severity]=\"'primary'\" variant=\"outlined\" [label]=\"dynamicDialogConfig.data.cancelBtnLabel\"\r\n [id]=\"dynamicDialogConfig.data.cancelBtnId\" [styleClass]=\"'cancel-btn confirmation-btn cancel-btn'\"\r\n (click)=\"close()\" />\r\n </div>\r\n </div>\r\n\r\n</div>\r\n}", styles: [""], dependencies: [{ kind: "component", type: AppButtonComponent, selector: "app-button" }, { kind: "ngmodule", type: AvatarModule }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "component", type: DynamicFormComponent, selector: "app-dynamic-form", inputs: ["dynamicFormData"], outputs: ["selectButtonChange", "selectChange", "switchChange", "autoCompleteSearch", "autoCompleteSelect"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
1977
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfirmationDialogComponent, isStandalone: true, selector: "app-confirm-dialog", providers: [DialogService, DynamicDialogStyle], usesInheritance: true, ngImport: i0, template: "@if (dynamicDialogConfig.data) {\r\n<div class=\"confirmation-dialog\">\r\n <div class=\"dialog-wrapper\">\r\n @if (dynamicDialogConfig.data) {\r\n <div class=\"confirmation-dialog__content my-4\">\r\n @if (dynamicDialogConfig.data.dialogIcon) {\r\n <em [class]=\"dynamicDialogConfig.data.dialogIcon\"></em>\r\n }\r\n <p class=\"confirmation-dialog__message text-xl mb-2\">\r\n {{ dynamicDialogConfig.data.message }}\r\n </p>\r\n @if (dynamicDialogConfig.data.hint) {\r\n <p class=\"confirmation-dialog__hint font-normal text-base\">\r\n {{ dynamicDialogConfig.data.hint }}\r\n </p>\r\n }\r\n @if (dynamicDialogConfig.data.inputForm) {\r\n <app-dynamic-form [dynamicFormData]=\"dialogFormData\" (popUpFilesUploaded)=\"onPopFilesUploaded($event)\" (fileDeleted)=\"onFileDeleted($event)\" ></app-dynamic-form>\r\n }\r\n </div>\r\n }\r\n <div class=\"confirmation-dialog__actions flex gap-2 mt-4\">\r\n <app-button [title]=\"dynamicDialogConfig.data?.confirmLabel || ('actions.confirm' | translate)\"\r\n [disabled]=\"!!(dialogFormData && dialogFormData.formGroup?.invalid)\" [severity]=\"'primary'\"\r\n [id]=\"dynamicDialogConfig.data.confirmBtnId\" [icon]=\"dynamicDialogConfig.data.confirmBtnIcon || ''\"\r\n [label]=\"dynamicDialogConfig.data.confirmBtnLabel\"\r\n [iconPos]=\"dynamicDialogConfig.data.confirmBtnPosition || 'left'\" [styleClass]=\"'confirmation-btn'\"\r\n (click)=\"submit()\" />\r\n <app-button [title]=\"dynamicDialogConfig.data?.closeLabel || ('actions.cancel' | translate)\"\r\n [severity]=\"'primary'\" variant=\"outlined\" [label]=\"dynamicDialogConfig.data.cancelBtnLabel\"\r\n [id]=\"dynamicDialogConfig.data.cancelBtnId\" [styleClass]=\"'cancel-btn confirmation-btn cancel-btn'\"\r\n (click)=\"close()\" />\r\n </div>\r\n </div>\r\n\r\n</div>\r\n}\r\n", styles: [""], dependencies: [{ kind: "component", type: AppButtonComponent, selector: "app-button" }, { kind: "ngmodule", type: AvatarModule }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "component", type: DynamicFormComponent, selector: "app-dynamic-form", inputs: ["dynamicFormData"], outputs: ["selectButtonChange", "selectChange", "switchChange", "autoCompleteSearch", "autoCompleteSelect", "popUpFilesUploaded", "fileDeleted"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
1639
1978
|
}
|
|
1640
1979
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationDialogComponent, decorators: [{
|
|
1641
1980
|
type: Component,
|
|
@@ -1645,7 +1984,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
1645
1984
|
DynamicDialogModule,
|
|
1646
1985
|
DynamicFormComponent,
|
|
1647
1986
|
TranslatePipe,
|
|
1648
|
-
], providers: [DialogService, DynamicDialogStyle], template: "@if (dynamicDialogConfig.data) {\r\n<div class=\"confirmation-dialog\">\r\n <div class=\"dialog-wrapper\">\r\n @if (dynamicDialogConfig.data) {\r\n <div class=\"confirmation-dialog__content my-4\">\r\n @if (dynamicDialogConfig.data.dialogIcon) {\r\n <em [class]=\"dynamicDialogConfig.data.dialogIcon\"></em>\r\n }\r\n <p class=\"confirmation-dialog__message text-xl mb-2\">\r\n {{ dynamicDialogConfig.data.message }}\r\n </p>\r\n @if (dynamicDialogConfig.data.hint) {\r\n <p class=\"confirmation-dialog__hint font-normal text-base\">\r\n {{ dynamicDialogConfig.data.hint }}\r\n </p>\r\n }\r\n @if (dynamicDialogConfig.data.inputForm) {\r\n <app-dynamic-form [dynamicFormData]=\"dialogFormData\"></app-dynamic-form>\r\n }\r\n </div>\r\n }\r\n <div class=\"confirmation-dialog__actions flex gap-2 mt-4\">\r\n <app-button [title]=\"dynamicDialogConfig.data?.confirmLabel || ('actions.confirm' | translate)\"\r\n [disabled]=\"!!(dialogFormData && dialogFormData.formGroup?.invalid)\" [severity]=\"'primary'\"\r\n [id]=\"dynamicDialogConfig.data.confirmBtnId\" [icon]=\"dynamicDialogConfig.data.confirmBtnIcon || ''\"\r\n [label]=\"dynamicDialogConfig.data.confirmBtnLabel\"\r\n [iconPos]=\"dynamicDialogConfig.data.confirmBtnPosition || 'left'\" [styleClass]=\"'confirmation-btn'\"\r\n (click)=\"submit()\" />\r\n <app-button [title]=\"dynamicDialogConfig.data?.closeLabel || ('actions.cancel' | translate)\"\r\n [severity]=\"'primary'\" variant=\"outlined\" [label]=\"dynamicDialogConfig.data.cancelBtnLabel\"\r\n [id]=\"dynamicDialogConfig.data.cancelBtnId\" [styleClass]=\"'cancel-btn confirmation-btn cancel-btn'\"\r\n (click)=\"close()\" />\r\n </div>\r\n </div>\r\n\r\n</div>\r\n}" }]
|
|
1987
|
+
], providers: [DialogService, DynamicDialogStyle], template: "@if (dynamicDialogConfig.data) {\r\n<div class=\"confirmation-dialog\">\r\n <div class=\"dialog-wrapper\">\r\n @if (dynamicDialogConfig.data) {\r\n <div class=\"confirmation-dialog__content my-4\">\r\n @if (dynamicDialogConfig.data.dialogIcon) {\r\n <em [class]=\"dynamicDialogConfig.data.dialogIcon\"></em>\r\n }\r\n <p class=\"confirmation-dialog__message text-xl mb-2\">\r\n {{ dynamicDialogConfig.data.message }}\r\n </p>\r\n @if (dynamicDialogConfig.data.hint) {\r\n <p class=\"confirmation-dialog__hint font-normal text-base\">\r\n {{ dynamicDialogConfig.data.hint }}\r\n </p>\r\n }\r\n @if (dynamicDialogConfig.data.inputForm) {\r\n <app-dynamic-form [dynamicFormData]=\"dialogFormData\" (popUpFilesUploaded)=\"onPopFilesUploaded($event)\" (fileDeleted)=\"onFileDeleted($event)\" ></app-dynamic-form>\r\n }\r\n </div>\r\n }\r\n <div class=\"confirmation-dialog__actions flex gap-2 mt-4\">\r\n <app-button [title]=\"dynamicDialogConfig.data?.confirmLabel || ('actions.confirm' | translate)\"\r\n [disabled]=\"!!(dialogFormData && dialogFormData.formGroup?.invalid)\" [severity]=\"'primary'\"\r\n [id]=\"dynamicDialogConfig.data.confirmBtnId\" [icon]=\"dynamicDialogConfig.data.confirmBtnIcon || ''\"\r\n [label]=\"dynamicDialogConfig.data.confirmBtnLabel\"\r\n [iconPos]=\"dynamicDialogConfig.data.confirmBtnPosition || 'left'\" [styleClass]=\"'confirmation-btn'\"\r\n (click)=\"submit()\" />\r\n <app-button [title]=\"dynamicDialogConfig.data?.closeLabel || ('actions.cancel' | translate)\"\r\n [severity]=\"'primary'\" variant=\"outlined\" [label]=\"dynamicDialogConfig.data.cancelBtnLabel\"\r\n [id]=\"dynamicDialogConfig.data.cancelBtnId\" [styleClass]=\"'cancel-btn confirmation-btn cancel-btn'\"\r\n (click)=\"close()\" />\r\n </div>\r\n </div>\r\n\r\n</div>\r\n}\r\n" }]
|
|
1649
1988
|
}] });
|
|
1650
1989
|
|
|
1651
1990
|
class ReadMoreComponent {
|
|
@@ -2049,7 +2388,7 @@ class ConfirmationDialogService {
|
|
|
2049
2388
|
return of(false); // or EMPTY / throwError — depending on your logic
|
|
2050
2389
|
}
|
|
2051
2390
|
// Emit true/false when dialog closes
|
|
2052
|
-
return ref.onClose.pipe(filter$1((res) => res !== undefined), map((res) =>
|
|
2391
|
+
return ref.onClose.pipe(filter$1((res) => res !== undefined), map((res) => res));
|
|
2053
2392
|
}
|
|
2054
2393
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationDialogService, deps: [{ token: i1$8.DialogService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2055
2394
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationDialogService, providedIn: 'root' });
|