diff --git a/src/components/DynamicPicker.vue b/src/components/DynamicPicker.vue
index b12f8fe..1fbc51b 100644
--- a/src/components/DynamicPicker.vue
+++ b/src/components/DynamicPicker.vue
@@ -60,6 +60,63 @@
+
+
+
+
+
+
+
+
{{ slotProps.option.name }}
+
+ {{ slotProps.option.itemCount }} items
+
+ • {{ slotProps.option.subfolderCount }} subfolders
+
+
+
+
+
+
+
+
+
+ {{ placeholder || 'Select Folders' }}
+
+
+ {{ slotProps.value.length }} folder{{ slotProps.value.length > 1 ? 's' : '' }} selected
+
+
+
+
+
+
+
+
+ {{ folder.name }}
+
+
+
+
-
+
{
return Array.isArray(props.options) ? props.options : [];
});
+// Funzione per rimuovere una folder dalla selezione
+const removeFolder = (folderToRemove) => {
+ if (!selectedValue.value || !Array.isArray(selectedValue.value)) return;
+
+ const newValue = selectedValue.value.filter(folder => {
+ const currentPath = folder.path || folder.id || folder;
+ const removePathKey = folderToRemove.path || folderToRemove.id || folderToRemove;
+ return currentPath !== removePathKey;
+ });
+
+ selectedValue.value = newValue;
+ emit('change', newValue);
+};
+
const getFileIcon = (document) => {
if (!document) return 'pi pi-file';
@@ -228,7 +299,7 @@ const onSelectionChange = (event) => {
diff --git a/src/components/ExecutionInputTable.vue b/src/components/ExecutionInputTable.vue
index ce6d159..2d2e23d 100644
--- a/src/components/ExecutionInputTable.vue
+++ b/src/components/ExecutionInputTable.vue
@@ -17,9 +17,15 @@ const emit = defineEmits(['download-file']);
const filteredInputs = computed(() => {
const filtered = {};
for (const [key, value] of Object.entries(props.inputs)) {
- if (!(key.includes('input_multiselect') && key.endsWith('_id'))) {
- filtered[key] = value;
+ // Escludi le chiavi _id per multiselect
+ if (key.includes('input_multiselect') && key.endsWith('_id')) {
+ continue;
}
+ // Escludi selectedFolders_name e selectedFolders_id
+ if (key === 'selectedFolders_name' || key === 'selectedFolders_id') {
+ continue;
+ }
+ filtered[key] = value;
}
return filtered;
});
diff --git a/src/views/pages/ScenarioExec.vue b/src/views/pages/ScenarioExec.vue
index 1efb6e0..75a7d64 100644
--- a/src/views/pages/ScenarioExec.vue
+++ b/src/views/pages/ScenarioExec.vue
@@ -55,6 +55,8 @@ const uploadUrlOther = computed(() => `${uploadUrlBase}/uploadListFiles/${folder
const loadingOptionsFor = reactive({});
const ksDocuments = ref([]);
const videoGroups = ref([]);
+const ksFolders = ref([]);
+const folderToItemsMap = ref({});
// ============= File Output State =============
const fileType = ref('');
@@ -135,6 +137,122 @@ const loadVideoGroups = async () => {
videoGroups.value = await Promise.all(videoGroups.value);
};
+// Estrae tutte le folder/subfolder uniche dai documenti e video
+const extractFoldersFromItems = (items) => {
+ const folderMap = {};
+ const folderSet = new Set();
+
+ items.forEach((item) => {
+ // Filtra solo gli items che hanno il campo ingestionStatusV2
+ if (!item.ingestionStatusV2) {
+ return;
+ }
+
+ const path = item.ingestionInfo?.metadata?.ksKnowledgePath;
+
+ // 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
+ const cleanPath = path.startsWith('/') ? path.substring(1) : path;
+ if (!cleanPath) {
+ 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
+ const parts = cleanPath.split('/');
+
+ // Crea tutte le combinazioni di folder/subfolder
+ let currentPath = '';
+ parts.forEach((part, index) => {
+ currentPath = index === 0 ? part : `${currentPath}/${part}`;
+ const fullPath = `/${currentPath}`;
+
+ folderSet.add(fullPath);
+
+ if (!folderMap[fullPath]) {
+ folderMap[fullPath] = [];
+ }
+
+ if (fullPath === path) {
+ folderMap[fullPath].push({
+ id: item.id,
+ type: item.fileName ? 'document' : 'video',
+ name: item.fileName || item.name
+ });
+ }
+ });
+ });
+
+ return { folders: Array.from(folderSet).sort(), folderMap };
+};
+
+const loadKsFolders = async () => {
+ try {
+ const docsResponse = await KSDocumentService.getKSDocuments();
+ const documents = docsResponse.data || [];
+
+ const allItems = [...documents, ...videoGroups.value];
+ const { folders, folderMap } = extractFoldersFromItems(allItems);
+
+ // Calcola il numero di subfolder per ogni folder
+ const subfolderCounts = {};
+ folders.forEach((folderPath) => {
+ const subfolderCount = folders.filter((otherPath) => {
+ if (otherPath === folderPath) return false;
+
+ if (folderPath === '/') {
+ return otherPath !== '/' && otherPath.substring(1).indexOf('/') === -1;
+ }
+
+ const relativePath = otherPath.substring(folderPath.length);
+ return relativePath.startsWith('/') && relativePath.substring(1).split('/').length === 1;
+ }).length;
+ subfolderCounts[folderPath] = subfolderCount;
+ });
+
+ ksFolders.value = folders.map((path) => ({
+ id: path,
+ name: path === '/' ? '/ (Root)' : path,
+ path: path,
+ itemCount: folderMap[path]?.length || 0,
+ subfolderCount: subfolderCounts[path] || 0
+ }));
+
+ folderToItemsMap.value = folderMap;
+
+ console.log(`Loaded ${ksFolders.value.length} folders with items:`, folderToItemsMap.value);
+ } catch (error) {
+ console.error('Error loading KS folders:', error);
+ }
+};
+
const loadOptionsForScenario = async () => {
if (!scenario.value.inputs) return;
@@ -160,6 +278,13 @@ const loadOptionsForScenario = async () => {
break;
}
+ case 'ksFolders':
+ if (videoGroups.value.length === 0) {
+ await loadVideoGroups();
+ }
+ await loadKsFolders();
+ break;
+
default:
console.warn(`Unknown dataSource: ${dataSource}`);
}
@@ -179,6 +304,8 @@ const getOptionsForInput = (input) => {
return videoGroups.value;
case 'ksDocuments':
return ksDocuments.value;
+ case 'ksFolders':
+ return ksFolders.value;
default:
return [];
}
@@ -195,8 +322,37 @@ const getInputComponent = (type) => {
return components[type] || InputText;
};
-const onDynamicPickerChange = (inputName, value) => {
- formData.value[inputName] = value;
+const onDynamicPickerChange = (inputName, value, dataSource) => {
+ console.log(`Dynamic picker changed for ${inputName}:`, value);
+
+ // Gestione speciale per ksFolders: espande automaticamente 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;
+ 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;
+ }
};
// ============= File Upload Handlers =============
@@ -265,8 +421,32 @@ const processFormData = () => {
const selectedItems = processedData[input.name];
if (Array.isArray(selectedItems) && selectedItems.length > 0) {
- processedData[`${input.name}_id`] = JSON.stringify(selectedItems.map((item) => item.id || item));
- processedData[`${input.name}_name`] = JSON.stringify(selectedItems.map((item) => item.name || item.fileName || item));
+ // Elaborazione speciale per ksFolders
+ if (input.dataSource === 'ksFolders') {
+ const allItemIds = [];
+ const allItemNames = [];
+
+ selectedItems.forEach((folder) => {
+ const folderPath = folder.path || folder.id || folder;
+ const items = folderToItemsMap.value[folderPath] || [];
+
+ items.forEach((item) => {
+ allItemIds.push(item.id);
+ allItemNames.push(item.name);
+ });
+ });
+
+ processedData[`${input.name}_id`] = JSON.stringify(allItemIds);
+ processedData[`${input.name}_name`] = JSON.stringify(allItemNames);
+ processedData[`${input.name}_folders`] = JSON.stringify(selectedItems.map((item) => item.path || item.id || item));
+
+ console.log(`Folder selection - Total items: ${allItemIds.length}`, allItemIds);
+ } else {
+ // Elaborazione standard per videoGroups e ksDocuments
+ processedData[`${input.name}_id`] = JSON.stringify(selectedItems.map((item) => item.id || item));
+ processedData[`${input.name}_name`] = JSON.stringify(selectedItems.map((item) => item.name || item.fileName || item));
+ }
+
delete processedData[input.name];
}
}
@@ -432,7 +612,7 @@ const chatDisabled = () => {
:loading="loadingOptionsFor[input.dataSource] || false"
:show-status="input.dataSource === 'ksDocuments'"
no-margin
- @change="onDynamicPickerChange(input.name, $event)"
+ @change="onDynamicPickerChange(input.name, $event, input.dataSource)"
/>