fix picklist
This commit is contained in:
@@ -60,6 +60,60 @@
|
|||||||
</template>
|
</template>
|
||||||
</MultiSelect>
|
</MultiSelect>
|
||||||
|
|
||||||
|
<!-- KS Folders MultiSelect -->
|
||||||
|
<MultiSelect
|
||||||
|
v-else-if="dataSource === 'ksFolders'"
|
||||||
|
v-model="selectedValue"
|
||||||
|
:options="safeOptions"
|
||||||
|
optionLabel="name"
|
||||||
|
:filter="true"
|
||||||
|
:placeholder="placeholder || 'Select Folders'"
|
||||||
|
:disabled="disabled"
|
||||||
|
:loading="loading"
|
||||||
|
:virtualScrollerOptions="{ itemSize: 60 }"
|
||||||
|
class="w-full"
|
||||||
|
panelClass="ks-folders-panel"
|
||||||
|
@change="onSelectionChange"
|
||||||
|
display="chip"
|
||||||
|
>
|
||||||
|
<template #value="slotProps">
|
||||||
|
<div v-if="slotProps.value && slotProps.value.length > 0" class="flex flex-wrap gap-2">
|
||||||
|
<Chip
|
||||||
|
v-for="folder in slotProps.value"
|
||||||
|
:key="folder.id"
|
||||||
|
:label="folder.name"
|
||||||
|
removable
|
||||||
|
@remove="removeFolder(folder)"
|
||||||
|
class="folder-chip"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
<i class="pi pi-folder mr-2 text-violet-600"></i>
|
||||||
|
<span>{{ folder.name }}</span>
|
||||||
|
</template>
|
||||||
|
</Chip>
|
||||||
|
</div>
|
||||||
|
<span v-else class="p-placeholder">{{ placeholder || 'Select Folders' }}</span>
|
||||||
|
</template>
|
||||||
|
<template #option="slotProps">
|
||||||
|
<div class="flex align-items-center p-3 hover:bg-gray-50">
|
||||||
|
<i class="pi pi-folder mr-3 text-violet-600" style="font-size: 1.2rem;"></i>
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="font-medium text-sm mb-1">{{ slotProps.option.name }}</div>
|
||||||
|
<div class="flex gap-3 text-xs text-gray-600">
|
||||||
|
<span class="flex align-items-center gap-1">
|
||||||
|
<i class="pi pi-file" style="font-size: 0.75rem;"></i>
|
||||||
|
{{ slotProps.option.itemCount }} item{{ slotProps.option.itemCount !== 1 ? 's' : '' }}
|
||||||
|
</span>
|
||||||
|
<span class="flex align-items-center gap-1">
|
||||||
|
<i class="pi pi-folder-open" style="font-size: 0.75rem;"></i>
|
||||||
|
{{ slotProps.option.subfolderCount }} subfolder{{ slotProps.option.subfolderCount !== 1 ? 's' : '' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</MultiSelect>
|
||||||
|
|
||||||
<!-- Dropdown per selezione singola -->
|
<!-- Dropdown per selezione singola -->
|
||||||
<Dropdown
|
<Dropdown
|
||||||
v-else-if="multiple === false"
|
v-else-if="multiple === false"
|
||||||
@@ -112,6 +166,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import Chip from 'primevue/chip';
|
||||||
import Dropdown from 'primevue/dropdown';
|
import Dropdown from 'primevue/dropdown';
|
||||||
import MultiSelect from 'primevue/multiselect';
|
import MultiSelect from 'primevue/multiselect';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
@@ -223,6 +278,16 @@ const getFileIcon = (document) => {
|
|||||||
const onSelectionChange = (event) => {
|
const onSelectionChange = (event) => {
|
||||||
emit('change', event.value);
|
emit('change', event.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const removeFolder = (folderToRemove) => {
|
||||||
|
if (props.disabled) return;
|
||||||
|
|
||||||
|
const currentValue = Array.isArray(selectedValue.value) ? selectedValue.value : [];
|
||||||
|
const newValue = currentValue.filter(folder => folder.id !== folderToRemove.id);
|
||||||
|
|
||||||
|
selectedValue.value = newValue;
|
||||||
|
emit('change', newValue);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -242,6 +307,7 @@ const onSelectionChange = (event) => {
|
|||||||
/* Personalizzazione delle panel dei MultiSelect per migliorare la visualizzazione */
|
/* Personalizzazione delle panel dei MultiSelect per migliorare la visualizzazione */
|
||||||
.ks-documents-panel .p-multiselect-panel,
|
.ks-documents-panel .p-multiselect-panel,
|
||||||
.video-groups-panel .p-multiselect-panel,
|
.video-groups-panel .p-multiselect-panel,
|
||||||
|
.ks-folders-panel .p-multiselect-panel,
|
||||||
.generic-multiselect-panel .p-multiselect-panel {
|
.generic-multiselect-panel .p-multiselect-panel {
|
||||||
min-width: 350px;
|
min-width: 350px;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
@@ -249,12 +315,14 @@ const onSelectionChange = (event) => {
|
|||||||
|
|
||||||
.ks-documents-panel .p-multiselect-items,
|
.ks-documents-panel .p-multiselect-items,
|
||||||
.video-groups-panel .p-multiselect-items,
|
.video-groups-panel .p-multiselect-items,
|
||||||
|
.ks-folders-panel .p-multiselect-items,
|
||||||
.generic-multiselect-panel .p-multiselect-items {
|
.generic-multiselect-panel .p-multiselect-items {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ks-documents-panel .p-multiselect-item,
|
.ks-documents-panel .p-multiselect-item,
|
||||||
.video-groups-panel .p-multiselect-item,
|
.video-groups-panel .p-multiselect-item,
|
||||||
|
.ks-folders-panel .p-multiselect-item,
|
||||||
.generic-multiselect-panel .p-multiselect-item {
|
.generic-multiselect-panel .p-multiselect-item {
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
border-bottom: 1px solid #e9ecef;
|
border-bottom: 1px solid #e9ecef;
|
||||||
@@ -265,16 +333,42 @@ const onSelectionChange = (event) => {
|
|||||||
|
|
||||||
.ks-documents-panel .p-multiselect-item:last-child,
|
.ks-documents-panel .p-multiselect-item:last-child,
|
||||||
.video-groups-panel .p-multiselect-item:last-child,
|
.video-groups-panel .p-multiselect-item:last-child,
|
||||||
|
.ks-folders-panel .p-multiselect-item:last-child,
|
||||||
.generic-multiselect-panel .p-multiselect-item:last-child {
|
.generic-multiselect-panel .p-multiselect-item:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ks-documents-panel .p-multiselect-item:hover,
|
.ks-documents-panel .p-multiselect-item:hover,
|
||||||
.video-groups-panel .p-multiselect-item:hover,
|
.video-groups-panel .p-multiselect-item:hover,
|
||||||
|
.ks-folders-panel .p-multiselect-item:hover,
|
||||||
.generic-multiselect-panel .p-multiselect-item:hover {
|
.generic-multiselect-panel .p-multiselect-item:hover {
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Stili specifici per ks-folders */
|
||||||
|
.ks-folders-panel .p-multiselect-item {
|
||||||
|
min-height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ks-folders-panel .pi-folder {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stili per le chips delle folders */
|
||||||
|
.folder-chip {
|
||||||
|
background-color: #f3e8ff;
|
||||||
|
color: #7c3aed;
|
||||||
|
border: 1px solid #c4b5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-chip .pi-folder {
|
||||||
|
color: #7c3aed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-chip:hover {
|
||||||
|
background-color: #e9d5ff;
|
||||||
|
}
|
||||||
|
|
||||||
/* Stili per le icone dei file */
|
/* Stili per le icone dei file */
|
||||||
.ks-documents-panel .pi {
|
.ks-documents-panel .pi {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
|
|||||||
@@ -229,7 +229,12 @@ const filteredInputs = computed(() => {
|
|||||||
const filtered = {};
|
const filtered = {};
|
||||||
for (const [key, value] of Object.entries(inputs.value)) {
|
for (const [key, value] of Object.entries(inputs.value)) {
|
||||||
// Escludi tutti i campi che contengono "input_multiselect" e finiscono con "_id"
|
// Escludi tutti i campi che contengono "input_multiselect" e finiscono con "_id"
|
||||||
if (!(key.includes('input_multiselect') && key.endsWith('_id'))) {
|
// Escludi anche i campi "SelectedFolders_Name" e "SelectedFolders_Id"
|
||||||
|
const shouldExclude = (key.includes('input_multiselect') && key.endsWith('_id')) ||
|
||||||
|
key === 'selectedFolders_id' ||
|
||||||
|
key === 'selectedFolders_name';
|
||||||
|
|
||||||
|
if (!shouldExclude) {
|
||||||
filtered[key] = value;
|
filtered[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,7 +158,7 @@
|
|||||||
:loading="loadingOptionsFor[input.dataSource] || false"
|
:loading="loadingOptionsFor[input.dataSource] || false"
|
||||||
:show-status="input.dataSource === 'ksDocuments'"
|
:show-status="input.dataSource === 'ksDocuments'"
|
||||||
no-margin
|
no-margin
|
||||||
@change="onDynamicPickerChange(input.name, $event)"
|
@change="onDynamicPickerChange(input.name, $event, input.dataSource)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
@@ -432,12 +432,48 @@ const extractFoldersFromItems = (items) => {
|
|||||||
const folderSet = new Set();
|
const folderSet = new Set();
|
||||||
|
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
|
// Filtra solo gli items che hanno il campo ingestionStatusV2
|
||||||
|
if (!item.ingestionStatusV2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const path = item.ingestionInfo?.metadata?.ksKnowledgePath;
|
const path = item.ingestionInfo?.metadata?.ksKnowledgePath;
|
||||||
if (!path) return;
|
|
||||||
|
// Gestisci item nella root (senza path o con path vuoto o "/")
|
||||||
|
if (!path || path === '/' || path.trim() === '') {
|
||||||
|
const rootPath = '/';
|
||||||
|
folderSet.add(rootPath);
|
||||||
|
|
||||||
|
if (!folderMap[rootPath]) {
|
||||||
|
folderMap[rootPath] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
folderMap[rootPath].push({
|
||||||
|
id: item.id,
|
||||||
|
type: item.fileName ? 'document' : 'video',
|
||||||
|
name: item.fileName || item.name
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Rimuovi il leading slash se presente
|
// Rimuovi il leading slash se presente
|
||||||
const cleanPath = path.startsWith('/') ? path.substring(1) : path;
|
const cleanPath = path.startsWith('/') ? path.substring(1) : path;
|
||||||
if (!cleanPath) return;
|
if (!cleanPath) {
|
||||||
|
// Se dopo la pulizia il path è vuoto, è un item root
|
||||||
|
const rootPath = '/';
|
||||||
|
folderSet.add(rootPath);
|
||||||
|
|
||||||
|
if (!folderMap[rootPath]) {
|
||||||
|
folderMap[rootPath] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
folderMap[rootPath].push({
|
||||||
|
id: item.id,
|
||||||
|
type: item.fileName ? 'document' : 'video',
|
||||||
|
name: item.fileName || item.name
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Dividi il path in parti
|
// Dividi il path in parti
|
||||||
const parts = cleanPath.split('/');
|
const parts = cleanPath.split('/');
|
||||||
@@ -481,12 +517,33 @@ const loadKsFolders = async () => {
|
|||||||
// Estrai folder e crea la mappa
|
// Estrai folder e crea la mappa
|
||||||
const { folders, folderMap } = extractFoldersFromItems(allItems);
|
const { folders, folderMap } = extractFoldersFromItems(allItems);
|
||||||
|
|
||||||
|
// Calcola il numero di subfolder per ogni folder
|
||||||
|
const subfolderCounts = {};
|
||||||
|
folders.forEach((folderPath) => {
|
||||||
|
// Conta quante folder hanno questo path come parent
|
||||||
|
const subfolderCount = folders.filter((otherPath) => {
|
||||||
|
if (otherPath === folderPath) return false;
|
||||||
|
|
||||||
|
// Gestione speciale per la root: conta solo le folder di primo livello
|
||||||
|
if (folderPath === '/') {
|
||||||
|
// Una folder è di primo livello se non contiene altri "/" dopo il primo
|
||||||
|
return otherPath !== '/' && otherPath.substring(1).indexOf('/') === -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica se otherPath è una sottocartella diretta di folderPath
|
||||||
|
const relativePath = otherPath.substring(folderPath.length);
|
||||||
|
return relativePath.startsWith('/') && relativePath.substring(1).split('/').length === 1;
|
||||||
|
}).length;
|
||||||
|
subfolderCounts[folderPath] = subfolderCount;
|
||||||
|
});
|
||||||
|
|
||||||
// Crea la struttura per la picklist
|
// Crea la struttura per la picklist
|
||||||
ksFolders.value = folders.map((path) => ({
|
ksFolders.value = folders.map((path) => ({
|
||||||
id: path,
|
id: path,
|
||||||
name: path,
|
name: path === '/' ? '/ (Root)' : path, // Nome più chiaro per la root
|
||||||
path: path,
|
path: path,
|
||||||
itemCount: folderMap[path]?.length || 0
|
itemCount: folderMap[path]?.length || 0,
|
||||||
|
subfolderCount: subfolderCounts[path] || 0
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Salva la mappa folder->items per uso successivo
|
// Salva la mappa folder->items per uso successivo
|
||||||
@@ -996,9 +1053,38 @@ const getOptionsForInput = (input) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDynamicPickerChange = (inputName, value) => {
|
const onDynamicPickerChange = (inputName, value, dataSource) => {
|
||||||
console.log(`Dynamic picker changed for ${inputName}:`, value);
|
console.log(`Dynamic picker changed for ${inputName}:`, value);
|
||||||
formData.value[inputName] = value;
|
|
||||||
|
// Gestione speciale per ksFolders: se seleziono una folder padre, seleziono anche tutte le subfolder
|
||||||
|
if (dataSource === 'ksFolders' && Array.isArray(value)) {
|
||||||
|
const expandedSelection = new Set();
|
||||||
|
|
||||||
|
// Aggiungi tutte le folder selezionate dall'utente
|
||||||
|
value.forEach(folder => {
|
||||||
|
const folderPath = folder.path || folder.id || folder;
|
||||||
|
expandedSelection.add(folderPath);
|
||||||
|
|
||||||
|
// Trova e aggiungi tutte le subfolder (ricorsivamente)
|
||||||
|
ksFolders.value.forEach(subfolder => {
|
||||||
|
const subfolderPath = subfolder.path;
|
||||||
|
// Una subfolder ha come prefisso il path della folder padre seguito da '/'
|
||||||
|
if (subfolderPath !== folderPath && subfolderPath.startsWith(folderPath + '/')) {
|
||||||
|
expandedSelection.add(subfolderPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Converti il Set in un array di oggetti folder completi
|
||||||
|
const expandedFolders = Array.from(expandedSelection).map(path =>
|
||||||
|
ksFolders.value.find(f => f.path === path)
|
||||||
|
).filter(f => f !== undefined);
|
||||||
|
|
||||||
|
console.log(`Expanded selection from ${value.length} to ${expandedFolders.length} folders`);
|
||||||
|
formData.value[inputName] = expandedFolders;
|
||||||
|
} else {
|
||||||
|
formData.value[inputName] = value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Carica le opzioni necessarie basate sui dataSource presenti negli inputs dello scenario
|
// Carica le opzioni necessarie basate sui dataSource presenti negli inputs dello scenario
|
||||||
|
|||||||
Reference in New Issue
Block a user