From af8a8b67c3e7bc56a42378accca557dd4731cd5a Mon Sep 17 00:00:00 2001 From: Andrea Terzani Date: Fri, 12 Dec 2025 19:28:17 +0100 Subject: [PATCH] feat: Add Execution Response Section component and related composables for file handling and error management - Implemented ExecutionResponseSection.vue to display execution results and handle file downloads. - Created useBase64Decoder.js for base64 decoding utilities. - Developed useChatToggle.js for managing chat panel state. - Added useErrorHandler.js for standardized error handling with toast notifications. - Introduced useFileDownload.js for various file download operations. - Created useFileProcessing.js for processing files, including zip extraction and content display. - Implemented usePolling.js for polling backend API for execution status. - Added useScenarioRating.js for managing scenario execution ratings. - Developed CSV export utilities in csvExport.js for generating and downloading CSV files. - Created formDataProcessor.js for processing and validating multiselect form data. - Implemented inputComponents.js for mapping input types to PrimeVue components. - Enhanced ScenarioExecHistory.vue to integrate new components and functionalities. --- src/assets/layout/_menu.scss | 36 +- src/assets/layout/_topbar.scss | 36 +- src/assets/styles.scss | 12 + src/components/ChatClient.vue | 399 +++++-- src/components/ExecutionChatSection.vue | 65 ++ src/components/ExecutionInputSection.vue | 80 ++ src/components/ExecutionResponsePanel.vue | 263 +++++ src/components/ExecutionResponseSection.vue | 61 + src/components/ExecutionTimer.vue | 6 +- src/components/MarkdownViewer.vue | 88 +- src/composables/useBase64Decoder.js | 57 + src/composables/useChatToggle.js | 37 + src/composables/useErrorHandler.js | 74 ++ src/composables/useFileDownload.js | 141 +++ src/composables/useFileProcessing.js | 135 +++ src/composables/usePolling.js | 87 ++ src/composables/useScenarioRating.js | 70 ++ src/layout/AppMenu.vue | 238 +++- src/layout/AppTopbar.vue | 105 +- src/main.js | 30 +- src/router/index.js | 2 +- src/service/ScenarioService.js | 5 + src/utils/csvExport.js | 127 ++ src/utils/formDataProcessor.js | 71 ++ src/utils/inputComponents.js | 38 + src/views/pages/DashExecution.vue | 1168 +++++++++++-------- src/views/pages/OldScenarioExec.vue | 358 ------ src/views/pages/ScenarioExec.vue | 699 +++++++++-- src/views/pages/ScenarioExecHistory.vue | 364 ++++++ src/views/pages/ScenarioExecList.vue | 759 ++++++++---- src/views/pages/ScenarioList.vue | 608 ++++++++-- src/views/pages/chat/ChatPage.vue | 170 ++- 32 files changed, 4909 insertions(+), 1480 deletions(-) create mode 100644 src/components/ExecutionChatSection.vue create mode 100644 src/components/ExecutionInputSection.vue create mode 100644 src/components/ExecutionResponsePanel.vue create mode 100644 src/components/ExecutionResponseSection.vue create mode 100644 src/composables/useBase64Decoder.js create mode 100644 src/composables/useChatToggle.js create mode 100644 src/composables/useErrorHandler.js create mode 100644 src/composables/useFileDownload.js create mode 100644 src/composables/useFileProcessing.js create mode 100644 src/composables/usePolling.js create mode 100644 src/composables/useScenarioRating.js create mode 100644 src/utils/csvExport.js create mode 100644 src/utils/formDataProcessor.js create mode 100644 src/utils/inputComponents.js delete mode 100644 src/views/pages/OldScenarioExec.vue create mode 100644 src/views/pages/ScenarioExecHistory.vue diff --git a/src/assets/layout/_menu.scss b/src/assets/layout/_menu.scss index 25dc74a..3bc0fbe 100644 --- a/src/assets/layout/_menu.scss +++ b/src/assets/layout/_menu.scss @@ -10,8 +10,11 @@ transition: transform var(--layout-section-transition-duration), left var(--layout-section-transition-duration); - background-color: var(--surface-overlay); - border-radius: var(--content-border-radius); + background: linear-gradient(180deg, rgba(161, 0, 255, 0.05) 0%, rgba(123, 0, 204, 0.02) 100%); + backdrop-filter: blur(10px); + border: 1px solid rgba(161, 0, 255, 0.1); + box-shadow: 0 4px 20px rgba(161, 0, 255, 0.1); + border-radius: 16px; padding: 0.5rem 1.5rem; } @@ -25,8 +28,10 @@ font-size: 0.857rem; text-transform: uppercase; font-weight: 700; - color: var(--text-color); + color: #A100FF; margin: 0.75rem 0; + padding-bottom: 0.5rem; + border-bottom: 2px solid rgba(161, 0, 255, 0.2); } > a { @@ -65,13 +70,14 @@ color: var(--text-color); cursor: pointer; padding: 0.75rem 1rem; - border-radius: var(--content-border-radius); + border-radius: 12px; transition: - background-color var(--element-transition-duration), - box-shadow var(--element-transition-duration); + all 0.3s ease; + border-left: 3px solid transparent; .layout-menuitem-icon { margin-right: 0.5rem; + transition: all 0.3s ease; } .layout-submenu-toggler { @@ -82,11 +88,25 @@ &.active-route { font-weight: 700; - color: var(--primary-color); + color: #A100FF; + background: linear-gradient(90deg, rgba(161, 0, 255, 0.1) 0%, rgba(161, 0, 255, 0.05) 100%); + border-left-color: #A100FF; + box-shadow: 0 2px 8px rgba(161, 0, 255, 0.15); + + .layout-menuitem-icon { + color: #A100FF; + transform: scale(1.1); + } } &:hover { - background-color: var(--surface-hover); + background: linear-gradient(90deg, rgba(161, 0, 255, 0.08) 0%, rgba(161, 0, 255, 0.03) 100%); + border-left-color: rgba(161, 0, 255, 0.5); + transform: translateX(3px); + + .layout-menuitem-icon { + color: #A100FF; + } } &:focus { diff --git a/src/assets/layout/_topbar.scss b/src/assets/layout/_topbar.scss index de07a1a..2f57036 100644 --- a/src/assets/layout/_topbar.scss +++ b/src/assets/layout/_topbar.scss @@ -6,7 +6,8 @@ top: 0; width: 100%; padding: 0 2rem; - background-color: var(--surface-card); + background: linear-gradient(135deg, rgba(161, 0, 255, 0.85) 0%, #A100FF 50%, #7B00CC 100%); + box-shadow: 0 4px 20px rgba(161, 0, 255, 0.25); transition: left var(--layout-section-transition-duration); display: flex; align-items: center; @@ -22,12 +23,19 @@ align-items: center; font-size: 1.5rem; border-radius: var(--content-border-radius); - color: var(--text-color); - font-weight: 500; + color: white; + font-weight: 600; gap: 0.5rem; + transition: all 0.3s ease; svg { width: 3rem; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2)); + } + + &:hover { + transform: translateY(-2px); + text-shadow: 0 2px 8px rgba(255, 255, 255, 0.3); } &:focus-visible { @@ -39,16 +47,17 @@ display: inline-flex; justify-content: center; align-items: center; - color: var(--text-color-secondary); + color: rgba(255, 255, 255, 0.9); border-radius: 50%; width: 2.5rem; height: 2.5rem; - color: var(--text-color); - transition: background-color var(--element-transition-duration); + transition: all 0.3s ease; cursor: pointer; &:hover { - background-color: var(--surface-hover); + background-color: rgba(255, 255, 255, 0.15); + color: white; + transform: translateY(-2px); } &:focus-visible { @@ -65,8 +74,9 @@ } &.layout-topbar-action-highlight { - background-color: var(--primary-color); - color: var(--primary-contrast-color); + background-color: rgba(255, 255, 255, 0.2); + color: white; + box-shadow: 0 2px 8px rgba(255, 255, 255, 0.2); } } @@ -82,6 +92,7 @@ margin-left: auto; display: flex; gap: 1rem; + align-items: center; } .layout-topbar-menu-content { @@ -92,6 +103,13 @@ .layout-config-menu { display: flex; gap: 1rem; + align-items: center; + } + + .layout-topbar-theme { + color: rgba(255, 255, 255, 0.9); + font-weight: 500; + font-size: 0.95rem; } } diff --git a/src/assets/styles.scss b/src/assets/styles.scss index 83ce387..712375d 100644 --- a/src/assets/styles.scss +++ b/src/assets/styles.scss @@ -8,6 +8,18 @@ font-weight: bold !important; } +/* Global button rounded corners */ +.p-button { + border-radius: 12px !important; +} + +.p-inputtext, +.p-dropdown, +.p-calendar, +.p-multiselect { + border-radius: 8px !important; +} + // h2 { // font-size: 1em !important; // font-weight: bold !important; diff --git a/src/components/ChatClient.vue b/src/components/ChatClient.vue index 6898d73..6df3246 100644 --- a/src/components/ChatClient.vue +++ b/src/components/ChatClient.vue @@ -1,27 +1,3 @@ - - + + diff --git a/src/components/ExecutionChatSection.vue b/src/components/ExecutionChatSection.vue new file mode 100644 index 0000000..d165940 --- /dev/null +++ b/src/components/ExecutionChatSection.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/components/ExecutionInputSection.vue b/src/components/ExecutionInputSection.vue new file mode 100644 index 0000000..b0b2cd0 --- /dev/null +++ b/src/components/ExecutionInputSection.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/src/components/ExecutionResponsePanel.vue b/src/components/ExecutionResponsePanel.vue new file mode 100644 index 0000000..9786d0e --- /dev/null +++ b/src/components/ExecutionResponsePanel.vue @@ -0,0 +1,263 @@ + + + + + diff --git a/src/components/ExecutionResponseSection.vue b/src/components/ExecutionResponseSection.vue new file mode 100644 index 0000000..cbee78b --- /dev/null +++ b/src/components/ExecutionResponseSection.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/components/ExecutionTimer.vue b/src/components/ExecutionTimer.vue index 4ff58d7..9bc33be 100644 --- a/src/components/ExecutionTimer.vue +++ b/src/components/ExecutionTimer.vue @@ -64,13 +64,13 @@ defineExpose({