Merged PR 34: rating
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
{{ user.name + " " + user.surname }}
|
{{ user.name + " " + user.surname }}
|
||||||
</span>
|
</span>
|
||||||
<!-- <button @click="redirectProject()" class="p-button p-button-outlined">Projects</button> -->
|
<!-- <button @click="redirectProject()" class="p-button p-button-outlined">Projects</button> -->
|
||||||
<button @click="auth.logout()" class="p-button p-button-danger p-button-outlined">Logout</button>
|
<button @click="auth.logout()" class="p-button p-button-outlined">Logout</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -9,13 +9,11 @@ import App from './App.vue';
|
|||||||
import router from './router';
|
import router from './router';
|
||||||
|
|
||||||
|
|
||||||
import Aura from '@primevue/themes/aura';
|
import { definePreset } from '@primevue/themes';
|
||||||
import Lara from '@primevue/themes/lara';
|
|
||||||
import Nora from '@primevue/themes/nora';
|
import Nora from '@primevue/themes/nora';
|
||||||
import PrimeVue from 'primevue/config';
|
import PrimeVue from 'primevue/config';
|
||||||
import ConfirmationService from 'primevue/confirmationservice';
|
import ConfirmationService from 'primevue/confirmationservice';
|
||||||
import ToastService from 'primevue/toastservice';
|
import ToastService from 'primevue/toastservice';
|
||||||
import { definePreset } from '@primevue/themes';
|
|
||||||
|
|
||||||
import BlockViewer from '@/components/BlockViewer.vue';
|
import BlockViewer from '@/components/BlockViewer.vue';
|
||||||
|
|
||||||
@@ -172,3 +170,4 @@ axios.interceptors.response.use(function (response) {
|
|||||||
}, function (error) {
|
}, function (error) {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -20,6 +20,12 @@ export const ScenarioService = {
|
|||||||
getExecScenariosByUser() {
|
getExecScenariosByUser() {
|
||||||
return axios.get('/scenariosByUser')
|
return axios.get('/scenariosByUser')
|
||||||
|
|
||||||
|
},
|
||||||
|
getScenariosForRE(){
|
||||||
|
return axios.get('/getScenariosForRE')
|
||||||
|
},
|
||||||
|
updateScenarioExecRating(data) {
|
||||||
|
return axios.post('/updateRating', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
paginator
|
paginator
|
||||||
:paginatorTemplate="paginatorTemplate"
|
:paginatorTemplate="paginatorTemplate"
|
||||||
:totalRecords="scenario_execution_store.scenariosExecution.length"
|
:totalRecords="scenario_execution_store.scenariosExecution.length"
|
||||||
:first="first"
|
:first="first"
|
||||||
|
filterDisplay="menu"
|
||||||
@page="onPage" :globalFilterFields="['id', 'scenario.name', 'execSharedMap.user_input.selected_project', 'execSharedMap.user_input.selected_application']">
|
@page="onPage" :globalFilterFields="['id', 'scenario.name', 'execSharedMap.user_input.selected_project', 'execSharedMap.user_input.selected_application']">
|
||||||
|
|
||||||
<template #header>
|
<template #header>
|
||||||
@@ -37,41 +38,132 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- <Column field="id" header="Execution ID"></Column> -->
|
|
||||||
<Column field="scenario.name" header="Scenario Name">
|
<Column field="scenario.name" header="Scenario Name" sortable
|
||||||
<template #body="slotProps">
|
style="min-width: 12rem">
|
||||||
|
<template #body="slotProps">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
{{ slotProps.data.scenario.name }}
|
{{ slotProps.data.scenario?.name }}
|
||||||
<i
|
<i
|
||||||
class="pi pi-info-circle text-blue-500 cursor-pointer"
|
class="pi pi-info-circle text-violet-600 cursor-pointer"
|
||||||
v-tooltip="slotProps.data.scenario.description"
|
v-tooltip="slotProps.data?.scenario?.description || 'No description available'"
|
||||||
></i>
|
></i>
|
||||||
|
<!-- controllare il tooltip -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
<Column field="execSharedMap.user_input.selected_project" header="Project Input"></Column>
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
<Column field="execSharedMap.user_input.selected_application" header="Application Input"></Column>
|
placeholder="Search by File" />
|
||||||
<Column header="Start Date">
|
</template>
|
||||||
<template #body="slotProps">
|
</Column>
|
||||||
{{ moment(slotProps.data.startDate).format('DD-MM-YYYY HH:mm:ss') }}
|
<Column field="execSharedMap.user_input.selected_project" header="Project Input" sortable
|
||||||
</template>
|
style="min-width: 12rem">
|
||||||
</Column>
|
<template #body="slotProps">
|
||||||
<Column header="End Date">
|
<div class="flex items-center gap-2">
|
||||||
<template #body="slotProps">
|
{{ slotProps.data.execSharedMap?.user_input?.selected_project }}
|
||||||
{{ moment(slotProps.data.endDate).format('DD-MM-YYYY HH:mm:ss') }}
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
<Column field="scenario.aiModel.apiProvider" header="Model AI"></Column>
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
<Column field="scenario.aiModel.model" header="Version"></Column>
|
placeholder="Search by File" />
|
||||||
<Column field="usedTokens" header="Tokens used"></Column>
|
</template>
|
||||||
<Column header="Output Type">
|
</Column>
|
||||||
<template #body="slotProps">
|
<Column field="execSharedMap.user_input.selected_application" header="Application Input" sortable
|
||||||
{{ slotProps.data.scenario.outputType || 'text' }}
|
style="min-width: 12rem">
|
||||||
</template>
|
<template #body="slotProps">
|
||||||
</Column>
|
<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" @input="filterCallback()"
|
||||||
|
placeholder="Search by File" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="formattedEndDate"
|
||||||
|
filterField="endDate" 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="endDate"
|
||||||
|
header="End Date" sortable
|
||||||
|
style="min-width: 12rem">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
{{ moment(slotProps.data.endDate).format('DD-MM-YYYY HH:mm:ss') }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by File" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="scenario.aiModel.apiProvider" header="Model AI" sortable
|
||||||
|
style="min-width: 12rem">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
{{ slotProps.data.scenario?.aiModel?.apiProvider }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by File" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="scenario.aiModel.model" header="Version" sortable
|
||||||
|
style="min-width: 12rem">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
{{ slotProps.data.scenario?.aiModel?.model || 'N/A' }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by File" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="usedTokens" header="Tokens used" sortable
|
||||||
|
style="min-width: 12rem">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
{{ slotProps.data.usedTokens || 'N/A' }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by File" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column filterField="outputTypeFilter" header="Output Type" sortable
|
||||||
|
style="min-width: 12rem">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
{{ slotProps.data.scenario?.outputType || 'text' }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by File" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
<Column field="rating" header="Rating">
|
<Column field="rating" header="Rating">
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
<Rating :value="slotProps.data.rating" :stars="5" readonly cancel="false" />
|
<Rating :modelValue="slotProps.data.rating" :stars="5" @change="updateRating(slotProps.data, $event)" />
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
<Column field="id" :style="{ position: 'sticky', right: '0', zIndex: '1', background: '#f3f3f3'}">
|
<Column field="id" :style="{ position: 'sticky', right: '0', zIndex: '1', background: '#f3f3f3'}">
|
||||||
@@ -97,13 +189,15 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import { FilterMatchMode } from '@primevue/core/api';
|
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
|
||||||
import 'md-editor-v3/lib/style.css';
|
import 'md-editor-v3/lib/style.css';
|
||||||
|
import moment from 'moment';
|
||||||
import ProgressSpinner from 'primevue/progressspinner';
|
import ProgressSpinner from 'primevue/progressspinner';
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { ScenarioService } from '../../service/ScenarioService.js';
|
||||||
import { ScenarioExecutionStore } from '../../stores/ScenarioExecutionStore.js';
|
import { ScenarioExecutionStore } from '../../stores/ScenarioExecutionStore.js';
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
const first = ref(0);
|
const first = ref(0);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -121,19 +215,95 @@ const debug_modal = ref(false);
|
|||||||
const execution_id = ref("");
|
const execution_id = ref("");
|
||||||
const listScenarios = ref([]);
|
const listScenarios = ref([]);
|
||||||
const scenario_execution_store = ScenarioExecutionStore();
|
const scenario_execution_store = ScenarioExecutionStore();
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const filters = ref({
|
const filters = ref({
|
||||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||||
'id': { value: null, matchMode: FilterMatchMode.CONTAINS },
|
'id': { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||||
'scenario.name': { value: null, matchMode: FilterMatchMode.CONTAINS },
|
'scenario.name': {
|
||||||
'execSharedMap.user_input.selected_project': { value: null, matchMode: FilterMatchMode.CONTAINS },
|
operator: FilterOperator.AND,
|
||||||
'execSharedMap.user_input.selected_application': { value: null, matchMode: FilterMatchMode.CONTAINS }
|
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
|
||||||
|
},
|
||||||
|
'execSharedMap.user_input.selected_project': {
|
||||||
|
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.apiProvider': {
|
||||||
|
operator: FilterOperator.AND,
|
||||||
|
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
|
||||||
|
},
|
||||||
|
'scenario.aiModel.model': {
|
||||||
|
operator: FilterOperator.AND,
|
||||||
|
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
|
||||||
|
},
|
||||||
|
'usedTokens': {
|
||||||
|
operator: FilterOperator.AND,
|
||||||
|
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
|
||||||
|
},
|
||||||
|
outputTypeFilter: {
|
||||||
|
operator: FilterOperator.AND,
|
||||||
|
constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }]
|
||||||
|
},
|
||||||
|
'startDate': {
|
||||||
|
operator: FilterOperator.AND,
|
||||||
|
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||||
|
},
|
||||||
|
'endDate': {
|
||||||
|
operator: FilterOperator.AND,
|
||||||
|
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
scenario_execution_store.fetchScenariosExecution()
|
scenario_execution_store.fetchScenariosExecution()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function updateRating(rowData, newRating) {
|
||||||
|
|
||||||
|
// Aggiorna il rating nell'oggetto prima di inviarlo
|
||||||
|
rowData.rating = newRating.value;
|
||||||
|
console.log('data rating:', rowData);
|
||||||
|
// Mostra un loader se necessario
|
||||||
|
loading_data.value = true;
|
||||||
|
ScenarioService.updateScenarioExecRating(rowData).then((response) => {
|
||||||
|
|
||||||
|
console.log('response:', response);
|
||||||
|
if (response.data === "OK") {
|
||||||
|
console.log('Rating aggiornato con successo:', response.data);
|
||||||
|
scenario_execution_store.fetchScenariosExecution()
|
||||||
|
toast.add({
|
||||||
|
severity: 'success', // Tipo di notifica (successo)
|
||||||
|
summary: 'Successo', // Titolo della notifica
|
||||||
|
detail: 'Rating updated with success.', // Messaggio dettagliato
|
||||||
|
life: 3000 // Durata della notifica in millisecondi
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Errore nell\'aggiornamento del rating', response.data);
|
||||||
|
toast.add({
|
||||||
|
severity: 'error', // Tipo di notifica (errore)
|
||||||
|
summary: 'Errore', // Titolo della notifica
|
||||||
|
detail: 'Error updating rating. Try later.', // Messaggio dettagliato
|
||||||
|
life: 3000 // Durata della notifica in millisecondi
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('Errore durante la chiamata al backend:', error);
|
||||||
|
}).finally(() => {
|
||||||
|
loading_data.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const goToScenarioExec = (execScenarioItem) => {
|
const goToScenarioExec = (execScenarioItem) => {
|
||||||
console.log(execScenarioItem);
|
console.log(execScenarioItem);
|
||||||
|
|||||||
Reference in New Issue
Block a user