@5minds/node-red-dashboard-2-processcube-dynamic-form 2.6.1 → 2.7.0-develop-86aad3-mh4xebm6
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.
|
@@ -80,20 +80,28 @@
|
|
|
80
80
|
</p>
|
|
81
81
|
</div>
|
|
82
82
|
<div v-else-if="createComponent(field).isFileField" class="ui-dynamic-form-file-wrapper">
|
|
83
|
-
<div v-if="getFilePreviewsForField(field.id).length > 0" class="ui-dynamic-form-
|
|
83
|
+
<div v-if="getFilePreviewsForField(field.id).length > 0" class="ui-dynamic-form-file-previews">
|
|
84
84
|
<h4>Current files:</h4>
|
|
85
85
|
<div class="ui-dynamic-form-preview-grid">
|
|
86
86
|
<div
|
|
87
87
|
v-for="preview in getFilePreviewsForField(field.id)"
|
|
88
88
|
:key="preview.name"
|
|
89
89
|
class="ui-dynamic-form-preview-item"
|
|
90
|
+
@click="openFileModal(preview)"
|
|
90
91
|
>
|
|
92
|
+
<!-- Image preview -->
|
|
91
93
|
<img
|
|
94
|
+
v-if="preview.isImage"
|
|
92
95
|
:src="preview.url"
|
|
93
96
|
:alt="preview.name"
|
|
94
97
|
class="ui-dynamic-form-preview-image"
|
|
95
|
-
@click="openImageModal(preview)"
|
|
96
98
|
/>
|
|
99
|
+
<!-- File icon for non-images -->
|
|
100
|
+
<div v-else class="ui-dynamic-form-file-icon">
|
|
101
|
+
<v-icon size="48" :color="getFileIconColor(preview.type)">
|
|
102
|
+
{{ getFileIcon(preview.type) }}
|
|
103
|
+
</v-icon>
|
|
104
|
+
</div>
|
|
97
105
|
<div class="ui-dynamic-form-preview-info">
|
|
98
106
|
<span class="ui-dynamic-form-preview-name">{{ preview.name }}</span>
|
|
99
107
|
<span class="ui-dynamic-form-preview-size">{{ formatFileSize(preview.size) }}</span>
|
|
@@ -169,26 +177,37 @@
|
|
|
169
177
|
<UIDynamicFormFooterAction :actions="actions" :actionCallback="actionFn" />
|
|
170
178
|
</div>
|
|
171
179
|
|
|
172
|
-
<v-dialog v-model="
|
|
173
|
-
<v-card v-if="
|
|
174
|
-
<v-card-title class="headline">{{
|
|
180
|
+
<v-dialog v-model="fileModalOpen" max-width="800px">
|
|
181
|
+
<v-card v-if="modalFile">
|
|
182
|
+
<v-card-title class="headline">{{ modalFile.name }}</v-card-title>
|
|
175
183
|
<v-card-text>
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
184
|
+
<!-- Image preview -->
|
|
185
|
+
<div v-if="modalFile.isImage">
|
|
186
|
+
<img
|
|
187
|
+
:src="modalFile.url"
|
|
188
|
+
:alt="modalFile.name"
|
|
189
|
+
style="width: 100%; max-height: 70vh; object-fit: contain"
|
|
190
|
+
/>
|
|
191
|
+
</div>
|
|
192
|
+
<!-- File icon for non-images -->
|
|
193
|
+
<div v-else class="ui-dynamic-form-modal-file-icon">
|
|
194
|
+
<v-icon size="120" :color="getFileIconColor(modalFile.type)">
|
|
195
|
+
{{ getFileIcon(modalFile.type) }}
|
|
196
|
+
</v-icon>
|
|
197
|
+
<p class="text-h6 mt-4">{{ getFileTypeDescription(modalFile.type) }}</p>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
181
200
|
<div style="margin-top: 16px">
|
|
182
|
-
<strong>Size:</strong> {{ formatFileSize(
|
|
183
|
-
<strong>Type:</strong> {{
|
|
201
|
+
<strong>Size:</strong> {{ formatFileSize(modalFile.size) }}<br />
|
|
202
|
+
<strong>Type:</strong> {{ modalFile.type }}
|
|
184
203
|
</div>
|
|
185
204
|
</v-card-text>
|
|
186
205
|
<v-card-actions>
|
|
187
|
-
<a href="
|
|
206
|
+
<a :href="modalFile.url" :download="modalFile.name">
|
|
188
207
|
<v-btn variant="tonal" rounded="lg">Herunterladen</v-btn>
|
|
189
208
|
</a>
|
|
190
209
|
<v-spacer></v-spacer>
|
|
191
|
-
<v-btn variant="flat" rounded="lg" @click="
|
|
210
|
+
<v-btn variant="flat" rounded="lg" @click="closeFileModal">Schließen</v-btn>
|
|
192
211
|
</v-card-actions>
|
|
193
212
|
</v-card>
|
|
194
213
|
</v-dialog>
|
|
@@ -350,8 +369,8 @@ export default {
|
|
|
350
369
|
msg: null,
|
|
351
370
|
collapsed: false,
|
|
352
371
|
firstFormFieldRef: null,
|
|
353
|
-
|
|
354
|
-
|
|
372
|
+
fileModalOpen: false,
|
|
373
|
+
modalFile: null,
|
|
355
374
|
objectUrlsByField: {},
|
|
356
375
|
previewCache: {},
|
|
357
376
|
};
|
|
@@ -1450,6 +1469,11 @@ export default {
|
|
|
1450
1469
|
|
|
1451
1470
|
return `data:${fileData.type};base64,${fileData.data}`;
|
|
1452
1471
|
},
|
|
1472
|
+
generateFileDownloadUrl(fileData) {
|
|
1473
|
+
if (!fileData || !fileData.data || !fileData.type) return null;
|
|
1474
|
+
|
|
1475
|
+
return `data:${fileData.type};base64,${fileData.data}`;
|
|
1476
|
+
},
|
|
1453
1477
|
getFilePreviewsForField(fieldId) {
|
|
1454
1478
|
const currentData = this.formData[fieldId] || null;
|
|
1455
1479
|
const cachedOriginalData = this.originalFileData[fieldId] || null;
|
|
@@ -1480,12 +1504,13 @@ export default {
|
|
|
1480
1504
|
} else if (originalFileData) {
|
|
1481
1505
|
const fileArray = Array.isArray(originalFileData) ? originalFileData : [originalFileData];
|
|
1482
1506
|
previews = fileArray
|
|
1483
|
-
.filter((file) =>
|
|
1507
|
+
.filter((file) => file && file.name) // Accept all files, not just images
|
|
1484
1508
|
.map((file) => ({
|
|
1485
1509
|
name: file.name,
|
|
1486
|
-
url: this.generateImagePreviewUrl(file),
|
|
1510
|
+
url: this.isImageFile(file) ? this.generateImagePreviewUrl(file) : this.generateFileDownloadUrl(file),
|
|
1487
1511
|
size: file.size,
|
|
1488
1512
|
type: file.type,
|
|
1513
|
+
isImage: this.isImageFile(file),
|
|
1489
1514
|
}));
|
|
1490
1515
|
}
|
|
1491
1516
|
|
|
@@ -1513,7 +1538,7 @@ export default {
|
|
|
1513
1538
|
actualFile = fileItem[0];
|
|
1514
1539
|
}
|
|
1515
1540
|
|
|
1516
|
-
return actualFile
|
|
1541
|
+
return actualFile; // Accept all files, not just images
|
|
1517
1542
|
})
|
|
1518
1543
|
.map((fileItem) => {
|
|
1519
1544
|
let actualFile = null;
|
|
@@ -1540,6 +1565,7 @@ export default {
|
|
|
1540
1565
|
url: url,
|
|
1541
1566
|
size: actualFile.size,
|
|
1542
1567
|
type: actualFile.type,
|
|
1568
|
+
isImage: actualFile.type && actualFile.type.startsWith('image/'),
|
|
1543
1569
|
isObjectUrl: true,
|
|
1544
1570
|
};
|
|
1545
1571
|
})
|
|
@@ -1589,6 +1615,79 @@ export default {
|
|
|
1589
1615
|
this.previewCache = {};
|
|
1590
1616
|
}
|
|
1591
1617
|
},
|
|
1618
|
+
getFileIcon(mimeType) {
|
|
1619
|
+
if (!mimeType) return 'mdi-file';
|
|
1620
|
+
|
|
1621
|
+
if (mimeType.startsWith('image/')) return 'mdi-image';
|
|
1622
|
+
if (mimeType === 'application/pdf') return 'mdi-file-pdf-box';
|
|
1623
|
+
if (mimeType.includes('word') || mimeType.includes('msword') ||
|
|
1624
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
|
|
1625
|
+
return 'mdi-file-word';
|
|
1626
|
+
}
|
|
1627
|
+
if (mimeType.includes('excel') || mimeType.includes('spreadsheet') ||
|
|
1628
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
|
|
1629
|
+
return 'mdi-file-excel';
|
|
1630
|
+
}
|
|
1631
|
+
if (mimeType.includes('powerpoint') || mimeType.includes('presentation') ||
|
|
1632
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.presentationml.presentation') {
|
|
1633
|
+
return 'mdi-file-powerpoint';
|
|
1634
|
+
}
|
|
1635
|
+
if (mimeType === 'text/plain') return 'mdi-file-document';
|
|
1636
|
+
if (mimeType.includes('zip') || mimeType.includes('rar') || mimeType.includes('7z')) {
|
|
1637
|
+
return 'mdi-folder-zip';
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
return 'mdi-file';
|
|
1641
|
+
},
|
|
1642
|
+
getFileIconColor(mimeType) {
|
|
1643
|
+
if (!mimeType) return 'grey';
|
|
1644
|
+
|
|
1645
|
+
if (mimeType.startsWith('image/')) return 'green';
|
|
1646
|
+
if (mimeType === 'application/pdf') return 'red';
|
|
1647
|
+
if (mimeType.includes('word') || mimeType.includes('msword') ||
|
|
1648
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
|
|
1649
|
+
return 'blue';
|
|
1650
|
+
}
|
|
1651
|
+
if (mimeType.includes('excel') || mimeType.includes('spreadsheet') ||
|
|
1652
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
|
|
1653
|
+
return 'green';
|
|
1654
|
+
}
|
|
1655
|
+
if (mimeType.includes('powerpoint') || mimeType.includes('presentation') ||
|
|
1656
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.presentationml.presentation') {
|
|
1657
|
+
return 'orange';
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
return 'grey';
|
|
1661
|
+
},
|
|
1662
|
+
getFileTypeDescription(mimeType) {
|
|
1663
|
+
if (!mimeType) return 'Unbekannter Dateityp';
|
|
1664
|
+
|
|
1665
|
+
if (mimeType === 'application/pdf') return 'PDF-Dokument';
|
|
1666
|
+
if (mimeType.includes('word') || mimeType.includes('msword') ||
|
|
1667
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
|
|
1668
|
+
return 'Word-Dokument';
|
|
1669
|
+
}
|
|
1670
|
+
if (mimeType.includes('excel') || mimeType.includes('spreadsheet') ||
|
|
1671
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
|
|
1672
|
+
return 'Excel-Arbeitsmappe';
|
|
1673
|
+
}
|
|
1674
|
+
if (mimeType.includes('powerpoint') || mimeType.includes('presentation') ||
|
|
1675
|
+
mimeType === 'application/vnd.openxmlformats-officedocument.presentationml.presentation') {
|
|
1676
|
+
return 'PowerPoint-Präsentation';
|
|
1677
|
+
}
|
|
1678
|
+
if (mimeType === 'text/plain') return 'Textdatei';
|
|
1679
|
+
if (mimeType.startsWith('image/')) return 'Bilddatei';
|
|
1680
|
+
|
|
1681
|
+
return 'Datei';
|
|
1682
|
+
},
|
|
1683
|
+
openFileModal(file) {
|
|
1684
|
+
this.modalFile = file;
|
|
1685
|
+
this.fileModalOpen = true;
|
|
1686
|
+
},
|
|
1687
|
+
closeFileModal() {
|
|
1688
|
+
this.fileModalOpen = false;
|
|
1689
|
+
this.modalFile = null;
|
|
1690
|
+
},
|
|
1592
1691
|
},
|
|
1593
1692
|
};
|
|
1594
1693
|
|
|
@@ -701,3 +701,56 @@ code {
|
|
|
701
701
|
.ui-dynamic-form-dark .ui-dynamic-form-preview-size {
|
|
702
702
|
color: #ccc;
|
|
703
703
|
}
|
|
704
|
+
|
|
705
|
+
/* File icon styles for non-image files */
|
|
706
|
+
.ui-dynamic-form-file-icon {
|
|
707
|
+
display: flex;
|
|
708
|
+
align-items: center;
|
|
709
|
+
justify-content: center;
|
|
710
|
+
width: 100px;
|
|
711
|
+
height: 100px;
|
|
712
|
+
background-color: #f8f9fa;
|
|
713
|
+
border: 2px dashed #dee2e6;
|
|
714
|
+
border-radius: 8px;
|
|
715
|
+
margin-bottom: 8px;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
.ui-dynamic-form-dark .ui-dynamic-form-file-icon {
|
|
719
|
+
background-color: #2d2d2d;
|
|
720
|
+
border-color: #555;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/* Modal file icon styles */
|
|
724
|
+
.ui-dynamic-form-modal-file-icon {
|
|
725
|
+
display: flex;
|
|
726
|
+
flex-direction: column;
|
|
727
|
+
align-items: center;
|
|
728
|
+
justify-content: center;
|
|
729
|
+
padding: 40px;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/* Update class name for general file previews */
|
|
733
|
+
.ui-dynamic-form-file-previews {
|
|
734
|
+
margin-bottom: 16px;
|
|
735
|
+
padding: 16px;
|
|
736
|
+
background-color: #f8f9fa;
|
|
737
|
+
border-radius: 8px;
|
|
738
|
+
border: 1px solid #dee2e6;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
.ui-dynamic-form-file-previews h4 {
|
|
742
|
+
margin: 0 0 12px 0;
|
|
743
|
+
color: #495057;
|
|
744
|
+
font-size: 14px;
|
|
745
|
+
font-weight: 600;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/* Dark theme adjustments for file previews */
|
|
749
|
+
.ui-dynamic-form-dark .ui-dynamic-form-file-previews {
|
|
750
|
+
background-color: #2d2d2d;
|
|
751
|
+
border-color: #555;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
.ui-dynamic-form-dark .ui-dynamic-form-file-previews h4 {
|
|
755
|
+
color: #fff;
|
|
756
|
+
}
|