From e062d3ee22cde6def24f400b2bafb5265e9a7d12 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 11:19:43 +0100 Subject: [PATCH 01/16] createCopyEOCWidget --- .../source/class/osparc/FlashMessenger.js | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index 1067c4f65700..cccc9724d3c5 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -86,7 +86,49 @@ qx.Class.define("osparc.FlashMessenger", { console.error(error); } const msg = this.extractMessage(error, defaultMessage); - return this.getInstance().logAs(msg, "ERROR", duration); + const flashMessage = this.getInstance().logAs(msg, "ERROR", duration); + error["supportId"] = "1234"; + if (error && error["supportId"]) { + flashMessage.addWidget(this.self().createCopyEOCWidget(error["supportId"])); + } + return flashMessage; + }, + + createCopyEOCWidget: function(supportId) { + const widget = new qx.ui.container.Composite(new qx.ui.layout.VBox(5)); + const showErrorLabel = new qx.ui.basic.Atom().set({ + label: this.tr("Show error code"), + icon: "@FontAwesome5Solid/chevron-right/10", + cursor: "pointer", + visibility: "visible", + }); + widget.add(showErrorLabel); + const hideErrorLabel = new qx.ui.basic.Atom().set({ + label: this.tr("Hide error code"), + icon: "@FontAwesome5Solid/chevron-down/10", + cursor: "pointer", + visibility: "exclude", + }); + widget.add(hideErrorLabel); + const errorLabel = new qx.ui.basic.Atom().set({ + label: this.tr("Show error code"), + icon: "@FontAwesome5Solid/chevron-down/10", + cursor: "pointer", + visibility: "exclude", + }); + showErrorLabel.addListener("tap", () => { + showErrorLabel.exclude(); + hideErrorLabel.show(); + errorLabel.show(); + }); + hideErrorLabel.addListener("tap", () => { + hideErrorLabel.exclude(); + errorLabel.exclude(); + showErrorLabel.show(); + }); + errorLabel.addListener("tap", () => osparc.utils.Utils.copyTextToClipboard(supportId)); + widget.add(errorLabel); + return widget; }, }, From f3f548eb994b5ad2cc7990191699b75354e82706 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 11:30:41 +0100 Subject: [PATCH 02/16] copy error code --- .../source/class/osparc/FlashMessenger.js | 19 +++++++++++-------- .../class/osparc/ui/message/FlashMessage.js | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index cccc9724d3c5..0b3449b8699b 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -95,27 +95,30 @@ qx.Class.define("osparc.FlashMessenger", { }, createCopyEOCWidget: function(supportId) { - const widget = new qx.ui.container.Composite(new qx.ui.layout.VBox(5)); + const widget = new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({ + paddingLeft: 10 + }); const showErrorLabel = new qx.ui.basic.Atom().set({ - label: this.tr("Show error code"), + label: qx.locale.Manager.tr("Show error code"), icon: "@FontAwesome5Solid/chevron-right/10", cursor: "pointer", visibility: "visible", }); widget.add(showErrorLabel); const hideErrorLabel = new qx.ui.basic.Atom().set({ - label: this.tr("Hide error code"), + label: qx.locale.Manager.tr("Hide error code"), icon: "@FontAwesome5Solid/chevron-down/10", cursor: "pointer", - visibility: "exclude", + visibility: "excluded", }); widget.add(hideErrorLabel); const errorLabel = new qx.ui.basic.Atom().set({ - label: this.tr("Show error code"), - icon: "@FontAwesome5Solid/chevron-down/10", + label: supportId, + icon: "@FontAwesome5Solid/copy/10", cursor: "pointer", - visibility: "exclude", + visibility: "excluded", }); + widget.add(errorLabel); showErrorLabel.addListener("tap", () => { showErrorLabel.exclude(); hideErrorLabel.show(); @@ -127,7 +130,6 @@ qx.Class.define("osparc.FlashMessenger", { showErrorLabel.show(); }); errorLabel.addListener("tap", () => osparc.utils.Utils.copyTextToClipboard(supportId)); - widget.add(errorLabel); return widget; }, }, @@ -191,6 +193,7 @@ qx.Class.define("osparc.FlashMessenger", { const wordCount = message.split(" ").length; duration = Math.max(5500, wordCount*500); // An average reader takes 300ms to read a word } + duration = 10000; if (duration !== 0) { qx.event.Timer.once(() => this.removeMessage(flashMessage), this, duration); } diff --git a/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js b/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js index d111984ad1e7..8af12cb9a505 100644 --- a/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js +++ b/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js @@ -31,7 +31,7 @@ qx.Class.define("osparc.ui.message.FlashMessage", { */ construct: function(message, level, duration) { this.base(arguments); - this._setLayout(new qx.ui.layout.VBox(15)); + this._setLayout(new qx.ui.layout.VBox(10)); this.set({ padding: 18, From 46589ddbff2e0c84d790b582a5ec2b591af0ba83 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 11:37:20 +0100 Subject: [PATCH 03/16] refactor --- .../source/class/osparc/FlashMessenger.js | 8 +------ .../class/osparc/ui/message/FlashMessage.js | 24 +++++++++---------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index 0b3449b8699b..47d00824ee3f 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -187,13 +187,7 @@ qx.Class.define("osparc.FlashMessenger", { } this.__displayedMessagesCount++; - let duration = flashMessage.getDuration(); - if (duration === null) { - const message = flashMessage.getMessage(); - const wordCount = message.split(" ").length; - duration = Math.max(5500, wordCount*500); // An average reader takes 300ms to read a word - } - duration = 10000; + const duration = flashMessage.getDuration(); if (duration !== 0) { qx.event.Timer.once(() => this.removeMessage(flashMessage), this, duration); } diff --git a/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js b/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js index 8af12cb9a505..91c07b2db871 100644 --- a/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js +++ b/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js @@ -48,14 +48,13 @@ qx.Class.define("osparc.ui.message.FlashMessage", { textColor: this.self().LOG_LEVEL_COLOR_MAP[level].color }); - if (message) { - this.setMessage(message); - } + this.setMessage(message); - // also support duration 0: the message won't be automatically removed - if (duration != null) { - this.setDuration(duration); + if ([null, undefined].includes(duration)) { + const wordCount = message.split(" ").length; + duration = Math.max(5500, wordCount*500); // An average reader takes 300ms to read a word } + this.setDuration(duration); this.getChildControl("closebutton"); }, @@ -68,13 +67,15 @@ qx.Class.define("osparc.ui.message.FlashMessage", { message: { check: "String", - nullable: true, - apply: "__applyMessage" + nullable: false, + apply: "__applyMessage", }, duration: { check: "Number", - nullable: true + init: null, + nullable: true, + event: "changeDuration", } }, @@ -142,10 +143,7 @@ qx.Class.define("osparc.ui.message.FlashMessage", { }, __applyMessage: function(value) { - const label = this.getChildControl("message"); - if (label) { - label.setValue(value); - } + this.getChildControl("message").setValue(value); }, addWidget: function(widget) { From cdf73adcd1da3639df7c52d6bb2c2efd90142187 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 11:43:12 +0100 Subject: [PATCH 04/16] clear timeout --- .../client/source/class/osparc/FlashMessenger.js | 12 +++++++++--- .../source/class/osparc/ui/message/FlashMessage.js | 1 - 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index 47d00824ee3f..60e73bffaafb 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -89,12 +89,12 @@ qx.Class.define("osparc.FlashMessenger", { const flashMessage = this.getInstance().logAs(msg, "ERROR", duration); error["supportId"] = "1234"; if (error && error["supportId"]) { - flashMessage.addWidget(this.self().createCopyEOCWidget(error["supportId"])); + flashMessage.addWidget(this.__createCopyEOCWidget(flashMessage, error["supportId"])); } return flashMessage; }, - createCopyEOCWidget: function(supportId) { + __createCopyEOCWidget: function(flashMessage, supportId) { const widget = new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({ paddingLeft: 10 }); @@ -123,6 +123,12 @@ qx.Class.define("osparc.FlashMessenger", { showErrorLabel.exclude(); hideErrorLabel.show(); errorLabel.show(); + + if (flashMessage.timer) { + // let the user close it + clearTimeout(flashMessage.timer); + delete flashMessage.timer; + } }); hideErrorLabel.addListener("tap", () => { hideErrorLabel.exclude(); @@ -189,7 +195,7 @@ qx.Class.define("osparc.FlashMessenger", { const duration = flashMessage.getDuration(); if (duration !== 0) { - qx.event.Timer.once(() => this.removeMessage(flashMessage), this, duration); + flashMessage.timer = setTimeout(() => this.removeMessage(flashMessage), duration); } }, diff --git a/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js b/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js index 91c07b2db871..c7a8f811dfec 100644 --- a/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js +++ b/services/static-webserver/client/source/class/osparc/ui/message/FlashMessage.js @@ -75,7 +75,6 @@ qx.Class.define("osparc.ui.message.FlashMessage", { check: "Number", init: null, nullable: true, - event: "changeDuration", } }, From 3a31976281df940cca47b8db58789c2eb0857ad0 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 11:45:18 +0100 Subject: [PATCH 05/16] minor --- .../client/source/class/osparc/FlashMessenger.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index 60e73bffaafb..8a0fd48332aa 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -87,7 +87,7 @@ qx.Class.define("osparc.FlashMessenger", { } const msg = this.extractMessage(error, defaultMessage); const flashMessage = this.getInstance().logAs(msg, "ERROR", duration); - error["supportId"] = "1234"; + error["supportId"] = "OEC:12346789"; if (error && error["supportId"]) { flashMessage.addWidget(this.__createCopyEOCWidget(flashMessage, error["supportId"])); } @@ -96,7 +96,7 @@ qx.Class.define("osparc.FlashMessenger", { __createCopyEOCWidget: function(flashMessage, supportId) { const widget = new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({ - paddingLeft: 10 + paddingLeft: 8 }); const showErrorLabel = new qx.ui.basic.Atom().set({ label: qx.locale.Manager.tr("Show error code"), From c917c97b620d2a0503002b18136363237e64c02d Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 11:45:46 +0100 Subject: [PATCH 06/16] last --- .../client/source/class/osparc/FlashMessenger.js | 1 - 1 file changed, 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index 8a0fd48332aa..c08fc2a11cad 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -87,7 +87,6 @@ qx.Class.define("osparc.FlashMessenger", { } const msg = this.extractMessage(error, defaultMessage); const flashMessage = this.getInstance().logAs(msg, "ERROR", duration); - error["supportId"] = "OEC:12346789"; if (error && error["supportId"]) { flashMessage.addWidget(this.__createCopyEOCWidget(flashMessage, error["supportId"])); } From 72817bf6d05febe83655998a241513d97a36c914 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 11:59:57 +0100 Subject: [PATCH 07/16] wording --- .../client/source/class/osparc/FlashMessenger.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index c08fc2a11cad..7348f758de10 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -98,14 +98,14 @@ qx.Class.define("osparc.FlashMessenger", { paddingLeft: 8 }); const showErrorLabel = new qx.ui.basic.Atom().set({ - label: qx.locale.Manager.tr("Show error code"), + label: qx.locale.Manager.tr("Show Support ID"), icon: "@FontAwesome5Solid/chevron-right/10", cursor: "pointer", visibility: "visible", }); widget.add(showErrorLabel); const hideErrorLabel = new qx.ui.basic.Atom().set({ - label: qx.locale.Manager.tr("Hide error code"), + label: qx.locale.Manager.tr("Hide Support ID"), icon: "@FontAwesome5Solid/chevron-down/10", cursor: "pointer", visibility: "excluded", From d3be679dabf5cc4ca30b13cf5f515a6003f08acf Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 12:51:49 +0100 Subject: [PATCH 08/16] minorDoc --- .../client/source/class/osparc/FlashMessenger.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index 7348f758de10..aa07878fc7f1 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -95,7 +95,8 @@ qx.Class.define("osparc.FlashMessenger", { __createCopyEOCWidget: function(flashMessage, supportId) { const widget = new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({ - paddingLeft: 8 + paddingLeft: 8, + paddingRight: 8, }); const showErrorLabel = new qx.ui.basic.Atom().set({ label: qx.locale.Manager.tr("Show Support ID"), @@ -111,6 +112,13 @@ qx.Class.define("osparc.FlashMessenger", { visibility: "excluded", }); widget.add(hideErrorLabel); + const minorDoc = new qx.ui.basic.Label().set({ + value: qx.locale.Manager.tr("If you contact support, please include this Support ID so we can quickly locate the issue."), + rich: true, + wrap: true, + visibility: "excluded", + }); + widget.add(minorDoc); const errorLabel = new qx.ui.basic.Atom().set({ label: supportId, icon: "@FontAwesome5Solid/copy/10", @@ -121,6 +129,7 @@ qx.Class.define("osparc.FlashMessenger", { showErrorLabel.addListener("tap", () => { showErrorLabel.exclude(); hideErrorLabel.show(); + minorDoc.show(); errorLabel.show(); if (flashMessage.timer) { @@ -130,9 +139,10 @@ qx.Class.define("osparc.FlashMessenger", { } }); hideErrorLabel.addListener("tap", () => { + showErrorLabel.show(); hideErrorLabel.exclude(); + minorDoc.exclude(); errorLabel.exclude(); - showErrorLabel.show(); }); errorLabel.addListener("tap", () => osparc.utils.Utils.copyTextToClipboard(supportId)); return widget; From 250c39f22db0c8cf48634cd3bf0aeaf48a8b788f Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 13:08:09 +0100 Subject: [PATCH 09/16] @pcrespov reword the reworded message --- .../src/servicelib/aiohttp/rest_middlewares.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py index 0fc11dda7a2a..54cd39a8fcc0 100644 --- a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py +++ b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py @@ -25,9 +25,7 @@ DEFAULT_API_VERSION = "v0" _FMSG_INTERNAL_ERROR_USER_FRIENDLY_WITH_OEC = ( - "We apologize for the inconvenience. " - "Our team has recorded the issue [SupportID={error_code}]. " - "If the issue persists please report it." + "We apologize for the inconvenience — the issue has been recorded, but please report it if it persists." ) From 21d6d419fc942fa60662c0b2b51280cf2384ff93 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 13:41:49 +0100 Subject: [PATCH 10/16] minor --- .../service-library/src/servicelib/aiohttp/rest_middlewares.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py index 54cd39a8fcc0..d5c4cadba59d 100644 --- a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py +++ b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py @@ -25,7 +25,8 @@ DEFAULT_API_VERSION = "v0" _FMSG_INTERNAL_ERROR_USER_FRIENDLY_WITH_OEC = ( - "We apologize for the inconvenience — the issue has been recorded, but please report it if it persists." + "We apologize for the inconvenience. " + "The issue has been recorded, but please report it if it persists." ) From 362a81d0f52ae54da528e676dc52174dca2ee710 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 19 Mar 2025 13:42:23 +0100 Subject: [PATCH 11/16] minor --- .../src/servicelib/aiohttp/rest_middlewares.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py index d5c4cadba59d..b48c68b43654 100644 --- a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py +++ b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py @@ -25,8 +25,8 @@ DEFAULT_API_VERSION = "v0" _FMSG_INTERNAL_ERROR_USER_FRIENDLY_WITH_OEC = ( - "We apologize for the inconvenience. " - "The issue has been recorded, but please report it if it persists." + "We apologize for the inconvenience. " + "The issue has been recorded, but please report it if it persists." ) From fef39e8235ed7ee292fcacc8da4e84f2ea57c790 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 20 Mar 2025 13:02:43 +0100 Subject: [PATCH 12/16] no but --- .../service-library/src/servicelib/aiohttp/rest_middlewares.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py index b48c68b43654..1d9741fd71fe 100644 --- a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py +++ b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py @@ -26,7 +26,7 @@ DEFAULT_API_VERSION = "v0" _FMSG_INTERNAL_ERROR_USER_FRIENDLY_WITH_OEC = ( "We apologize for the inconvenience. " - "The issue has been recorded, but please report it if it persists." + "The issue has been recorded, please report it if it persists." ) From b9cc607c60a4db98f6021e755c3d6a34ed3e9704 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 20 Mar 2025 13:03:03 +0100 Subject: [PATCH 13/16] show OEC and copy object to clipboard --- .../source/class/osparc/FlashMessenger.js | 62 +++++-------------- 1 file changed, 15 insertions(+), 47 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index aa07878fc7f1..4971779c5bec 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -88,64 +88,32 @@ qx.Class.define("osparc.FlashMessenger", { const msg = this.extractMessage(error, defaultMessage); const flashMessage = this.getInstance().logAs(msg, "ERROR", duration); if (error && error["supportId"]) { - flashMessage.addWidget(this.__createCopyEOCWidget(flashMessage, error["supportId"])); + flashMessage.addWidget(this.__createCopyEOCWidget(msg, error["supportId"])); } return flashMessage; }, - __createCopyEOCWidget: function(flashMessage, supportId) { - const widget = new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({ - paddingLeft: 8, - paddingRight: 8, - }); - const showErrorLabel = new qx.ui.basic.Atom().set({ - label: qx.locale.Manager.tr("Show Support ID"), - icon: "@FontAwesome5Solid/chevron-right/10", - cursor: "pointer", - visibility: "visible", - }); - widget.add(showErrorLabel); - const hideErrorLabel = new qx.ui.basic.Atom().set({ - label: qx.locale.Manager.tr("Hide Support ID"), - icon: "@FontAwesome5Solid/chevron-down/10", - cursor: "pointer", - visibility: "excluded", - }); - widget.add(hideErrorLabel); - const minorDoc = new qx.ui.basic.Label().set({ - value: qx.locale.Manager.tr("If you contact support, please include this Support ID so we can quickly locate the issue."), - rich: true, - wrap: true, - visibility: "excluded", - }); - widget.add(minorDoc); + __createCopyEOCWidget: function(message, supportId) { const errorLabel = new qx.ui.basic.Atom().set({ label: supportId, icon: "@FontAwesome5Solid/copy/10", + iconPosition: "right", + gap: 8, cursor: "pointer", - visibility: "excluded", + alignX: "center", + allowGrowX: true, }); - widget.add(errorLabel); - showErrorLabel.addListener("tap", () => { - showErrorLabel.exclude(); - hideErrorLabel.show(); - minorDoc.show(); - errorLabel.show(); - - if (flashMessage.timer) { - // let the user close it - clearTimeout(flashMessage.timer); - delete flashMessage.timer; + errorLabel.addListener("tap", () => { + const dataToClipboard = { + message, + supportId, + timestamp: new Date().toString(), + url: window.location.href, + studyId: osparc.store.Store.getInstance().getCurrentStudy() ? osparc.store.Store.getInstance().getCurrentStudy().getUuid() : "", } + osparc.utils.Utils.copyTextToClipboard(JSON.stringify(dataToClipboard)); }); - hideErrorLabel.addListener("tap", () => { - showErrorLabel.show(); - hideErrorLabel.exclude(); - minorDoc.exclude(); - errorLabel.exclude(); - }); - errorLabel.addListener("tap", () => osparc.utils.Utils.copyTextToClipboard(supportId)); - return widget; + return errorLabel; }, }, From 4a362b72e0f2b84007410f66f5a5acfd947d9bf3 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 20 Mar 2025 13:45:54 +0100 Subject: [PATCH 14/16] aesthetics --- .../client/source/class/osparc/FlashMessenger.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/FlashMessenger.js b/services/static-webserver/client/source/class/osparc/FlashMessenger.js index 4971779c5bec..d9c886fd5066 100644 --- a/services/static-webserver/client/source/class/osparc/FlashMessenger.js +++ b/services/static-webserver/client/source/class/osparc/FlashMessenger.js @@ -88,12 +88,13 @@ qx.Class.define("osparc.FlashMessenger", { const msg = this.extractMessage(error, defaultMessage); const flashMessage = this.getInstance().logAs(msg, "ERROR", duration); if (error && error["supportId"]) { - flashMessage.addWidget(this.__createCopyEOCWidget(msg, error["supportId"])); + flashMessage.addWidget(this.__createCopyOECWidget(msg, error["supportId"])); + flashMessage.setDuration(flashMessage.getDuration()*2); } return flashMessage; }, - __createCopyEOCWidget: function(message, supportId) { + __createCopyOECWidget: function(message, supportId) { const errorLabel = new qx.ui.basic.Atom().set({ label: supportId, icon: "@FontAwesome5Solid/copy/10", @@ -101,7 +102,7 @@ qx.Class.define("osparc.FlashMessenger", { gap: 8, cursor: "pointer", alignX: "center", - allowGrowX: true, + allowGrowX: false, }); errorLabel.addListener("tap", () => { const dataToClipboard = { @@ -109,7 +110,7 @@ qx.Class.define("osparc.FlashMessenger", { supportId, timestamp: new Date().toString(), url: window.location.href, - studyId: osparc.store.Store.getInstance().getCurrentStudy() ? osparc.store.Store.getInstance().getCurrentStudy().getUuid() : "", + studyId: osparc.store.Store.getInstance().getCurrentStudy() || "", } osparc.utils.Utils.copyTextToClipboard(JSON.stringify(dataToClipboard)); }); From bb55f64945dbb186746b05e2363934a39bf57dba Mon Sep 17 00:00:00 2001 From: Pedro Crespo-Valero <32402063+pcrespov@users.noreply.github.com> Date: Thu, 20 Mar 2025 18:28:01 +0100 Subject: [PATCH 15/16] fixes test --- .../src/servicelib/aiohttp/rest_middlewares.py | 4 ++-- .../tests/aiohttp/test_rest_middlewares.py | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py index 1d9741fd71fe..4847389b7195 100644 --- a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py +++ b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py @@ -24,7 +24,7 @@ from .typing_extension import Handler, Middleware DEFAULT_API_VERSION = "v0" -_FMSG_INTERNAL_ERROR_USER_FRIENDLY_WITH_OEC = ( +_FMSG_INTERNAL_ERROR_USER_FRIENDLY = ( "We apologize for the inconvenience. " "The issue has been recorded, please report it if it persists." ) @@ -51,7 +51,7 @@ def _process_and_raise_unexpected_error(request: web.BaseRequest, err: Exception "request.path": f"{request.path}", } - user_error_msg = _FMSG_INTERNAL_ERROR_USER_FRIENDLY_WITH_OEC.format( + user_error_msg = _FMSG_INTERNAL_ERROR_USER_FRIENDLY.format( error_code=error_code ) http_error = create_http_error( diff --git a/packages/service-library/tests/aiohttp/test_rest_middlewares.py b/packages/service-library/tests/aiohttp/test_rest_middlewares.py index 0adfa6cf80dc..0bd501066d9b 100644 --- a/packages/service-library/tests/aiohttp/test_rest_middlewares.py +++ b/packages/service-library/tests/aiohttp/test_rest_middlewares.py @@ -13,11 +13,9 @@ import pytest from aiohttp import web from aiohttp.test_utils import TestClient -from common_library.error_codes import parse_error_codes from common_library.json_serialization import json_dumps from servicelib.aiohttp import status from servicelib.aiohttp.rest_middlewares import ( - _FMSG_INTERNAL_ERROR_USER_FRIENDLY_WITH_OEC, envelope_middleware_factory, error_middleware_factory, ) @@ -234,14 +232,6 @@ async def test_raised_unhandled_exception( assert not data assert error - # user friendly message with OEC reference - assert "OEC" in error["message"] - parsed_oec = parse_error_codes(error["message"]).pop() - assert ( - _FMSG_INTERNAL_ERROR_USER_FRIENDLY_WITH_OEC.format(error_code=parsed_oec) - == error["message"] - ) - # avoids details assert not error.get("errors") assert not error.get("logs") From 525cb29cb38f53317e2f390c396e820a72298647 Mon Sep 17 00:00:00 2001 From: Pedro Crespo-Valero <32402063+pcrespov@users.noreply.github.com> Date: Thu, 20 Mar 2025 18:33:32 +0100 Subject: [PATCH 16/16] removes error-code from messages --- .../simcore_service_webserver/login/_constants.py | 4 +--- .../simcore_service_webserver/login/_registration.py | 12 +++++------- .../src/simcore_service_webserver/login/errors.py | 7 +++---- .../login/handlers_confirmation.py | 3 +-- .../login/handlers_registration.py | 4 ++-- .../simcore_service_webserver/users/_users_rest.py | 3 +-- .../simcore_service_webserver/wallets/_handlers.py | 10 +++++----- .../tests/unit/with_dbs/03/login/test_login_2fa.py | 6 ++---- 8 files changed, 20 insertions(+), 29 deletions(-) diff --git a/services/web/server/src/simcore_service_webserver/login/_constants.py b/services/web/server/src/simcore_service_webserver/login/_constants.py index 3743c981617a..cc10d6ed3407 100644 --- a/services/web/server/src/simcore_service_webserver/login/_constants.py +++ b/services/web/server/src/simcore_service_webserver/login/_constants.py @@ -1,9 +1,7 @@ from typing import Final MSG_2FA_CODE_SENT: Final[str] = "A code was sent by SMS to {phone_number}." -MSG_2FA_UNAVAILABLE_OEC: Final[str] = ( - "Two-factor authentication is temporarily unavailable. Please try again later. ({error_code})" -) +MSG_2FA_UNAVAILABLE: Final[str] = "Two-factor authentication is temporarily unavailable" MSG_ACTIVATED: Final[str] = "Your account has been activated." MSG_ACTIVATION_REQUIRED: Final[str] = ( "Please activate your account via the email we sent before logging in." diff --git a/services/web/server/src/simcore_service_webserver/login/_registration.py b/services/web/server/src/simcore_service_webserver/login/_registration.py index 2cbabf647060..0e924def7b18 100644 --- a/services/web/server/src/simcore_service_webserver/login/_registration.py +++ b/services/web/server/src/simcore_service_webserver/login/_registration.py @@ -1,7 +1,7 @@ -""" Core functionality and tools for user's registration +"""Core functionality and tools for user's registration - - registration code - - invitation code +- registration code +- invitation code """ import logging @@ -214,9 +214,7 @@ def _invitations_request_context(invitation_code: str) -> Iterator[URL]: except (ValidationError, InvalidInvitationError) as err: error_code = create_error_code(err) - user_error_msg = ( - f"Invalid invitation. {MSG_INVITATIONS_CONTACT_SUFFIX} [{error_code}]" - ) + user_error_msg = f"Invalid invitation. {MSG_INVITATIONS_CONTACT_SUFFIX}" _logger.exception( **create_troubleshotting_log_kwargs( @@ -233,7 +231,7 @@ def _invitations_request_context(invitation_code: str) -> Iterator[URL]: except InvitationsServiceUnavailableError as err: error_code = create_error_code(err) - user_error_msg = f"Unable to process your invitation since the invitations service is currently unavailable [{error_code}]" + user_error_msg = "Unable to process your invitation since the invitations service is currently unavailable" _logger.exception( **create_troubleshotting_log_kwargs( diff --git a/services/web/server/src/simcore_service_webserver/login/errors.py b/services/web/server/src/simcore_service_webserver/login/errors.py index 56588b87df68..835c971d312f 100644 --- a/services/web/server/src/simcore_service_webserver/login/errors.py +++ b/services/web/server/src/simcore_service_webserver/login/errors.py @@ -7,13 +7,12 @@ from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from ..errors import WebServerBaseError -from ._constants import MSG_2FA_UNAVAILABLE_OEC +from ._constants import MSG_2FA_UNAVAILABLE _logger = logging.getLogger(__name__) -class LoginError(WebServerBaseError, ValueError): - ... +class LoginError(WebServerBaseError, ValueError): ... class SendingVerificationSmsError(LoginError): @@ -32,7 +31,7 @@ async def wrapper(request: web.Request) -> web.StreamResponse: except (SendingVerificationSmsError, SendingVerificationEmailError) as exc: error_code = exc.error_code() - front_end_msg = MSG_2FA_UNAVAILABLE_OEC.format(error_code=error_code) + front_end_msg = MSG_2FA_UNAVAILABLE # in these cases I want to log the cause _logger.exception( **create_troubleshotting_log_kwargs( diff --git a/services/web/server/src/simcore_service_webserver/login/handlers_confirmation.py b/services/web/server/src/simcore_service_webserver/login/handlers_confirmation.py index 6ae9f3175110..f4b9bb755a8b 100644 --- a/services/web/server/src/simcore_service_webserver/login/handlers_confirmation.py +++ b/services/web/server/src/simcore_service_webserver/login/handlers_confirmation.py @@ -187,8 +187,7 @@ async def validate_confirmation_and_redirect(request: web.Request): error_code = create_error_code(err) user_error_msg = ( f"Sorry, we cannot confirm your {action}." - "Please try again in a few moments. " - f"If the problem persist please contact support attaching this code ({error_code})" + "Please try again in a few moments." ) _logger.exception( diff --git a/services/web/server/src/simcore_service_webserver/login/handlers_registration.py b/services/web/server/src/simcore_service_webserver/login/handlers_registration.py index 541218ae9975..e91556f4424b 100644 --- a/services/web/server/src/simcore_service_webserver/login/handlers_registration.py +++ b/services/web/server/src/simcore_service_webserver/login/handlers_registration.py @@ -274,7 +274,7 @@ async def register(request: web.Request): ) except Exception as err: # pylint: disable=broad-except error_code = create_error_code(err) - user_error_msg = f"{MSG_CANT_SEND_MAIL} [{error_code}]" + user_error_msg = MSG_CANT_SEND_MAIL _logger.exception( **create_troubleshotting_log_kwargs( @@ -416,7 +416,7 @@ async def register_phone(request: web.Request): except Exception as err: # pylint: disable=broad-except # Unhandled errors -> 503 error_code = create_error_code(err) - user_error_msg = f"Currently we cannot register phone numbers [{error_code}]" + user_error_msg = "Currently we cannot register phone numbers" _logger.exception( **create_troubleshotting_log_kwargs( diff --git a/services/web/server/src/simcore_service_webserver/users/_users_rest.py b/services/web/server/src/simcore_service_webserver/users/_users_rest.py index b83c33db6003..6b3f00ac1b07 100644 --- a/services/web/server/src/simcore_service_webserver/users/_users_rest.py +++ b/services/web/server/src/simcore_service_webserver/users/_users_rest.py @@ -59,8 +59,7 @@ MissingGroupExtraPropertiesForProductError: HttpErrorInfo( status.HTTP_503_SERVICE_UNAVAILABLE, "The product is not ready for use until the configuration is fully completed. " - "Please wait and try again. " - "If this issue persists, contact support indicating this support code: {error_code}.", + "Please wait and try again. ", ), } diff --git a/services/web/server/src/simcore_service_webserver/wallets/_handlers.py b/services/web/server/src/simcore_service_webserver/wallets/_handlers.py index cc2833ecfd27..22d085b90f1e 100644 --- a/services/web/server/src/simcore_service_webserver/wallets/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/wallets/_handlers.py @@ -97,7 +97,7 @@ async def wrapper(request: web.Request) -> web.StreamResponse: except BillingDetailsNotFoundError as exc: error_code = create_error_code(exc) - user_error_msg = f"{MSG_BILLING_DETAILS_NOT_DEFINED_ERROR} [{error_code}]" + user_error_msg = MSG_BILLING_DETAILS_NOT_DEFINED_ERROR _logger.exception( **create_troubleshotting_log_kwargs( @@ -155,10 +155,10 @@ async def create_wallet(request: web.Request): async def list_wallets(request: web.Request): req_ctx = WalletsRequestContext.model_validate(request) - wallets: list[ - WalletGetWithAvailableCredits - ] = await _api.list_wallets_with_available_credits_for_user( - app=request.app, user_id=req_ctx.user_id, product_name=req_ctx.product_name + wallets: list[WalletGetWithAvailableCredits] = ( + await _api.list_wallets_with_available_credits_for_user( + app=request.app, user_id=req_ctx.user_id, product_name=req_ctx.product_name + ) ) return envelope_json_response(wallets) diff --git a/services/web/server/tests/unit/with_dbs/03/login/test_login_2fa.py b/services/web/server/tests/unit/with_dbs/03/login/test_login_2fa.py index 30f05227ab26..588e95182b61 100644 --- a/services/web/server/tests/unit/with_dbs/03/login/test_login_2fa.py +++ b/services/web/server/tests/unit/with_dbs/03/login/test_login_2fa.py @@ -32,7 +32,7 @@ ) from simcore_service_webserver.login._constants import ( CODE_2FA_SMS_CODE_REQUIRED, - MSG_2FA_UNAVAILABLE_OEC, + MSG_2FA_UNAVAILABLE, ) from simcore_service_webserver.login.storage import AsyncpgStorage from simcore_service_webserver.products import products_web @@ -456,9 +456,7 @@ async def test_2fa_sms_failure_during_login( response, status.HTTP_503_SERVICE_UNAVAILABLE ) assert not data - assert error["errors"][0]["message"].startswith( - MSG_2FA_UNAVAILABLE_OEC[:10] - ) + assert error["errors"][0]["message"].startswith(MSG_2FA_UNAVAILABLE[:10]) # Expects logs like 'Failed while setting up 2FA code and sending SMS to 157XXXXXXXX3 [OEC:140392495277888]' assert f"{fake_user_phone_number[:3]}" in caplog.text