Merged PR 116: Create videoGroup picklist for KT scenario
Create videoGroup picklist for KT scenario
This commit is contained in:
20
src/service/KsVideoGroupService.js
Normal file
20
src/service/KsVideoGroupService.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export const KsVideoGroupService = {
|
||||||
|
getKsVideoGroups(projectId) {
|
||||||
|
return axios.get(`/project`, {
|
||||||
|
params: {
|
||||||
|
projectId: projectId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
findByProjectId(projectId) {
|
||||||
|
return axios.get(`/project/${projectId}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
getVideoGroupById(id) {
|
||||||
|
return axios.get(`/${id}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
40
src/stores/KsVideoGroupStore.js
Normal file
40
src/stores/KsVideoGroupStore.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { KsVideoGroupService } from '../service/KsVideoGroupService';
|
||||||
|
|
||||||
|
export const KsVideoGroupStore = defineStore('ksvideogroup_store', () => {
|
||||||
|
const lstKsVideoGroup = ref([]);
|
||||||
|
const selectedKsVideoGroup = ref(null);
|
||||||
|
|
||||||
|
async function fetchKsVideoGroup(projectId) {
|
||||||
|
try {
|
||||||
|
const response = await KsVideoGroupService.getKsVideoGroups(projectId);
|
||||||
|
lstKsVideoGroup.value = response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching video groups:', error);
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ksVideoGroup = computed(() => {
|
||||||
|
return lstKsVideoGroup.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getSelectedKsVideoGroup = computed(() => {
|
||||||
|
return selectedKsVideoGroup.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
async function setSelectedKsVideoGroup(group) {
|
||||||
|
selectedKsVideoGroup.value = group;
|
||||||
|
console.log('selectedVideoGroup', selectedKsVideoGroup.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
fetchKsVideoGroup,
|
||||||
|
selectedKsVideoGroup,
|
||||||
|
lstKsVideoGroup,
|
||||||
|
ksVideoGroup,
|
||||||
|
getSelectedKsVideoGroup,
|
||||||
|
setSelectedKsVideoGroup
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -17,10 +17,9 @@
|
|||||||
<div v-else class="flex mt-2">
|
<div v-else class="flex mt-2">
|
||||||
<div class="card flex flex-col w-full">
|
<div class="card flex flex-col w-full">
|
||||||
<MdPreview :class="['markdown-content', 'ml-[-20px]']" v-model="scenario.hint" language="en-US" />
|
<MdPreview :class="['markdown-content', 'ml-[-20px]']" v-model="scenario.hint" language="en-US" />
|
||||||
|
|
||||||
<template v-if="scenario.inputs">
|
<template v-if="scenario.inputs">
|
||||||
<div class="grid grid-cols-2 md:grid-cols-1">
|
<div class="grid grid-cols-2 md:grid-cols-1">
|
||||||
<div v-for="input in scenario.inputs" :key="input.name" >
|
<div v-for="input in scenario.inputs" :key="input.name">
|
||||||
<div v-if="input.type === 'singlefile' || input.type === 'singlefile_acceptall'">
|
<div v-if="input.type === 'singlefile' || input.type === 'singlefile_acceptall'">
|
||||||
<label :for="input.name">
|
<label :for="input.name">
|
||||||
<b>{{ input.label }}</b>
|
<b>{{ input.label }}</b>
|
||||||
@@ -82,7 +81,6 @@
|
|||||||
<p class="mt-2 mb-2 text-m">Drag and drop files here to upload.</p>
|
<p class="mt-2 mb-2 text-m">Drag and drop files here to upload.</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</FileUpload>
|
</FileUpload>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -151,6 +149,14 @@
|
|||||||
</FileUpload>
|
</FileUpload>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<label :for="input.name"
|
<label :for="input.name"
|
||||||
><b>{{ input.label }}</b></label
|
><b>{{ input.label }}</b></label
|
||||||
@@ -162,7 +168,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="data_loaded && scenario.chatEnabled" class="flex justify-center">
|
<div v-if="data_loaded && scenario.chatEnabled" class="flex justify-center">
|
||||||
<div v-if ="!chat_enabled" class="flex gap-4 mt-6">
|
<div v-if="!chat_enabled" class="flex gap-4 mt-6">
|
||||||
<Button :disabled="loadingStore.exectuion_loading || !isInputFilled" label="Execute" @click="execScenario" size="large" iconPos="right" icon="pi pi-cog"></Button>
|
<Button :disabled="loadingStore.exectuion_loading || !isInputFilled" label="Execute" @click="execScenario" size="large" iconPos="right" icon="pi pi-cog"></Button>
|
||||||
<Button label="Open Chat" @click="chatEnabled" size="large" iconPos="right" icon="pi pi-comments"></Button>
|
<Button label="Open Chat" @click="chatEnabled" size="large" iconPos="right" icon="pi pi-comments"></Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -269,7 +275,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="card flex flex-col gap-4 w-full">
|
<div class="card flex flex-col gap-4 w-full">
|
||||||
<ChatClient :scenarioExecutionId="exec_id"/>
|
<ChatClient :scenarioExecutionId="exec_id" />
|
||||||
</div>
|
</div>
|
||||||
</Panel>
|
</Panel>
|
||||||
</div>
|
</div>
|
||||||
@@ -278,7 +284,9 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import ChangeImpactOutputViewer from '@/components/ChangeImpactOutputViewer.vue';
|
import ChangeImpactOutputViewer from '@/components/ChangeImpactOutputViewer.vue';
|
||||||
import ChatClient from '@/components/ChatClient.vue';
|
import ChatClient from '@/components/ChatClient.vue';
|
||||||
|
import { KsVideoGroupStore } from '@/stores/KsVideoGroupStore';
|
||||||
import { LoadingStore } from '@/stores/LoadingStore';
|
import { LoadingStore } from '@/stores/LoadingStore';
|
||||||
|
import { UserPrefStore } from '@/stores/UserPrefStore';
|
||||||
import { useAuth } from '@websanova/vue-auth/src/v3.js';
|
import { useAuth } from '@websanova/vue-auth/src/v3.js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import JsonEditorVue from 'json-editor-vue';
|
import JsonEditorVue from 'json-editor-vue';
|
||||||
@@ -289,6 +297,7 @@ import 'md-editor-v3/lib/style.css';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { usePrimeVue } from 'primevue/config';
|
import { usePrimeVue } from 'primevue/config';
|
||||||
import InputText from 'primevue/inputtext';
|
import InputText from 'primevue/inputtext';
|
||||||
|
import MultiSelect from 'primevue/multiselect';
|
||||||
import Select from 'primevue/select';
|
import Select from 'primevue/select';
|
||||||
import Textarea from 'primevue/textarea';
|
import Textarea from 'primevue/textarea';
|
||||||
import { useConfirm } from 'primevue/useconfirm';
|
import { useConfirm } from 'primevue/useconfirm';
|
||||||
@@ -317,6 +326,9 @@ const debug_modal = ref(false);
|
|||||||
let pollingInterval = null;
|
let pollingInterval = null;
|
||||||
const folderName = ref('');
|
const folderName = ref('');
|
||||||
const fileNamesOutput = ref([]);
|
const fileNamesOutput = ref([]);
|
||||||
|
const ksVideoGroupStore = KsVideoGroupStore();
|
||||||
|
const userPrefStore = UserPrefStore();
|
||||||
|
const videoGroups = ref([]);
|
||||||
// URL di upload
|
// URL di upload
|
||||||
const uploadUrlBase = import.meta.env.VITE_BACKEND_URL;
|
const uploadUrlBase = import.meta.env.VITE_BACKEND_URL;
|
||||||
const uploadUrl = ref('');
|
const uploadUrl = ref('');
|
||||||
@@ -365,6 +377,14 @@ const isInputFilled = computed(() => {
|
|||||||
if (formData.value[input.name] === undefined || formData.value[input.name] === '') {
|
if (formData.value[input.name] === undefined || formData.value[input.name] === '') {
|
||||||
console.log('Input not filled: ', input.name);
|
console.log('Input not filled: ', input.name);
|
||||||
isFilled = false;
|
isFilled = false;
|
||||||
|
} else {
|
||||||
|
const processedData = { ...formData.value };
|
||||||
|
if (processedData.video_group) {
|
||||||
|
|
||||||
|
processedData.video_group = JSON.stringify(
|
||||||
|
processedData.video_group.map((item) => item.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return isFilled;
|
return isFilled;
|
||||||
@@ -372,6 +392,7 @@ const isInputFilled = computed(() => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchScenario(route.params.id);
|
fetchScenario(route.params.id);
|
||||||
|
loadVideoGroups();
|
||||||
const timestamp = Date.now(); // Ottiene il timestamp corrente
|
const timestamp = Date.now(); // Ottiene il timestamp corrente
|
||||||
const randomNumber = Math.floor(Math.random() * 1000);
|
const randomNumber = Math.floor(Math.random() * 1000);
|
||||||
folderName.value = `${timestamp}_${randomNumber}`;
|
folderName.value = `${timestamp}_${randomNumber}`;
|
||||||
@@ -381,6 +402,14 @@ onMounted(() => {
|
|||||||
console.log('Upload URL:', uploadUrl);
|
console.log('Upload URL:', uploadUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loadVideoGroups = async () => {
|
||||||
|
await ksVideoGroupStore.fetchKsVideoGroup(userPrefStore.selectedProject.id).then(async () => {
|
||||||
|
videoGroups.value = [...(ksVideoGroupStore.ksVideoGroup || [])];
|
||||||
|
//Wait for all video counts to be fetched
|
||||||
|
videoGroups.value = await Promise.all(videoGroups.value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Ricarica i dati quando cambia il parametro `id`
|
// Ricarica i dati quando cambia il parametro `id`
|
||||||
watch(() => route.params.id, fetchScenario);
|
watch(() => route.params.id, fetchScenario);
|
||||||
|
|
||||||
@@ -402,7 +431,7 @@ function fetchScenario(id) {
|
|||||||
}
|
}
|
||||||
if (scenario.value.inputs.some((input) => input.type === 'singlefile_acceptall')) {
|
if (scenario.value.inputs.some((input) => input.type === 'singlefile_acceptall')) {
|
||||||
reqMultiFile.value = false;
|
reqMultiFile.value = false;
|
||||||
acceptedFormats.value = "";
|
acceptedFormats.value = '';
|
||||||
//acceptedFormats.value = '.doc,.docx,.pdf,.msg,.txt,.xlx,.xlxs,.logs,.pptx,.json,.odt,.rtf,.xml,.html';
|
//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')) {
|
if (scenario.value.inputs.some((input) => input.type === 'singlefile')) {
|
||||||
@@ -433,18 +462,20 @@ const getInputComponent = (type) => {
|
|||||||
return Textarea;
|
return Textarea;
|
||||||
case 'select':
|
case 'select':
|
||||||
return Select;
|
return Select;
|
||||||
|
case 'multiselect':
|
||||||
|
return MultiSelect;
|
||||||
default:
|
default:
|
||||||
return InputText;
|
return InputText;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const chatEnabled = () =>{
|
const chatEnabled = () => {
|
||||||
chat_enabled.value = true;
|
chat_enabled.value = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
const chatDisabled = () =>{
|
const chatDisabled = () => {
|
||||||
chat_enabled.value = false;
|
chat_enabled.value = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
const execScenario = () => {
|
const execScenario = () => {
|
||||||
if (numberPrFiles.value !== 1 && reqMultiFile.value) {
|
if (numberPrFiles.value !== 1 && reqMultiFile.value) {
|
||||||
@@ -461,9 +492,17 @@ const execScenario = () => {
|
|||||||
|
|
||||||
loadingStore.exectuion_loading = true;
|
loadingStore.exectuion_loading = true;
|
||||||
|
|
||||||
|
// Crea una copia dei dati del form
|
||||||
|
const processedData = { ...formData.value };
|
||||||
|
if (processedData.video_group) {
|
||||||
|
processedData.video_group = JSON.stringify(
|
||||||
|
processedData.video_group.map((item) => item.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
scenario_id: scenario.value.id,
|
scenario_id: scenario.value.id,
|
||||||
inputs: { ...formData.value }
|
inputs: processedData
|
||||||
};
|
};
|
||||||
|
|
||||||
axios
|
axios
|
||||||
@@ -475,7 +514,6 @@ const execScenario = () => {
|
|||||||
scenario_output.value = response.data.stringOutput;
|
scenario_output.value = response.data.stringOutput;
|
||||||
exec_id.value = response.data.scenarioExecution_id;
|
exec_id.value = response.data.scenarioExecution_id;
|
||||||
loadingStore.setIdExecLoading(exec_id.value);
|
loadingStore.setIdExecLoading(exec_id.value);
|
||||||
// Start polling
|
|
||||||
startPolling();
|
startPolling();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -506,50 +544,42 @@ const pollBackendAPI = () => {
|
|||||||
scenario_response_message.value = null; //if != null, next scenario starts with old message
|
scenario_response_message.value = null; //if != null, next scenario starts with old message
|
||||||
console.log('Scenario 3:', scenario.value);
|
console.log('Scenario 3:', scenario.value);
|
||||||
|
|
||||||
// Controlla se l'array `inputs` contiene un elemento con `name = 'MultiFileUpload'`
|
// Controlla se l'array `inputs` contiene un elemento con `name = 'MultiFileUpload'`
|
||||||
if (scenario.value.inputs.some((input) => input.name === 'MultiFileUpload')) {
|
if (scenario.value.inputs.some((input) => input.name === 'MultiFileUpload')) {
|
||||||
|
if (response.data.status == 'OK') {
|
||||||
if(response.data.status == 'OK' ){
|
// Accedi al primo step e controlla se esiste l'attributo `codegenie_output_type`
|
||||||
// Accedi al primo step e controlla se esiste l'attributo `codegenie_output_type`
|
const firstStep = scenario.value.steps[0];
|
||||||
const firstStep = scenario.value.steps[0];
|
if (firstStep?.attributes?.['codegenie_output_type']) {
|
||||||
if (firstStep?.attributes?.['codegenie_output_type']) {
|
// Controlla se `codegenie_output_type` è uguale a 'FILE'
|
||||||
// Controlla se `codegenie_output_type` è uguale a 'FILE'
|
// if (firstStep.attributes['codegenie_output_type'] === 'FILE') {
|
||||||
// if (firstStep.attributes['codegenie_output_type'] === 'FILE') {
|
// console.log('base64 ', scenario_output.value);
|
||||||
// console.log('base64 ', scenario_output.value);
|
|
||||||
|
|
||||||
// Chiama la funzione `extractFiles` con il valore di `scenario_output.value`
|
|
||||||
//extractFiles(scenario_output.value);
|
|
||||||
//}
|
|
||||||
if(firstStep.attributes['codegenie_output_type'] == 'FILE'){
|
|
||||||
//console.log('base64 ', scenario_output.value)
|
|
||||||
//extractFiles(scenario_output.value, 'output', zipOutput)
|
|
||||||
fileType.value = 'FILE'
|
|
||||||
|
|
||||||
|
// Chiama la funzione `extractFiles` con il valore di `scenario_output.value`
|
||||||
|
//extractFiles(scenario_output.value);
|
||||||
|
//}
|
||||||
|
if (firstStep.attributes['codegenie_output_type'] == 'FILE') {
|
||||||
|
//console.log('base64 ', scenario_output.value)
|
||||||
|
//extractFiles(scenario_output.value, 'output', zipOutput)
|
||||||
|
fileType.value = 'FILE';
|
||||||
|
} else if (firstStep.attributes['codegenie_output_type'] == 'MARKDOWN') {
|
||||||
|
fileType.value = 'MARKDOWN';
|
||||||
|
showFileContent(scenario_output.value, 'MARKDOWN');
|
||||||
|
} else if (firstStep.attributes['codegenie_output_type'] == 'JSON') {
|
||||||
|
fileType.value = 'JSON';
|
||||||
|
showFileContent(scenario_output.value, 'JSON');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(firstStep.attributes['codegenie_output_type'] == 'MARKDOWN'){
|
} else {
|
||||||
fileType.value = 'MARKDOWN'
|
console.log('Error in execution');
|
||||||
showFileContent(scenario_output.value, 'MARKDOWN')
|
}
|
||||||
}
|
|
||||||
else if(firstStep.attributes['codegenie_output_type'] == 'JSON'){
|
|
||||||
fileType.value = 'JSON'
|
|
||||||
showFileContent(scenario_output.value, 'JSON')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
|
||||||
console.log("Error in execution");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
console.log("Condition not met, polling continues.");
|
|
||||||
scenario_response.value = response.data;
|
|
||||||
scenario_response_message.value = response.data.message;
|
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
}
|
console.log('Condition not met, polling continues.');
|
||||||
|
scenario_response.value = response.data;
|
||||||
|
scenario_response_message.value = response.data.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const showFileContent = (base64String, type) => {
|
const showFileContent = (base64String, type) => {
|
||||||
try {
|
try {
|
||||||
@@ -648,7 +678,7 @@ async function updateRating(newRating) {
|
|||||||
life: 3000 // Durata della notifica in millisecondi
|
life: 3000 // Durata della notifica in millisecondi
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error("Errore during rating update", response.data);
|
console.error('Errore during rating update', response.data);
|
||||||
toast.add({
|
toast.add({
|
||||||
severity: 'error', // Tipo di notifica (errore)
|
severity: 'error', // Tipo di notifica (errore)
|
||||||
summary: 'Error', // Titolo della notifica
|
summary: 'Error', // Titolo della notifica
|
||||||
@@ -735,7 +765,6 @@ const onUpload = (event, uploadType) => {
|
|||||||
const { xhr } = event; // Estraggo l'oggetto XMLHttpRequest
|
const { xhr } = event; // Estraggo l'oggetto XMLHttpRequest
|
||||||
|
|
||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
|
|
||||||
if (uploadType === 'SingleFileUpload') {
|
if (uploadType === 'SingleFileUpload') {
|
||||||
//formData.value['SingleFileUpload'] = "OK";
|
//formData.value['SingleFileUpload'] = "OK";
|
||||||
if (event.files && event.files.length > 0) {
|
if (event.files && event.files.length > 0) {
|
||||||
@@ -744,7 +773,7 @@ const onUpload = (event, uploadType) => {
|
|||||||
} else {
|
} else {
|
||||||
formData.value['SingleFileUpload'] = 'UnknownFile';
|
formData.value['SingleFileUpload'] = 'UnknownFile';
|
||||||
}
|
}
|
||||||
console.log("Length of uploaded files", event.files.length);
|
console.log('Length of uploaded files', event.files.length);
|
||||||
numberPrFiles.value += 1;
|
numberPrFiles.value += 1;
|
||||||
console.log('Number of PR files: ', numberPrFiles.value);
|
console.log('Number of PR files: ', numberPrFiles.value);
|
||||||
}
|
}
|
||||||
@@ -760,10 +789,10 @@ const onUpload = (event, uploadType) => {
|
|||||||
detail: 'File uploaded successfully!',
|
detail: 'File uploaded successfully!',
|
||||||
life: 3000
|
life: 3000
|
||||||
});
|
});
|
||||||
console.log("Length of uploaded files", uploadedFiles.value.length);
|
console.log('Length of uploaded files', uploadedFiles.value.length);
|
||||||
} else {
|
} else {
|
||||||
// Errore durante l'upload
|
// Errore durante l'upload
|
||||||
console.error("Error during upload. Status:", xhr.status, 'Response:', xhr.response);
|
console.error('Error during upload. Status:', xhr.status, 'Response:', xhr.response);
|
||||||
|
|
||||||
toast.add({
|
toast.add({
|
||||||
severity: 'error',
|
severity: 'error',
|
||||||
@@ -835,11 +864,9 @@ const formatSize = (bytes) => {
|
|||||||
|
|
||||||
return `${truncatedSize} ${sizes[i]}`;
|
return `${truncatedSize} ${sizes[i]}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.input-container {
|
.input-container {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
@@ -863,7 +890,6 @@ const formatSize = (bytes) => {
|
|||||||
list-style-type: disc !important;
|
list-style-type: disc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
white-space: pre-wrap; /* Fa andare a capo il contenuto automaticamente */
|
white-space: pre-wrap; /* Fa andare a capo il contenuto automaticamente */
|
||||||
word-wrap: break-word; /* Interrompe le parole troppo lunghe */
|
word-wrap: break-word; /* Interrompe le parole troppo lunghe */
|
||||||
@@ -883,6 +909,5 @@ pre {
|
|||||||
max-width: 100%; /* Adatta il contenuto alla larghezza del contenitore */
|
max-width: 100%; /* Adatta il contenuto alla larghezza del contenitore */
|
||||||
overflow-x: auto; /* Aggiunge scorrimento orizzontale solo se necessario */
|
overflow-x: auto; /* Aggiunge scorrimento orizzontale solo se necessario */
|
||||||
background-color: #f5f5f5; /* Sfondo per distinguere il contenuto */
|
background-color: #f5f5f5; /* Sfondo per distinguere il contenuto */
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user