From 87ce7544ecf6c082d4ddd84fd07a7039784f5ce5 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Mon, 6 Oct 2025 16:59:48 +0200 Subject: [PATCH 01/11] let ellipsis work --- .../client/source/class/osparc/support/ConversationListItem.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js b/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js index ab88649bfad7..45dd7cd3ace1 100644 --- a/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js +++ b/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js @@ -27,6 +27,9 @@ qx.Class.define("osparc.support.ConversationListItem", { // decorate this.getChildControl("thumbnail").setDecorator("circled"); + this.getChildControl("title").set({ + rich: false, // let ellipsis work + }); this.getChildControl("subtitle").set({ textColor: "text-disabled", }); From 315af666f243ffdbd1257eb309d67137f25fb62f Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Mon, 6 Oct 2025 16:59:58 +0200 Subject: [PATCH 02/11] wider support center --- .../client/source/class/osparc/support/SupportCenter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/support/SupportCenter.js b/services/static-webserver/client/source/class/osparc/support/SupportCenter.js index c13997267df9..76bde6c257ed 100644 --- a/services/static-webserver/client/source/class/osparc/support/SupportCenter.js +++ b/services/static-webserver/client/source/class/osparc/support/SupportCenter.js @@ -51,7 +51,7 @@ qx.Class.define("osparc.support.SupportCenter", { }, statics: { - WINDOW_WIDTH: 430, + WINDOW_WIDTH: 450, WINDOW_HEIGHT: 700, REQUEST_CALL_MESSAGE: "Dear Support,\nI would like to make an appointment for a support call.", From 2c5f013fee04db795275640ac9bf4e737db94b8a Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Mon, 6 Oct 2025 17:00:06 +0200 Subject: [PATCH 03/11] rename --- .../client/source/class/osparc/desktop/StudyEditor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js b/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js index 773af71ce609..2aab56d6e683 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js +++ b/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js @@ -288,7 +288,7 @@ qx.Class.define("osparc.desktop.StudyEditor", { }, this); study.listenToChanges(); // this includes the listener on the workbench and ui - study.addListener("projectDocumentChanged", e => this.projectDocumentChanged(e.getData()), this); + study.addListener("projectDocumentChanged", e => this.__projectDocumentChanged(e.getData()), this); if (osparc.utils.DisabledPlugins.isRTCEnabled()) { this.__listenToProjectDocument(); @@ -998,7 +998,7 @@ qx.Class.define("osparc.desktop.StudyEditor", { /** * @param {JSON Patch} data It will soon be used to patch the project document https://datatracker.ietf.org/doc/html/rfc6902 */ - projectDocumentChanged: function(patchData) { + __projectDocumentChanged: function(patchData) { patchData["userGroupId"] = osparc.auth.Data.getInstance().getGroupId(); // avoid echo loop if (this.__blockUpdates) { From 6016d67ef34379f238ffcea58da5d5f704488f9f Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Mon, 6 Oct 2025 18:15:53 +0200 Subject: [PATCH 04/11] __fetchFirstAndLastMessages --- .../class/osparc/data/model/Conversation.js | 47 ++++++++++++------- .../osparc/store/ConversationsSupport.js | 24 ++++++---- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/data/model/Conversation.js b/services/static-webserver/client/source/class/osparc/data/model/Conversation.js index 6f59640c9e14..30a4d2b56822 100644 --- a/services/static-webserver/client/source/class/osparc/data/model/Conversation.js +++ b/services/static-webserver/client/source/class/osparc/data/model/Conversation.js @@ -45,7 +45,7 @@ qx.Class.define("osparc.data.model.Conversation", { this.__listenToConversationMessageWS(); if (conversationData.type === "SUPPORT") { - this.__fetchLastMessage(); + this.__fetchFirstAndLastMessages(); } }, @@ -132,6 +132,13 @@ qx.Class.define("osparc.data.model.Conversation", { event: "changeNameAlias", }, + firstMessage: { + check: "Object", + nullable: true, + init: null, + event: "changeFirstMessage", + }, + lastMessage: { check: "Object", nullable: true, @@ -154,7 +161,7 @@ qx.Class.define("osparc.data.model.Conversation", { }, members: { - __fetchLastMessagePromise: null, + __fetchingFirstAndLastMessage: null, __nextRequestParams: null, __messages: null, @@ -200,24 +207,30 @@ qx.Class.define("osparc.data.model.Conversation", { }); }, - __fetchLastMessage: function() { - if (this.__fetchLastMessagePromise) { - return this.__fetchLastMessagePromise; + __fetchFirstAndLastMessages: function() { + if (this.__fetchingFirstAndLastMessage) { + return this.__fetchingFirstAndLastMessage; } - let promise = osparc.store.ConversationsSupport.getInstance().fetchLastMessage(this.getConversationId()); - promise - .then(lastMessage => { - this.addMessage(lastMessage); - promise = null; - return lastMessage; + this.__fetchingFirstAndLastMessage = true; + osparc.store.ConversationsSupport.getInstance().fetchLastMessage(this.getConversationId()) + .then(resp => { + const messages = resp["data"]; + if (messages.length) { + this.addMessage(messages[0]); + this.setLastMessage(messages[0]); + } + // fetch first message only if there is more than one message + if (resp["_meta"]["total"] === 1) { + this.setFirstMessage(messages[0]); + } else if (resp["_meta"]["total"] > 1) { + osparc.store.ConversationsSupport.getInstance().fetchFirstMessage(this.getConversationId(), resp["_meta"]) + .then(firstMessage => this.setFirstMessage(firstMessage)); + } + return null; }) - .finally(() => { - this.__fetchLastMessagePromise = null; - }); - - this.__fetchLastMessagePromise = promise; - return promise; + .catch(err => osparc.FlashMessenger.logError(err)) + .finally(() => this.__fetchingFirstAndLastMessage = null); }, amIOwner: function() { diff --git a/services/static-webserver/client/source/class/osparc/store/ConversationsSupport.js b/services/static-webserver/client/source/class/osparc/store/ConversationsSupport.js index 53a2150bbbb2..5d266f9e1608 100644 --- a/services/static-webserver/client/source/class/osparc/store/ConversationsSupport.js +++ b/services/static-webserver/client/source/class/osparc/store/ConversationsSupport.js @@ -154,15 +154,21 @@ qx.Class.define("osparc.store.ConversationsSupport", { limit: 1, } }; - return osparc.data.Resources.fetch("conversationsSupport", "getMessagesPage", params) - .then(messagesData => { - if (messagesData && messagesData.length) { - const lastMessage = messagesData[0]; - this.__addMessageToConversation(conversationId, lastMessage); - return lastMessage; - } - return null; - }); + const options = { + resolveWResponse: true + }; + return osparc.data.Resources.fetch("conversationsSupport", "getMessagesPage", params, options); + }, + + fetchFirstMessage: function(conversationId, conversationPaginationMetadata) { + const params = { + url: { + conversationId, + offset: Math.max(0, conversationPaginationMetadata["total"] - 1), + limit: 1, + } + }; + return osparc.data.Resources.fetch("conversationsSupport", "getMessagesPage", params); }, postMessage: function(conversationId, message) { From c11ab1c68c0ab40af6df42033f215ff5b9d563d2 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Mon, 6 Oct 2025 19:10:05 +0200 Subject: [PATCH 05/11] setFirstMessage --- .../client/source/class/osparc/data/model/Conversation.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/data/model/Conversation.js b/services/static-webserver/client/source/class/osparc/data/model/Conversation.js index 30a4d2b56822..f09ae798c51f 100644 --- a/services/static-webserver/client/source/class/osparc/data/model/Conversation.js +++ b/services/static-webserver/client/source/class/osparc/data/model/Conversation.js @@ -225,7 +225,11 @@ qx.Class.define("osparc.data.model.Conversation", { this.setFirstMessage(messages[0]); } else if (resp["_meta"]["total"] > 1) { osparc.store.ConversationsSupport.getInstance().fetchFirstMessage(this.getConversationId(), resp["_meta"]) - .then(firstMessage => this.setFirstMessage(firstMessage)); + .then(firstMessages => { + if (firstMessages.length) { + this.setFirstMessage(firstMessages[0]); + } + }); } return null; }) From 2d423f67f4930281a22cfb7322f3446524b9dcb1 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Mon, 6 Oct 2025 19:10:17 +0200 Subject: [PATCH 06/11] minor --- .../source/class/osparc/store/ConversationsSupport.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/store/ConversationsSupport.js b/services/static-webserver/client/source/class/osparc/store/ConversationsSupport.js index 5d266f9e1608..89f849bf68b9 100644 --- a/services/static-webserver/client/source/class/osparc/store/ConversationsSupport.js +++ b/services/static-webserver/client/source/class/osparc/store/ConversationsSupport.js @@ -140,13 +140,6 @@ qx.Class.define("osparc.store.ConversationsSupport", { }, fetchLastMessage: function(conversationId) { - if ( - conversationId in this.__conversationsCached && - this.__conversationsCached[conversationId].getLastMessage() - ) { - return Promise.resolve(this.__conversationsCached[conversationId].getLastMessage()); - } - const params = { url: { conversationId, From e4cefc8f65671c4432d5fd1311572ad1d08dc277 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Mon, 6 Oct 2025 19:11:00 +0200 Subject: [PATCH 07/11] subSubtitle --- .../osparc/support/ConversationListItem.js | 39 +++++++++++++++++-- .../source/class/osparc/ui/list/ListItem.js | 29 +++++++++++++- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js b/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js index 45dd7cd3ace1..fc0ee5e26ded 100644 --- a/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js +++ b/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js @@ -31,6 +31,10 @@ qx.Class.define("osparc.support.ConversationListItem", { rich: false, // let ellipsis work }); this.getChildControl("subtitle").set({ + // textColor: "text-disabled", + rich: false, // let ellipsis work + }); + this.getChildControl("sub-subtitle").set({ textColor: "text-disabled", }); }, @@ -51,14 +55,18 @@ qx.Class.define("osparc.support.ConversationListItem", { this.__populateWithLastMessage(); conversation.addListener("changeLastMessage", this.__populateWithLastMessage, this); + + this.__populateWithFirstMessage(); + conversation.addListener("changeFirstMessage", this.__populateWithFirstMessage, this); }, __populateWithLastMessage: function() { - const lastMessage = this.getConversation().getLastMessage(); + const conversation = this.getConversation(); + const lastMessage = conversation.getLastMessage(); if (lastMessage) { const date = osparc.utils.Utils.formatDateAndTime(new Date(lastMessage.created)); this.set({ - subtitle: date, + role: date, }); const userGroupId = lastMessage.userGroupId; osparc.store.Users.getInstance().getUser(userGroupId) @@ -66,11 +74,34 @@ qx.Class.define("osparc.support.ConversationListItem", { if (user) { this.set({ thumbnail: user.getThumbnail(), - subtitle: user.getLabel() + " - " + date, + subtitle: user.getLabel() + ": " + lastMessage["content"], + }); + } + }); + } + }, + + __populateWithFirstMessage: function() { + const conversation = this.getConversation(); + const firstMessage = conversation.getFirstMessage(); + if (firstMessage) { + const userGroupId = firstMessage.userGroupId; + osparc.store.Users.getInstance().getUser(userGroupId) + .then(user => { + if (user) { + const amISupporter = osparc.store.Groups.getInstance().amIASupportUser(); + let subSubtitle = "Started"; + if (amISupporter) { + subSubtitle += " by " + user.getLabel(); + } + const date = osparc.utils.Utils.formatDateAndTime(new Date(firstMessage.created)); + subSubtitle += " on " + date; + this.set({ + subSubtitle, }); } }); } }, - } + }, }); diff --git a/services/static-webserver/client/source/class/osparc/ui/list/ListItem.js b/services/static-webserver/client/source/class/osparc/ui/list/ListItem.js index 257c7d3185c2..19bb4d2473a0 100644 --- a/services/static-webserver/client/source/class/osparc/ui/list/ListItem.js +++ b/services/static-webserver/client/source/class/osparc/ui/list/ListItem.js @@ -108,6 +108,12 @@ qx.Class.define("osparc.ui.list.ListItem", { nullable : true }, + subSubtitle: { + check : "String", + apply : "__applySubSubtitle", + nullable : true + }, + role: { check : "String", apply : "__applyRole", @@ -146,7 +152,7 @@ qx.Class.define("osparc.ui.list.ListItem", { this._add(control, { row: 0, column: 0, - rowSpan: 2 + rowSpan: 3 }); break; case "title": @@ -183,6 +189,17 @@ qx.Class.define("osparc.ui.list.ListItem", { column: 1 }); break; + case "sub-subtitle": + control = new qx.ui.basic.Label().set({ + font: "text-12", + selectable: true, + rich: true, + }); + this._add(control, { + row: 2, + column: 1 + }); + break; case "role": control = new qx.ui.basic.Label().set({ font: "text-13", @@ -191,7 +208,7 @@ qx.Class.define("osparc.ui.list.ListItem", { this._add(control, { row: 0, column: 2, - rowSpan: 2 + rowSpan: 3 }); break; } @@ -247,6 +264,14 @@ qx.Class.define("osparc.ui.list.ListItem", { label.setValue(value); }, + __applySubSubtitle: function(value) { + if (value === null) { + return; + } + const label = this.getChildControl("sub-subtitle"); + label.setValue(value); + }, + __applyRole: function(value) { if (value === null) { return; From 7a7072953bb46d46c1dae3f4cbc17f4dbb2bc0ff Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Tue, 7 Oct 2025 10:42:38 +0200 Subject: [PATCH 08/11] minor --- .../client/source/class/osparc/support/Conversation.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/support/Conversation.js b/services/static-webserver/client/source/class/osparc/support/Conversation.js index 6bb15a6384e2..f8c891185056 100644 --- a/services/static-webserver/client/source/class/osparc/support/Conversation.js +++ b/services/static-webserver/client/source/class/osparc/support/Conversation.js @@ -155,7 +155,9 @@ qx.Class.define("osparc.support.Conversation", { if (showLayout) { this.__populateShareProjectCB(); const currentStudy = osparc.store.Store.getInstance().getCurrentStudy(); - currentStudy.addListener("changeAccessRights", () => this.__populateShareProjectCB(), this); + if (currentStudy) { + currentStudy.addListener("changeAccessRights", () => this.__populateShareProjectCB(), this); + } } }, From b825f80ab8dae2acb112473daed7e654fbaa322b Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Tue, 7 Oct 2025 10:50:25 +0200 Subject: [PATCH 09/11] show project id --- .../source/class/osparc/support/ConversationPage.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/support/ConversationPage.js b/services/static-webserver/client/source/class/osparc/support/ConversationPage.js index fd6381b3ba09..6d190dfa9cbd 100644 --- a/services/static-webserver/client/source/class/osparc/support/ConversationPage.js +++ b/services/static-webserver/client/source/class/osparc/support/ConversationPage.js @@ -249,6 +249,11 @@ qx.Class.define("osparc.support.ConversationPage", { if (extraContext && Object.keys(extraContext).length) { const ticketIdLabel = createExtraContextLabel(`Ticket ID: ${osparc.utils.Utils.uuidToShort(conversation.getConversationId())}`); extraContextLayout.add(ticketIdLabel); + const contextProjectId = conversation.getContextProjectId(); + if (contextProjectId) { + const projectIdLabel = createExtraContextLabel(`Project ID: ${osparc.utils.Utils.uuidToShort(contextProjectId)}`); + extraContextLayout.add(projectIdLabel); + } if (amISupporter) { const fogbugzLink = conversation.getFogbugzLink(); if (fogbugzLink) { @@ -260,12 +265,6 @@ qx.Class.define("osparc.support.ConversationPage", { }); extraContextLayout.add(fogbugzLabel); } - const contextProjectId = conversation.getContextProjectId(); - if (contextProjectId) { - const projectIdLabel = createExtraContextLabel(`Project ID: ${osparc.utils.Utils.uuidToShort(contextProjectId)}`); - extraContextLayout.add(projectIdLabel); - } - } } }; From 23c66a6d24016fae6c245b2868d8a8cdf1d6a816 Mon Sep 17 00:00:00 2001 From: Odei Maiz <33152403+odeimaiz@users.noreply.github.com> Date: Tue, 7 Oct 2025 11:00:54 +0200 Subject: [PATCH 10/11] Update services/static-webserver/client/source/class/osparc/support/ConversationListItem.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../client/source/class/osparc/support/ConversationListItem.js | 1 - 1 file changed, 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js b/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js index fc0ee5e26ded..d605405d07bd 100644 --- a/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js +++ b/services/static-webserver/client/source/class/osparc/support/ConversationListItem.js @@ -31,7 +31,6 @@ qx.Class.define("osparc.support.ConversationListItem", { rich: false, // let ellipsis work }); this.getChildControl("subtitle").set({ - // textColor: "text-disabled", rich: false, // let ellipsis work }); this.getChildControl("sub-subtitle").set({ From 00f3e66b5e867d1db86ac823bc6744051a6b0197 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Tue, 7 Oct 2025 11:26:07 +0200 Subject: [PATCH 11/11] extend ListItemWithMenu --- .../osparc/ui/list/CollaboratorListItem.js | 49 ++----------------- 1 file changed, 3 insertions(+), 46 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/ui/list/CollaboratorListItem.js b/services/static-webserver/client/source/class/osparc/ui/list/CollaboratorListItem.js index 78b6aec28f97..211b126b7d68 100644 --- a/services/static-webserver/client/source/class/osparc/ui/list/CollaboratorListItem.js +++ b/services/static-webserver/client/source/class/osparc/ui/list/CollaboratorListItem.js @@ -16,7 +16,7 @@ ************************************************************************ */ qx.Class.define("osparc.ui.list.CollaboratorListItem", { - extend: osparc.ui.list.ListItem, + extend: osparc.ui.list.ListItemWithMenu, properties: { collabType: { @@ -30,20 +30,6 @@ qx.Class.define("osparc.ui.list.CollaboratorListItem", { nullable: true }, - accessRights: { - check: "Object", - apply: "__applyAccessRights", - event: "changeAccessRights", - nullable: true - }, - - showOptions: { - check: "Boolean", - apply: "__applyShowOptions", - event: "changeShowOptions", - nullable: true - }, - resourceType : { check: "String", event: "changeResourceType", @@ -103,31 +89,6 @@ qx.Class.define("osparc.ui.list.CollaboratorListItem", { return roleInfo; }, - _createChildControlImpl: function(id) { - let control; - switch (id) { - case "options": { - const iconSize = 25; - control = new qx.ui.form.MenuButton().set({ - maxWidth: iconSize, - maxHeight: iconSize, - alignX: "center", - alignY: "middle", - icon: "@FontAwesome5Solid/ellipsis-v/"+(iconSize-11), - focusable: false - }); - this._add(control, { - row: 0, - column: 3, - rowSpan: 2 - }); - break; - } - } - - return control || this.base(arguments, id); - }, - // overridden _applyTitle: function(value) { if (value === null) { @@ -175,7 +136,8 @@ qx.Class.define("osparc.ui.list.CollaboratorListItem", { } }, - __applyAccessRights: function(value) { + // overridden + _applyAccessRights: function(value) { if (value === null) { return; } @@ -278,10 +240,5 @@ qx.Class.define("osparc.ui.list.CollaboratorListItem", { return menu; }, - - __applyShowOptions: function(value) { - const optionsMenu = this.getChildControl("options"); - optionsMenu.setVisibility(value ? "visible" : "excluded"); - } } });