Merged PR 205: Create document picklist and refactor axios call

Create document picklist and refactor axios call
This commit is contained in:
2025-11-06 14:08:53 +00:00
7 changed files with 662 additions and 155 deletions

View File

@@ -0,0 +1,228 @@
<template>
<div class="dynamic-picker" :class="{ 'mt-4': !noMargin }">
<label :for="inputName" v-if="label">
<b>{{ label }}</b>
</label>
<div class="input-wrapper">
<!-- Video Groups MultiSelect -->
<MultiSelect
v-if="dataSource === 'videoGroups'"
v-model="selectedValue"
:options="options"
:filter="true"
:placeholder="placeholder || 'Select VideoGroups'"
:disabled="disabled"
:loading="loading"
class="w-full md:w-80"
@change="onSelectionChange"
>
<template #option="slotProps">
<div class="flex align-items-center">
<i class="pi pi-video mr-2"></i>
<div>
<div>{{ slotProps.option.name }}</div>
<small class="text-muted" v-if="slotProps.option.description">
{{ slotProps.option.description }}
</small>
</div>
</div>
</template>
</MultiSelect>
<!-- KS Documents MultiSelect -->
<MultiSelect
v-else-if="dataSource === 'ksDocuments'"
v-model="selectedValue"
:options="options"
:filter="true"
:placeholder="placeholder || 'Select Documents'"
:disabled="disabled"
:loading="loading"
class="w-full md:w-80"
@change="onSelectionChange"
>
<template #option="slotProps">
<div class="flex align-items-center">
<i :class="getFileIcon(slotProps.option)" class="mr-2"></i>
<div>
<div>{{ slotProps.option.fileName }}</div>
<small class="text-muted" v-if="slotProps.option.description">
{{ slotProps.option.description }}
</small>
</div>
</div>
</template>
</MultiSelect>
<!-- Dropdown per selezione singola -->
<Dropdown
v-else-if="multiple === false"
v-model="selectedValue"
:options="options"
:filter="true"
:placeholder="placeholder || 'Select an option'"
:disabled="disabled"
:loading="loading"
class="w-full md:w-80"
@change="onSelectionChange"
/>
<!-- MultiSelect generico per altri tipi -->
<MultiSelect
v-else
v-model="selectedValue"
:options="options"
:filter="true"
:placeholder="placeholder || 'Select options'"
:disabled="disabled"
:loading="loading"
class="w-full md:w-80"
@change="onSelectionChange"
/>
</div>
<!-- Loading indicator -->
<div v-if="loading" class="text-sm text-gray-500 mt-1">
<i class="pi pi-spin pi-spinner mr-1"></i>
Loading options...
</div>
<!-- Error message -->
<div v-if="error" class="text-red-500 text-sm mt-1">
<i class="pi pi-exclamation-triangle mr-1"></i>
{{ error }}
</div>
<!-- Info message -->
<div v-if="options.length === 0 && !loading && !error" class="text-gray-500 text-sm mt-1">
<i class="pi pi-info-circle mr-1"></i>
No options available
</div>
</div>
</template>
<script setup>
import Dropdown from 'primevue/dropdown';
import MultiSelect from 'primevue/multiselect';
import { computed } from 'vue';
// Props
const props = defineProps({
modelValue: {
type: [Array, Object, String, Number],
default: null
},
inputName: {
type: String,
required: true
},
label: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
dataSource: {
type: String,
required: true
},
options: {
type: Array,
default: () => []
},
disabled: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
},
error: {
type: String,
default: ''
},
multiple: {
type: Boolean,
default: true
},
showStatus: {
type: Boolean,
default: false
},
noMargin: {
type: Boolean,
default: false
}
});
// Emits
const emit = defineEmits(['update:modelValue', 'change']);
// Computed
const selectedValue = computed({
get() {
return props.modelValue;
},
set(value) {
emit('update:modelValue', value);
}
});
const getFileIcon = (document) => {
if (!document) return 'pi pi-file';
const fileName = document.fileName || document.name || '';
const extension = fileName.toLowerCase().split('.').pop();
switch (extension) {
case 'pdf':
return 'pi pi-file-pdf text-red-500';
case 'doc':
return 'pi pi-file-word text-blue-500';
case 'docx':
return 'pi pi-file-word text-blue-500';
case 'xls':
return 'pi pi-file-excel text-green-500';
case 'xlsx':
return 'pi pi-file-excel text-green-500';
case 'txt':
return 'pi pi-file text-gray-500';
case 'ppt':
return 'pi pi-file text-red-500';
case 'pptx':
return 'pi pi-file text-red-500';
case 'json':
return 'pi pi-file text-orange-500';
case 'gif':
return 'pi pi-image text-purple-500';
case 'rar':
return 'pi pi-file-archive text-yellow-500';
default:
return 'pi pi-file text-gray-400';
}
};
const onSelectionChange = (event) => {
emit('change', event.value);
};
</script>
<style scoped>
.input-wrapper {
display: flex;
align-items: center;
gap: 0.5em;
margin-top: 10px;
}
.text-muted {
color: #6c757d;
}
</style>

View File

@@ -0,0 +1,21 @@
import axios from 'axios';
export const FileUploadService = {
/**
* Elimina un file dal server
* @param {string} fileName - Nome del file da eliminare
* @param {string} folderName - Nome della cartella contenente il file
* @returns {Promise} Promise con la risposta del server
*/
deleteFile(fileName, folderName) {
return axios.post(
'/deleteFile',
{ fileName, folderName },
{
headers: {
'Content-Type': 'application/json'
}
}
);
}
};

View File

@@ -0,0 +1,28 @@
import axios from 'axios';
export const KSDocumentService = {
/**
* Recupera tutti i KSDocument per il progetto selezionato dall'utente corrente
* @returns {Promise} Promise con la lista di KSDocument
*/
getKSDocuments() {
return axios.get('/ksDocuments');
},
/**
* Recupera tutti i KSDocument completati per il progetto selezionato dall'utente corrente
* @returns {Promise} Promise con la lista di KSDocument completati
*/
getCompletedKSDocuments() {
return axios.get('/ksDocuments/completed');
},
/**
* Recupera tutti i KSDocument per un progetto specifico
* @param {string} projectId - ID del progetto
* @returns {Promise} Promise con la lista di KSDocument
*/
getKSDocumentsByProject(projectId) {
return axios.post('/ksDocuments/byProject', projectId);
}
};

View File

@@ -1,39 +1,52 @@
import axios from 'axios';
export const ScenarioService = {
getScenarios() {
return axios.get('/scenarios')
return axios.get('/scenarios');
},
getScenariosProject(projectId) {
return axios.post('/scenariosProject' , projectId)
return axios.post('/scenariosProject', projectId);
},
getScenariosApplication(app) {
return axios.post('/scenariosByApp' , app)
return axios.post('/scenariosByApp', app);
},
getScenariosCross() {
return axios.get('/scenariosCross')
return axios.get('/scenariosCross');
},
getExecScenariosByUser(page = 0, size = 10, filters = {}, sortField, sortOrder) {
// Filtri potrebbero essere vuoti, quindi rimuoviamoli se non necessari
const requestBody = { page, size, ...filters, sortField, sortOrder };
const requestBody = { page, size, ...filters, sortField, sortOrder };
return axios.post('/executions', requestBody);
}
,
getScenariosForRE(){
return axios.get('/getScenariosForRE')
},
updateScenarioExecRating(id, rating) {
return axios.get('/updateRating?id=' + id + '&rating=' + rating)
},
getExecScenarioByProject () {
return axios.get('/getExecScenarioByProject')
}
getScenariosForRE() {
return axios.get('/getScenariosForRE');
},
updateScenarioExecRating(id, rating) {
return axios.get('/updateRating?id=' + id + '&rating=' + rating);
},
}
getExecScenarioByProject() {
return axios.get('/getExecScenarioByProject');
},
// Nuovo metodo per recuperare un singolo scenario
getScenarioById(id) {
return axios.get(`/scenarios/${id}`);
},
// Nuovo metodo per eseguire uno scenario in modo asincrono
executeScenarioAsync(data) {
return axios.post('/scenarios/execute-async', data);
},
// Nuovo metodo per recuperare i dettagli di esecuzione di uno scenario
getScenarioExecution(execId) {
return axios.get('/scenarios/execute/' + execId);
},
// Nuovo metodo per recuperare il progresso di esecuzione
getExecutionProgress(execId) {
return axios.get('/scenarios/getExecutionProgress/' + execId);
}
};

View File

@@ -0,0 +1,55 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { FileUploadService } from '../service/FileUploadService';
export const FileUploadStore = defineStore('file_upload_store', () => {
const uploadedFiles = ref([]);
const folderName = ref('');
const numberPrFiles = ref(0);
// Funzione per eliminare un file
async function deleteFile(fileName, folderName) {
try {
const response = await FileUploadService.deleteFile(fileName, folderName);
return response;
} catch (error) {
console.error('Error deleting file:', error);
throw error;
}
}
// Funzione per generare un ID univoco per la cartella
function generateUniqueFolderId() {
const timestamp = Date.now();
const randomNumber = Math.floor(Math.random() * 1000);
const newFolderName = `${timestamp}_${randomNumber}`;
folderName.value = newFolderName;
return newFolderName;
}
// Funzione per resettare lo store
function resetStore() {
uploadedFiles.value = [];
folderName.value = '';
numberPrFiles.value = 0;
}
// Funzione per aggiornare il numero di file PR
function updatePrFilesCount(increment = true) {
if (increment) {
numberPrFiles.value += 1;
} else {
numberPrFiles.value -= 1;
}
}
return {
uploadedFiles,
folderName,
numberPrFiles,
deleteFile,
generateUniqueFolderId,
resetStore,
updatePrFilesCount
};
});

View File

@@ -1,11 +1,15 @@
import { defineStore } from 'pinia';
import { computed, ref } from 'vue';
import { ScenarioExecutionService } from '../service/ScenarioExecutionService';
import { ScenarioService } from '../service/ScenarioService';
import { LoadingStore } from './LoadingStore';
export const ScenarioExecutionStore = defineStore('scenario_execution_store', () => {
const lstScenarioExecution = ref([]);
const selectedExecScenario = ref(null);
const currentScenario = ref({});
const currentExecution = ref(null);
const executionProgress = ref(null);
const loadingStore = LoadingStore();
const totalRecords = ref(0); // Numero totale di record
@@ -30,6 +34,53 @@ export const ScenarioExecutionStore = defineStore('scenario_execution_store', ()
}
}
// Funzione per recuperare un singolo scenario
async function fetchScenario(id) {
try {
const response = await ScenarioService.getScenarioById(id);
currentScenario.value = response.data;
return response.data;
} catch (error) {
console.error('Error fetching scenario:', error);
throw error;
}
}
// Funzione per eseguire uno scenario
async function executeScenario(data) {
try {
const response = await ScenarioService.executeScenarioAsync(data);
currentExecution.value = response.data;
return response.data;
} catch (error) {
console.error('Error executing scenario:', error);
throw error;
}
}
// Funzione per recuperare i dettagli di esecuzione
async function getScenarioExecution(execId) {
try {
const response = await ScenarioService.getScenarioExecution(execId);
return response.data;
} catch (error) {
console.error('Error getting scenario execution:', error);
throw error;
}
}
// Funzione per recuperare il progresso di esecuzione
async function getExecutionProgress(execId) {
try {
const response = await ScenarioService.getExecutionProgress(execId);
executionProgress.value = response.data;
return response.data;
} catch (error) {
console.error('Error getting execution progress:', error);
throw error;
}
}
async function downloadFile(filePath, executionId) {
loadingStore.scenario_loading = true;
try {
@@ -80,6 +131,18 @@ export const ScenarioExecutionStore = defineStore('scenario_execution_store', ()
return totalRecords.value;
});
const getCurrentScenario = computed(() => {
return currentScenario.value;
});
const getCurrentExecution = computed(() => {
return currentExecution.value;
});
const getExecutionProgressData = computed(() => {
return executionProgress.value;
});
const setSelectedExecScenario = (execScenario) => {
selectedExecScenario.value = execScenario;
};
@@ -96,6 +159,9 @@ export const ScenarioExecutionStore = defineStore('scenario_execution_store', ()
const resetStore = () => {
lstScenarioExecution.value = [];
selectedExecScenario.value = null;
currentScenario.value = {};
currentExecution.value = null;
executionProgress.value = null;
totalRecords.value = 0;
currentPage.value = 0;
pageSize.value = 10;
@@ -106,15 +172,22 @@ export const ScenarioExecutionStore = defineStore('scenario_execution_store', ()
getCurrentPage,
getPageSize,
getTotalRecords,
getCurrentScenario,
getCurrentExecution,
getExecutionProgressData,
fetchScenariosExecution,
fetchScenario,
executeScenario,
getScenarioExecution,
getExecutionProgress,
downloadFile,
selectedExecScenario,
lstScenarioExecution,
scenariosExecution,
getSelectedExecScenario,
setSelectedExecScenario,
updateFilters, // Aggiunto per aggiornare i filtri
updateFilters,
filters,
resetStore // Rende disponibile i filtri come parte dello store
resetStore
};
});

View File

@@ -148,12 +148,18 @@
</div>
</div>
<div v-else-if="input.type === 'multiselect'" class="mt-4">
<label :for="input.name">
<b>{{ input.label }}</b>
</label>
<div class="input-wrapper">
<MultiSelect v-model="formData[input.name]" :options="videoGroups" optionLabel="name" filter placeholder="Select VideoGroups" class="w-full md:w-80" />
</div>
<DynamicPicker
v-model="formData[input.name]"
:input-name="input.name"
:label="input.label"
:data-source="input.dataSource || 'videoGroups'"
:options="getOptionsForInput(input)"
:disabled="loadingStore.exectuion_loading"
:loading="loadingOptionsFor[input.dataSource] || false"
:show-status="input.dataSource === 'ksDocuments'"
no-margin
@change="onDynamicPickerChange(input.name, $event)"
/>
</div>
<div v-else>
<label :for="input.name"
@@ -276,11 +282,14 @@
<script setup>
import ChangeImpactOutputViewer from '@/components/ChangeImpactOutputViewer.vue';
import ChatClient from '@/components/ChatClient.vue';
import DynamicPicker from '@/components/DynamicPicker.vue';
import { KSDocumentService } from '@/service/KSDocumentService';
import { FileUploadStore } from '@/stores/FileUploadStore';
import { KsVideoGroupStore } from '@/stores/KsVideoGroupStore';
import { LoadingStore } from '@/stores/LoadingStore';
import { ScenarioExecutionStore } from '@/stores/ScenarioExecutionStore';
import { UserPrefStore } from '@/stores/UserPrefStore';
import { useAuth } from '@websanova/vue-auth/src/v3.js';
import axios from 'axios';
import JsonEditorVue from 'json-editor-vue';
import JSZip from 'jszip';
import { marked } from 'marked';
@@ -294,12 +303,14 @@ import Select from 'primevue/select';
import Textarea from 'primevue/textarea';
import { useConfirm } from 'primevue/useconfirm';
import { useToast } from 'primevue/usetoast';
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { JellyfishLoader } from 'vue3-spinner';
import { ScenarioService } from '../../service/ScenarioService';
const loadingStore = LoadingStore();
const scenarioExecutionStore = ScenarioExecutionStore();
const fileUploadStore = FileUploadStore();
const toast = useToast();
const zip = ref(null);
const route = useRoute();
@@ -316,6 +327,8 @@ const formData = ref({});
const exec_id = ref(null);
const exec_scenario = ref({});
const debug_modal = ref(false);
const loadingOptionsFor = reactive({});
const ksDocuments = ref([]);
let pollingInterval = null;
const folderName = ref('');
const fileNamesOutput = ref([]);
@@ -368,13 +381,20 @@ const isInputFilled = computed(() => {
return false;
}
scenario.value.inputs.forEach((input) => {
if (formData.value[input.name] === undefined || formData.value[input.name] === '') {
console.log('Input not filled: ', input.name);
isFilled = false;
} else {
const processedData = { ...formData.value };
if (processedData.input_multiselect) {
processedData.input_multiselect = JSON.stringify(processedData.input_multiselect.map((item) => item.id));
const inputValue = formData.value[input.name];
// Controllo per input multiselect
if (input.type === 'multiselect') {
if (!inputValue || !Array.isArray(inputValue) || inputValue.length === 0) {
console.log('Multiselect input not filled: ', input.name);
isFilled = false;
}
}
// Controllo per altri tipi di input
else {
if (inputValue === undefined || inputValue === '') {
console.log('Input not filled: ', input.name);
isFilled = false;
}
}
});
@@ -388,10 +408,8 @@ onBeforeUnmount(() => {
onMounted(() => {
fetchScenario(route.params.id);
loadVideoGroups();
const timestamp = Date.now(); // Ottiene il timestamp corrente
const randomNumber = Math.floor(Math.random() * 1000);
folderName.value = `${timestamp}_${randomNumber}`;
const newFolderName = fileUploadStore.generateUniqueFolderId();
folderName.value = newFolderName;
uploadUrl.value = uploadUrlBase + '/uploadListFiles/' + folderName.value;
uploadUrlPR.value = uploadUrl.value + '/PR';
uploadUrlOther.value = uploadUrl.value + '/OTHER';
@@ -410,37 +428,38 @@ const loadVideoGroups = async () => {
watch(() => route.params.id, fetchScenario);
//Function to fetch scenarios
function fetchScenario(id) {
async function fetchScenario(id) {
chatDisabled();
scenario.value.inputs = null;
data_loaded.value = false;
formData.value = {};
loading.value = true;
axios
.get(`/scenarios/${id}`)
.then((response) => {
scenario.value = response.data;
console.log('Scenario fetched:', scenario.value);
if (scenario.value.inputs.some((input) => input.name === 'MultiFileUpload' || input.name === 'SingleFileUpload')) {
reqMultiFile.value = true;
}
if (scenario.value.inputs.some((input) => input.type === 'singlefile_acceptall')) {
reqMultiFile.value = false;
acceptedFormats.value = '';
//acceptedFormats.value = '.doc,.docx,.pdf,.msg,.txt,.xlx,.xlxs,.logs,.pptx,.json,.odt,.rtf,.xml,.html';
}
if (scenario.value.inputs.some((input) => input.type === 'singlefile')) {
reqMultiFile.value = false;
acceptedFormats.value = '.docx';
}
})
.catch((error) => {
console.error('Error fetching scenario:', error);
})
.finally(() => {
loading.value = false;
});
try {
const response = await scenarioExecutionStore.fetchScenario(id);
scenario.value = response;
console.log('Scenario fetched:', scenario.value);
// Carica le opzioni necessarie basate sui dataSource presenti negli inputs
await loadOptionsForScenario();
if (scenario.value.inputs.some((input) => input.name === 'MultiFileUpload' || input.name === 'SingleFileUpload')) {
reqMultiFile.value = true;
}
if (scenario.value.inputs.some((input) => input.type === 'singlefile_acceptall')) {
reqMultiFile.value = false;
acceptedFormats.value = '';
//acceptedFormats.value = '.doc,.docx,.pdf,.msg,.txt,.xlx,.xlxs,.logs,.pptx,.json,.odt,.rtf,.xml,.html';
}
if (scenario.value.inputs.some((input) => input.type === 'singlefile')) {
reqMultiFile.value = false;
acceptedFormats.value = '.docx';
}
} catch (error) {
console.error('Error fetching scenario:', error);
} finally {
loading.value = false;
}
}
const onBeforeSend = (event) => {
@@ -473,7 +492,7 @@ const chatDisabled = () => {
chat_enabled.value = false;
};
const execScenario = () => {
const execScenario = async () => {
if (numberPrFiles.value !== 1 && reqMultiFile.value) {
toast.add({
severity: 'warn', // Tipo di notifica (errore)
@@ -490,10 +509,23 @@ const execScenario = () => {
// Crea una copia dei dati del form
const processedData = { ...formData.value };
if (processedData.input_multiselect) {
processedData.input_multiselect_id = JSON.stringify(processedData.input_multiselect.map((item) => item.id));
processedData.input_multiselect_name = JSON.stringify(processedData.input_multiselect.map((item) => item.name));
delete processedData.input_multiselect;
// Elabora tutti i multiselect dinamici
if (scenario.value.inputs) {
scenario.value.inputs.forEach((input) => {
if (input.type === 'multiselect' && processedData[input.name]) {
const selectedItems = processedData[input.name];
if (Array.isArray(selectedItems) && selectedItems.length > 0) {
// Elaborazione per VideoGroups (backward compatibility)
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));
// Rimuovi l'array originale
delete processedData[input.name];
}
}
});
}
const data = {
@@ -501,55 +533,58 @@ const execScenario = () => {
inputs: processedData
};
axios
.post('/scenarios/execute-async', data)
.then((response) => {
console.log('Response data exec 1:', response.data);
scenario_response.value = response.data;
scenario_response_message.value = response.data.message;
scenario_output.value = response.data.stringOutput;
exec_id.value = response.data.scenarioExecution_id;
loadingStore.setIdExecLoading(exec_id.value);
startPolling();
})
.catch((error) => {
console.error('Error executing scenario:', error);
loadingStore.exectuion_loading = false;
});
try {
const response = await scenarioExecutionStore.executeScenario(data);
console.log('Response data exec 1:', response);
scenario_response.value = response;
scenario_response_message.value = response.message;
scenario_output.value = response.stringOutput;
exec_id.value = response.scenarioExecution_id;
loadingStore.setIdExecLoading(exec_id.value);
startPolling();
} catch (error) {
console.error('Error executing scenario:', error);
loadingStore.exectuion_loading = false;
}
}
};
const openDebug = () => {
axios.get('/scenarios/execute/' + exec_id.value).then((resp) => {
exec_scenario.value = resp.data;
const openDebug = async () => {
try {
const resp = await scenarioExecutionStore.getScenarioExecution(exec_id.value);
exec_scenario.value = resp;
debug_modal.value = true;
});
} catch (error) {
console.error('Error opening debug:', error);
}
};
const pollBackendAPI = () => {
const pollBackendAPI = async () => {
errored_execution.value = false;
axios.get('/scenarios/getExecutionProgress/' + exec_id.value).then((response) => {
if (response.data.status == 'OK' || response.data.status == 'ERROR') {
try {
const response = await scenarioExecutionStore.getExecutionProgress(exec_id.value);
if (response.status == 'OK' || response.status == 'ERROR') {
console.log('Condition met, stopping polling.');
stopPolling();
stopTimer();
if(response.data.status == 'ERROR') {
if (response.status == 'ERROR') {
errored_execution.value = true;
error_message.value = response.data.message;
error_message.value = response.message;
}
loading_data.value = false;
data_loaded.value = true;
scenario_output.value = response.data.stringOutput;
console.log('Response data exec 2:', response.data);
exec_id.value = response.data.scenarioExecution_id;
scenario_output.value = response.stringOutput;
console.log('Response data exec 2:', response);
exec_id.value = response.scenarioExecution_id;
scenario_response_message.value = null; //if != null, next scenario starts with old message
console.log('Scenario 3:', scenario.value);
// Controlla se l'array `inputs` contiene un elemento con `name = 'MultiFileUpload'`
if (scenario.value.inputs.some((input) => input.name === 'MultiFileUpload')) {
if (response.data.status == 'OK') {
if (response.status == 'OK') {
// Accedi al primo step e controlla se esiste l'attributo `codegenie_output_type`
const firstStep = scenario.value.steps[0];
if (firstStep?.attributes?.['codegenie_output_type']) {
@@ -569,10 +604,12 @@ const pollBackendAPI = () => {
}
} else {
console.log('Condition not met, polling continues.');
scenario_response.value = response.data;
scenario_response_message.value = response.data.message;
scenario_response.value = response;
scenario_response_message.value = response.message;
}
});
} catch (error) {
console.error('Error polling backend API:', error);
}
};
const showFileContent = (base64String, type) => {
@@ -691,66 +728,53 @@ function generateUniqueId() {
return Date.now(); // Puoi usare anche UUID.randomUUID() o una libreria simile
}
const onRemove = (event, removeUploadedFileCallback, type) => {
const onRemove = async (event, removeUploadedFileCallback, type) => {
const { file, index } = event;
console.log('Removing file:', folderName.value);
try {
axios
.post(
`/deleteFile`,
{ fileName: file.name, folderName: folderName.value }, // Invio nome del file come payload
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then((response) => {
if (response.status === 200) {
console.log('File removed successfully:', response.data);
const response = await fileUploadStore.deleteFile(file.name, folderName.value);
// Mostra notifica di successo
toast.add({
severity: 'success',
summary: 'Success',
detail: 'File removed successfully!',
life: 3000
});
if (response.status === 200) {
console.log('File removed successfully:', response.data);
if (type === 'SingleFileUpload') {
numberPrFiles.value -= 1;
console.log('Number of PR files: ', numberPrFiles.value);
formData.value['SingleFileUpload'] = ''
}
// Aggiorna lista dei file caricati
removeUploadedFileCallback(index);
} else {
console.error('Failed to remove file:', response.statusText);
// Mostra notifica di errore
toast.add({
severity: 'error',
summary: 'Error',
detail: `Failed to remove file. Status: ${response.statusText}`,
life: 3000
});
}
})
.catch((error) => {
console.error('Error while removing file:', error);
// Mostra notifica di errore
toast.add({
severity: 'error',
summary: 'Error',
detail: `Error while removing file: ${error.message}`,
life: 3000
});
// Mostra notifica di successo
toast.add({
severity: 'success',
summary: 'Success',
detail: 'File removed successfully!',
life: 3000
});
if (type === 'SingleFileUpload') {
numberPrFiles.value -= 1;
console.log('Number of PR files: ', numberPrFiles.value);
formData.value['SingleFileUpload'] = '';
}
// Aggiorna lista dei file caricati
removeUploadedFileCallback(index);
} else {
console.error('Failed to remove file:', response.statusText);
// Mostra notifica di errore
toast.add({
severity: 'error',
summary: 'Error',
detail: `Failed to remove file. Status: ${response.statusText}`,
life: 3000
});
}
} catch (error) {
console.error('Error while removing file:', error);
// Mostra notifica di errore
toast.add({
severity: 'error',
summary: 'Error',
detail: `Error while removing file: ${error.message}`,
life: 3000
});
}
};
@@ -859,6 +883,71 @@ const formatSize = (bytes) => {
return `${truncatedSize} ${sizes[i]}`;
};
// Metodi per la gestione delle picklist dinamiche
const getOptionsForInput = (input) => {
// Basato sul dataSource, restituisce le opzioni appropriate
switch (input.dataSource) {
case 'videoGroups':
return videoGroups.value;
case 'ksDocuments':
return ksDocuments.value;
default:
return [];
}
};
const onDynamicPickerChange = (inputName, value) => {
console.log(`Dynamic picker changed for ${inputName}:`, value);
formData.value[inputName] = value;
};
// Carica le opzioni necessarie basate sui dataSource presenti negli inputs dello scenario
const loadOptionsForScenario = async () => {
if (!scenario.value.inputs) return;
console.log('Loading options for scenario inputs...');
// Trova tutti i dataSource unici negli input multiselect
const dataSources = new Set();
scenario.value.inputs.forEach((input) => {
if (input.type === 'multiselect' && input.dataSource) {
dataSources.add(input.dataSource);
}
});
// Crea le funzioni di caricamento per ogni dataSource
const loadingPromises = Array.from(dataSources).map(async (dataSource) => {
try {
// Imposta lo stato di loading per questo dataSource
loadingOptionsFor[dataSource] = true;
console.log(`Loading options for dataSource: ${dataSource}`);
switch (dataSource) {
case 'videoGroups':
await loadVideoGroups();
break;
case 'ksDocuments':
const docsResponse = await KSDocumentService.getKSDocuments();
ksDocuments.value = docsResponse.data;
console.log(`Loaded ${ksDocuments.value.length} KS documents`);
break;
default:
console.warn(`Unknown dataSource: ${dataSource}`);
}
} catch (error) {
console.error(`Error loading options for ${dataSource}:`, error);
} finally {
// Reset lo stato di loading per questo dataSource
loadingOptionsFor[dataSource] = false;
}
});
// Aspetta che tutti i caricamenti siano completati
await Promise.all(loadingPromises);
};
</script>
<style scoped>