diff --git a/services/static-webserver/client/source/class/osparc/Application.js b/services/static-webserver/client/source/class/osparc/Application.js index 8435f9e42ed..c5f760188e5 100644 --- a/services/static-webserver/client/source/class/osparc/Application.js +++ b/services/static-webserver/client/source/class/osparc/Application.js @@ -63,14 +63,13 @@ qx.Class.define("osparc.Application", { return; } - const intlTelInput = osparc.wrapper.IntlTelInput.getInstance(); - intlTelInput.init(); + // libs + osparc.wrapper.IntlTelInput.getInstance().init(); + osparc.wrapper.Three.getInstance().init(); - const threejs = osparc.wrapper.Three.getInstance(); - threejs.init(); - - const announcementsTracker = osparc.announcement.Tracker.getInstance(); - announcementsTracker.startTracker(); + // trackers + osparc.announcement.Tracker.getInstance().startTracker(); + osparc.WindowSizeTracker.getInstance().startTracker(); const webSocket = osparc.wrapper.WebSocket.getInstance(); webSocket.addListener("connect", () => osparc.WatchDog.getInstance().setOnline(true)); @@ -467,6 +466,7 @@ qx.Class.define("osparc.Application", { __loadMainPage: function(studyId = null) { // logged in + osparc.WindowSizeTracker.getInstance().evaluateTooSmallDialog(); osparc.data.Resources.getOne("profile") .then(profile => { if (profile) { diff --git a/services/static-webserver/client/source/class/osparc/TooSmallDialog.js b/services/static-webserver/client/source/class/osparc/TooSmallDialog.js new file mode 100644 index 00000000000..b60219820f6 --- /dev/null +++ b/services/static-webserver/client/source/class/osparc/TooSmallDialog.js @@ -0,0 +1,82 @@ +/* ************************************************************************ + + osparc - the simcore frontend + + https://osparc.io + + Copyright: + 2024 IT'IS Foundation, https://itis.swiss + + License: + MIT: https://opensource.org/licenses/MIT + + Authors: + * Odei Maiz (odeimaiz) + +************************************************************************ */ + +qx.Class.define("osparc.TooSmallDialog", { + extend: osparc.ui.window.SingletonWindow, + + construct: function() { + this.base(arguments, "too-small-logout", this.tr("Window too small")); + + this.set({ + layout: new qx.ui.layout.VBox(10), + contentPadding: 15, + modal: true, + showMaximize: false, + showMinimize: false, + }); + + this.__buildLayout(); + }, + + statics: { + openWindow: function() { + const orgsWindow = new osparc.TooSmallDialog(); + orgsWindow.center(); + orgsWindow.open(); + return orgsWindow; + } + }, + + members: { + __buildLayout: function() { + const message = this.__createMessage(); + this.add(message); + + // if the user is logged in, let them log out, the user menu might be unreachable + const logoutButton = this.__createLogoutButton(); + this.add(logoutButton); + }, + + __createMessage: function() { + const introText = this.tr("The application can't perform in such a small window."); + const introLabel = new qx.ui.basic.Label(introText); + return introLabel; + }, + + __createLogoutButton: function() { + const layout = new qx.ui.container.Composite(new qx.ui.layout.HBox().set({ + alignX: "right" + })); + + const button = new qx.ui.form.Button().set({ + allowGrowX: false + }); + button.addListener("execute", () => qx.core.Init.getApplication().logout()); + layout.add(button); + + const authData = osparc.auth.Data.getInstance(); + authData.bind("loggedIn", layout, "visibility", { + converter: isLoggedIn => isLoggedIn ? "visible" : "excluded" + }); + authData.bind("guest", button, "label", { + converter: isGuest => isGuest ? this.tr("Exit") : this.tr("Log out") + }); + + return layout; + }, + } +}); diff --git a/services/static-webserver/client/source/class/osparc/WindowSizeTracker.js b/services/static-webserver/client/source/class/osparc/WindowSizeTracker.js index 671ec04e865..569120b3472 100644 --- a/services/static-webserver/client/source/class/osparc/WindowSizeTracker.js +++ b/services/static-webserver/client/source/class/osparc/WindowSizeTracker.js @@ -40,7 +40,7 @@ qx.Class.define("osparc.WindowSizeTracker", { }, tooSmall: { - check: [null, "shortText", "longText"], // display short message, long one or none + check: [null, "logout", "shortText", "longText"], init: null, nullable: true, apply: "__applyTooSmall" @@ -48,12 +48,14 @@ qx.Class.define("osparc.WindowSizeTracker", { }, statics: { + WIDTH_LOGOUT_BREAKPOINT: 600, + WIDTH_COMPACT_BREAKPOINT: 1100, WIDTH_BREAKPOINT: 1180, // - iPad Pro 11" 1194x834 inclusion HEIGHT_BREAKPOINT: 720, // - iPad Pro 11" 1194x834 inclusion - WIDTH_COMPACT_BREAKPOINT: 1100 }, members: { + __tooSmallDialog: null, __lastRibbonMessage: null, startTracker: function() { @@ -69,8 +71,12 @@ qx.Class.define("osparc.WindowSizeTracker", { this.setCompactVersion(width < this.self().WIDTH_COMPACT_BREAKPOINT); - if (width < this.self().WIDTH_BREAKPOINT || height < this.self().HEIGHT_BREAKPOINT) { - this.setTooSmall(width < this.self().WIDTH_COMPACT_BREAKPOINT ? "shortText" : "longText"); + if (width < this.self().WIDTH_LOGOUT_BREAKPOINT) { + this.setTooSmall("logout"); + } else if (width < this.self().WIDTH_COMPACT_BREAKPOINT) { + this.setTooSmall("shortText"); + } else if (width < this.self().WIDTH_BREAKPOINT) { + this.setTooSmall("longText"); } else { this.setTooSmall(null); } @@ -89,7 +95,7 @@ qx.Class.define("osparc.WindowSizeTracker", { } let notification = null; - if (tooSmall === "shortText") { + if (tooSmall === "logout" || tooSmall === "shortText") { notification = new osparc.notification.RibbonNotification(null, "smallWindow", true); } else if (tooSmall === "longText") { const text = this.__getLongText(true); @@ -97,6 +103,8 @@ qx.Class.define("osparc.WindowSizeTracker", { } osparc.notification.RibbonNotifications.getInstance().addNotification(notification); this.__lastRibbonMessage = notification; + + this.evaluateTooSmallDialog(); }, __getLongText: function() { @@ -111,6 +119,21 @@ qx.Class.define("osparc.WindowSizeTracker", { osparc.notification.RibbonNotifications.getInstance().removeNotification(this.__lastRibbonMessage); this.__lastRibbonMessage = null; } + }, + + evaluateTooSmallDialog: function() { + const tooSmall = this.getTooSmall(); + if (tooSmall === "logout") { + if (this.__tooSmallDialog) { + this.__tooSmallDialog.center(); + this.__tooSmallDialog.open(); + } else { + this.__tooSmallDialog = osparc.TooSmallDialog.openWindow(); + this.__tooSmallDialog.addListener("close", () => this.__tooSmallDialog = null, this); + } + } else if (this.__tooSmallDialog) { + this.__tooSmallDialog.close(); + } } } }); diff --git a/services/static-webserver/client/source/class/osparc/auth/Data.js b/services/static-webserver/client/source/class/osparc/auth/Data.js index 013a6f8ee51..276de264a4c 100644 --- a/services/static-webserver/client/source/class/osparc/auth/Data.js +++ b/services/static-webserver/client/source/class/osparc/auth/Data.js @@ -58,7 +58,8 @@ qx.Class.define("osparc.auth.Data", { auth: { init: null, nullable: true, - check: "osparc.io.request.authentication.Token" + check: "osparc.io.request.authentication.Token", + apply: "__applyAuth" }, /** @@ -104,10 +105,21 @@ qx.Class.define("osparc.auth.Data", { nullable: true, check: "Date", event: "changeExpirationDate" + }, + + loggedIn: { + check: "Boolean", + nullable: false, + init: false, + event: "changeLoggedIn", } }, members: { + __applyAuth: function(auth) { + this.setLoggedIn(auth !== null && auth instanceof osparc.io.request.authentication.Token); + }, + __applyRole: function(role) { if (role && ["user", "tester", "product_owner", "admin"].includes(role)) { this.setGuest(false); diff --git a/services/static-webserver/client/source/class/osparc/auth/Manager.js b/services/static-webserver/client/source/class/osparc/auth/Manager.js index c5c94bdad10..d45f7ce15a5 100644 --- a/services/static-webserver/client/source/class/osparc/auth/Manager.js +++ b/services/static-webserver/client/source/class/osparc/auth/Manager.js @@ -26,23 +26,10 @@ qx.Class.define("osparc.auth.Manager", { extend: qx.core.Object, type: "singleton", - /* - ***************************************************************************** - EVENTS - ***************************************************************************** - */ - events: { "loggedOut": "qx.event.type.Event" }, - - /* - ***************************************************************************** - MEMBERS - ***************************************************************************** - */ - members: { register: function(userData) { const params = { @@ -130,11 +117,7 @@ qx.Class.define("osparc.auth.Manager", { }, isLoggedIn: function() { - // TODO: how to store this locally?? See http://www.qooxdoo.org/devel/pages/data_binding/stores.html#offline-store - // TODO: check if expired?? - // TODO: request server if token is still valid (e.g. expired, etc) - const auth = osparc.auth.Data.getInstance().getAuth(); - return auth !== null && auth instanceof osparc.io.request.authentication.Token; + return osparc.auth.Data.getInstance().isLoggedIn(); }, /* diff --git a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js index 44fab7818ee..bc22291e7bc 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js @@ -170,6 +170,10 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { }, __reloadFolders: function() { + if (!osparc.auth.Manager.getInstance().isLoggedIn()) { + return; + } + if (osparc.utils.DisabledPlugins.isFoldersEnabled()) { const folderId = this.getCurrentFolderId(); const workspaceId = this.getCurrentWorkspaceId(); @@ -186,7 +190,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { }, __reloadStudies: function() { - if (this._loadingResourcesBtn.isFetching()) { + if (this._loadingResourcesBtn.isFetching() || !osparc.auth.Manager.getInstance().isLoggedIn()) { return; } const workspaceId = this.getCurrentWorkspaceId(); diff --git a/services/static-webserver/client/source/class/osparc/data/model/Study.js b/services/static-webserver/client/source/class/osparc/data/model/Study.js index 2d4633dd584..912f838486f 100644 --- a/services/static-webserver/client/source/class/osparc/data/model/Study.js +++ b/services/static-webserver/client/source/class/osparc/data/model/Study.js @@ -443,6 +443,39 @@ qx.Class.define("osparc.data.model.Study", { }); }, + __getFoldersPath: function(childId, foldersPath = []) { + foldersPath.unshift(childId); + const childFolder = osparc.store.Folders.getInstance().getFolder(childId); + if (childFolder) { + const parentFolder = osparc.store.Folders.getInstance().getFolder(childFolder.getParentFolderId()); + if (parentFolder) { + this.__getFoldersPath(parentFolder.getFolderId(), foldersPath); + } + } + return foldersPath; + }, + + getLocationString: function() { + const location = []; + + if (this.getWorkspaceId()) { + const workspace = osparc.store.Workspaces.getInstance().getWorkspace(this.getWorkspaceId()); + location.push(workspace.getName()); + } else { + location.push(qx.locale.Manager.tr("My Workspace")); + } + + const foldersPathIds = this.__getFoldersPath(this.getFolderId()); + foldersPathIds.forEach(folderId => { + const folder = osparc.store.Folders.getInstance().getFolder(folderId); + if (folder) { + location.push(folder.getName()); + } + }); + + return location.join(" / "); + }, + // Used for updating some node data through the "nodeUpdated" websocket event nodeUpdated: function(nodeUpdatedData) { const studyId = nodeUpdatedData["project_id"]; diff --git a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js index f84d436ffd5..d2b72acfdcc 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js +++ b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js @@ -54,7 +54,6 @@ qx.Class.define("osparc.desktop.MainPage", { this._add(navBar); // Some resources request before building the main stack - osparc.WindowSizeTracker.getInstance().startTracker(); osparc.MaintenanceTracker.getInstance().startTracker(); osparc.CookieExpirationTracker.getInstance().startTracker(); osparc.NewUITracker.getInstance().startTracker(); diff --git a/services/static-webserver/client/source/class/osparc/info/StudyLarge.js b/services/static-webserver/client/source/class/osparc/info/StudyLarge.js index d058f584aca..3351ed0fc96 100644 --- a/services/static-webserver/client/source/class/osparc/info/StudyLarge.js +++ b/services/static-webserver/client/source/class/osparc/info/StudyLarge.js @@ -189,6 +189,16 @@ qx.Class.define("osparc.info.StudyLarge", { }; } + if (osparc.utils.DisabledPlugins.isFoldersEnabled() && !this.__isTemplate) { + const pathLabel = new qx.ui.basic.Label(); + pathLabel.setValue(this.getStudy().getLocationString()); + extraInfo["LOCATION"] = { + label: this.tr("Location:"), + view: pathLabel, + action: null + }; + } + return extraInfo; }, diff --git a/services/static-webserver/client/source/class/osparc/info/StudyUtils.js b/services/static-webserver/client/source/class/osparc/info/StudyUtils.js index 0e10bc93d1f..95ea7f20b7f 100644 --- a/services/static-webserver/client/source/class/osparc/info/StudyUtils.js +++ b/services/static-webserver/client/source/class/osparc/info/StudyUtils.js @@ -299,7 +299,12 @@ qx.Class.define("osparc.info.StudyUtils", { inline: true, column: 0, row: 6, - } + }, + LOCATION: { + inline: true, + column: 0, + row: 7, + }, }; const grid = new qx.ui.layout.Grid(15, 5); diff --git a/services/static-webserver/client/source/class/osparc/viewer/MainPage.js b/services/static-webserver/client/source/class/osparc/viewer/MainPage.js index 073d7d249ef..1586023b062 100644 --- a/services/static-webserver/client/source/class/osparc/viewer/MainPage.js +++ b/services/static-webserver/client/source/class/osparc/viewer/MainPage.js @@ -29,7 +29,6 @@ qx.Class.define("osparc.viewer.MainPage", { navBar.populateLayout(); this._add(navBar); - osparc.WindowSizeTracker.getInstance().startTracker(); osparc.MaintenanceTracker.getInstance().startTracker(); const nodeViewer = new osparc.viewer.NodeViewer(studyId, viewerNodeId); diff --git a/services/static-webserver/client/source/resource/osparc/S4LEngine_ComingSoon.html b/services/static-webserver/client/source/resource/osparc/S4LEngine_ComingSoon.html index e45e9bc2d79..3b40620bd6e 100644 --- a/services/static-webserver/client/source/resource/osparc/S4LEngine_ComingSoon.html +++ b/services/static-webserver/client/source/resource/osparc/S4LEngine_ComingSoon.html @@ -9,7 +9,7 @@ position: fixed; top: 0; left: 0; - /* Preserve aspet ratio */ + /* Preserve aspect ratio */ min-width: 100%; min-height: 100%; }