Files
hermione-fe/src/views/pages/ScenarioExecList.vue

361 lines
14 KiB
Vue

<template>
<div v-if="loading" class="flex justify-center">
<ProgressSpinner style="width: 50px; height: 50px; margin-top: 50px" strokeWidth="3" fill="transparent"/>
</div>
<div v-else >
<h2 class="text-xl font-bold mt-6">Executions List</h2>
<DataTable v-model:filters="filters" v-model:expandedRows="expandedRows" @rowExpand="onRowExpand"
@rowCollapse="onRowCollapse" :value="scenario_execution_store.scenariosExecution"
:loading="loading_data"
:paginator="true"
:lazy="true"
:rows="scenario_execution_store.getPageSize"
:first="scenario_execution_store.getCurrentPage * scenario_execution_store.getPageSize"
:totalRecords="scenario_execution_store.getTotalRecords"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} records"
:rowsPerPageOptions="[10, 15, 20, 50, 100]" dataKey="id" :rowHover="true" rowGroupMode="subheader"
:sortOrder="1" filterDisplay="menu"
tableStyle="min-width: 70rem"
@page="onPage"
@sort="onSort"
removableSort>
<template #header>
<div class="flex justify-end">
<IconField>
<Button label="Clear Filters" @click="clearFilters" class="mr-2" />
<InputIcon>
<i class="pi pi-search" />
</InputIcon>
<InputText v-model="filters['_id'].constraints[0].value" placeholder="ID" />
<Button label="Apply" @click="fetchData(0, 10)" />
</IconField>
</div>
</template>
<Column field="scenario.name" header="Scenario Name" sortable :showFilterOperator="false" :showApplyButton="false" :showAddButton="false" :showClearButton="false"
style="min-width: 12rem" >
<template #body="slotProps">
<div class="flex items-center gap-2">
{{ slotProps.data.scenario?.name }}
<i
class="pi pi-info-circle text-violet-600 cursor-pointer"
v-tooltip="slotProps.data?.scenario?.description || 'No description available'"
></i>
<!-- controllare il tooltip -->
</div>
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text" placeholder="Search by ScenarioName" />
<Button label="Apply" @click="fetchDataWithFilters(filterCallback)" />
</template>
</Column>
<Column field="execSharedMap.user_input.selected_application" header="Application Input" sortable :showFilterOperator="false" :showApplyButton="false" :showAddButton="false" :showClearButton="false"
style="min-width: 12rem">
<template #body="slotProps">
<div class="flex items-center gap-2">
{{ slotProps.data.execSharedMap?.user_input?.selected_application }}
</div>
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text"
placeholder="Search by Application" />
<Button label="Apply" @click="fetchDataWithFilters(filterCallback)" />
</template>
</Column>
<!-- <Column field="startDate"
filterField="startDate" header="Start Date" sortable
style="min-width: 12rem">
<template #body="slotProps">
<div class="flex items-center gap-2">
{{ moment(slotProps.data.startDate).format('DD-MM-YYYY HH:mm:ss') }}
</div>
</template>
<template #filter="{ filterModel, filterCallback }">
<Calendar
v-model="filterModel.value"
@input="(value) => {
filterModel.value = new Date(value); // Converte in oggetto Date
filterCallback();
}"
dateFormat="yy-mm-dd"
placeholder="Filter by Date"
/>
</template>
</Column> -->
<Column field="startDate" header="Start Date" filterField="startDate" dataType="date" style="min-width: 10rem" sortable>
<template #body="slotProps">
{{ moment(slotProps.data.startDate).format('DD-MM-YYYY HH:mm:ss') }}
</template>
<!-- <template #filter="{ filterModel, filterCallback }">
<DatePicker v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" />
<Button label="Apply" @click="fetchDataWithFilters(filterCallback)" />
</template> -->
</Column>
<Column field="scenario.aiModel.model" header="Model AI"
style="min-width: 12rem">
<template #body="slotProps">
<div class="flex items-center gap-2">
{{ slotProps.data.scenario?.aiModel?.model }}
<i
class="pi pi-info-circle text-violet-600 cursor-pointer"
v-tooltip="'Provider: ' + slotProps.data?.scenario?.aiModel?.apiProvider + ' Token used: ' + slotProps.data?.usedTokens || 'No description available'"
></i>
</div>
</template>
<!-- <template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text"
placeholder="Search by Model" />
<Button label="Apply" @click="fetchDataWithFilters(filterCallback)" />
</template> -->
</Column>
<Column field="executedByUsername" header="Executed By" sortable
style="min-width: 12rem" :showApplyButton="false" :showFilterOperator="false" :showAddButton="false" :showClearButton="false">
<template #body="slotProps">
<div class="flex items-center gap-2">
{{ slotProps.data.executedByUsername || 'N/A' }}
</div>
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text"
placeholder="Search by Username" />
<Button label="Apply" @click="fetchDataWithFilters(filterCallback)" />
</template>
</Column>
<Column field="rating" header="Rating" sortable :showApplyButton="false" :showFilterMatchModes="false" :showFilterOperator="false" :showAddButton="false" :showClearButton="false">
<template #body="slotProps">
<Rating :modelValue="slotProps.data.rating" :stars="5" :readonly="true" />
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text" placeholder="Search (1,2,3,4,5)" />
<Button label="Apply" @click="fetchDataWithFilters(filterCallback)" />
</template>
</Column>
<Column field="id" :style="{ position: 'sticky', right: '0', zIndex: '1', background: '#f3f3f3'}">
<template #body="slotProps">
<div class="flex justify-center items-center h-full">
<Button label="View" @click="goToScenarioExec(slotProps.data)" class="mt-0 ml-0" />
</div>
</template>
</Column>
<template #empty>
<tr>
<td :colspan="9" class="text-center">No execution found</td>
</tr>
</template>
</DataTable>
</div>
<div v-if="loading_data" class="flex justify-center">
<ProgressSpinner style="width: 30px; height: 30px; margin: 30px" strokeWidth="6" fill="transparent"/>
</div>
</template>
<script setup>
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
import 'md-editor-v3/lib/style.css';
import moment from 'moment';
import ProgressSpinner from 'primevue/progressspinner';
import { useToast } from 'primevue/usetoast';
import { onMounted, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ScenarioExecutionStore } from '../../stores/ScenarioExecutionStore.js';
import { UserPrefStore } from '../../stores/UserPrefStore.js';
const first = ref(0);
const router = useRouter();
const route = useRoute();
const value = ref('');
const scenario = ref({});
const scenario_output = ref(null);
const loading = ref(false);
const data_loaded = ref(false);
const loading_data = ref(false);
const formData = ref({});
const exec_id = ref(null);
const exec_scenario = ref({});
const debug_modal = ref(false);
const execution_id = ref("");
const listScenarios = ref([]);
const scenario_execution_store = ScenarioExecutionStore();
const toast = useToast();
const userPrefStore = UserPrefStore();
const records = ref(788);
const actualPage = ref(0);
const actualPageSize = ref(10);
const sortField = ref(null);
const sortOrder = ref(null);
const filters = ref({
'_id': { operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
},
'scenario.name': {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
},
'execSharedMap.user_input.selected_application': {
operator: FilterOperator.AND,
constraints: [{
value: userPrefStore.getSelApp?.fe_name || null, matchMode: FilterMatchMode.CONTAINS
}]
},
'scenario.aiModel.model': {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
},
'executedByUsername': {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
},
'startDate': {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
},
'rating': {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
}
});
onMounted(() => {
updateFilters();
});
watch(() => route.params.name, updateFilters);
// watch([() => filters.value], () => {
// scenario_execution_store.updateFilters(filters.value); // Applica i filtri e carica i dati
// });
// watch([() => filters.value, () => first.value], () => {
// fetchData(Math.floor(first.value / scenario_execution_store.getPageSize), scenario_execution_store.getPageSize, filters.value);
// });
function updateFilters() {
const selectedScenario = userPrefStore.getSelScenario;
if (selectedScenario && route.params.name!=='all') {
console.log('selectedScenario: im in');
filters.value['scenario.name'].constraints[0].value = selectedScenario;
}else{
filters.value['scenario.name'].constraints[0].value = null;
}
fetchData(0, 10);
}
function fetchDataWithFilters(filterCallback) {
filterCallback();
fetchData(0, actualPageSize.value);
}
function onSort(event) {
console.log('Sorting event:', event);
sortField.value = event.sortField;
sortOrder.value = event.sortOrder;
fetchData(0,actualPageSize.value);
}
const fetchData = async (page, size) => {
loading_data.value = true;
try {
scenario_execution_store.fetchScenariosExecution(page, size, filters.value, sortField.value, sortOrder.value);
//const response = await ScenarioService.getScenarioExecutionList(page, size, filtersForRequest);
// aggiorna il store con i risultati della query
} catch (error) {
console.error('Error fetching data', error);
} finally {
loading_data.value = false;
}
};
function clearFilters() {
filters.value = {
'_id': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }] },
'scenario.name': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }] },
'execSharedMap.user_input.selected_application': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }] },
'scenario.aiModel.model': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }] },
'executedByUsername': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }] },
'startDate': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] }
};
fetchData(0, actualPageSize.value);
}
const goToScenarioExec = (execScenarioItem) => {
console.log(execScenarioItem);
router.push({ name: 'scenario-exec-history', query: { id:execScenarioItem.id } });
// scenario_execution_store.setSelectedExecScenario(execScenarioItem).then(() => {
// router.push({ name: 'scenario-exec-history', query: { id:execScenarioItem.id } });
// });
};
function onPage(event) {
actualPage.value = event.page;
actualPageSize.value = event.rows;
fetchData(event.page, event.rows);
console.log('event onpage:', event);
//updateFilters();
}
// function onPage(event) {
// first.value = event.first; // Imposta la pagina corrente
// fetchData(Math.floor(first.value / scenario_execution_store.getPageSize), scenario_execution_store.getPageSize);
// }
</script>
<style scoped>
.input-container {
margin-bottom: 1em;
}
.input-wrapper {
display: flex;
align-items: center;
gap: 0.5em;
margin-top: 10px;
}
.full-width-input {
width: 100%;
}
.editor ol {
list-style-type: decimal !important;
}
.editor ul {
list-style-type: disc !important;
}
</style>