diff --git a/services/static-webserver/client/source/class/osparc/Application.js b/services/static-webserver/client/source/class/osparc/Application.js index 5a2e11883d3..8435f9e42ed 100644 --- a/services/static-webserver/client/source/class/osparc/Application.js +++ b/services/static-webserver/client/source/class/osparc/Application.js @@ -432,7 +432,7 @@ qx.Class.define("osparc.Application", { .then(data => { if (data.role.toLowerCase() === "guest") { // Logout a guest trying to access the Dashboard - osparc.auth.Manager.getInstance().logout(); + this.logout(); } else { this.__loadMainPage(); } @@ -564,18 +564,22 @@ qx.Class.define("osparc.Application", { * Resets session and restarts */ logout: function(forcedReason) { - if (forcedReason) { - osparc.FlashMessenger.getInstance().logAs(forcedReason, "WARNING", 0); - } else { - osparc.FlashMessenger.getInstance().logAs(this.tr("You are logged out"), "INFO"); - } const isLoggedIn = osparc.auth.Manager.getInstance().isLoggedIn(); if (isLoggedIn) { osparc.auth.Manager.getInstance().logout() - .finally(() => this.__closeAllAndToLoginPage()); + .finally(() => this.__loggedOut(forcedReason)); + } else { + this.__loggedOut(forcedReason); + } + }, + + __loggedOut: function(forcedReason) { + if (forcedReason) { + osparc.FlashMessenger.getInstance().logAs(forcedReason, "WARNING", 0); } else { - this.__closeAllAndToLoginPage(); + osparc.FlashMessenger.getInstance().logAs(this.tr("You are logged out"), "INFO"); } + this.__closeAllAndToLoginPage(); }, __closeAllAndToLoginPage: function() { 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 57ba202e98c..c5c94bdad10 100644 --- a/services/static-webserver/client/source/class/osparc/auth/Manager.js +++ b/services/static-webserver/client/source/class/osparc/auth/Manager.js @@ -212,10 +212,15 @@ qx.Class.define("osparc.auth.Manager", { "client_session_id": osparc.utils.Utils.getClientSessionID() } }; - return osparc.data.Resources.fetch("auth", "postLogout", params) - .then(data => this.fireEvent("loggedOut")) - .catch(error => console.log("already logged out")) - .finally(this.__logoutUser()); + const options = { + timeout: 5000, + timeoutRetries: 5 + }; + return osparc.data.Resources.fetch("auth", "postLogout", params, options) + .finally(() => { + this.__logoutUser(); + this.fireEvent("loggedOut"); + }); }, resetPasswordRequest: function(email, successCbk, failCbk, context) { diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ResourceFilter.js b/services/static-webserver/client/source/class/osparc/dashboard/ResourceFilter.js index 81e317dfb1c..18464aa3755 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceFilter.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceFilter.js @@ -180,7 +180,7 @@ qx.Class.define("osparc.dashboard.ResourceFilter", { }); - if (this.__tagButtons.length >= maxTags) { + if (this.__tagButtons.length > maxTags) { const showAllButton = new qx.ui.form.Button(this.tr("All Tags..."), "@FontAwesome5Solid/tags/20"); showAllButton.set({ appearance: "filter-toggle-button" diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js b/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js index 22860e3704b..a84549d1a5b 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js @@ -128,10 +128,10 @@ qx.Class.define("osparc.dashboard.ServiceBrowser", { this._hideLoadingPage(); const params = { url: { - "studyId": studyId + studyId } }; - osparc.data.Resources.fetch("studies", "delete", params, studyId); + osparc.data.Resources.fetch("studies", "delete", params); }; const isStudyCreation = true; this._startStudyById(studyId, openCB, cancelCB, isStudyCreation); 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 c60730c757b..0df2104e821 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js @@ -672,24 +672,24 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { limit: osparc.dashboard.ResourceBrowserBase.PAGINATED_STUDIES, } }; - const nextPageParams = this.__getNextPageParams(); if (nextPageParams) { params.url.offset = nextPageParams.offset; params.url.limit = nextPageParams.limit; } - const options = { - resolveWResponse: true - }; - const requestParams = this.__getRequestParams(); Object.entries(requestParams).forEach(([key, value]) => { params.url[key] = value; }); + + const options = { + resolveWResponse: true + }; + if ("text" in requestParams) { - return osparc.data.Resources.fetch("studies", "getPageSearch", params, undefined, options); + return osparc.data.Resources.fetch("studies", "getPageSearch", params, options); } - return osparc.data.Resources.fetch("studies", "getPage", params, undefined, options); + return osparc.data.Resources.fetch("studies", "getPage", params, options); }, invalidateStudies: function() { @@ -1220,7 +1220,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { studyId } }; - osparc.data.Resources.fetch("studies", "delete", params, studyId); + osparc.data.Resources.fetch("studies", "delete", params); }; const isStudyCreation = true; this._startStudyById(studyId, openCB, cancelCB, isStudyCreation); @@ -1545,7 +1545,10 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { "studyId": studyData["uuid"] } }; - const fetchPromise = osparc.data.Resources.fetch("studies", "duplicate", params, null, {"pollTask": true}); + const options = { + pollTask: true + }; + const fetchPromise = osparc.data.Resources.fetch("studies", "duplicate", params, options); const interval = 1000; const pollTasks = osparc.data.PollTasks.getInstance(); pollTasks.createPollingTask(fetchPromise, interval) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js b/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js index 951166b354b..2b200676688 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js @@ -145,10 +145,10 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", { this._hideLoadingPage(); const params = { url: { - "studyId": studyId + studyId } }; - osparc.data.Resources.fetch("studies", "delete", params, studyId); + osparc.data.Resources.fetch("studies", "delete", params); }; const isStudyCreation = true; this._startStudyById(studyId, openCB, cancelCB, isStudyCreation); diff --git a/services/static-webserver/client/source/class/osparc/data/Resources.js b/services/static-webserver/client/source/class/osparc/data/Resources.js index ac1cddbdda5..9460f522a71 100644 --- a/services/static-webserver/client/source/class/osparc/data/Resources.js +++ b/services/static-webserver/client/source/class/osparc/data/Resources.js @@ -113,6 +113,7 @@ qx.Class.define("osparc.data.Resources", { "studies": { useCache: true, idField: "uuid", + deleteId: "studyId", endpoints: { get: { method: "GET", @@ -711,6 +712,7 @@ qx.Class.define("osparc.data.Resources", { "tokens": { useCache: true, idField: "service", + deleteId: "service", endpoints: { get: { method: "GET", @@ -1200,8 +1202,9 @@ qx.Class.define("osparc.data.Resources", { * TAGS */ "tags": { - idField: "id", useCache: true, + idField: "id", + deleteId: "tagId", endpoints: { get: { method: "GET", @@ -1244,22 +1247,24 @@ qx.Class.define("osparc.data.Resources", { * @param {String} resource Name of the resource as defined in the static property 'resources'. * @param {String} endpoint Name of the endpoint. Several endpoints can be defined for each resource. * @param {Object} params Object containing the parameters for the url and for the body of the request, under the properties 'url' and 'data', respectively. - * @param {String} deleteId When deleting, id of the element that needs to be deleted from the cache. - * @param {Object} options Collections of options + * @param {Object} options Collections of options (pollTask, resolveWResponse, timeout, timeoutRetries) */ - fetch: function(resource, endpoint, params = {}, deleteId, options = {}) { + fetch: function(resource, endpoint, params = {}, options = {}) { return new Promise((resolve, reject) => { if (this.self().resources[resource] == null) { reject(Error(`Error while fetching ${resource}: the resource is not defined`)); } const resourceDefinition = this.self().resources[resource]; - const res = new osparc.io.rest.Resource(resourceDefinition.endpoints); - + const res = new osparc.io.rest.Resource(resourceDefinition.endpoints, options.timeout); if (!res.includesRoute(endpoint)) { reject(Error(`Error while fetching ${resource}: the endpoint is not defined`)); } + const sendRequest = () => { + res[endpoint](params.url || null, params.data || null); + } + res.addListenerOnce(endpoint + "Success", e => { const response = e.getRequest().getResponse(); const endpointDef = resourceDefinition.endpoints[endpoint]; @@ -1276,7 +1281,8 @@ qx.Class.define("osparc.data.Resources", { } } if (useCache) { - if (endpoint.includes("delete")) { + if (endpoint.includes("delete") && resourceDefinition["deleteId"] && resourceDefinition["deleteId"] in params.url) { + const deleteId = params.url[resourceDefinition["deleteId"]]; this.__removeCached(resource, deleteId); } else if (endpointDef.method === "POST" && options.pollTask !== true) { this.__addCached(resource, data); @@ -1297,7 +1303,15 @@ qx.Class.define("osparc.data.Resources", { } }, this); - res.addListenerOnce(endpoint + "Error", e => { + res.addListener(endpoint + "Error", e => { + if (e.getPhase() === "timeout") { + if (options.timeout && options.timeoutRetries) { + options.timeoutRetries--; + sendRequest(); + return; + } + } + let message = null; let status = null; if (e.getData().error) { @@ -1330,7 +1344,7 @@ qx.Class.define("osparc.data.Resources", { if ("status" in err && err.status === 401) { // Unauthorized again, the cookie might have expired. // We can assume that all calls after this will respond with 401, so bring the user ot the login page. - qx.core.Init.getApplication().logout(qx.locale.Manager.tr("You were logged out")); + qx.core.Init.getApplication().logout(qx.locale.Manager.tr("You were logged out. Your cookie might have expired.")); } }); } @@ -1345,7 +1359,7 @@ qx.Class.define("osparc.data.Resources", { reject(err); }); - res[endpoint](params.url || null, params.data || null); + sendRequest(); }); }, @@ -1362,7 +1376,7 @@ qx.Class.define("osparc.data.Resources", { const options = { resolveWResponse: true }; - this.fetch(resource, endpoint, params, null, options) + this.fetch(resource, endpoint, params, options) .then(resp => { // sometimes there is a kind of a double "data" const meta = ("_meta" in resp["data"]) ? resp["data"]["_meta"] : resp["_meta"]; @@ -1426,14 +1440,14 @@ qx.Class.define("osparc.data.Resources", { * @param {Object} params Object containing the parameters for the url and for the body of the request, under the properties 'url' and 'data', respectively. * @param {Boolean} useCache Whether the cache has to be used. If false, an API call will be issued. */ - get: function(resource, params, useCache = true) { + get: function(resource, params = {}, useCache = true, options = {}) { if (useCache) { const stored = this.__getCached(resource); if (stored) { return Promise.resolve(stored); } } - return this.fetch(resource, "get", params || {}); + return this.fetch(resource, "get", params, options); }, /** @@ -1489,14 +1503,14 @@ qx.Class.define("osparc.data.Resources", { statics: { API: "/v0", - fetch: function(resource, endpoint, params, deleteId, options = {}) { - return this.getInstance().fetch(resource, endpoint, params, deleteId, options); + fetch: function(resource, endpoint, params, options = {}) { + return this.getInstance().fetch(resource, endpoint, params, options); }, getOne: function(resource, params, id, useCache) { return this.getInstance().getOne(resource, params, id, useCache); }, - get: function(resource, params, useCache) { - return this.getInstance().get(resource, params, useCache); + get: function(resource, params, useCache, options) { + return this.getInstance().get(resource, params, useCache, options); }, getServiceUrl: function(key, version) { 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 7302f93ee7e..f84d436ffd5 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js +++ b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js @@ -232,7 +232,10 @@ qx.Class.define("osparc.desktop.MainPage", { }, data: data["studyData"] }; - const fetchPromise = osparc.data.Resources.fetch("studies", "postToTemplate", params, null, {"pollTask": true}); + const options = { + pollTask: true + }; + const fetchPromise = osparc.data.Resources.fetch("studies", "postToTemplate", params, options); const pollTasks = osparc.data.PollTasks.getInstance(); const interval = 1000; pollTasks.createPollingTask(fetchPromise, interval) diff --git a/services/static-webserver/client/source/class/osparc/desktop/StudyEditorIdlingTracker.js b/services/static-webserver/client/source/class/osparc/desktop/StudyEditorIdlingTracker.js index 88b12f3669e..3ffac59d401 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/StudyEditorIdlingTracker.js +++ b/services/static-webserver/client/source/class/osparc/desktop/StudyEditorIdlingTracker.js @@ -101,17 +101,18 @@ qx.Class.define("osparc.desktop.StudyEditorIdlingTracker", { const timeSinceInactivityThreshold = this.__idlingTime - inactivityThresholdT; if (timeSinceInactivityThreshold % this.self().INACTIVITY_REQUEST_PERIOD_S == 0) { // check if backend reports project as inactive - osparc.data.Resources.fetch("studies", "getInactivity", { + const params = { url: { studyId: this.__studyUuid } - }).then(data => { - if (data["is_inactive"]) { - this.__displayFlashMessage(flashMessageDurationS); - } - }).catch(err => { - console.error(err); - }); + }; + osparc.data.Resources.fetch("studies", "getInactivity", params) + .then(data => { + if (data["is_inactive"]) { + this.__displayFlashMessage(flashMessageDurationS); + } + }) + .catch(err => console.error(err)); } } }; diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/TransactionsTableModel.js b/services/static-webserver/client/source/class/osparc/desktop/credits/TransactionsTableModel.js index 203187d1d0a..530f532c0ca 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/TransactionsTableModel.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/TransactionsTableModel.js @@ -53,14 +53,16 @@ qx.Class.define("osparc.desktop.credits.TransactionsTableModel", { members: { // overridden _loadRowCount() { - osparc.data.Resources.fetch("payments", "get", { + const params = { url: { limit: 1, offset: 0 } - }, undefined, { + }; + const options = { resolveWResponse: true - }) + }; + osparc.data.Resources.fetch("payments", "get", params, options) .then(({ data: resp }) => { this._onRowCountLoaded(resp["_meta"].total) }) diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/UsageTableModel.js b/services/static-webserver/client/source/class/osparc/desktop/credits/UsageTableModel.js index 5859d5f7dce..1c1cd2e94f5 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/UsageTableModel.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/UsageTableModel.js @@ -77,7 +77,7 @@ qx.Class.define("osparc.desktop.credits.UsageTableModel", { // overridden _loadRowCount() { const endpoint = this.getWalletId() == null ? "get" : "getWithWallet" - osparc.data.Resources.fetch("resourceUsage", endpoint, { + const params = { url: { walletId: this.getWalletId(), limit: 1, @@ -89,9 +89,11 @@ qx.Class.define("osparc.desktop.credits.UsageTableModel", { null, orderBy: JSON.stringify(this.getOrderBy()) } - }, undefined, { + }; + const options = { resolveWResponse: true - }) + }; + osparc.data.Resources.fetch("resourceUsage", endpoint, params, options) .then(resp => { this._onRowCountLoaded(resp["_meta"].total) }) diff --git a/services/static-webserver/client/source/class/osparc/desktop/preferences/pages/TokensPage.js b/services/static-webserver/client/source/class/osparc/desktop/preferences/pages/TokensPage.js index 2067f393ea8..cd19c6f73df 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/preferences/pages/TokensPage.js +++ b/services/static-webserver/client/source/class/osparc/desktop/preferences/pages/TokensPage.js @@ -296,7 +296,7 @@ qx.Class.define("osparc.desktop.preferences.pages.TokensPage", { service } }; - osparc.data.Resources.fetch("tokens", "delete", params, service) + osparc.data.Resources.fetch("tokens", "delete", params) .then(() => this.__rebuildTokensList()) .catch(err => console.error(err)); } diff --git a/services/static-webserver/client/source/class/osparc/form/tag/TagItem.js b/services/static-webserver/client/source/class/osparc/form/tag/TagItem.js index 6d708797d8a..7e79bb54bf3 100644 --- a/services/static-webserver/client/source/class/osparc/form/tag/TagItem.js +++ b/services/static-webserver/client/source/class/osparc/form/tag/TagItem.js @@ -229,7 +229,7 @@ qx.Class.define("osparc.form.tag.TagItem", { tagId: this.getId() } }; - osparc.data.Resources.fetch("tags", "delete", params, this.getId()) + osparc.data.Resources.fetch("tags", "delete", params) .then(() => this.fireEvent("deleteTag")) .catch(console.error) .finally(() => deleteButton.setFetching(false)); diff --git a/services/static-webserver/client/source/class/osparc/info/CommentsList.js b/services/static-webserver/client/source/class/osparc/info/CommentsList.js index bba201fca14..d0b605132c8 100644 --- a/services/static-webserver/client/source/class/osparc/info/CommentsList.js +++ b/services/static-webserver/client/source/class/osparc/info/CommentsList.js @@ -105,7 +105,7 @@ qx.Class.define("osparc.info.CommentsList", { const options = { resolveWResponse: true }; - return osparc.data.Resources.fetch("studyComments", "getPage", params, undefined, options); + return osparc.data.Resources.fetch("studyComments", "getPage", params, options); }, __addComments: function(comments) { diff --git a/services/static-webserver/client/source/class/osparc/io/rest/AbstractResource.js b/services/static-webserver/client/source/class/osparc/io/rest/AbstractResource.js index b9fb0cd9950..2fcc25e653c 100644 --- a/services/static-webserver/client/source/class/osparc/io/rest/AbstractResource.js +++ b/services/static-webserver/client/source/class/osparc/io/rest/AbstractResource.js @@ -55,7 +55,6 @@ qx.Class.define("osparc.io.rest.AbstractResource", { }, members:{ - /** * Default implementation * Can be overriden in subclass to change prefix @@ -64,7 +63,4 @@ qx.Class.define("osparc.io.rest.AbstractResource", { return osparc.io.rest.AbstractResource.API + tail; } } - - - }); diff --git a/services/static-webserver/client/source/class/osparc/io/rest/Resource.js b/services/static-webserver/client/source/class/osparc/io/rest/Resource.js index c701c15756e..6a68dc551a4 100644 --- a/services/static-webserver/client/source/class/osparc/io/rest/Resource.js +++ b/services/static-webserver/client/source/class/osparc/io/rest/Resource.js @@ -21,13 +21,19 @@ qx.Class.define("osparc.io.rest.Resource", { extend: qx.io.rest.Resource, - construct: function(description) { + construct: function(description, timeout = 0) { this.base(arguments, description); this.configureRequest(request => { const headers = [{ key: "Accept", value: "application/json" + }, { + key: "Content-Type", + value: "application/json" + }, { + key: "X-Simcore-Products-Name", + value: qx.core.Environment.get("product.name") }]; if (this.AUTHENTICATION !== undefined && this.AUTHENTICATION !== null) { @@ -36,10 +42,9 @@ qx.Class.define("osparc.io.rest.Resource", { headers.forEach(item => request.setRequestHeader(item.key, item.value)); - request.setRequestHeader("Content-Type", "application/json"); - - const productName = qx.core.Environment.get("product.name"); - request.setRequestHeader("X-Simcore-Products-Name", productName); + if (timeout) { + request.setTimeout(timeout); + } }); }, diff --git a/services/static-webserver/client/source/class/osparc/store/Store.js b/services/static-webserver/client/source/class/osparc/store/Store.js index 1c03b85ea44..3a180897e28 100644 --- a/services/static-webserver/client/source/class/osparc/store/Store.js +++ b/services/static-webserver/client/source/class/osparc/store/Store.js @@ -430,11 +430,11 @@ qx.Class.define("osparc.store.Store", { deleteStudy: function(studyId) { const params = { url: { - "studyId": studyId + studyId } }; return new Promise((resolve, reject) => { - osparc.data.Resources.fetch("studies", "delete", params, studyId) + osparc.data.Resources.fetch("studies", "delete", params) .then(() => { this.remove("studies", "uuid", studyId); resolve(); diff --git a/services/static-webserver/client/source/class/osparc/study/Utils.js b/services/static-webserver/client/source/class/osparc/study/Utils.js index ef8d53c173c..dab2bd53bd8 100644 --- a/services/static-webserver/client/source/class/osparc/study/Utils.js +++ b/services/static-webserver/client/source/class/osparc/study/Utils.js @@ -165,7 +165,10 @@ qx.Class.define("osparc.study.Utils", { createStudyAndPoll: function(params) { return new Promise((resolve, reject) => { - const fetchPromise = osparc.data.Resources.fetch("studies", "postNewStudy", params, null, {"pollTask": true}); + const options = { + pollTask: true + }; + const fetchPromise = osparc.data.Resources.fetch("studies", "postNewStudy", params, options); const pollTasks = osparc.data.PollTasks.getInstance(); const interval = 1000; pollTasks.createPollingTask(fetchPromise, interval) @@ -204,7 +207,10 @@ qx.Class.define("osparc.study.Utils", { }, data: minStudyData }; - const fetchPromise = osparc.data.Resources.fetch("studies", "postNewStudyFromTemplate", params, null, {"pollTask": true}); + const options = { + pollTask: true + }; + const fetchPromise = osparc.data.Resources.fetch("studies", "postNewStudyFromTemplate", params, options); const pollTasks = osparc.data.PollTasks.getInstance(); const interval = 1000; pollTasks.createPollingTask(fetchPromise, interval)