Create document picklist and refactor axios call
This commit is contained in:
228
src/components/DynamicPicker.vue
Normal file
228
src/components/DynamicPicker.vue
Normal 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>
|
||||
21
src/service/FileUploadService.js
Normal file
21
src/service/FileUploadService.js
Normal 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'
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
28
src/service/KSDocumentService.js
Normal file
28
src/service/KSDocumentService.js
Normal 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);
|
||||
}
|
||||
};
|
||||
@@ -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 };
|
||||
return axios.post('/executions', requestBody);
|
||||
}
|
||||
},
|
||||
|
||||
,
|
||||
getScenariosForRE(){
|
||||
return axios.get('/getScenariosForRE')
|
||||
getScenariosForRE() {
|
||||
return axios.get('/getScenariosForRE');
|
||||
},
|
||||
updateScenarioExecRating(id, rating) {
|
||||
return axios.get('/updateRating?id=' + id + '&rating=' + rating)
|
||||
return axios.get('/updateRating?id=' + id + '&rating=' + rating);
|
||||
},
|
||||
|
||||
getExecScenarioByProject () {
|
||||
return axios.get('/getExecScenarioByProject')
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
55
src/stores/FileUploadStore.js
Normal file
55
src/stores/FileUploadStore.js
Normal 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
|
||||
};
|
||||
});
|
||||
@@ -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
|
||||
};
|
||||
});
|
||||
|
||||
@@ -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] === '') {
|
||||
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;
|
||||
} else {
|
||||
const processedData = { ...formData.value };
|
||||
if (processedData.input_multiselect) {
|
||||
processedData.input_multiselect = JSON.stringify(processedData.input_multiselect.map((item) => item.id));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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,18 +428,21 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -434,13 +455,11 @@ function fetchScenario(id) {
|
||||
reqMultiFile.value = false;
|
||||
acceptedFormats.value = '.docx';
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
} catch (error) {
|
||||
console.error('Error fetching scenario:', error);
|
||||
})
|
||||
.finally(() => {
|
||||
} 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;
|
||||
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) => {
|
||||
} 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,22 +728,13 @@ 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) => {
|
||||
const response = await fileUploadStore.deleteFile(file.name, folderName.value);
|
||||
|
||||
if (response.status === 200) {
|
||||
console.log('File removed successfully:', response.data);
|
||||
|
||||
@@ -721,7 +749,7 @@ const onRemove = (event, removeUploadedFileCallback, type) => {
|
||||
if (type === 'SingleFileUpload') {
|
||||
numberPrFiles.value -= 1;
|
||||
console.log('Number of PR files: ', numberPrFiles.value);
|
||||
formData.value['SingleFileUpload'] = ''
|
||||
formData.value['SingleFileUpload'] = '';
|
||||
}
|
||||
|
||||
// Aggiorna lista dei file caricati
|
||||
@@ -737,8 +765,7 @@ const onRemove = (event, removeUploadedFileCallback, type) => {
|
||||
life: 3000
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
} catch (error) {
|
||||
console.error('Error while removing file:', error);
|
||||
|
||||
// Mostra notifica di errore
|
||||
@@ -748,9 +775,6 @@ const onRemove = (event, removeUploadedFileCallback, type) => {
|
||||
detail: `Error while removing file: ${error.message}`,
|
||||
life: 3000
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error while removing file:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user