From 3b2797c6121935af021f3ea78e06b621c02b7e17 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Thu, 30 Oct 2025 17:49:34 +0100 Subject: [PATCH 01/37] Base Skeleton --- packages/vscode-extension/messages.json | 16 ++ packages/vscode-extension/package.json | 8 +- .../src/service/TranslationKeys.ts | 20 +++ packages/vscode-extension/src/suitecloud.ts | 8 + .../src/webviews/FeedbackForm.html | 83 +++++++++++ .../src/webviews/FeedbackFormWebview.ts | 141 ++++++++++++++++++ .../src/webviews/feedbackForm.css | 94 ++++++++++++ 7 files changed, 369 insertions(+), 1 deletion(-) create mode 100644 packages/vscode-extension/src/webviews/FeedbackForm.html create mode 100644 packages/vscode-extension/src/webviews/FeedbackFormWebview.ts create mode 100644 packages/vscode-extension/src/webviews/feedbackForm.css diff --git a/packages/vscode-extension/messages.json b/packages/vscode-extension/messages.json index 7ba56104..ba47f078 100644 --- a/packages/vscode-extension/messages.json +++ b/packages/vscode-extension/messages.json @@ -54,6 +54,22 @@ "DEPLOY_QUESTIONS_CHOICES_ACCOUNT_SPECIFIC_VALUES_CANCEL_PROCESS": "Cancel the deployment process", "DEPLOY_QUESTIONS_CHOICES_ACCOUNT_SPECIFIC_VALUES_DISPLAY_WARNING": "Display a warning and continue the deployment process", + "DEVASSIST_SERVICE_FEEDBACK_FORM_DOCUMENT_TITLE": "SuiteCloud Developer Assistant Feedback Form", + "DEVASSIST_SERVICE_FEEDBACK_FORM_TITLE": "SuiteCloud Developer Assistant Feedback", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBTITLE": "Share quick feedback about the SuiteCloud Developer Assistant. Works fully offline—no data leaves this page.", + "DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_SUBTITLE": "Your feedback", + "DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_HINT": "What worked well? What should be improved?", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_SUBTITLE": "This feedback is about", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_1": "Explain Code", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_2": "Generate SuiteScript Code", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_3": "Generate SDF Objects", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_4": "Unit Testing", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_5": "Other", + "DEVASSIST_SERVICE_FEEDBACK_FORM_RATING_SUBTITLE": "Rating (1-5)", + "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SEND": "Send", + "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_CANCEL": "Cancel", + + "DEVASSIST_SERVICE_IS_DISABLED_NOTIFICATION": "SuiteCloud Developer Assistant service has been disabled.", "DEVASSIST_SERVICE_IS_DISABLED_OUTPUT": "SuiteCloud Developer Assistant service has been disabled.", "DEVASSIST_SERVICE_IS_RUNNING_NOTIFICATION": "SuiteCloud Developer Assistant service is running. Use Cline Base URL to: {0}", diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index 2416a6f9..6b009754 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -111,7 +111,13 @@ "title": "Open DevAssist settings", "category": "SuiteCloud", "enablement": "false" - } + }, + { + "command": "suitecloud.opendevassistfeedbackform", + "title": "Open DevAssist Feedback Forms", + "category": "SuiteCloud", + "enablement": "true" + } ], "keybindings": [ { diff --git a/packages/vscode-extension/src/service/TranslationKeys.ts b/packages/vscode-extension/src/service/TranslationKeys.ts index 545e7336..2866e636 100644 --- a/packages/vscode-extension/src/service/TranslationKeys.ts +++ b/packages/vscode-extension/src/service/TranslationKeys.ts @@ -98,6 +98,26 @@ export const DEPLOY = { }; export const DEVASSIST_SERVICE = { + FEEDBACK_FORM: { + WEBVIEW_TITLE: 'DEVASSIST_SERVICE_FEEDBACK_FORM_DOCUMENT_TITLE', + TITLE: 'DEVASSIST_SERVICE_FEEDBACK_FORM_TITLE', + SUBTITLE: 'DEVASSIST_SERVICE_FEEDBACK_FORM_SUBTITLE', + TEXTAREA_SUBTITLE: 'DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_SUBTITLE', + TEXTAREA_HINT: 'DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_HINT', + CHECKBOX_LIST_SUBTITLE: 'DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_SUBTITLE', + CHECKBOX_LIST_OPTIONS: { + OPTION_1: 'DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_1', + OPTION_2: 'DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_2', + OPTION_3: 'DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_3', + OPTION_4: 'DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_4', + OPTION_5: 'DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_5', + }, + RATING_SUBTITLE: 'DEVASSIST_SERVICE_FEEDBACK_FORM_RATING_SUBTITLE', + BUTTON: { + SEND: 'DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SEND', + CANCEL: 'DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_CANCEL' + } + }, IS_DISABLED: { NOTIFICATION: 'DEVASSIST_SERVICE_IS_DISABLED_NOTIFICATION', OUTPUT: 'DEVASSIST_SERVICE_IS_DISABLED_OUTPUT', diff --git a/packages/vscode-extension/src/suitecloud.ts b/packages/vscode-extension/src/suitecloud.ts index 38403896..3a15642b 100644 --- a/packages/vscode-extension/src/suitecloud.ts +++ b/packages/vscode-extension/src/suitecloud.ts @@ -29,6 +29,7 @@ import { VSTranslationService } from './service/VSTranslationService'; import { devAssistConfigurationChangeHandler, startDevAssistProxyIfEnabled } from './startup/DevAssistConfiguration'; import { showSetupAccountWarningMessageIfNeeded } from './startup/ShowSetupAccountWarning'; import { createAuthIDStatusBar, createDevAssistStatusBar, createSuiteCloudProjectStatusBar, updateAuthIDStatusBarIfNeeded, updateStatusBars } from './startup/StatusBarItemsFunctions'; +import { openDevAssistFeedbackForm } from './webviews/FeedbackFormWebview'; const SCLOUD_OUTPUT_CHANNEL_NAME = 'SuiteCloud'; @@ -94,6 +95,13 @@ export async function activate(context: vscode.ExtensionContext) { vscode.workspace.onDidChangeConfiguration((configurationChangeEvent => devAssistConfigurationChangeHandler(configurationChangeEvent, devAssistStatusBar))) ); + // DevAssist Feedback Form WebView + context.subscriptions.push( + vscode.commands.registerCommand('suitecloud.opendevassistfeedbackform', + () => openDevAssistFeedbackForm(context) + ) + ); + // Use the console to output diagnostic information (console.log) and errors (console.error) // This line of code will only be executed once when your extension is activated console.log('SuiteCloud Extension for Visual Studio Code has been activated.'); diff --git a/packages/vscode-extension/src/webviews/FeedbackForm.html b/packages/vscode-extension/src/webviews/FeedbackForm.html new file mode 100644 index 00000000..0e113932 --- /dev/null +++ b/packages/vscode-extension/src/webviews/FeedbackForm.html @@ -0,0 +1,83 @@ + + + + + DevAssist Feedback + + + +
+

DevAssist Feedback

+

Share quick feedback about an AI answer. Works fully offline - no data leaves this page

+
+ + + +
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + +
+
+ +
+ + +
+
+
+ + + \ No newline at end of file diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts new file mode 100644 index 00000000..285c9baf --- /dev/null +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -0,0 +1,141 @@ +import * as vscode from 'vscode'; +import * as path from 'path'; +import { VSTranslationService } from '../service/VSTranslationService'; +import { DEVASSIST_SERVICE, STATUS_BARS } from '../service/TranslationKeys'; + +const translationService = new VSTranslationService(); + +let feedbackFormPanel: vscode.WebviewPanel | undefined; + +export const openDevAssistFeedbackForm = (context : vscode.ExtensionContext) => { + + // if one FeedbackForm is already open, reveal it instead of creating a new one + if (feedbackFormPanel) { + feedbackFormPanel.reveal(vscode.ViewColumn.One); + return; + } + + feedbackFormPanel = vscode.window.createWebviewPanel( + 'devassistfeedbackform', // viewtype (used internally by vscode) + translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.WEBVIEW_TITLE), + vscode.ViewColumn.One, + { + enableScripts: true, + localResourceRoots: [ + vscode.Uri.file(path.join(context.extensionPath, 'media')) + ] + } + ); + + // Read HTML and inject the correct webview resource URIs for the CSS file + feedbackFormPanel.webview.html = getFeedbackFormHTMLContent(); + + // Clean up the reference when the panel is closed + feedbackFormPanel.onDidDispose( + () => { feedbackFormPanel = undefined; }, + null, + context.subscriptions + ); + + // Handle messages sent from the webview + feedbackFormPanel.webview.onDidReceiveMessage( + message => { + switch (message.type) { + case 'submit': + vscode.window.showInformationMessage('Thanks for your feedback!'); + // Handle/store feedback as needed + feedbackFormPanel?.dispose(); + break; + case 'cancel': + feedbackFormPanel?.dispose(); + break; + } + }, + undefined, + context.subscriptions + ); +} + +const getCheckboxesHTMLContent = () => { + const optionsList = Object.values(DEVASSIST_SERVICE.FEEDBACK_FORM.CHECKBOX_LIST_OPTIONS); + return optionsList.map(option => { + const optionValue = translationService.getMessage(option); + const optionID = optionValue.toLowerCase().replace(/\s+/g, '-'); + return `
+ + +
`; }).join(''); +} + +const getFeedbackFormHTMLContent = () => { + return ` + + + + DevAssist Feedback + + + +
+

${DEVASSIST_SERVICE.FEEDBACK_FORM.TITLE}

+

${DEVASSIST_SERVICE.FEEDBACK_FORM.SUBTITLE}

+
+ + + +
+ + ${getCheckboxesHTMLContent} +
+ +
+ +
+ + + + + +
+
+ +
+ + +
+
+
+ + + `; +} \ No newline at end of file diff --git a/packages/vscode-extension/src/webviews/feedbackForm.css b/packages/vscode-extension/src/webviews/feedbackForm.css new file mode 100644 index 00000000..86ffd89b --- /dev/null +++ b/packages/vscode-extension/src/webviews/feedbackForm.css @@ -0,0 +1,94 @@ +body { + font-family: Arial, sans-serif; + background: #20232a; + color: #ededed; + margin: 0; + padding: 0; +} + +.container { + max-width: 480px; + margin: 32px auto; + background: #2c2f36; + padding: 24px; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +h1 { + font-size: 1.7em; + margin-bottom: 0.5em; +} + +h2 { + font-size: 1.1em; + color: #ffefbf; + margin-bottom: 1.4em; + font-weight: normal; +} + +label { + font-weight: bold; + margin-bottom: 0.5em; + display: block; +} + +textarea { + width: 100%; + border-radius: 4px; + border: 1px solid #4b5563; + resize: vertical; + padding: 8px; + background: #23272f; + color: #ededed; + margin-bottom: 1.2em; + min-height: 80px; +} + +.checkbox-group div { + margin: 0.4em 0; +} + +.rating-group { + margin: 1.2em 0; +} + +.stars { + font-size: 1.7em; + color: #bbb; + cursor: pointer; + user-select: none; +} + +.stars .selected { + color: #fae34f; +} + +.button-group { + margin-top: 2em; + display: flex; + justify-content: flex-end; + gap: 1.2em; +} + +button { + padding: 0.6em 1.6em; + border: none; + border-radius: 4px; + font-size: 1em; + cursor: pointer; +} + +#cancel-button { + background: #6b7280; + color: #fff; +} + +#send-button { + background: #2186d4; + color: #fff; +} + +button:active { + opacity: 0.8; +} \ No newline at end of file From 6d6bf0d2d705656383958ea5c636c30b3b3a094c Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Fri, 31 Oct 2025 17:50:47 +0100 Subject: [PATCH 02/37] New HTML --- .../src/webviews/FeedbackForm.html | 131 +++++++------ .../src/webviews/FeedbackFormWebview.ts | 176 ++++++++++------- .../src/webviews/feedbackForm.css | 184 +++++++++++++----- 3 files changed, 308 insertions(+), 183 deletions(-) diff --git a/packages/vscode-extension/src/webviews/FeedbackForm.html b/packages/vscode-extension/src/webviews/FeedbackForm.html index 0e113932..3567c3bc 100644 --- a/packages/vscode-extension/src/webviews/FeedbackForm.html +++ b/packages/vscode-extension/src/webviews/FeedbackForm.html @@ -3,81 +3,96 @@ DevAssist Feedback - + -
-

DevAssist Feedback

-

Share quick feedback about an AI answer. Works fully offline - no data leaves this page

-
- - +
+
+

${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.TITLE)}

+

${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBTITLE)}

+
+ +
+ + +
-
- -
- - -
-
- - -
-
- - -
-
- - +
+ ${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.CHECKBOX_LIST_SUBTITLE)} +
+ ${getCheckboxesHTMLContent()}
-
+ -
- -
- - - - - +
+ +
+ + + + + + + + + + +
-
- - +
+ + +
+ +
+ See payload + +
\ No newline at end of file diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index 285c9baf..c2028d93 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -1,13 +1,15 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { VSTranslationService } from '../service/VSTranslationService'; -import { DEVASSIST_SERVICE, STATUS_BARS } from '../service/TranslationKeys'; +import { DEVASSIST_SERVICE } from '../service/TranslationKeys'; const translationService = new VSTranslationService(); +const cssFileName = 'feedbackForm.css'; +const cssFilePath = './src/webviews/' + cssFileName; let feedbackFormPanel: vscode.WebviewPanel | undefined; -export const openDevAssistFeedbackForm = (context : vscode.ExtensionContext) => { +export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // if one FeedbackForm is already open, reveal it instead of creating a new one if (feedbackFormPanel) { @@ -22,19 +24,22 @@ export const openDevAssistFeedbackForm = (context : vscode.ExtensionContext) => { enableScripts: true, localResourceRoots: [ - vscode.Uri.file(path.join(context.extensionPath, 'media')) - ] - } + vscode.Uri.file(path.join(context.extensionPath, 'src/webviews')), + ], + }, ); // Read HTML and inject the correct webview resource URIs for the CSS file - feedbackFormPanel.webview.html = getFeedbackFormHTMLContent(); + const cssUri = feedbackFormPanel.webview.asWebviewUri(vscode.Uri.file(path.join(context.extensionPath, cssFilePath))); + feedbackFormPanel.webview.html = getFeedbackFormHTMLContent(cssUri); // Clean up the reference when the panel is closed feedbackFormPanel.onDidDispose( - () => { feedbackFormPanel = undefined; }, + () => { + feedbackFormPanel = undefined; + }, null, - context.subscriptions + context.subscriptions, ); // Handle messages sent from the webview @@ -52,90 +57,117 @@ export const openDevAssistFeedbackForm = (context : vscode.ExtensionContext) => } }, undefined, - context.subscriptions + context.subscriptions, ); -} +}; const getCheckboxesHTMLContent = () => { const optionsList = Object.values(DEVASSIST_SERVICE.FEEDBACK_FORM.CHECKBOX_LIST_OPTIONS); return optionsList.map(option => { const optionValue = translationService.getMessage(option); const optionID = optionValue.toLowerCase().replace(/\s+/g, '-'); - return `
- - -
`; }).join(''); -} + return ``; + }).join(''); +}; + +const getFeedbackFormHTMLContent = (cssUri: any) => { -const getFeedbackFormHTMLContent = () => { return ` DevAssist Feedback - + -
-

${DEVASSIST_SERVICE.FEEDBACK_FORM.TITLE}

-

${DEVASSIST_SERVICE.FEEDBACK_FORM.SUBTITLE}

-
- - - -
- - ${getCheckboxesHTMLContent} -
- -
- -
- - - - - -
+
+
+

${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.TITLE)}

+

${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBTITLE)}

+
+ +
+ + +
+ +
+ ${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.CHECKBOX_LIST_SUBTITLE)} +
+ ${getCheckboxesHTMLContent()}
- -
- - +
+ +
+ +
+ + + + + + + + + + +
- -
- + copyBtn.addEventListener('click', async () => { + const data = collect(); + const json = JSON.stringify(data, null, 2); + try { + await navigator.clipboard.writeText(json); + copyBtn.textContent = 'Copied!'; + setTimeout(() => (copyBtn.textContent = 'Copy JSON'), 1200); + } catch (err) { + // Fallback: show in pane if clipboard blocked + result.textContent = json + '\\n\\n(Clipboard blocked by browser)'; + result.classList.remove('hidden'); + } + }); + `; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/packages/vscode-extension/src/webviews/feedbackForm.css b/packages/vscode-extension/src/webviews/feedbackForm.css index 86ffd89b..8616ec57 100644 --- a/packages/vscode-extension/src/webviews/feedbackForm.css +++ b/packages/vscode-extension/src/webviews/feedbackForm.css @@ -1,94 +1,172 @@ +:root { + --gap: 12px; + --radius: 12px; + --border: #e5e7eb; + --text: #111827; + --muted: #6b7280 +} + +* { + box-sizing: border-box +} + body { - font-family: Arial, sans-serif; - background: #20232a; - color: #ededed; + font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Helvetica, Arial, sans-serif; + color: var(--text); + background: #f8fafc; margin: 0; - padding: 0; + padding: 24px } -.container { - max-width: 480px; - margin: 32px auto; - background: #2c2f36; - padding: 24px; - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0,0,0,0.2); +.card { + max-width: 760px; + margin: auto; + background: #fff; + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: 0 10px 25px rgba(0, 0, 0, .05) +} + +.card header { + padding: 20px 24px; + border-bottom: 1px solid var(--border) } h1 { - font-size: 1.7em; - margin-bottom: 0.5em; + font-size: 20px; + margin: 0 } -h2 { - font-size: 1.1em; - color: #ffefbf; - margin-bottom: 1.4em; - font-weight: normal; +.content { + padding: 20px 24px; + display: grid; + gap: var(--gap) } label { - font-weight: bold; - margin-bottom: 0.5em; - display: block; + font-weight: 600 } textarea { width: 100%; - border-radius: 4px; - border: 1px solid #4b5563; + min-height: 120px; + padding: 12px; + border: 1px solid var(--border); + border-radius: 10px; resize: vertical; - padding: 8px; - background: #23272f; - color: #ededed; - margin-bottom: 1.2em; - min-height: 80px; + font: inherit +} + +fieldset { + border: 1px solid var(--border); + border-radius: 10px; + padding: 12px } -.checkbox-group div { - margin: 0.4em 0; +legend { + padding: 0 6px; + color: var(--muted) } -.rating-group { - margin: 1.2em 0; +.checks { + display: grid; + grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); + gap: 8px 14px; + margin-top: 6px +} + +.checks label { + font-weight: 500; + display: flex; + align-items: center; + gap: 8px +} + +.checks input { + transform: translateY(1px) } .stars { - font-size: 1.7em; - color: #bbb; + display: inline-flex; + flex-direction: row-reverse; + gap: 6px +} + +.stars input { + display: none +} + +.star { cursor: pointer; - user-select: none; + font-size: 28px; + line-height: 1; + filter: grayscale(.6); + transition: transform .05s ease +} + +.star::before { + content: "☆" +} + +.stars label.star:hover, +.stars label.star:hover ~ label.star { + transform: scale(1.05) +} + +/* Fill stars up to the selected one */ +.stars input:checked + label.star::before, +.stars input:checked + label.star ~ label.star::before { + content: "★" } -.stars .selected { - color: #fae34f; +.stars input:checked + label.star, +.stars input:checked + label.star ~ label.star { + filter: none; + color: #f59e0b } -.button-group { - margin-top: 2em; +.row { + display: grid; + gap: 6px +} + +.actions { display: flex; + gap: 10px; justify-content: flex-end; - gap: 1.2em; + margin-top: 8px } button { - padding: 0.6em 1.6em; - border: none; - border-radius: 4px; - font-size: 1em; - cursor: pointer; + appearance: none; + border: 1px solid var(--border); + background: #111827; + color: #fff; + padding: 10px 14px; + border-radius: 10px; + font-weight: 600; + cursor: pointer } -#cancel-button { - background: #6b7280; - color: #fff; +button.secondary { + background: #fff; + color: #111827 } -#send-button { - background: #2186d4; - color: #fff; +.note { + color: var(--muted); + font-size: 12px +} + +pre { + background: #0b1020; + color: #d1d5db; + padding: 12px; + border-radius: 10px; + overflow: auto; + max-height: 240px } -button:active { - opacity: 0.8; +.hidden { + display: none } \ No newline at end of file From 09c7cb84786fe1ba37d7e0b08cbde4d78dd8744b Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Mon, 3 Nov 2025 13:12:30 +0100 Subject: [PATCH 03/37] More changes --- packages/vscode-extension/messages.json | 2 +- packages/vscode-extension/package.json | 8 +- .../src/service/TranslationKeys.ts | 2 +- packages/vscode-extension/src/suitecloud.ts | 7 +- .../src/webviews/FeedbackFormWebview.ts | 78 ++++++++++++++++++- 5 files changed, 90 insertions(+), 7 deletions(-) diff --git a/packages/vscode-extension/messages.json b/packages/vscode-extension/messages.json index ba47f078..8cac7dce 100644 --- a/packages/vscode-extension/messages.json +++ b/packages/vscode-extension/messages.json @@ -66,7 +66,7 @@ "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_4": "Unit Testing", "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_5": "Other", "DEVASSIST_SERVICE_FEEDBACK_FORM_RATING_SUBTITLE": "Rating (1-5)", - "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SEND": "Send", + "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SUBMIT": "Submit", "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_CANCEL": "Cancel", diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index 6b009754..db56ec51 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -117,7 +117,13 @@ "title": "Open DevAssist Feedback Forms", "category": "SuiteCloud", "enablement": "true" - } + }, + { + "command": "suitecloud.debugCall", + "title": "DevAssist Feedback Forms: Debug Call", + "category": "SuiteCloud", + "enablement": "true" + } ], "keybindings": [ { diff --git a/packages/vscode-extension/src/service/TranslationKeys.ts b/packages/vscode-extension/src/service/TranslationKeys.ts index 2866e636..3aaf80c3 100644 --- a/packages/vscode-extension/src/service/TranslationKeys.ts +++ b/packages/vscode-extension/src/service/TranslationKeys.ts @@ -114,7 +114,7 @@ export const DEVASSIST_SERVICE = { }, RATING_SUBTITLE: 'DEVASSIST_SERVICE_FEEDBACK_FORM_RATING_SUBTITLE', BUTTON: { - SEND: 'DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SEND', + SUBMIT: 'DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SUBMIT', CANCEL: 'DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_CANCEL' } }, diff --git a/packages/vscode-extension/src/suitecloud.ts b/packages/vscode-extension/src/suitecloud.ts index 3a15642b..b512b5fe 100644 --- a/packages/vscode-extension/src/suitecloud.ts +++ b/packages/vscode-extension/src/suitecloud.ts @@ -29,7 +29,7 @@ import { VSTranslationService } from './service/VSTranslationService'; import { devAssistConfigurationChangeHandler, startDevAssistProxyIfEnabled } from './startup/DevAssistConfiguration'; import { showSetupAccountWarningMessageIfNeeded } from './startup/ShowSetupAccountWarning'; import { createAuthIDStatusBar, createDevAssistStatusBar, createSuiteCloudProjectStatusBar, updateAuthIDStatusBarIfNeeded, updateStatusBars } from './startup/StatusBarItemsFunctions'; -import { openDevAssistFeedbackForm } from './webviews/FeedbackFormWebview'; +import { openDevAssistFeedbackForm, debugCall } from './webviews/FeedbackFormWebview'; const SCLOUD_OUTPUT_CHANNEL_NAME = 'SuiteCloud'; @@ -99,7 +99,10 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push( vscode.commands.registerCommand('suitecloud.opendevassistfeedbackform', () => openDevAssistFeedbackForm(context) - ) + ), + vscode.commands.registerCommand('suitecloud.debugCall', + () => debugCall() + ), ); // Use the console to output diagnostic information (console.log) and errors (console.error) diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index c2028d93..d42e7773 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -1,8 +1,10 @@ import * as vscode from 'vscode'; import * as path from 'path'; +import MessageService from '../service/MessageService'; import { VSTranslationService } from '../service/VSTranslationService'; import { DEVASSIST_SERVICE } from '../service/TranslationKeys'; +const messageService = new MessageService(); const translationService = new VSTranslationService(); const cssFileName = 'feedbackForm.css'; const cssFilePath = './src/webviews/' + cssFileName; @@ -44,12 +46,28 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // Handle messages sent from the webview feedbackFormPanel.webview.onDidReceiveMessage( - message => { + async (message) => { switch (message.type) { case 'submit': + console.log(message); vscode.window.showInformationMessage('Thanks for your feedback!'); + feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); + try { + const response = await fetch('http://127.0.0.1:8181/api/internal/devassist', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: message.data + }); + if (response.ok) { + feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); + } else { + feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'error' }); + } + } catch (e) { + feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'error' }); + } // Handle/store feedback as needed - feedbackFormPanel?.dispose(); + // feedbackFormPanel?.dispose(); break; case 'cancel': feedbackFormPanel?.dispose(); @@ -61,6 +79,16 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { ); }; +export const debugCall = () => { + if (!feedbackFormPanel) { + return; + } + + // Send a message to our webview. + // You can send any JSON serializable data. + feedbackFormPanel.webview.postMessage({ type: 'status', value: 'success' }); +}; + const getCheckboxesHTMLContent = () => { const optionsList = Object.values(DEVASSIST_SERVICE.FEEDBACK_FORM.CHECKBOX_LIST_OPTIONS); return optionsList.map(option => { @@ -122,6 +150,7 @@ const getFeedbackFormHTMLContent = (cssUri: any) => {
+
@@ -132,9 +161,11 @@ const getFeedbackFormHTMLContent = (cssUri: any) => {
`; From 49b1ae78decb55dbbed02c378fff7dd65fa3fd04 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Mon, 3 Nov 2025 15:38:39 +0100 Subject: [PATCH 04/37] Initial Alert Implementation --- .../src/startup/DevAssistConfiguration.ts | 2 +- .../src/webviews/FeedbackFormWebview.ts | 87 ++++++++++--------- .../src/webviews/feedbackForm.css | 54 ++++++++++++ 3 files changed, 99 insertions(+), 44 deletions(-) diff --git a/packages/vscode-extension/src/startup/DevAssistConfiguration.ts b/packages/vscode-extension/src/startup/DevAssistConfiguration.ts index 340d9e59..380eeba5 100644 --- a/packages/vscode-extension/src/startup/DevAssistConfiguration.ts +++ b/packages/vscode-extension/src/startup/DevAssistConfiguration.ts @@ -208,7 +208,7 @@ const updateDevAssistConfigStatus = (): void => { devAssistConfigStatus.previous = previousConfig; } -const getDevAssistCurrentSettings = (): devAssistConfig => { +export const getDevAssistCurrentSettings = (): devAssistConfig => { const devAssistConfigSection = vscode.workspace.getConfiguration(DEVASSIST.CONFIG_KEYS.devAssistSection); // * The *effective* value (returned by {@linkcode WorkspaceConfiguration.get get}) is computed by overriding or merging the values in the following order: diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index d42e7773..a99986e4 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import MessageService from '../service/MessageService'; import { VSTranslationService } from '../service/VSTranslationService'; import { DEVASSIST_SERVICE } from '../service/TranslationKeys'; +import { getDevAssistCurrentSettings } from '../startup/DevAssistConfiguration'; const messageService = new MessageService(); const translationService = new VSTranslationService(); @@ -52,8 +53,10 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { console.log(message); vscode.window.showInformationMessage('Thanks for your feedback!'); feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); + + const currentProxySettings = getDevAssistCurrentSettings(); try { - const response = await fetch('http://127.0.0.1:8181/api/internal/devassist', { + const response = await fetch(`http://127.0.0.1:$${currentProxySettings.localPort}/api/internal/devassist`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: message.data @@ -86,7 +89,8 @@ export const debugCall = () => { // Send a message to our webview. // You can send any JSON serializable data. - feedbackFormPanel.webview.postMessage({ type: 'status', value: 'success' }); + feedbackFormPanel.webview.postMessage({ type: 'spawnAlertEvent', value: 'info', message: 'Random test message info / error' }); + feedbackFormPanel.webview.postMessage({ type: 'spawnAlertEvent', value: 'error', message: 'Random test message info / error'}); }; const getCheckboxesHTMLContent = () => { @@ -148,10 +152,9 @@ const getFeedbackFormHTMLContent = (cssUri: any) => {
- - - + +
@@ -160,12 +163,12 @@ const getFeedbackFormHTMLContent = (cssUri: any) => {
+
diff --git a/packages/vscode-extension/src/webviews/feedbackForm.css b/packages/vscode-extension/src/webviews/feedbackForm.css index 8616ec57..0b4dc5a6 100644 --- a/packages/vscode-extension/src/webviews/feedbackForm.css +++ b/packages/vscode-extension/src/webviews/feedbackForm.css @@ -169,4 +169,58 @@ pre { .hidden { display: none +} + +#alert-container { + position: fixed; + z-index: 9999; + bottom: 24px; + right: 24px; + display: flex; + flex-direction: column-reverse; /* new alerts on top */ + gap: 12px; + max-width: 340px; + pointer-events: none; +} +.toast-alert { + display: flex; + align-items: start; + background: #e7f5ff; + color: #155577; + border-left: 4px solid #228be6; + border-radius: 6px; + box-shadow: 0 2px 8px rgba(0,0,0,0.13); + margin: 0; + padding: 16px 44px 16px 16px; + font-size: 15px; + position: relative; + min-width: 220px; + pointer-events: auto; +} +.toast-alert.toast-info { + background: #e7f5ff; + border-color: #228be6; + color: #155577; +} +.toast-alert.toast-error { + background: #fff1f0; + border-color: #ff4d4f; + color: #a8071a; +} +.toast-close { + position: absolute; + top: 8px; + right: 10px; + background: none; + border: none; + color: inherit; + font-size: 19px; + cursor: pointer; + line-height: 1; + padding: 0; + opacity: 0.65; + transition: opacity 0.19s; +} +.toast-close:hover { + opacity: 1; } \ No newline at end of file From d841c26d47d1ddbfb7f02dcc5d9efb8db738abbf Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Tue, 4 Nov 2025 10:55:59 +0100 Subject: [PATCH 05/37] Messages --- packages/vscode-extension/messages.json | 30 +++++++++---------- .../src/webviews/FeedbackFormWebview.ts | 22 ++++++++++---- .../src/webviews/feedbackForm.css | 2 +- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/packages/vscode-extension/messages.json b/packages/vscode-extension/messages.json index 8cac7dce..14de8a78 100644 --- a/packages/vscode-extension/messages.json +++ b/packages/vscode-extension/messages.json @@ -54,21 +54,20 @@ "DEPLOY_QUESTIONS_CHOICES_ACCOUNT_SPECIFIC_VALUES_CANCEL_PROCESS": "Cancel the deployment process", "DEPLOY_QUESTIONS_CHOICES_ACCOUNT_SPECIFIC_VALUES_DISPLAY_WARNING": "Display a warning and continue the deployment process", - "DEVASSIST_SERVICE_FEEDBACK_FORM_DOCUMENT_TITLE": "SuiteCloud Developer Assistant Feedback Form", - "DEVASSIST_SERVICE_FEEDBACK_FORM_TITLE": "SuiteCloud Developer Assistant Feedback", - "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBTITLE": "Share quick feedback about the SuiteCloud Developer Assistant. Works fully offline—no data leaves this page.", - "DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_SUBTITLE": "Your feedback", - "DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_HINT": "What worked well? What should be improved?", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_SUBTITLE": "This feedback is about", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_1": "Explain Code", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_2": "Generate SuiteScript Code", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_3": "Generate SDF Objects", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_4": "Unit Testing", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_5": "Other", - "DEVASSIST_SERVICE_FEEDBACK_FORM_RATING_SUBTITLE": "Rating (1-5)", - "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SUBMIT": "Submit", - "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_CANCEL": "Cancel", - + "DEVASSIST_SERVICE_FEEDBACK_FORM_DOCUMENT_TITLE": "SuiteCloud Developer Assistant Feedback", + "DEVASSIST_SERVICE_FEEDBACK_FORM_TITLE": "SuiteCloud Developer Assistant Feedback", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBTITLE": "Take a moment to share your thoughts on the SuiteCloud Developer Assistant. Any data you provide will remain anonymous.", + "DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_SUBTITLE": "Your Feedback", + "DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_HINT": "What worked well? What should be improved? Any suggestions?", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_SUBTITLE": "This Feedback is about", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_1": "Code Explanation", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_2": "SDF Objects Generation", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_3": "SuiteScript Code Generation", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_4": "Unit Testing", + "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_5": "Other", + "DEVASSIST_SERVICE_FEEDBACK_FORM_RATING_SUBTITLE": "Rate Your Overall Satisfaction (1-5)", + "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SUBMIT": "Submit", + "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_CANCEL": "Cancel", "DEVASSIST_SERVICE_IS_DISABLED_NOTIFICATION": "SuiteCloud Developer Assistant service has been disabled.", "DEVASSIST_SERVICE_IS_DISABLED_OUTPUT": "SuiteCloud Developer Assistant service has been disabled.", @@ -85,7 +84,6 @@ "DEVASSIST_SERVICE_STARTUP_MESSAGE": "SuiteCloud Developer Assistant is here. Open settings to start using it.", "DEVASSIST_SERVICE_STATUSBAR_TOOLTIP": "Shows the status of SuiteCloud Developer Assistant service.", - "DISMISS": "Dismiss", "ERRORS_COURRUPTED_SDK_JAR_DEPENDENCY": "There was a problem with SuiteCloud Extension dependencies. Restart your Visual Studio Code instance.", diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index a99986e4..0dd24f4f 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -47,11 +47,10 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // Handle messages sent from the webview feedbackFormPanel.webview.onDidReceiveMessage( - async (message) => { - switch (message.type) { + async (webviewMessage) => { + switch (webviewMessage.type) { case 'submit': - console.log(message); - vscode.window.showInformationMessage('Thanks for your feedback!'); + console.log(webviewMessage); feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); const currentProxySettings = getDevAssistCurrentSettings(); @@ -59,7 +58,7 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { const response = await fetch(`http://127.0.0.1:$${currentProxySettings.localPort}/api/internal/devassist`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: message.data + body: webviewMessage.data }); if (response.ok) { feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); @@ -82,6 +81,13 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { ); }; +// TODO: define a FormData structure instead of using 'any' +const validateFormData = (formData : any) => { + + +} + + export const debugCall = () => { if (!feedbackFormPanel) { return; @@ -102,6 +108,11 @@ const getCheckboxesHTMLContent = () => { }).join(''); }; +// Submitting feedback + +// Thank you for your feedback! You can close this window\n [Close Window, write another feedback BUTTON] +// Woah! Something went wrong when submitting your feedback.\n Please try again later + const getFeedbackFormHTMLContent = (cssUri: any) => { return ` @@ -235,6 +246,7 @@ const getFeedbackFormHTMLContent = (cssUri: any) => { vscode.postMessage({ type: 'cancel' }); }); + // Listen to VSCode Events window.addEventListener('message', event => { const { type, value, message } = event.data; if (type === 'spawnAlertEvent') { diff --git a/packages/vscode-extension/src/webviews/feedbackForm.css b/packages/vscode-extension/src/webviews/feedbackForm.css index 0b4dc5a6..64cddaf2 100644 --- a/packages/vscode-extension/src/webviews/feedbackForm.css +++ b/packages/vscode-extension/src/webviews/feedbackForm.css @@ -88,7 +88,7 @@ legend { .stars { display: inline-flex; - flex-direction: row-reverse; + /* flex-direction: row-reverse;*/ gap: 6px } From ccab222307e142038cb55a13cee9f500c5d54b32 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Tue, 4 Nov 2025 16:25:53 +0100 Subject: [PATCH 06/37] Moved HTML --- .../media/FeedbackForm.css} | 55 +++--- .../resources/media/FeedbackForm.html | 149 +++++++++++++++ .../src/util/ExtensionUtil.ts | 7 +- .../src/webviews/FeedbackForm.html | 98 ---------- .../src/webviews/FeedbackFormWebview.ts | 177 ++---------------- 5 files changed, 204 insertions(+), 282 deletions(-) rename packages/vscode-extension/{src/webviews/feedbackForm.css => resources/media/FeedbackForm.css} (82%) create mode 100644 packages/vscode-extension/resources/media/FeedbackForm.html delete mode 100644 packages/vscode-extension/src/webviews/FeedbackForm.html diff --git a/packages/vscode-extension/src/webviews/feedbackForm.css b/packages/vscode-extension/resources/media/FeedbackForm.css similarity index 82% rename from packages/vscode-extension/src/webviews/feedbackForm.css rename to packages/vscode-extension/resources/media/FeedbackForm.css index 64cddaf2..f2d50e6f 100644 --- a/packages/vscode-extension/src/webviews/feedbackForm.css +++ b/packages/vscode-extension/resources/media/FeedbackForm.css @@ -88,41 +88,46 @@ legend { .stars { display: inline-flex; - /* flex-direction: row-reverse;*/ - gap: 6px + flex-direction: row-reverse; /* shows stars in correct LTR order */ + gap: 6px; + width: fit-content; } - .stars input { - display: none + display: none; } - .star { cursor: pointer; font-size: 28px; line-height: 1; filter: grayscale(.6); - transition: transform .05s ease + transition: transform .05s ease; } - .star::before { - content: "☆" + content: "☆"; } - +/* On hover, fill all stars to the left (and including hovered) */ .stars label.star:hover, .stars label.star:hover ~ label.star { - transform: scale(1.05) + transform: scale(1.25); } - -/* Fill stars up to the selected one */ -.stars input:checked + label.star::before, -.stars input:checked + label.star ~ label.star::before { - content: "★" +.stars label.star:hover::before, +.stars label.star:hover ~ label.star::before { + content: "★"; + color: #f59e0b; + filter: none; +} +.stars label.star:hover, +.stars label.star:hover ~ label.star { + color: #f59e0b; + filter: none; } -.stars input:checked + label.star, -.stars input:checked + label.star ~ label.star { +/* On checked, fill all stars to the left (and including selected) */ +.stars input:checked ~ label.star::before, +.stars input:checked ~ label.star { + content: "★"; + color: #f59e0b; filter: none; - color: #f59e0b } .row { @@ -130,13 +135,6 @@ legend { gap: 6px } -.actions { - display: flex; - gap: 10px; - justify-content: flex-end; - margin-top: 8px -} - button { appearance: none; border: 1px solid var(--border); @@ -171,6 +169,13 @@ pre { display: none } +.actions { + display: flex; + gap: 10px; + justify-content: flex-end; + margin-top: 8px +} + #alert-container { position: fixed; z-index: 9999; diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html new file mode 100644 index 00000000..ac0fec23 --- /dev/null +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -0,0 +1,149 @@ + + + + + DevAssist Feedback + + + +
+
+

SuiteCloud Developer Assistant Feedback

+

+ Take a moment to share your thoughts on the SuiteCloud Developer Assistant. Any data you provide + will remain anonymous.

+
+
+
+ + +
+ +
+ This Feedback is about +
+ + + + + +
+
+ +
+ +
+ + + + + + + + + + +
+
+ +
+ + + +
+ +
+ See payload + +
+
+
+
+ + + \ No newline at end of file diff --git a/packages/vscode-extension/src/util/ExtensionUtil.ts b/packages/vscode-extension/src/util/ExtensionUtil.ts index b026ee14..6eb81def 100644 --- a/packages/vscode-extension/src/util/ExtensionUtil.ts +++ b/packages/vscode-extension/src/util/ExtensionUtil.ts @@ -65,7 +65,12 @@ export class SuiteCloudAuthProxyService extends SuiteCloudAuthProxyServiceTypedJ export const AccountCredentialsFormatter: { getInfoString(accountCredentials: any): string; } = require('@oracle/suitecloud-cli/src/utils/AccountCredentialsFormatter'); -export const FileUtils = require('@oracle/suitecloud-cli/src/utils/FileUtils'); +export const FileUtils : { + readAsJson(filePath: string) : any; + readAsString(fileName: string) : string; + exists(fileName: string) : boolean; + createDirectory(dirPath: string) : void; +} = require('@oracle/suitecloud-cli/src/utils/FileUtils'); export const InteractiveAnswersValidator: { showValidationResults(value: string, ...funcs: Function[]): string | boolean; diff --git a/packages/vscode-extension/src/webviews/FeedbackForm.html b/packages/vscode-extension/src/webviews/FeedbackForm.html deleted file mode 100644 index 3567c3bc..00000000 --- a/packages/vscode-extension/src/webviews/FeedbackForm.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - DevAssist Feedback - - - -
-
-

${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.TITLE)}

-

${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBTITLE)}

-
-
-
- - -
- -
- ${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.CHECKBOX_LIST_SUBTITLE)} -
- ${getCheckboxesHTMLContent()} -
-
- -
- -
- - - - - - - - - - - -
-
- -
- - - -
- -
- See payload - -
-
-
- - - \ No newline at end of file diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index 0dd24f4f..6453b137 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -4,11 +4,18 @@ import MessageService from '../service/MessageService'; import { VSTranslationService } from '../service/VSTranslationService'; import { DEVASSIST_SERVICE } from '../service/TranslationKeys'; import { getDevAssistCurrentSettings } from '../startup/DevAssistConfiguration'; +import { FileUtils } from '../util/ExtensionUtil'; const messageService = new MessageService(); const translationService = new VSTranslationService(); -const cssFileName = 'feedbackForm.css'; -const cssFilePath = './src/webviews/' + cssFileName; + +const MEDIA_DIR = 'resources/media' +const WEBVIEW_FILE_NAMES = { + FEEDBACK_FORM : { + HTML : "FeedbackForm.html", + CSS : "FeedbackForm.css" + } +} let feedbackFormPanel: vscode.WebviewPanel | undefined; @@ -27,14 +34,15 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { { enableScripts: true, localResourceRoots: [ - vscode.Uri.file(path.join(context.extensionPath, 'src/webviews')), + vscode.Uri.file(path.join(context.extensionPath, MEDIA_DIR)), ], }, ); // Read HTML and inject the correct webview resource URIs for the CSS file - const cssUri = feedbackFormPanel.webview.asWebviewUri(vscode.Uri.file(path.join(context.extensionPath, cssFilePath))); - feedbackFormPanel.webview.html = getFeedbackFormHTMLContent(cssUri); + const feedbackFormHTMLFilePath = path.join(context.extensionPath, MEDIA_DIR, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.HTML); + const feedbackFormCSSFilePath = path.join(context.extensionPath, MEDIA_DIR, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.CSS); + feedbackFormPanel.webview.html = getWebviewHTMLContent(feedbackFormHTMLFilePath, feedbackFormCSSFilePath.toString()); // Clean up the reference when the panel is closed feedbackFormPanel.onDidDispose( @@ -99,162 +107,15 @@ export const debugCall = () => { feedbackFormPanel.webview.postMessage({ type: 'spawnAlertEvent', value: 'error', message: 'Random test message info / error'}); }; -const getCheckboxesHTMLContent = () => { - const optionsList = Object.values(DEVASSIST_SERVICE.FEEDBACK_FORM.CHECKBOX_LIST_OPTIONS); - return optionsList.map(option => { - const optionValue = translationService.getMessage(option); - const optionID = optionValue.toLowerCase().replace(/\s+/g, '-'); - return ``; - }).join(''); -}; - // Submitting feedback // Thank you for your feedback! You can close this window\n [Close Window, write another feedback BUTTON] // Woah! Something went wrong when submitting your feedback.\n Please try again later -const getFeedbackFormHTMLContent = (cssUri: any) => { - - return ` - - - - DevAssist Feedback - - - -
-
-

${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.TITLE)}

-

${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBTITLE)}

-
-
-
- - -
- -
- ${translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.CHECKBOX_LIST_SUBTITLE)} -
- ${getCheckboxesHTMLContent()} -
-
- -
- -
- - - - - - - - - - - -
-
- -
- - - -
- -
- See payload - -
-
-
-
- - - `; -}; \ No newline at end of file + return htmlFileContent; +} \ No newline at end of file From 51efa53d5c857c54ecfa4be10fc25ceece1fc8f4 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Tue, 4 Nov 2025 17:31:29 +0100 Subject: [PATCH 07/37] More stuff --- .../resources/media/FeedbackForm.html | 268 +++++++++--------- .../resources/media/FeedbackFormFailure.html | 34 +++ .../media/FeedbackFormSubmitting.html | 35 +++ .../resources/media/FeedbackFormSucess.html | 39 +++ .../src/webviews/FeedbackFormWebview.ts | 95 ++++--- 5 files changed, 298 insertions(+), 173 deletions(-) create mode 100644 packages/vscode-extension/resources/media/FeedbackFormFailure.html create mode 100644 packages/vscode-extension/resources/media/FeedbackFormSubmitting.html create mode 100644 packages/vscode-extension/resources/media/FeedbackFormSucess.html diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html index ac0fec23..845e8018 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.html +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -6,144 +6,144 @@ -
-
-

SuiteCloud Developer Assistant Feedback

-

- Take a moment to share your thoughts on the SuiteCloud Developer Assistant. Any data you provide - will remain anonymous.

-
-
-
- - -
- -
- This Feedback is about -
- - - - - +
+
+

SuiteCloud Developer Assistant Feedback

+

+ Take a moment to share your thoughts on the SuiteCloud Developer Assistant. Any data you provide + will remain anonymous.

+
+ +
+ +
-
- -
- -
- - - - - - - - - - + +
+ This Feedback is about +
+ + + + + +
+
+ +
+ +
+ + + + + + + + + + +
+
+ +
+ + +
-
- -
- - - -
- -
- See payload - -
- -
-
- + + // VS Code API + const vscode = acquireVsCodeApi(); + + form.addEventListener('submit', (e) => { + e.preventDefault(); + + const checkedTopics = document.querySelectorAll('input[name="topics"]:checked'); + const ratingChecked = document.querySelector('input[name="rating"]:checked'); + + const data = collect(); + const json = JSON.stringify(data, null, 2); + result.textContent = json; + result.classList.remove('hidden'); + + // TODO: VSCode Security forbids FETCHing content directly from within the Webview. + // const response = await fetch("http://127.0.0.1:8181/api/internal/devassist", { + // method: "POST", + // headers: { "Content-Type": "application/json" }, + // body: json + // }); + + vscode.postMessage({ type: 'SUBMIT_FEEDBACK', data: json }); + }); + + cancelBtn.addEventListener('click', () => { + vscode.postMessage({ type: 'CLOSE_WEBVIEW' }); + }); + + // Listen to VSCode Events + window.addEventListener('message', event => { + const { type, value, message } = event.data; + if (type === 'spawnAlertEvent') { + if (value === 'info') spawnAlert(message, 'info', 0); + else if (value === 'error') spawnAlert(message, 'error', 10000); + } + }); + \ No newline at end of file diff --git a/packages/vscode-extension/resources/media/FeedbackFormFailure.html b/packages/vscode-extension/resources/media/FeedbackFormFailure.html new file mode 100644 index 00000000..503b4720 --- /dev/null +++ b/packages/vscode-extension/resources/media/FeedbackFormFailure.html @@ -0,0 +1,34 @@ + + + + + DevAssist Feedback + + + +
+
+

SuiteCloud Developer Assistant Feedback

+

+ Take a moment to share your thoughts on the SuiteCloud Developer Assistant. Any data you provide + will remain anonymous.

+
+
+ + +
+
+
+ +
+ + + \ No newline at end of file diff --git a/packages/vscode-extension/resources/media/FeedbackFormSubmitting.html b/packages/vscode-extension/resources/media/FeedbackFormSubmitting.html new file mode 100644 index 00000000..ae684073 --- /dev/null +++ b/packages/vscode-extension/resources/media/FeedbackFormSubmitting.html @@ -0,0 +1,35 @@ + + + + + DevAssist Feedback + + + +
+
+

SuiteCloud Developer Assistant Feedback

+

+ Take a moment to share your thoughts on the SuiteCloud Developer Assistant. Any data you provide + will remain anonymous.

+
+
+ +
+
+ + + \ No newline at end of file diff --git a/packages/vscode-extension/resources/media/FeedbackFormSucess.html b/packages/vscode-extension/resources/media/FeedbackFormSucess.html new file mode 100644 index 00000000..86e3dd99 --- /dev/null +++ b/packages/vscode-extension/resources/media/FeedbackFormSucess.html @@ -0,0 +1,39 @@ + + + + + DevAssist Feedback + + + +
+
+

SuiteCloud Developer Assistant Feedback

+

+ Take a moment to share your thoughts on the SuiteCloud Developer Assistant. Any data you provide + will remain anonymous.

+
+
+ +
+
+ + +
+
+ + + \ No newline at end of file diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index 6453b137..f2fdccaf 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -12,13 +12,22 @@ const translationService = new VSTranslationService(); const MEDIA_DIR = 'resources/media' const WEBVIEW_FILE_NAMES = { FEEDBACK_FORM : { - HTML : "FeedbackForm.html", - CSS : "FeedbackForm.css" - } + HTML : 'FeedbackForm.html', + CSS : 'FeedbackForm.css' + }, + SUBMITTING_HTML : 'FeedbackFormSubmitting.html', + SUCCESS_HTML : 'FeedbackFormSucess.html', + FAILURE_HTML : 'FeedbackFormFailure.html', } -let feedbackFormPanel: vscode.WebviewPanel | undefined; +const WEBVIEW_EVENTS = { + CLOSE : "CLOSE_WEBVIEW", + SUBMIT_FEEDBACK : "SUBMIT_FEEDBACK", + OPEN_NEW_FEEDBACK_FORM : "OPEN_NEW_FEEDBACK_FORM" +} +let feedbackFormPanel: vscode.WebviewPanel | undefined; +let extensionMediaPath : string; export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // if one FeedbackForm is already open, reveal it instead of creating a new one @@ -27,24 +36,27 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { return; } + extensionMediaPath = context.extensionPath; feedbackFormPanel = vscode.window.createWebviewPanel( - 'devassistfeedbackform', // viewtype (used internally by vscode) - translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.WEBVIEW_TITLE), + 'devassistfeedbackform', + 'SuiteCloud Developer Assistant Feedback', vscode.ViewColumn.One, { enableScripts: true, localResourceRoots: [ - vscode.Uri.file(path.join(context.extensionPath, MEDIA_DIR)), + vscode.Uri.file(path.join(extensionMediaPath, MEDIA_DIR)), ], }, ); // Read HTML and inject the correct webview resource URIs for the CSS file - const feedbackFormHTMLFilePath = path.join(context.extensionPath, MEDIA_DIR, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.HTML); - const feedbackFormCSSFilePath = path.join(context.extensionPath, MEDIA_DIR, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.CSS); + const fullMediaPath = path.join(extensionMediaPath, MEDIA_DIR); + const feedbackFormHTMLFilePath = path.join(fullMediaPath, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.HTML); + const feedbackFormCSSFilePath = path.join(fullMediaPath, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.CSS); feedbackFormPanel.webview.html = getWebviewHTMLContent(feedbackFormHTMLFilePath, feedbackFormCSSFilePath.toString()); - // Clean up the reference when the panel is closed + + // Clean up the reference when the WebviewPanel is closed feedbackFormPanel.onDidDispose( () => { feedbackFormPanel = undefined; @@ -55,35 +67,7 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // Handle messages sent from the webview feedbackFormPanel.webview.onDidReceiveMessage( - async (webviewMessage) => { - switch (webviewMessage.type) { - case 'submit': - console.log(webviewMessage); - feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); - - const currentProxySettings = getDevAssistCurrentSettings(); - try { - const response = await fetch(`http://127.0.0.1:$${currentProxySettings.localPort}/api/internal/devassist`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: webviewMessage.data - }); - if (response.ok) { - feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); - } else { - feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'error' }); - } - } catch (e) { - feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'error' }); - } - // Handle/store feedback as needed - // feedbackFormPanel?.dispose(); - break; - case 'cancel': - feedbackFormPanel?.dispose(); - break; - } - }, + (webviewMessage) => handleWebviewMessage(webviewMessage), undefined, context.subscriptions, ); @@ -112,6 +96,39 @@ export const debugCall = () => { // Thank you for your feedback! You can close this window\n [Close Window, write another feedback BUTTON] // Woah! Something went wrong when submitting your feedback.\n Please try again later +const handleWebviewMessage = async (webviewMessage : any) : Promise => { + switch (webviewMessage.type) { + + case WEBVIEW_EVENTS.SUBMIT_FEEDBACK: + console.log(webviewMessage); + feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); + + const currentProxySettings = getDevAssistCurrentSettings(); + try { + const response = await fetch(`http://127.0.0.1:$${currentProxySettings.localPort}/api/internal/devassist`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: webviewMessage.data + }); + if (response.ok) { + feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'success' }); + } else { + feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'error' }); + } + } catch (e) { + feedbackFormPanel?.webview.postMessage({ type: 'status', value: 'error' }); + } + // Handle/store feedback as needed + // feedbackFormPanel?.dispose(); + break; + + + case WEBVIEW_EVENTS.CLOSE: + feedbackFormPanel?.dispose(); + break; + } +} + const getWebviewHTMLContent = (htmlFilePath : string, cssFilePath : string): string => { let htmlFileContent = FileUtils.readAsString(htmlFilePath); const cssUri = feedbackFormPanel?.webview.asWebviewUri(vscode.Uri.file(cssFilePath)); From 4111bbb613fae30f04c1fcaeaf1c2ca89c946c04 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Wed, 5 Nov 2025 13:00:16 +0100 Subject: [PATCH 08/37] Finalizing the Functional Side of things --- packages/vscode-extension/messages.json | 17 +----- packages/vscode-extension/package.json | 4 +- .../resources/media/FeedbackFormFailure.html | 11 ++-- .../resources/media/FeedbackFormSucess.html | 8 +-- .../src/service/MessageService.ts | 6 +- .../src/service/TranslationKeys.ts | 21 +------ .../src/startup/DevAssistConfiguration.ts | 18 +++++- .../src/webviews/FeedbackFormWebview.ts | 60 +++++++++++++------ 8 files changed, 81 insertions(+), 64 deletions(-) diff --git a/packages/vscode-extension/messages.json b/packages/vscode-extension/messages.json index 14de8a78..3ba8e456 100644 --- a/packages/vscode-extension/messages.json +++ b/packages/vscode-extension/messages.json @@ -54,24 +54,13 @@ "DEPLOY_QUESTIONS_CHOICES_ACCOUNT_SPECIFIC_VALUES_CANCEL_PROCESS": "Cancel the deployment process", "DEPLOY_QUESTIONS_CHOICES_ACCOUNT_SPECIFIC_VALUES_DISPLAY_WARNING": "Display a warning and continue the deployment process", - "DEVASSIST_SERVICE_FEEDBACK_FORM_DOCUMENT_TITLE": "SuiteCloud Developer Assistant Feedback", - "DEVASSIST_SERVICE_FEEDBACK_FORM_TITLE": "SuiteCloud Developer Assistant Feedback", - "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBTITLE": "Take a moment to share your thoughts on the SuiteCloud Developer Assistant. Any data you provide will remain anonymous.", - "DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_SUBTITLE": "Your Feedback", - "DEVASSIST_SERVICE_FEEDBACK_FORM_TEXTAREA_HINT": "What worked well? What should be improved? Any suggestions?", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_SUBTITLE": "This Feedback is about", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_1": "Code Explanation", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_2": "SDF Objects Generation", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_3": "SuiteScript Code Generation", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_4": "Unit Testing", - "DEVASSIST_SERVICE_FEEDBACK_FORM_CHECKBOX_LIST_OPTIONS_OPTION_5": "Other", - "DEVASSIST_SERVICE_FEEDBACK_FORM_RATING_SUBTITLE": "Rate Your Overall Satisfaction (1-5)", - "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_SUBMIT": "Submit", - "DEVASSIST_SERVICE_FEEDBACK_FORM_BUTTON_CANCEL": "Cancel", + "DEVASSIST_SERVICE_FEEDBACK_FORM_FIELD_VALIDATION_ERROR": "Field Validation Error:
{0}", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR": "Unable to connect to the Developer Assistant Service...
Is it running?", "DEVASSIST_SERVICE_IS_DISABLED_NOTIFICATION": "SuiteCloud Developer Assistant service has been disabled.", "DEVASSIST_SERVICE_IS_DISABLED_OUTPUT": "SuiteCloud Developer Assistant service has been disabled.", "DEVASSIST_SERVICE_IS_RUNNING_NOTIFICATION": "SuiteCloud Developer Assistant service is running. Use Cline Base URL to: {0}", + "DEVASSIST_SERVICE_IS_RUNNING_NOTIFICATION_BUTTON": "Submit Feedback", "DEVASSIST_SERVICE_IS_RUNNING_OUTPUT": "SuiteCloud Developer Assistant service is now running at {0} and is using the {1} auth ID.\nUse this Cline Base URL {2}.", "DEVASSIST_SERVICE_IS_RUNNING_STATUSBAR": "Dev Assist: running", "DEVASSIST_SERVICE_IS_STOPPED_NOTIFICATION": "Something went wrong with SuiteCloud Developer Assistant service.", diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index db56ec51..eb7a38a9 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -114,13 +114,13 @@ }, { "command": "suitecloud.opendevassistfeedbackform", - "title": "Open DevAssist Feedback Forms", + "title": "Open DevAssist Feedback Forms //TODO: Remove", "category": "SuiteCloud", "enablement": "true" }, { "command": "suitecloud.debugCall", - "title": "DevAssist Feedback Forms: Debug Call", + "title": "DevAssist Feedback Forms: Debug Call //TODO: Remove", "category": "SuiteCloud", "enablement": "true" } diff --git a/packages/vscode-extension/resources/media/FeedbackFormFailure.html b/packages/vscode-extension/resources/media/FeedbackFormFailure.html index 503b4720..27d94814 100644 --- a/packages/vscode-extension/resources/media/FeedbackFormFailure.html +++ b/packages/vscode-extension/resources/media/FeedbackFormFailure.html @@ -14,13 +14,14 @@

SuiteCloud Developer Assistant Feedback

will remain anonymous.

- - + + +
+ +
-
- -
From 3975808ef87ac57bcaf6e48dc78cef9c0ee7fe19 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Fri, 7 Nov 2025 17:37:52 +0100 Subject: [PATCH 19/37] Minor comments --- .../resources/media/FeedbackForm.css | 4 ---- .../resources/media/FeedbackForm.html | 23 ++++--------------- .../resources/media/FeedbackFormSucess.html | 2 +- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/packages/vscode-extension/resources/media/FeedbackForm.css b/packages/vscode-extension/resources/media/FeedbackForm.css index f2d50e6f..d7e9136d 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.css +++ b/packages/vscode-extension/resources/media/FeedbackForm.css @@ -165,10 +165,6 @@ pre { max-height: 240px } -.hidden { - display: none -} - .actions { display: flex; gap: 10px; diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html index 34ca3600..22eba1c6 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.html +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -49,33 +49,24 @@

SuiteCloud Developer Assistant Feedback

- + -
- -
- See Payload - -
From 141908d298d9f3ff30534411bb9f8b86c4a9b401 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Wed, 12 Nov 2025 16:00:52 +0100 Subject: [PATCH 26/37] Messages Reviewed pt3 --- .../resources/media/FeedbackForm.html | 14 +++++++------- .../src/webviews/FeedbackFormWebview.ts | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html index 161932a9..c8996857 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.html +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -13,26 +13,26 @@

SuiteCloud Developer Assistant Feedback

- +
- This Feedback Is About + This feedback is about
- - - - + + + +
+ Rate your overall satisfaction (1-5)
diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index a9d68f90..2e5139a9 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -96,11 +96,11 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { const validateFormData = (formData : FeedbackFormData) => { // validate feedback field (textArea) - let validationResult = validateTextAreaField("Your Feedback (textarea)", formData.feedback, 1000); + let validationResult = validateTextAreaField("Your feedback (text area)", formData.feedback, 1000); if (typeof validationResult === 'string') return validationResult; // validate selectedTopic field - validationResult = validateMultipleOptionField("Your Feedback (topic multi-choice selector)", formData.topics, VALID_FEEDBACK_TOPICS); + validationResult = validateMultipleOptionField("Your feedback (topic multi-choice selector)", formData.topics, VALID_FEEDBACK_TOPICS); if (typeof validationResult === 'string') return validationResult; // validate rating field (integer 0 < x <= 5) From 5e369001d8f4a1555904bf05f2457fc71bc1d8d9 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Wed, 12 Nov 2025 16:01:34 +0100 Subject: [PATCH 27/37] curly stuff --- .../src/webviews/FeedbackFormWebview.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index 2e5139a9..d6a6f676 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -97,15 +97,22 @@ const validateFormData = (formData : FeedbackFormData) => { // validate feedback field (textArea) let validationResult = validateTextAreaField("Your feedback (text area)", formData.feedback, 1000); - if (typeof validationResult === 'string') return validationResult; + if (typeof validationResult === 'string') { + return validationResult; + } // validate selectedTopic field validationResult = validateMultipleOptionField("Your feedback (topic multi-choice selector)", formData.topics, VALID_FEEDBACK_TOPICS); - if (typeof validationResult === 'string') return validationResult; + if (typeof validationResult === 'string') { + return validationResult; + } // validate rating field (integer 0 < x <= 5) validationResult = validateIntegerWithinInterval("Rating", formData.rating, 1, 5); - if (typeof validationResult === 'string') return validationResult; + if (typeof validationResult === 'string') { + return validationResult; + } + return true; } From 2119a461d0c28b8b6e7c91a0e6c05fa2a629b2bf Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Thu, 13 Nov 2025 15:46:41 +0100 Subject: [PATCH 28/37] David Changes --- .../resources/media/FeedbackForm.html | 20 +- .../resources/media/FeedbackFormFailure.html | 2 +- .../resources/media/FeedbackFormSuccess.html | 4 +- .../src/service/MediaFileKeys.ts | 16 ++ .../src/service/MediaFileService.ts | 33 +++ .../src/startup/DevAssistConfiguration.ts | 34 +-- packages/vscode-extension/src/suitecloud.ts | 14 +- .../src/webviews/FeedbackFormWebview.ts | 199 +++++++++--------- .../webviews/WebviewFieldValidationUtils.ts | 5 + 9 files changed, 192 insertions(+), 135 deletions(-) create mode 100644 packages/vscode-extension/src/service/MediaFileKeys.ts create mode 100644 packages/vscode-extension/src/service/MediaFileService.ts diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html index c8996857..3faf9a29 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.html +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -111,22 +111,24 @@

SuiteCloud Developer Assistant Feedback

// }); const data = collect(); - vscode.postMessage({ type: 'SUBMIT_FEEDBACK', data: data }); + vscode.postMessage({ eventType: 'SUBMIT_FEEDBACK', eventData: data }); }); cancelBtn.addEventListener('click', () => { - vscode.postMessage({ type: 'CLOSE_WEBVIEW' }); + vscode.postMessage({ eventType: 'CLOSE_WEBVIEW' }); }); // Listen to VSCode Events - window.addEventListener('message', event => { - const { type, value, message } = event.data; - if (type === 'spawnAlertEvent') { - if (value === 'info') { - spawnAlert(message, 'info', 0); + window.addEventListener('message', message => { + console.log(message); + const { eventType, eventData } = message.data; + if (eventType === 'SPAWN_ALERT_MESSAGE') { + console.log(eventData); + if (eventData.alertLevel === 'info') { + spawnAlert(eventData.alertMessage, 'info', 0); } - else if (value === 'error') { - spawnAlert(message, 'error', 0); + else if (eventData.alertLevel === 'error') { + spawnAlert(eventData.alertMessage, 'error', 0); } } }); diff --git a/packages/vscode-extension/resources/media/FeedbackFormFailure.html b/packages/vscode-extension/resources/media/FeedbackFormFailure.html index 25d71eae..6cf2eedf 100644 --- a/packages/vscode-extension/resources/media/FeedbackFormFailure.html +++ b/packages/vscode-extension/resources/media/FeedbackFormFailure.html @@ -27,7 +27,7 @@

SuiteCloud Developer Assistant Feedback

/* Button Actions */ closeBtn.addEventListener('click', () => { - vscode.postMessage({ type: 'CLOSE_WEBVIEW' }); + vscode.postMessage({ eventType: 'CLOSE_WEBVIEW' }); }); diff --git a/packages/vscode-extension/resources/media/FeedbackFormSuccess.html b/packages/vscode-extension/resources/media/FeedbackFormSuccess.html index 92e9622d..77cf5599 100644 --- a/packages/vscode-extension/resources/media/FeedbackFormSuccess.html +++ b/packages/vscode-extension/resources/media/FeedbackFormSuccess.html @@ -27,11 +27,11 @@

SuiteCloud Developer Assistant Feedback

/* Button Actions */ closeBtn.addEventListener('click', () => { - vscode.postMessage({ type: 'CLOSE_WEBVIEW' }); + vscode.postMessage({ eventType: 'CLOSE_WEBVIEW' }); }); newFeedbackFormBtn.addEventListener('click', () => { - vscode.postMessage({ type: 'OPEN_NEW_FEEDBACK_FORM' }); + vscode.postMessage({ eventType: 'OPEN_NEW_FEEDBACK_FORM' }); }); diff --git a/packages/vscode-extension/src/service/MediaFileKeys.ts b/packages/vscode-extension/src/service/MediaFileKeys.ts new file mode 100644 index 00000000..1e369443 --- /dev/null +++ b/packages/vscode-extension/src/service/MediaFileKeys.ts @@ -0,0 +1,16 @@ +/* + ** Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + */ + +export const MEDIA_DIRECTORY = 'resources/media'; + +export const FEEDBACK_FORM_FILE_NAMES = { + MAIN_PAGE : { + HTML : 'FeedbackForm.html', + CSS : 'FeedbackForm.css' + }, + SUBMITTING_HTML : 'FeedbackFormSubmitting.html', + SUCCESS_HTML : 'FeedbackFormSuccess.html', + FAILURE_HTML : 'FeedbackFormFailure.html', +} \ No newline at end of file diff --git a/packages/vscode-extension/src/service/MediaFileService.ts b/packages/vscode-extension/src/service/MediaFileService.ts new file mode 100644 index 00000000..e6295ff8 --- /dev/null +++ b/packages/vscode-extension/src/service/MediaFileService.ts @@ -0,0 +1,33 @@ +/* + ** Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + */ + +import * as vscode from 'vscode'; +import * as path from 'path'; +import { FileUtils } from '../util/ExtensionUtil'; +import { MEDIA_DIRECTORY } from './MediaFileKeys'; + +export class MediaFileService { + private vscodeExtensionMediaPath : string; + + constructor(context: vscode.ExtensionContext) { + this.vscodeExtensionMediaPath = path.join(context.extensionPath, MEDIA_DIRECTORY); + } + + public getMediaDirectoryFullPath = () => { + return this.vscodeExtensionMediaPath; + } + + public getMediaFileFullPath = (fileName : string) => { + return path.join(this.vscodeExtensionMediaPath, fileName); + } + + public generateHTMLContentFromMediaFile = (htmlFileName : string, cssWebviewUri : string) => { + const htmlFilePath = this.getMediaFileFullPath(htmlFileName); + let htmlFileContent = FileUtils.readAsString(htmlFilePath); + + htmlFileContent = htmlFileContent.replace('{{CSS_FILE.css}}', cssWebviewUri); + return htmlFileContent; + } +} \ No newline at end of file diff --git a/packages/vscode-extension/src/startup/DevAssistConfiguration.ts b/packages/vscode-extension/src/startup/DevAssistConfiguration.ts index 08ec325a..25b6cd27 100644 --- a/packages/vscode-extension/src/startup/DevAssistConfiguration.ts +++ b/packages/vscode-extension/src/startup/DevAssistConfiguration.ts @@ -148,22 +148,9 @@ const initializeDevAssistService = (devAssistStatusBar: vscode.StatusBarItem) => const startDevAssistService = async (devAssistAuthID: string, localPort: number, devAssistStatusBar: vscode.StatusBarItem) => { await devAssistProxyService.start(devAssistAuthID, localPort); + const proxyUrl = getProxyUrl(localPort); setSuccessDevAssistStausBarMessage(devAssistStatusBar); - const proxyUrl = getProxyUrl(localPort); - const infoMessage: string = translationService.getMessage(DEVASSIST_SERVICE.IS_RUNNING.NOTIFICATION, proxyUrl); - const buttonsAndActions: { buttonMessage: string, buttonAction: () => void }[] = [ - { - buttonMessage: translationService.getMessage(BUTTONS.SEE_DETAILS), - buttonAction: vsNotificationService.showOutput - }, - { - buttonMessage: translationService.getMessage(DEVASSIST_SERVICE.IS_RUNNING.NOTIFICATION_BUTTON), - buttonAction: () => { - vscode.commands.executeCommand('suitecloud.opendevassistfeedbackform') - } - }, - ]; - vsNotificationService.showCommandInfoWithSpecificButtonsAndActions(infoMessage, buttonsAndActions); + showDevAssistIsRunningNotification(proxyUrl); vsLogger.printTimestamp(); vsLogger.info(translationService.getMessage(DEVASSIST_SERVICE.IS_RUNNING.OUTPUT, getProxyUrlWithoutPath(localPort), devAssistAuthID, proxyUrl)); @@ -206,6 +193,23 @@ const showDevAssistStartUpNotification = () => { vsNotificationService.showCommandInfoWithSpecificButtonsAndActions(infoMessage, buttonsAndActions); } +const showDevAssistIsRunningNotification = (proxyUrl : string) => { + const infoMessage: string = translationService.getMessage(DEVASSIST_SERVICE.IS_RUNNING.NOTIFICATION, proxyUrl); + const buttonsAndActions: { buttonMessage: string, buttonAction: () => void }[] = [ + { + buttonMessage: translationService.getMessage(BUTTONS.SEE_DETAILS), + buttonAction: vsNotificationService.showOutput + }, + { + buttonMessage: translationService.getMessage(DEVASSIST_SERVICE.IS_RUNNING.NOTIFICATION_BUTTON), + buttonAction: () => { + vscode.commands.executeCommand('suitecloud.opendevassistfeedbackform') + } + }, + ]; + vsNotificationService.showCommandInfoWithSpecificButtonsAndActions(infoMessage, buttonsAndActions); +} + const showStartDevAssistProblemNotification = (errorStage: string, error: string, devAssistStatusBar: vscode.StatusBarItem) => { // console.log(`There was a problem when starting DevAssist service. (${errorStage})\n${error}`) setErrorDevAssistStausBarMessage(devAssistStatusBar); diff --git a/packages/vscode-extension/src/suitecloud.ts b/packages/vscode-extension/src/suitecloud.ts index 3a15642b..d096df88 100644 --- a/packages/vscode-extension/src/suitecloud.ts +++ b/packages/vscode-extension/src/suitecloud.ts @@ -88,13 +88,6 @@ export async function activate(context: vscode.ExtensionContext) { () => vscode.commands.executeCommand('workbench.action.openWorkspaceSettings', DEVASSIST.CONFIG_KEYS.devAssistSection)) ); - // add watchers needed to update the status bars - context.subscriptions.push( - vscode.window.onDidChangeActiveTextEditor((textEditor) => updateStatusBars(textEditor, suitecloudProjectStatusBar, authIDStatusBar)), - vscode.workspace.createFileSystemWatcher(`**/${FILES.PROJECT_JSON}`).onDidChange((uri) => updateAuthIDStatusBarIfNeeded(uri, authIDStatusBar)), - vscode.workspace.onDidChangeConfiguration((configurationChangeEvent => devAssistConfigurationChangeHandler(configurationChangeEvent, devAssistStatusBar))) - ); - // DevAssist Feedback Form WebView context.subscriptions.push( vscode.commands.registerCommand('suitecloud.opendevassistfeedbackform', @@ -102,6 +95,13 @@ export async function activate(context: vscode.ExtensionContext) { ) ); + // add watchers needed to update the status bars + context.subscriptions.push( + vscode.window.onDidChangeActiveTextEditor((textEditor) => updateStatusBars(textEditor, suitecloudProjectStatusBar, authIDStatusBar)), + vscode.workspace.createFileSystemWatcher(`**/${FILES.PROJECT_JSON}`).onDidChange((uri) => updateAuthIDStatusBarIfNeeded(uri, authIDStatusBar)), + vscode.workspace.onDidChangeConfiguration((configurationChangeEvent => devAssistConfigurationChangeHandler(configurationChangeEvent, devAssistStatusBar))) + ); + // Use the console to output diagnostic information (console.log) and errors (console.error) // This line of code will only be executed once when your extension is activated console.log('SuiteCloud Extension for Visual Studio Code has been activated.'); diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index d6a6f676..384728d8 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -1,37 +1,33 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + */ + import * as vscode from 'vscode'; -import * as path from 'path'; -import { VSTranslationService } from '../service/VSTranslationService'; +import { DEVASSIST } from '../ApplicationConstants'; import { DEVASSIST_SERVICE } from '../service/TranslationKeys'; +import { MediaFileService } from '../service/MediaFileService'; +import { FEEDBACK_FORM_FILE_NAMES } from '../service/MediaFileKeys'; +import { VSTranslationService } from '../service/VSTranslationService'; import { getDevAssistCurrentSettings } from '../startup/DevAssistConfiguration'; -import { ApplicationConstants, FileUtils } from '../util/ExtensionUtil'; +import { ApplicationConstants } from '../util/ExtensionUtil'; import VSConsoleLogger from '../loggers/VSConsoleLogger'; import { validateIntegerWithinInterval, validateMultipleOptionField, validateTextAreaField, } from './WebviewFieldValidationUtils'; -import { DEVASSIST } from '../ApplicationConstants'; const translationService = new VSTranslationService(); const vsLogger = new VSConsoleLogger(); -const MEDIA_DIR = 'resources/media' const PROXY_URL = DEVASSIST.PROXY_URL; -const WEBVIEW_FILE_NAMES = { - FEEDBACK_FORM : { - HTML : 'FeedbackForm.html', - CSS : 'FeedbackForm.css' - }, - SUBMITTING_HTML : 'FeedbackFormSubmitting.html', - SUCCESS_HTML : 'FeedbackFormSuccess.html', - FAILURE_HTML : 'FeedbackFormFailure.html', -} - const WEBVIEW_EVENTS = { CLOSE : "CLOSE_WEBVIEW", SUBMIT_FEEDBACK : "SUBMIT_FEEDBACK", OPEN_NEW_FEEDBACK_FORM : "OPEN_NEW_FEEDBACK_FORM", + SPAWN_ALERT_MESSAGE : "SPAWN_ALERT_MESSAGE", } type FeedbackFormData = { @@ -49,7 +45,7 @@ const VALID_FEEDBACK_TOPICS = [ ] let feedbackFormPanel: vscode.WebviewPanel | undefined; -let vscodeExtensionMediaPath : string; +let mediaService: MediaFileService; export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // if one FeedbackForm is already open, reveal it instead of creating a new one @@ -58,7 +54,7 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { return; } - vscodeExtensionMediaPath = path.join(context.extensionPath, MEDIA_DIR); + mediaService = new MediaFileService(context); feedbackFormPanel = vscode.window.createWebviewPanel( 'devassistfeedbackform', 'SuiteCloud Developer Assistant Feedback', @@ -66,15 +62,15 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { { enableScripts: true, localResourceRoots: [ - vscode.Uri.file(vscodeExtensionMediaPath), + vscode.Uri.file(mediaService.getMediaDirectoryFullPath()), ], }, ); // Read HTML and inject the correct webview resource URIs for the CSS file - const feedbackFormHTMLFilePath = path.join(vscodeExtensionMediaPath, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.HTML); - const feedbackFormCSSFilePath = path.join(vscodeExtensionMediaPath, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.CSS); - feedbackFormPanel.webview.html = generateWebviewHTMLContent(feedbackFormHTMLFilePath, feedbackFormCSSFilePath); + const cssFilePath = mediaService.getMediaFileFullPath(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.CSS); + const cssWebviewUri = feedbackFormPanel?.webview.asWebviewUri(vscode.Uri.file(cssFilePath)).toString(); + feedbackFormPanel.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); // Clean up the reference when the WebviewPanel is closed feedbackFormPanel.onDidDispose( @@ -87,12 +83,92 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // Handle messages/events sent from the webview feedbackFormPanel.webview.onDidReceiveMessage( - (webviewMessage) => handleWebviewMessage(webviewMessage, feedbackFormCSSFilePath), + (webviewMessage) => handleWebviewMessage(webviewMessage, cssWebviewUri), undefined, context.subscriptions, ); }; +const handleWebviewMessage = async (webviewMessage : any, cssWebviewUri : string) : Promise => { + switch (webviewMessage.eventType) { + case WEBVIEW_EVENTS.SUBMIT_FEEDBACK: + handleSubmitFeedbackFormEvent(webviewMessage.eventData, cssWebviewUri); + break; + + case WEBVIEW_EVENTS.OPEN_NEW_FEEDBACK_FORM: + feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); + break; + + case WEBVIEW_EVENTS.CLOSE: + feedbackFormPanel?.dispose(); + break; + } +} + +const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWebviewUri : string) => { + + // validate Feedback Form Data + const validationResult = validateFormData(formData); + if (typeof validationResult === 'string') { + await spawnErrorMessageOnWebview(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.GENERIC_VALIDATION_ERROR_WRAPPER, validationResult)); + return; + } + + feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.SUBMITTING_HTML, cssWebviewUri); + + // Send request to NetSuite Backend through Proxy + try { + const currentProxySettings = getDevAssistCurrentSettings(); + const requestBody = JSON.stringify(formData); + const response = await fetch(`${PROXY_URL.SCHEME}${PROXY_URL.LOCALHOST_IP}:${currentProxySettings.localPort}${PROXY_URL.FEEDBACK_PATH}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: requestBody + }); + + if (response.ok || response.status === 463) { + vsLogger.printTimestamp(); + vsLogger.info("Feedback Form Success: " + response.status + ' ' + response.statusText); + vsLogger.info(''); + feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.SUCCESS_HTML, cssWebviewUri); + } + else { + vsLogger.printTimestamp(); + vsLogger.error("Feedback Form External Failure: " + response.status + ' ' + response.statusText); + vsLogger.error(''); + + // "Manual reauthentication is needed" proxy event + if (response.status === ApplicationConstants.HTTP_RESPONSE_CODE.FORBIDDEN) { + const responseBody : any = await response.json(); + feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); + await spawnErrorMessageOnWebview(`Error 403: "${responseBody.error}"`); + } + else { + feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.FAILURE_HTML, cssWebviewUri); + } + } + } catch (e) { + vsLogger.printTimestamp(); + vsLogger.error("Feedback Form Internal Failure: " + e); + vsLogger.error(''); + + // TODO: Find a way to not delete the user input when swaping HTML / clicking out + // -> https://code.visualstudio.com/api/extension-guides/webview#getstate-and-setstate + feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); + await spawnErrorMessageOnWebview(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR)); + } +} + + +const spawnErrorMessageOnWebview = async (message: string) => { + await feedbackFormPanel!.webview.postMessage({ + eventType: WEBVIEW_EVENTS.SPAWN_ALERT_MESSAGE, + eventData: { + alertLevel : 'error', + alertMessage: message} + }); +} + const validateFormData = (formData : FeedbackFormData) => { // validate feedback field (textArea) @@ -114,83 +190,4 @@ const validateFormData = (formData : FeedbackFormData) => { } return true; -} - -const handleWebviewMessage = async (webviewMessage : any, feedbackFormCSSFilePath : string) : Promise => { - switch (webviewMessage.type) { - case WEBVIEW_EVENTS.SUBMIT_FEEDBACK: - console.log(webviewMessage); - - // validate Feedback Form Data - const validationResult = validateFormData(webviewMessage.data); - if (typeof validationResult === 'string') { - feedbackFormPanel!.webview.postMessage({ type: 'spawnAlertEvent', value: 'error', message: translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.GENERIC_VALIDATION_ERROR_WRAPPER, validationResult)}); - return; - } - - const submittingHTMLFilePath = path.join(vscodeExtensionMediaPath, WEBVIEW_FILE_NAMES.SUBMITTING_HTML); - feedbackFormPanel!.webview.html = generateWebviewHTMLContent(submittingHTMLFilePath, feedbackFormCSSFilePath); - - // Send request to NetSuite Backend through Proxy - try { - const currentProxySettings = getDevAssistCurrentSettings(); - const response = await fetch(`${PROXY_URL.SCHEME}${PROXY_URL.LOCALHOST_IP}:${currentProxySettings.localPort}${PROXY_URL.FEEDBACK_PATH}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: webviewMessage.data - }); - if (response.ok) { - vsLogger.printTimestamp(); - vsLogger.info("Feedback Form Success: " + response.status + ' ' + response.statusText); - vsLogger.info(''); - const successHTMLFilePath = path.join(vscodeExtensionMediaPath, WEBVIEW_FILE_NAMES.SUCCESS_HTML); - feedbackFormPanel!.webview.html = generateWebviewHTMLContent(successHTMLFilePath, feedbackFormCSSFilePath); - } - else { - vsLogger.printTimestamp(); - vsLogger.error("Feedback Form External Failure: " + response.status + ' ' + response.statusText); - vsLogger.error(''); - - // "Manual reauthentication is needed" proxy event - if (response.status === ApplicationConstants.HTTP_RESPONSE_CODE.FORBIDDEN) { - const responseBody : any = await response.json(); - const feedbackFormHTMLFilePath = path.join(vscodeExtensionMediaPath, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.HTML); - feedbackFormPanel!.webview.html = generateWebviewHTMLContent(feedbackFormHTMLFilePath, feedbackFormCSSFilePath); - feedbackFormPanel!.webview.postMessage({ type: 'spawnAlertEvent', value: 'error', message: `Error 403: "${responseBody.error}"`}); - } - else { - const failureHTMLFilePath = path.join(vscodeExtensionMediaPath, WEBVIEW_FILE_NAMES.FAILURE_HTML); - feedbackFormPanel!.webview.html = generateWebviewHTMLContent(failureHTMLFilePath, feedbackFormCSSFilePath); - } - } - } catch (e) { - vsLogger.printTimestamp(); - vsLogger.error("Feedback Form Internal Failure: " + e); - vsLogger.error(''); - - // TODO: Find a way to not delete the user input when swaping HTML / clicking out - // -> https://code.visualstudio.com/api/extension-guides/webview#getstate-and-setstate - const feedbackFormHTMLFilePath = path.join(vscodeExtensionMediaPath, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.HTML); - feedbackFormPanel!.webview.html = generateWebviewHTMLContent(feedbackFormHTMLFilePath, feedbackFormCSSFilePath); - feedbackFormPanel!.webview.postMessage({ type: 'spawnAlertEvent', value: 'error', message: translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR)}); - } - break; - - case WEBVIEW_EVENTS.OPEN_NEW_FEEDBACK_FORM: - const feedbackFormHTMLFilePath = path.join(vscodeExtensionMediaPath, WEBVIEW_FILE_NAMES.FEEDBACK_FORM.HTML); - feedbackFormPanel!.webview.html = generateWebviewHTMLContent(feedbackFormHTMLFilePath, feedbackFormCSSFilePath); - break; - - case WEBVIEW_EVENTS.CLOSE: - feedbackFormPanel?.dispose(); - break; - } -} - -const generateWebviewHTMLContent = (htmlFilePath : string, cssFilePath : string): string => { - let htmlFileContent = FileUtils.readAsString(htmlFilePath); - const cssUri = feedbackFormPanel?.webview.asWebviewUri(vscode.Uri.file(cssFilePath)); - htmlFileContent = htmlFileContent.replace('{{CSS_FILE.css}}', cssUri!.toString()); - - return htmlFileContent; } \ No newline at end of file diff --git a/packages/vscode-extension/src/webviews/WebviewFieldValidationUtils.ts b/packages/vscode-extension/src/webviews/WebviewFieldValidationUtils.ts index e7afc248..0e8909b5 100644 --- a/packages/vscode-extension/src/webviews/WebviewFieldValidationUtils.ts +++ b/packages/vscode-extension/src/webviews/WebviewFieldValidationUtils.ts @@ -1,3 +1,8 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + */ + import { DEVASSIST_SERVICE } from '../service/TranslationKeys'; import { VSTranslationService } from '../service/VSTranslationService'; From 569e8e9bf7c705c71db5bc4ad5c8efe9ffd9e1aa Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Fri, 14 Nov 2025 09:57:22 +0100 Subject: [PATCH 29/37] More improvements --- .../resources/media/FeedbackForm.html | 12 +++--------- .../src/webviews/FeedbackFormWebview.ts | 10 +++++----- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html index 3faf9a29..e87fe469 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.html +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -97,19 +97,13 @@

SuiteCloud Developer Assistant Feedback

if (timeout !== 0) setTimeout(removeAlert, timeout); } - // VS Code API + // necessary initialization of VSCode API (establish a communication flow) const vscode = acquireVsCodeApi(); + // Internal PageEvent Handlers (generated within the HTML and handled here) form.addEventListener('submit', (e) => { e.preventDefault(); - // TODO (for Reviewers): VSCode Security forbids FETCHing content directly from within the Webview. - // const response = await fetch("http://127.0.0.1:8181/api/internal/devassist", { - // method: "POST", - // headers: { "Content-Type": "application/json" }, - // body: json - // }); - const data = collect(); vscode.postMessage({ eventType: 'SUBMIT_FEEDBACK', eventData: data }); }); @@ -118,7 +112,7 @@

SuiteCloud Developer Assistant Feedback

vscode.postMessage({ eventType: 'CLOSE_WEBVIEW' }); }); - // Listen to VSCode Events + // External VSCodeEvent Handler (generated on the Extension code via webview.postMessage) window.addEventListener('message', message => { console.log(message); const { eventType, eventData } = message.data; diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index 384728d8..250d300c 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -83,16 +83,16 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // Handle messages/events sent from the webview feedbackFormPanel.webview.onDidReceiveMessage( - (webviewMessage) => handleWebviewMessage(webviewMessage, cssWebviewUri), + (webviewEvent) => handleWebviewEventMessage(webviewEvent, cssWebviewUri), undefined, context.subscriptions, ); }; -const handleWebviewMessage = async (webviewMessage : any, cssWebviewUri : string) : Promise => { - switch (webviewMessage.eventType) { +const handleWebviewEventMessage = async (webviewEvent : any, cssWebviewUri : string) : Promise => { + switch (webviewEvent.eventType) { case WEBVIEW_EVENTS.SUBMIT_FEEDBACK: - handleSubmitFeedbackFormEvent(webviewMessage.eventData, cssWebviewUri); + handleSubmitFeedbackFormEvent(webviewEvent.eventData, cssWebviewUri); break; case WEBVIEW_EVENTS.OPEN_NEW_FEEDBACK_FORM: @@ -126,7 +126,7 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb body: requestBody }); - if (response.ok || response.status === 463) { + if (response.ok) { vsLogger.printTimestamp(); vsLogger.info("Feedback Form Success: " + response.status + ' ' + response.statusText); vsLogger.info(''); From 1ea9342530de7c942fc8ef45bc95af0b7403458b Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Fri, 14 Nov 2025 10:06:02 +0100 Subject: [PATCH 30/37] More improvements 2 --- .../src/webviews/FeedbackFormWebview.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index 250d300c..fb7cadba 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -30,6 +30,11 @@ const WEBVIEW_EVENTS = { SPAWN_ALERT_MESSAGE : "SPAWN_ALERT_MESSAGE", } +type WebviewEventMessage = { + eventType: string; + eventData?: FeedbackFormData +}; + type FeedbackFormData = { feedback: string; topics: string[]; @@ -67,7 +72,7 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { }, ); - // Read HTML and inject the correct webview resource URIs for the CSS file + // calculate cssUri as a proper Webview File Path and generate HTML content with it const cssFilePath = mediaService.getMediaFileFullPath(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.CSS); const cssWebviewUri = feedbackFormPanel?.webview.asWebviewUri(vscode.Uri.file(cssFilePath)).toString(); feedbackFormPanel.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); @@ -81,7 +86,7 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { context.subscriptions, ); - // Handle messages/events sent from the webview + // Handle messages/events sent from the webview page feedbackFormPanel.webview.onDidReceiveMessage( (webviewEvent) => handleWebviewEventMessage(webviewEvent, cssWebviewUri), undefined, @@ -89,10 +94,10 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { ); }; -const handleWebviewEventMessage = async (webviewEvent : any, cssWebviewUri : string) : Promise => { +const handleWebviewEventMessage = async (webviewEvent : WebviewEventMessage, cssWebviewUri : string) : Promise => { switch (webviewEvent.eventType) { case WEBVIEW_EVENTS.SUBMIT_FEEDBACK: - handleSubmitFeedbackFormEvent(webviewEvent.eventData, cssWebviewUri); + await handleSubmitFeedbackFormEvent(webviewEvent.eventData!, cssWebviewUri); break; case WEBVIEW_EVENTS.OPEN_NEW_FEEDBACK_FORM: From 6189c5950c662b28f14c1a1eb7e39089eaef90fd Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Fri, 14 Nov 2025 11:00:24 +0100 Subject: [PATCH 31/37] maxlength --- packages/vscode-extension/resources/media/FeedbackForm.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html index e87fe469..70c365b3 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.html +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -14,8 +14,7 @@

SuiteCloud Developer Assistant Feedback

- -
From 14420f512898039680fd66c7bea5cd61391b0179 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Fri, 14 Nov 2025 12:07:02 +0100 Subject: [PATCH 32/37] Updating TranslationKeys Buttons --- packages/vscode-extension/messages.json | 9 ++++----- .../vscode-extension/src/service/TranslationKeys.ts | 11 ++++------- .../src/startup/DevAssistConfiguration.ts | 12 ++++++------ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/vscode-extension/messages.json b/packages/vscode-extension/messages.json index e2a041a3..39c9c433 100644 --- a/packages/vscode-extension/messages.json +++ b/packages/vscode-extension/messages.json @@ -10,9 +10,12 @@ "ANSWERS_NO": "No", "ANSWERS_YES": "Yes", + "BUTTONS_DONT_SHOW_AGAIN": "Don't show again", + "BUTTONS_GIVE_FEEDBACK": "Give Feedback", + "BUTTONS_OK": "Ok", + "BUTTONS_OPEN_SETTINGS": "Open Settings", "BUTTONS_RESTART_NOW": "Restart Now", "BUTTONS_SEE_DETAILS": "See Details", - "BUTTONS_OK": "Ok", "COMMAND_ERROR": "Something went wrong with '{0}'.", "COMMAND_SUCCESS": "'{0}' has been successfully executed.", @@ -71,16 +74,12 @@ "DEVASSIST_SERVICE_IS_DISABLED_NOTIFICATION": "SuiteCloud Developer Assistant service has been disabled.", "DEVASSIST_SERVICE_IS_DISABLED_OUTPUT": "SuiteCloud Developer Assistant service has been disabled.", "DEVASSIST_SERVICE_IS_RUNNING_NOTIFICATION": "SuiteCloud Developer Assistant service is running. Use Cline Base URL to: {0}", - "DEVASSIST_SERVICE_IS_RUNNING_NOTIFICATION_BUTTON": "Give Feedback", "DEVASSIST_SERVICE_IS_RUNNING_OUTPUT": "SuiteCloud Developer Assistant service is now running at {0} and is using the {1} auth ID.\nUse this Cline Base URL {2}.", "DEVASSIST_SERVICE_IS_RUNNING_STATUSBAR": "Dev Assist: running", "DEVASSIST_SERVICE_IS_STOPPED_NOTIFICATION": "Something went wrong with SuiteCloud Developer Assistant service.", "DEVASSIST_SERVICE_IS_STOPPED_OUTPUT": "There was a problem when starting SuiteCloud Developer Assistant service.\n{0}", "DEVASSIST_SERVICE_IS_STOPPED_STATUSBAR": "Dev Assist: stopped", "DEVASSIST_SERVICE_SERVER_ERROR_OUTPUT": "A server error has occurred while running SuiteCloud Developer Assistant service.\nError: {0}", - "DEVASSIST_SERVICE_STARTUP_BUTTON_DONT_SHOW_AGAIN": "Don't show again", - "DEVASSIST_SERVICE_STARTUP_BUTTON_OPEN_SETTINGS": "Open Settings", - "DEVASSIST_SERVICE_SEE_DETAILS_BUTTON": "See Details", "DEVASSIST_SERVICE_STARTUP_MESSAGE": "SuiteCloud Developer Assistant is here. Open settings to start using it.", "DEVASSIST_SERVICE_STATUSBAR_TOOLTIP": "Shows the status of SuiteCloud Developer Assistant service.", diff --git a/packages/vscode-extension/src/service/TranslationKeys.ts b/packages/vscode-extension/src/service/TranslationKeys.ts index 7c06fd4e..d7a2e4dd 100644 --- a/packages/vscode-extension/src/service/TranslationKeys.ts +++ b/packages/vscode-extension/src/service/TranslationKeys.ts @@ -20,9 +20,12 @@ export const ANSWERS = { }; export const BUTTONS = { + DONT_SHOW_AGAIN: "BUTTONS_DONT_SHOW_AGAIN", + GIVE_FEEDBACK: "BUTTONS_GIVE_FEEDBACK", + OK: 'BUTTONS_OK', + OPEN_SETTINGS: "BUTTONS_OPEN_SETTINGS", RESTART_NOW: 'BUTTONS_RESTART_NOW', SEE_DETAILS: 'BUTTONS_SEE_DETAILS', - OK: 'BUTTONS_OK' }; export const COMMAND = { @@ -125,7 +128,6 @@ export const DEVASSIST_SERVICE = { }, IS_RUNNING: { NOTIFICATION: 'DEVASSIST_SERVICE_IS_RUNNING_NOTIFICATION', - NOTIFICATION_BUTTON: 'DEVASSIST_SERVICE_IS_RUNNING_NOTIFICATION_BUTTON', OUTPUT: 'DEVASSIST_SERVICE_IS_RUNNING_OUTPUT', STATUSBAR: 'DEVASSIST_SERVICE_IS_RUNNING_STATUSBAR' }, @@ -135,14 +137,9 @@ export const DEVASSIST_SERVICE = { STATUSBAR: 'DEVASSIST_SERVICE_IS_STOPPED_STATUSBAR' }, STARTUP: { - BUTTON: { - DONT_SHOW_AGAIN: 'DEVASSIST_SERVICE_STARTUP_BUTTON_DONT_SHOW_AGAIN', - OPEN_SETTINGS: 'DEVASSIST_SERVICE_STARTUP_BUTTON_OPEN_SETTINGS', - }, MESSAGE: 'DEVASSIST_SERVICE_STARTUP_MESSAGE', }, STATUSBAR_TOOLTIP: 'DEVASSIST_SERVICE_STATUSBAR_TOOLTIP', - SEE_DETAILS_BUTTON: 'DEVASSIST_SERVICE_SEE_DETAILS_BUTTON' } export const DISMISS = 'DISMISS'; diff --git a/packages/vscode-extension/src/startup/DevAssistConfiguration.ts b/packages/vscode-extension/src/startup/DevAssistConfiguration.ts index d844a1bd..029b3891 100644 --- a/packages/vscode-extension/src/startup/DevAssistConfiguration.ts +++ b/packages/vscode-extension/src/startup/DevAssistConfiguration.ts @@ -179,11 +179,11 @@ const showDevAssistStartUpNotification = () => { const infoMessage: string = translationService.getMessage(DEVASSIST_SERVICE.STARTUP.MESSAGE); const buttonsAndActions: { buttonMessage: string, buttonAction: () => void }[] = [ { - buttonMessage: translationService.getMessage(DEVASSIST_SERVICE.STARTUP.BUTTON.OPEN_SETTINGS), + buttonMessage: translationService.getMessage(BUTTONS.OPEN_SETTINGS), buttonAction: openDevAssistSettings }, { - buttonMessage: translationService.getMessage(DEVASSIST_SERVICE.STARTUP.BUTTON.DONT_SHOW_AGAIN), + buttonMessage: translationService.getMessage(BUTTONS.DONT_SHOW_AGAIN), buttonAction: () => { const devAssistConfigSection = vscode.workspace.getConfiguration(DEVASSIST.CONFIG_KEYS.devAssistSection); devAssistConfigSection.update(DEVASSIST.CONFIG_KEYS.startupNotificationDisabled, true); @@ -201,7 +201,7 @@ const showDevAssistIsRunningNotification = (proxyUrl : string) => { buttonAction: vsNotificationService.showOutput }, { - buttonMessage: translationService.getMessage(DEVASSIST_SERVICE.IS_RUNNING.NOTIFICATION_BUTTON), + buttonMessage: translationService.getMessage(BUTTONS.GIVE_FEEDBACK), buttonAction: () => { vscode.commands.executeCommand('suitecloud.opendevassistfeedbackform') } @@ -218,7 +218,7 @@ const showStartDevAssistProblemNotification = (errorStage: string, error: string const errorMessage = translationService.getMessage(DEVASSIST_SERVICE.IS_STOPPED.NOTIFICATION); const buttonsAndActions: { buttonMessage: string, buttonAction: () => void }[] = [ { - buttonMessage: translationService.getMessage(DEVASSIST_SERVICE.SEE_DETAILS_BUTTON), + buttonMessage: translationService.getMessage(BUTTONS.SEE_DETAILS), buttonAction: () => { // show suitecloud output and devassist settings output.show(); @@ -235,7 +235,7 @@ const showDevAssistEmitProblemLog = (errorStage: string, emitError: string, devA const errorMessage = translationService.getMessage(DEVASSIST_SERVICE.IS_STOPPED.NOTIFICATION); const buttonsAndActions: { buttonMessage: string, buttonAction: () => void }[] = [ { - buttonMessage: translationService.getMessage(DEVASSIST_SERVICE.SEE_DETAILS_BUTTON), + buttonMessage: translationService.getMessage(BUTTONS.SEE_DETAILS), buttonAction: () => output.show(), }, ]; @@ -250,7 +250,7 @@ const showDevAssistEmitProblemNotification = (errorStage: string, emitError: str const errorMessage = translationService.getMessage(DEVASSIST_SERVICE.IS_STOPPED.NOTIFICATION); const buttonsAndActions: { buttonMessage: string, buttonAction: () => void }[] = [ { - buttonMessage: translationService.getMessage(DEVASSIST_SERVICE.SEE_DETAILS_BUTTON), + buttonMessage: translationService.getMessage(BUTTONS.SEE_DETAILS), buttonAction: () => { // show suitecloud output and devassist settings output.show() From 0d4fd5415a8bc0ea735036cd3e1b304ae01c7d22 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Fri, 14 Nov 2025 13:34:40 +0100 Subject: [PATCH 33/37] Code Clarity --- .../resources/media/FeedbackForm.html | 73 ++++++++++--------- .../resources/media/FeedbackFormFailure.html | 6 +- .../media/FeedbackFormSubmitting.html | 6 +- .../resources/media/FeedbackFormSuccess.html | 10 ++- .../src/webviews/FeedbackFormWebview.ts | 36 +++++---- 5 files changed, 71 insertions(+), 60 deletions(-) diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html index 70c365b3..3c59b534 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.html +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -56,10 +56,41 @@

SuiteCloud Developer Assistant Feedback

\ No newline at end of file diff --git a/packages/vscode-extension/resources/media/FeedbackFormFailure.html b/packages/vscode-extension/resources/media/FeedbackFormFailure.html index 6cf2eedf..7fc888cc 100644 --- a/packages/vscode-extension/resources/media/FeedbackFormFailure.html +++ b/packages/vscode-extension/resources/media/FeedbackFormFailure.html @@ -22,11 +22,13 @@

SuiteCloud Developer Assistant Feedback

diff --git a/packages/vscode-extension/resources/media/FeedbackFormSubmitting.html b/packages/vscode-extension/resources/media/FeedbackFormSubmitting.html index 8fa29787..ef087f44 100644 --- a/packages/vscode-extension/resources/media/FeedbackFormSubmitting.html +++ b/packages/vscode-extension/resources/media/FeedbackFormSubmitting.html @@ -26,9 +26,9 @@

SuiteCloud Developer Assistant Feedback

// Thinking animation ('' -> '.' -> '..' -> '...' -> '') feedbackLabel.textContent = pageText; setInterval(() => { - feedbackLabel.textContent = pageText + dots[idx]; - idx = (idx + 1) % dots.length; - }, msBetweenAnimationFrames); + feedbackLabel.textContent = pageText + dots[idx]; + idx = (idx + 1) % dots.length; + }, msBetweenAnimationFrames); \ No newline at end of file diff --git a/packages/vscode-extension/resources/media/FeedbackFormSuccess.html b/packages/vscode-extension/resources/media/FeedbackFormSuccess.html index 77cf5599..50d14677 100644 --- a/packages/vscode-extension/resources/media/FeedbackFormSuccess.html +++ b/packages/vscode-extension/resources/media/FeedbackFormSuccess.html @@ -21,16 +21,20 @@

SuiteCloud Developer Assistant Feedback

diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts index fb7cadba..f40322dd 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts @@ -23,11 +23,15 @@ const vsLogger = new VSConsoleLogger(); const PROXY_URL = DEVASSIST.PROXY_URL; -const WEBVIEW_EVENTS = { - CLOSE : "CLOSE_WEBVIEW", - SUBMIT_FEEDBACK : "SUBMIT_FEEDBACK", - OPEN_NEW_FEEDBACK_FORM : "OPEN_NEW_FEEDBACK_FORM", - SPAWN_ALERT_MESSAGE : "SPAWN_ALERT_MESSAGE", +const FEEDBACK_FORM_EVENTS = { + WEBVIEW_CONTROLLER: { + CLOSE : "CLOSE_WEBVIEW", + SUBMIT_FEEDBACK : "SUBMIT_FEEDBACK", + OPEN_NEW_FEEDBACK_FORM : "OPEN_NEW_FEEDBACK_FORM", + }, + HTML_PAGE: { + RENDER_TOAST_MESSAGE : "RENDER_TOAST_MESSAGE", + } } type WebviewEventMessage = { @@ -86,7 +90,7 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { context.subscriptions, ); - // Handle messages/events sent from the webview page + // Handle messages/events sent from HTML to this Webview controller feedbackFormPanel.webview.onDidReceiveMessage( (webviewEvent) => handleWebviewEventMessage(webviewEvent, cssWebviewUri), undefined, @@ -96,15 +100,15 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { const handleWebviewEventMessage = async (webviewEvent : WebviewEventMessage, cssWebviewUri : string) : Promise => { switch (webviewEvent.eventType) { - case WEBVIEW_EVENTS.SUBMIT_FEEDBACK: + case FEEDBACK_FORM_EVENTS.WEBVIEW_CONTROLLER.SUBMIT_FEEDBACK: await handleSubmitFeedbackFormEvent(webviewEvent.eventData!, cssWebviewUri); break; - case WEBVIEW_EVENTS.OPEN_NEW_FEEDBACK_FORM: + case FEEDBACK_FORM_EVENTS.WEBVIEW_CONTROLLER.OPEN_NEW_FEEDBACK_FORM: feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); break; - case WEBVIEW_EVENTS.CLOSE: + case FEEDBACK_FORM_EVENTS.WEBVIEW_CONTROLLER.CLOSE: feedbackFormPanel?.dispose(); break; } @@ -115,7 +119,7 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb // validate Feedback Form Data const validationResult = validateFormData(formData); if (typeof validationResult === 'string') { - await spawnErrorMessageOnWebview(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.GENERIC_VALIDATION_ERROR_WRAPPER, validationResult)); + await sendErrorEventToWebview(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.GENERIC_VALIDATION_ERROR_WRAPPER, validationResult)); return; } @@ -146,7 +150,7 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb if (response.status === ApplicationConstants.HTTP_RESPONSE_CODE.FORBIDDEN) { const responseBody : any = await response.json(); feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); - await spawnErrorMessageOnWebview(`Error 403: "${responseBody.error}"`); + await sendErrorEventToWebview(`Error 403: "${responseBody.error}"`); } else { feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.FAILURE_HTML, cssWebviewUri); @@ -160,17 +164,17 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb // TODO: Find a way to not delete the user input when swaping HTML / clicking out // -> https://code.visualstudio.com/api/extension-guides/webview#getstate-and-setstate feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); - await spawnErrorMessageOnWebview(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR)); + await sendErrorEventToWebview(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR)); } } -const spawnErrorMessageOnWebview = async (message: string) => { +const sendErrorEventToWebview = async (message: string) => { await feedbackFormPanel!.webview.postMessage({ - eventType: WEBVIEW_EVENTS.SPAWN_ALERT_MESSAGE, + eventType: FEEDBACK_FORM_EVENTS.HTML_PAGE.RENDER_TOAST_MESSAGE, eventData: { - alertLevel : 'error', - alertMessage: message} + toastMessageLevel : 'error', + toastMessageContent: message} }); } From cda0d06c7d22cfb2e3bb1a39d0b42f71335aa1d5 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Mon, 17 Nov 2025 09:15:59 +0100 Subject: [PATCH 34/37] Naming --- packages/vscode-extension/src/suitecloud.ts | 2 +- ...ew.ts => FeedbackFormWebviewController.ts} | 43 ++++++++++--------- 2 files changed, 23 insertions(+), 22 deletions(-) rename packages/vscode-extension/src/webviews/{FeedbackFormWebview.ts => FeedbackFormWebviewController.ts} (80%) diff --git a/packages/vscode-extension/src/suitecloud.ts b/packages/vscode-extension/src/suitecloud.ts index d096df88..f42af494 100644 --- a/packages/vscode-extension/src/suitecloud.ts +++ b/packages/vscode-extension/src/suitecloud.ts @@ -29,7 +29,7 @@ import { VSTranslationService } from './service/VSTranslationService'; import { devAssistConfigurationChangeHandler, startDevAssistProxyIfEnabled } from './startup/DevAssistConfiguration'; import { showSetupAccountWarningMessageIfNeeded } from './startup/ShowSetupAccountWarning'; import { createAuthIDStatusBar, createDevAssistStatusBar, createSuiteCloudProjectStatusBar, updateAuthIDStatusBarIfNeeded, updateStatusBars } from './startup/StatusBarItemsFunctions'; -import { openDevAssistFeedbackForm } from './webviews/FeedbackFormWebview'; +import { openDevAssistFeedbackForm } from './webviews/FeedbackFormWebviewController'; const SCLOUD_OUTPUT_CHANNEL_NAME = 'SuiteCloud'; diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts similarity index 80% rename from packages/vscode-extension/src/webviews/FeedbackFormWebview.ts rename to packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts index f40322dd..fc08f3a7 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebview.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts @@ -24,17 +24,17 @@ const vsLogger = new VSConsoleLogger(); const PROXY_URL = DEVASSIST.PROXY_URL; const FEEDBACK_FORM_EVENTS = { - WEBVIEW_CONTROLLER: { + HTML_PAGE: { CLOSE : "CLOSE_WEBVIEW", SUBMIT_FEEDBACK : "SUBMIT_FEEDBACK", OPEN_NEW_FEEDBACK_FORM : "OPEN_NEW_FEEDBACK_FORM", }, - HTML_PAGE: { + WEBVIEW_CONTROLLER: { RENDER_TOAST_MESSAGE : "RENDER_TOAST_MESSAGE", } } -type WebviewEventMessage = { +type HtmlEventMessage = { eventType: string; eventData?: FeedbackFormData }; @@ -83,32 +83,30 @@ export const openDevAssistFeedbackForm = (context: vscode.ExtensionContext) => { // Clean up the reference when the WebviewPanel is closed feedbackFormPanel.onDidDispose( - () => { - feedbackFormPanel = undefined; - }, + () => { feedbackFormPanel = undefined; }, null, context.subscriptions, ); // Handle messages/events sent from HTML to this Webview controller feedbackFormPanel.webview.onDidReceiveMessage( - (webviewEvent) => handleWebviewEventMessage(webviewEvent, cssWebviewUri), + (htmlEventMessage) => handleHtmlEventMessage(htmlEventMessage, cssWebviewUri), undefined, context.subscriptions, ); }; -const handleWebviewEventMessage = async (webviewEvent : WebviewEventMessage, cssWebviewUri : string) : Promise => { - switch (webviewEvent.eventType) { - case FEEDBACK_FORM_EVENTS.WEBVIEW_CONTROLLER.SUBMIT_FEEDBACK: - await handleSubmitFeedbackFormEvent(webviewEvent.eventData!, cssWebviewUri); +const handleHtmlEventMessage = async (htmlEventMessage : HtmlEventMessage, cssWebviewUri : string) : Promise => { + switch (htmlEventMessage.eventType) { + case FEEDBACK_FORM_EVENTS.HTML_PAGE.SUBMIT_FEEDBACK: + await handleSubmitFeedbackFormEvent(htmlEventMessage.eventData!, cssWebviewUri); break; - case FEEDBACK_FORM_EVENTS.WEBVIEW_CONTROLLER.OPEN_NEW_FEEDBACK_FORM: + case FEEDBACK_FORM_EVENTS.HTML_PAGE.OPEN_NEW_FEEDBACK_FORM: feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); break; - case FEEDBACK_FORM_EVENTS.WEBVIEW_CONTROLLER.CLOSE: + case FEEDBACK_FORM_EVENTS.HTML_PAGE.CLOSE: feedbackFormPanel?.dispose(); break; } @@ -119,7 +117,7 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb // validate Feedback Form Data const validationResult = validateFormData(formData); if (typeof validationResult === 'string') { - await sendErrorEventToWebview(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.GENERIC_VALIDATION_ERROR_WRAPPER, validationResult)); + await sendErrorEventToHtml(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.GENERIC_VALIDATION_ERROR_WRAPPER, validationResult)); return; } @@ -137,41 +135,44 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb if (response.ok) { vsLogger.printTimestamp(); - vsLogger.info("Feedback Form Success: " + response.status + ' ' + response.statusText); + vsLogger.info("Feedback Form Success: " + response.status + ' ' + response.statusText); // no need for status + statusText vsLogger.info(''); feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.SUCCESS_HTML, cssWebviewUri); } else { + // SERVER_ERROR (but proxy is running, a response was received) vsLogger.printTimestamp(); - vsLogger.error("Feedback Form External Failure: " + response.status + ' ' + response.statusText); + vsLogger.error("Feedback Form External Failure: " + response.status + ' ' + response.statusText); // try catch response body (if obtained print). vsLogger.error(''); // "Manual reauthentication is needed" proxy event if (response.status === ApplicationConstants.HTTP_RESPONSE_CODE.FORBIDDEN) { const responseBody : any = await response.json(); feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); - await sendErrorEventToWebview(`Error 403: "${responseBody.error}"`); + await sendErrorEventToHtml(`Error 403: "${responseBody.error}"`); } else { feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.FAILURE_HTML, cssWebviewUri); } } } catch (e) { + // https://corpjira.netsuitecorp.com/browse/PDPDEVTOOL-6307?filter=-2 + // VSCODE ERROR && PROXY_NOT_LOADED && PROXY_ERROR, REQUEST ERROR (Not even a response received) vsLogger.printTimestamp(); - vsLogger.error("Feedback Form Internal Failure: " + e); + vsLogger.error("Feedback Form Internal Failure: " + 'Timestamp' + e); vsLogger.error(''); // TODO: Find a way to not delete the user input when swaping HTML / clicking out // -> https://code.visualstudio.com/api/extension-guides/webview#getstate-and-setstate feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); - await sendErrorEventToWebview(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR)); + await sendErrorEventToHtml(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR)); } } -const sendErrorEventToWebview = async (message: string) => { +const sendErrorEventToHtml = async (message: string) => { await feedbackFormPanel!.webview.postMessage({ - eventType: FEEDBACK_FORM_EVENTS.HTML_PAGE.RENDER_TOAST_MESSAGE, + eventType: FEEDBACK_FORM_EVENTS.WEBVIEW_CONTROLLER.RENDER_TOAST_MESSAGE, eventData: { toastMessageLevel : 'error', toastMessageContent: message} From e1a0cbe580512c1390a2ce4e736cc021f490624a Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Mon, 17 Nov 2025 13:10:01 +0100 Subject: [PATCH 35/37] Log Messages Reviewed --- packages/vscode-extension/messages.json | 6 +++++- .../src/service/TranslationKeys.ts | 6 +++++- .../src/webviews/FeedbackFormWebviewController.ts | 15 +++++++-------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/vscode-extension/messages.json b/packages/vscode-extension/messages.json index 39c9c433..2a177ccf 100644 --- a/packages/vscode-extension/messages.json +++ b/packages/vscode-extension/messages.json @@ -66,7 +66,11 @@ "DEVASSIST_SERVICE_FEEDBACK_FORM_FIELD_CANNOT_HAVE_REPEATED_VALUES": "Select unique values (provided: {0}).", "DEVASSIST_SERVICE_FEEDBACK_FORM_FIELD_MUST_HAVE_BE_A_VALID_NUMBER": "Choose a natural number between {0} and {1}.", "DEVASSIST_SERVICE_FEEDBACK_FORM_FIELD_MUST_HAVE_SPECIFIC_VALUES": "Select any values from the ones available: {0}.", - "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR": "Unable to connect to the SuiteCloud Developer Assistant service. Is it running?", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR_REAUTHORIZE_TOAST": "Error 403: {0}", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR_TOAST": "Unable to connect to the SuiteCloud Developer Assistant service. Is it running?{0}", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_EXTERNAL_ERROR": "A server error has occurred while submitting feedback for the SuiteCloud Developer Assistant (Error {0}: {1}).", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_INTERNAL_ERROR": "There was a problem while submitting feedback for the SuiteCloud Developer Assistant. Is it running?", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMIT_SUCCESS": "Your feedback for the SuiteCloud Developer Assistant was successfully submitted.", "DEVASSIST_SERVICE_OUTPUT_PROXY_ERROR": "There was a problem while running SuiteCloud Developer Assistant service.\n{0}", "DEVASSIST_SERVICE_OUTPUT_SERVER_ERROR": "There was a server error while running SuiteCloud Developer Assistant service.\n{0}", diff --git a/packages/vscode-extension/src/service/TranslationKeys.ts b/packages/vscode-extension/src/service/TranslationKeys.ts index d7a2e4dd..38fec903 100644 --- a/packages/vscode-extension/src/service/TranslationKeys.ts +++ b/packages/vscode-extension/src/service/TranslationKeys.ts @@ -120,7 +120,11 @@ export const DEVASSIST_SERVICE = { MUST_HAVE_BE_A_VALID_NUMBER: 'DEVASSIST_SERVICE_FEEDBACK_FORM_FIELD_MUST_HAVE_BE_A_VALID_NUMBER', MUST_HAVE_SPECIFIC_VALUES: 'DEVASSIST_SERVICE_FEEDBACK_FORM_FIELD_MUST_HAVE_SPECIFIC_VALUES', }, - SUBMITTING_ERROR: 'DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR' + SUBMITTING_ERROR_REAUTHORIZE_TOAST: 'DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR_REAUTHORIZE_TOAST', + SUBMITTING_ERROR_TOAST: 'DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR_TOAST', + SUBMITTING_EXTERNAL_ERROR: 'DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_EXTERNAL_ERROR', + SUBMITTING_INTERNAL_ERROR: 'DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_INTERNAL_ERROR', + SUBMIT_SUCCESS: 'DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMIT_SUCCESS', }, IS_DISABLED: { NOTIFICATION: 'DEVASSIST_SERVICE_IS_DISABLED_NOTIFICATION', diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts index fc08f3a7..e88eeda0 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts @@ -135,37 +135,36 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb if (response.ok) { vsLogger.printTimestamp(); - vsLogger.info("Feedback Form Success: " + response.status + ' ' + response.statusText); // no need for status + statusText + vsLogger.info(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMIT_SUCCESS)); vsLogger.info(''); feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.SUCCESS_HTML, cssWebviewUri); } else { // SERVER_ERROR (but proxy is running, a response was received) vsLogger.printTimestamp(); - vsLogger.error("Feedback Form External Failure: " + response.status + ' ' + response.statusText); // try catch response body (if obtained print). + vsLogger.error(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_EXTERNAL_ERROR, response.status.toString(), response.statusText)); vsLogger.error(''); // "Manual reauthentication is needed" proxy event if (response.status === ApplicationConstants.HTTP_RESPONSE_CODE.FORBIDDEN) { const responseBody : any = await response.json(); feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); - await sendErrorEventToHtml(`Error 403: "${responseBody.error}"`); + await sendErrorEventToHtml(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR_REAUTHORIZE_TOAST, responseBody.error)); } else { feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.FAILURE_HTML, cssWebviewUri); } } - } catch (e) { - // https://corpjira.netsuitecorp.com/browse/PDPDEVTOOL-6307?filter=-2 - // VSCODE ERROR && PROXY_NOT_LOADED && PROXY_ERROR, REQUEST ERROR (Not even a response received) + } catch (error) { + // VSCODE ERROR, PROXY_NOT_LOADED, PROXY_ERROR, REQUEST_FORMATING_ERROR (Not even a response received) vsLogger.printTimestamp(); - vsLogger.error("Feedback Form Internal Failure: " + 'Timestamp' + e); + vsLogger.error(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR_TOAST, error ? '\n' + error : '')); vsLogger.error(''); // TODO: Find a way to not delete the user input when swaping HTML / clicking out // -> https://code.visualstudio.com/api/extension-guides/webview#getstate-and-setstate feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); - await sendErrorEventToHtml(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR)); + await sendErrorEventToHtml(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR_TOAST)); } } From a8d5fac72083f0ace918c778109c264f4b87ceca Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Mon, 17 Nov 2025 17:44:53 +0100 Subject: [PATCH 36/37] Last commit hopefully --- packages/vscode-extension/messages.json | 4 ++-- .../vscode-extension/resources/media/FeedbackForm.html | 10 +++++----- .../src/webviews/FeedbackFormWebviewController.ts | 2 +- .../src/webviews/WebviewFieldValidationUtils.ts | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/vscode-extension/messages.json b/packages/vscode-extension/messages.json index 2a177ccf..f7fcf84f 100644 --- a/packages/vscode-extension/messages.json +++ b/packages/vscode-extension/messages.json @@ -67,9 +67,9 @@ "DEVASSIST_SERVICE_FEEDBACK_FORM_FIELD_MUST_HAVE_BE_A_VALID_NUMBER": "Choose a natural number between {0} and {1}.", "DEVASSIST_SERVICE_FEEDBACK_FORM_FIELD_MUST_HAVE_SPECIFIC_VALUES": "Select any values from the ones available: {0}.", "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR_REAUTHORIZE_TOAST": "Error 403: {0}", - "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR_TOAST": "Unable to connect to the SuiteCloud Developer Assistant service. Is it running?{0}", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_ERROR_TOAST": "Unable to connect to the SuiteCloud Developer Assistant service. Is it running?", "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_EXTERNAL_ERROR": "A server error has occurred while submitting feedback for the SuiteCloud Developer Assistant (Error {0}: {1}).", - "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_INTERNAL_ERROR": "There was a problem while submitting feedback for the SuiteCloud Developer Assistant. Is it running?", + "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMITTING_INTERNAL_ERROR": "There was a problem while submitting feedback for the SuiteCloud Developer Assistant. Is it running?{0}", "DEVASSIST_SERVICE_FEEDBACK_FORM_SUBMIT_SUCCESS": "Your feedback for the SuiteCloud Developer Assistant was successfully submitted.", "DEVASSIST_SERVICE_OUTPUT_PROXY_ERROR": "There was a problem while running SuiteCloud Developer Assistant service.\n{0}", diff --git a/packages/vscode-extension/resources/media/FeedbackForm.html b/packages/vscode-extension/resources/media/FeedbackForm.html index 3c59b534..99b8b6b5 100644 --- a/packages/vscode-extension/resources/media/FeedbackForm.html +++ b/packages/vscode-extension/resources/media/FeedbackForm.html @@ -21,11 +21,11 @@

SuiteCloud Developer Assistant Feedback

This feedback is about
- - - - - + + + + +
diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts index e88eeda0..a893a01a 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts @@ -158,7 +158,7 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb } catch (error) { // VSCODE ERROR, PROXY_NOT_LOADED, PROXY_ERROR, REQUEST_FORMATING_ERROR (Not even a response received) vsLogger.printTimestamp(); - vsLogger.error(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR_TOAST, error ? '\n' + error : '')); + vsLogger.error(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_INTERNAL_ERROR, error ? '\n' + error : '')); vsLogger.error(''); // TODO: Find a way to not delete the user input when swaping HTML / clicking out diff --git a/packages/vscode-extension/src/webviews/WebviewFieldValidationUtils.ts b/packages/vscode-extension/src/webviews/WebviewFieldValidationUtils.ts index 0e8909b5..abca6ab2 100644 --- a/packages/vscode-extension/src/webviews/WebviewFieldValidationUtils.ts +++ b/packages/vscode-extension/src/webviews/WebviewFieldValidationUtils.ts @@ -38,7 +38,7 @@ export const validateMultipleOptionField = (fieldName : string, selectedOptions translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.FIELD.CANNOT_HAVE_REPEATED_VALUES, selectedOptions.toString())); } for (const option of selectedOptions) { - if (acceptableOptions.includes(option)) { + if (!acceptableOptions.includes(option)) { return translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.FIELD.VALIDATION_ERROR, fieldName, translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.FIELD.MUST_HAVE_SPECIFIC_VALUES, acceptableOptions.toString())); From b44e7cd1e4f28d56db1e88df52aea023ad977cf8 Mon Sep 17 00:00:00 2001 From: Jorge Borras i Duarte Date: Mon, 17 Nov 2025 18:11:01 +0100 Subject: [PATCH 37/37] Logging reauth better --- .../src/webviews/FeedbackFormWebviewController.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts b/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts index a893a01a..e5a83fbe 100644 --- a/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts +++ b/packages/vscode-extension/src/webviews/FeedbackFormWebviewController.ts @@ -143,17 +143,19 @@ const handleSubmitFeedbackFormEvent = async (formData : FeedbackFormData, cssWeb // SERVER_ERROR (but proxy is running, a response was received) vsLogger.printTimestamp(); vsLogger.error(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_EXTERNAL_ERROR, response.status.toString(), response.statusText)); - vsLogger.error(''); // "Manual reauthentication is needed" proxy event if (response.status === ApplicationConstants.HTTP_RESPONSE_CODE.FORBIDDEN) { const responseBody : any = await response.json(); feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.MAIN_PAGE.HTML, cssWebviewUri); await sendErrorEventToHtml(translationService.getMessage(DEVASSIST_SERVICE.FEEDBACK_FORM.SUBMITTING_ERROR_REAUTHORIZE_TOAST, responseBody.error)); + vsLogger.error(responseBody.error); + } else { feedbackFormPanel!.webview.html = mediaService.generateHTMLContentFromMediaFile(FEEDBACK_FORM_FILE_NAMES.FAILURE_HTML, cssWebviewUri); } + vsLogger.error(''); } } catch (error) { // VSCODE ERROR, PROXY_NOT_LOADED, PROXY_ERROR, REQUEST_FORMATING_ERROR (Not even a response received)