diff --git a/services/static-webserver/client/source/class/osparc/dashboard/FolderHeader.js b/services/static-webserver/client/source/class/osparc/dashboard/ContainerHeader.js
similarity index 68%
rename from services/static-webserver/client/source/class/osparc/dashboard/FolderHeader.js
rename to services/static-webserver/client/source/class/osparc/dashboard/ContainerHeader.js
index bd4582fd0fc..5322e8e8d67 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/FolderHeader.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ContainerHeader.js
@@ -20,7 +20,7 @@
*
*/
-qx.Class.define("osparc.dashboard.FolderHeader", {
+qx.Class.define("osparc.dashboard.ContainerHeader", {
extend: qx.ui.core.Widget,
construct: function() {
@@ -31,17 +31,21 @@ qx.Class.define("osparc.dashboard.FolderHeader", {
}));
},
- events: {
- "changeCurrentFolderId": "qx.event.type.Data"
- },
-
properties: {
+ currentWorkspaceId: {
+ check: "Number",
+ nullable: true,
+ init: null,
+ event: "changeCurrentWorkspaceId",
+ apply: "__buildBreadcrumbs"
+ },
+
currentFolderId: {
check: "Number",
nullable: true,
init: null,
event: "changeCurrentFolderId",
- apply: "__applyCurrentFolderId"
+ apply: "__buildBreadcrumbs"
}
},
@@ -55,24 +59,10 @@ qx.Class.define("osparc.dashboard.FolderHeader", {
}));
this._addAt(control, 0, {flex: 1});
break;
- case "permissions-info": {
- control = new qx.ui.container.Composite(new qx.ui.layout.HBox().set({
- alignY: "middle"
- })).set({
- paddingRight: 14
- });
- this._addAt(control, 1);
- break;
- }
}
return control || this.base(arguments, id);
},
- __applyCurrentFolderId: function() {
- this.__buildBreadcrumbs();
- this.__populatePermissions();
- },
-
__buildBreadcrumbs: function() {
const breadcrumbsLayout = this.getChildControl("breadcrumbs-layout");
breadcrumbsLayout.removeAll();
@@ -110,14 +100,38 @@ qx.Class.define("osparc.dashboard.FolderHeader", {
return this.__createFolderButton(currentFolder);
},
+ __createRootButton: function(workspaceId) {
+ let rootButton = null;
+ if (workspaceId) {
+ if (workspaceId === -1) {
+ rootButton = new qx.ui.form.Button(this.tr("Shared Workspaces"), osparc.store.Workspaces.iconPath());
+ } else {
+ const workspace = osparc.store.Workspaces.getWorkspace(workspaceId);
+ rootButton = new qx.ui.form.Button(workspace.getName(), osparc.store.Workspaces.iconPath());
+ }
+ rootButton.addListener("execute", () => this.set({
+ currentWorkspaceId: workspaceId,
+ currentFolderId: null,
+ }));
+ } else {
+ rootButton = new qx.ui.form.Button(this.tr("My Workspace"), "@FontAwesome5Solid/home/14");
+ rootButton.addListener("execute", () => this.set({
+ currentWorkspaceId: null,
+ currentFolderId: null,
+ }));
+ }
+ return rootButton;
+ },
+
__createFolderButton: function(folder) {
let folderButton = null;
if (folder) {
folderButton = new qx.ui.form.Button(folder.getName(), "@FontAwesome5Solid/folder/14");
+ folderButton.addListener("execute", () => this.fireDataEvent("changeCurrentFolderId", folder ? folder.getFolderId() : null), this);
} else {
- folderButton = new qx.ui.form.Button(this.tr("Home"), "@FontAwesome5Solid/home/14");
+ const workspaceId = this.getCurrentWorkspaceId();
+ folderButton = this.__createRootButton(workspaceId);
}
- folderButton.addListener("execute", () => this.fireDataEvent("changeCurrentFolderId", folder ? folder.getFolderId() : null), this);
folderButton.set({
backgroundColor: "transparent",
textColor: "text",
@@ -128,22 +142,6 @@ qx.Class.define("osparc.dashboard.FolderHeader", {
__createArrow: function() {
return new qx.ui.basic.Label("/");
- },
-
- __populatePermissions: function() {
- const permissionsLayout = this.getChildControl("permissions-info");
- permissionsLayout.removeAll();
-
- if (this.getCurrentFolderId()) {
- const currentFolder = osparc.store.Folders.getInstance().getFolder(this.getCurrentFolderId());
- const ar = currentFolder.getMyAccessRights();
- const permissions = ar["read"] + ar["write"] + ar["delete"];
- const roleTitle = new qx.ui.basic.Label().set({
- value: osparc.data.Roles.FOLDERS[permissions].label
- });
- permissionsLayout.add(roleTitle);
- permissionsLayout.add(osparc.data.Roles.createRolesFolderInfo(false));
- }
}
}
});
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js b/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js
index 82ccea53e3d..effe47c25c4 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js
@@ -167,7 +167,7 @@ qx.Class.define("osparc.dashboard.Dashboard", {
const preResourcePromises = [];
const store = osparc.store.Store.getInstance();
preResourcePromises.push(store.getAllGroupsAndMembers());
- preResourcePromises.push(osparc.service.Store.getServicesLatest(false));
+ preResourcePromises.push(osparc.store.Services.getServicesLatest(false));
if (permissions.canDo("study.tag")) {
preResourcePromises.push(osparc.data.Resources.get("tags"));
}
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/FolderButtonItem.js b/services/static-webserver/client/source/class/osparc/dashboard/FolderButtonItem.js
index b3c1bec4da6..d6a0d76769d 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/FolderButtonItem.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/FolderButtonItem.js
@@ -79,18 +79,6 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
apply: "__applyDescription"
},
- myAccessRights: {
- check: "Object",
- nullable: true,
- apply: "__applyMyAccessRights"
- },
-
- accessRights: {
- check: "Object",
- nullable: true,
- apply: "__applyAccessRights"
- },
-
lastModified: {
check: "Date",
nullable: true,
@@ -103,7 +91,8 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
let control;
switch (id) {
case "icon": {
- control = new osparc.dashboard.FolderWithSharedIcon().set({
+ control = new qx.ui.basic.Image().set({
+ source: "@FontAwesome5Solid/folder/26",
anonymous: true,
height: 40,
padding: 5
@@ -155,9 +144,9 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
folder.bind("parentId", this, "parentFolderId");
folder.bind("name", this, "title");
folder.bind("description", this, "description");
- folder.bind("accessRights", this, "accessRights");
folder.bind("lastModified", this, "lastModified");
- folder.bind("myAccessRights", this, "myAccessRights");
+
+ this.__addMenuButton();
},
__applyTitle: function(value) {
@@ -177,73 +166,51 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
}
},
- __applyMyAccessRights: function(value) {
- if (value && value["delete"]) {
- const menuButton = this.getChildControl("menu-button");
- menuButton.setVisibility("visible");
+ __addMenuButton: function() {
+ const menuButton = this.getChildControl("menu-button");
+ menuButton.setVisibility("visible");
- const menu = new qx.ui.menu.Menu().set({
- position: "bottom-right"
- });
+ const menu = new qx.ui.menu.Menu().set({
+ position: "bottom-right"
+ });
- const editButton = new qx.ui.menu.Button(this.tr("Rename..."), "@FontAwesome5Solid/pencil-alt/12");
- editButton.addListener("execute", () => {
- const folder = this.getFolder();
- const newFolder = false;
- const folderEditor = new osparc.editor.FolderEditor(newFolder).set({
- label: folder.getName(),
- description: folder.getDescription()
- });
- const title = this.tr("Edit Folder");
- const win = osparc.ui.window.Window.popUpInWindow(folderEditor, title, 300, 200);
- folderEditor.addListener("updateFolder", () => {
- const newName = folderEditor.getLabel();
- const newDescription = folderEditor.getDescription();
- const updateData = {
- "name": newName,
- "description": newDescription
- };
- osparc.data.model.Folder.putFolder(this.getFolderId(), updateData)
- .then(() => {
- folder.set({
- name: newName,
- description: newDescription
- });
- this.fireDataEvent("folderUpdated", folder.getFolderId());
- })
- .catch(err => console.error(err));
- win.close();
- });
- folderEditor.addListener("cancel", () => win.close());
+ const editButton = new qx.ui.menu.Button(this.tr("Rename..."), "@FontAwesome5Solid/pencil-alt/12");
+ editButton.addListener("execute", () => {
+ const folder = this.getFolder();
+ const newFolder = false;
+ const folderEditor = new osparc.editor.FolderEditor(newFolder).set({
+ label: folder.getName(),
+ description: folder.getDescription()
});
- menu.add(editButton);
-
- const shareButton = new qx.ui.menu.Button(this.tr("Share..."), "@FontAwesome5Solid/share-alt/12");
- shareButton.addListener("execute", () => this.__openShareWith(), this);
- menu.add(shareButton);
-
- menu.addSeparator();
-
- const deleteButton = new qx.ui.menu.Button(this.tr("Delete"), "@FontAwesome5Solid/trash/12");
- deleteButton.addListener("execute", () => this.__deleteStudyRequested(), this);
- menu.add(deleteButton);
+ const title = this.tr("Edit Folder");
+ const win = osparc.ui.window.Window.popUpInWindow(folderEditor, title, 300, 200);
+ folderEditor.addListener("updateFolder", () => {
+ const newName = folderEditor.getLabel();
+ const newDescription = folderEditor.getDescription();
+ const updateData = {
+ "name": newName,
+ "description": newDescription
+ };
+ osparc.data.model.Folder.putFolder(this.getFolderId(), updateData)
+ .then(() => {
+ folder.set({
+ name: newName,
+ description: newDescription
+ });
+ this.fireDataEvent("folderUpdated", folder.getFolderId());
+ })
+ .catch(err => console.error(err));
+ win.close();
+ });
+ folderEditor.addListener("cancel", () => win.close());
+ });
+ menu.add(editButton);
- menuButton.setMenu(menu);
- }
- },
+ const deleteButton = new qx.ui.menu.Button(this.tr("Delete"), "@FontAwesome5Solid/trash/12");
+ deleteButton.addListener("execute", () => this.__deleteStudyRequested(), this);
+ menu.add(deleteButton);
- __applyAccessRights: function(value) {
- if (value && Object.keys(value).length) {
- const shareIcon = this.getChildControl("icon").getChildControl("shared-icon");
- // if it's not shared don't show the share icon
- shareIcon.addListener("changeSource", e => {
- const newSource = e.getData();
- shareIcon.set({
- visibility: newSource.includes(osparc.dashboard.CardBase.SHARE_ICON) ? "hidden" : "visible"
- });
- });
- osparc.dashboard.CardBase.populateShareIcon(shareIcon, value);
- }
+ menuButton.setMenu(menu);
},
__updateTooltip: function() {
@@ -260,18 +227,6 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
this.setValue(false);
},
- __openShareWith: function() {
- const disableShare = true;
- if (disableShare) {
- osparc.FlashMessenger.getInstance().logAs(this.tr("Not yet implemented"), "WARNING");
- } else {
- const title = this.tr("Share Folder");
- const permissionsView = new osparc.share.CollaboratorsFolder(this.getFolder());
- osparc.ui.window.Window.popUpInWindow(permissionsView, title);
- permissionsView.addListener("updateAccessRights", () => this.__applyAccessRights(this.getFolder().getAccessRights()), this);
- }
- },
-
__deleteStudyRequested: function() {
const msg = this.tr("Are you sure you want to delete") + " " + this.getTitle() + "?";
const confirmationWin = new osparc.ui.window.Confirmation(msg).set({
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js b/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js
index 95986f1e293..40178ea468d 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js
@@ -42,10 +42,10 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
const mainLayoutWithSideSpacers = new qx.ui.container.Composite(new qx.ui.layout.HBox(spacing))
this._addToMainLayout(mainLayoutWithSideSpacers);
- this.__leftLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(10)).set({
+ this.__leftFilters = new qx.ui.container.Composite(new qx.ui.layout.VBox(10)).set({
width: leftColumnWidth
});
- mainLayoutWithSideSpacers.add(this.__leftLayout);
+ mainLayoutWithSideSpacers.add(this.__leftFilters);
this.__centerLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
mainLayoutWithSideSpacers.add(this.__centerLayout);
@@ -68,7 +68,6 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
}
const compactVersion = w < this.__centerLayout.getMinWidth() + leftColumnWidth + emptyColumnMinWidth;
- this.__leftLayout.setVisibility(compactVersion ? "excluded" : "visible");
rightColum.setVisibility(compactVersion ? "excluded" : "visible");
};
fitResourceCards();
@@ -83,7 +82,7 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
statics: {
PAGINATED_STUDIES: 10,
- MIN_GRID_CARDS_PER_ROW: 4,
+ MIN_GRID_CARDS_PER_ROW: 3,
SIDE_SPACER_WIDTH: 180,
checkLoggedIn: function() {
@@ -186,7 +185,7 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
},
members: {
- __leftLayout: null,
+ __leftFilters: null,
__centerLayout: null,
_resourceType: null,
_resourcesList: null,
@@ -254,6 +253,13 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
resourcesContainer.addListener("folderSelected", e => this._folderSelected(e.getData()));
resourcesContainer.addListener("folderUpdated", e => this._folderUpdated(e.getData()));
resourcesContainer.addListener("deleteFolderRequested", e => this._deleteFolderRequested(e.getData()));
+ resourcesContainer.addListener("workspaceSelected", e => {
+ const workspaceId = e.getData();
+ this._workspaceSelected(workspaceId);
+ this.__resourceFilter.workspaceSelected(workspaceId);
+ });
+ resourcesContainer.addListener("workspaceUpdated", e => this._workspaceUpdated(e.getData()));
+ resourcesContainer.addListener("deleteWorkspaceRequested", e => this._deleteWorkspaceRequested(e.getData()));
this._addToLayout(resourcesContainer);
},
@@ -349,17 +355,28 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
},
_addResourceFilter: function() {
- const resourceFilter = new osparc.dashboard.ResourceFilter(this._resourceType).set({
+ const resourceFilter = this.__resourceFilter = new osparc.dashboard.ResourceFilter(this._resourceType).set({
marginTop: osparc.dashboard.SearchBarFilter.HEIGHT + 10, // aligned with toolbar buttons: search bar + spacing
maxWidth: this.self().SIDE_SPACER_WIDTH,
width: this.self().SIDE_SPACER_WIDTH
});
resourceFilter.addListener("changeSharedWith", e => {
+ if (this._resourceType === "study") {
+ this.setCurrentWorkspaceId(null);
+ }
const sharedWith = e.getData();
this._searchBarFilter.setSharedWithActiveFilter(sharedWith.id, sharedWith.label);
}, this);
+ resourceFilter.addListener("changeWorkspace", e => {
+ const workspaceId = e.getData();
+ this.setCurrentWorkspaceId(workspaceId);
+ if (this._resourceType === "study") {
+ this._searchBarFilter.resetSharedWithActiveFilter();
+ }
+ }, this);
+
resourceFilter.addListener("changeSelectedTags", e => {
const selectedTagIds = e.getData();
this._searchBarFilter.setTagsActiveFilter(selectedTagIds);
@@ -375,7 +392,7 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
resourceFilter.filterChanged(filterData);
});
- this.__leftLayout.add(resourceFilter);
+ this.__leftFilters.add(resourceFilter);
},
/**
@@ -460,6 +477,18 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
throw new Error("Abstract method called!");
},
+ _workspaceSelected: function(workspaceId) {
+ throw new Error("Abstract method called!");
+ },
+
+ _workspaceUpdated: function(workspaceId) {
+ throw new Error("Abstract method called!");
+ },
+
+ _deleteWorkspaceRequested: function(workspaceId) {
+ throw new Error("Abstract method called!");
+ },
+
_getOpenMenuButton: function(resourceData) {
const openButton = new qx.ui.menu.Button(this.tr("Open"));
openButton["openResourceButton"] = true;
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ResourceContainerManager.js b/services/static-webserver/client/source/class/osparc/dashboard/ResourceContainerManager.js
index 01b4f7f861d..84b2e680f5f 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceContainerManager.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceContainerManager.js
@@ -21,22 +21,30 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
construct: function() {
this.base(arguments);
- this._setLayout(new qx.ui.layout.VBox(20));
+ this._setLayout(new qx.ui.layout.VBox(15));
this.set({
paddingBottom: 60
});
this.__foldersList = [];
+ this.__workspacesList = [];
this.__resourcesList = [];
+ this.__groupedContainersList = [];
+
+ const containerHeader = this.__containerHeader = new osparc.dashboard.ContainerHeader();
+ this._add(containerHeader);
+ containerHeader.setVisibility(osparc.utils.DisabledPlugins.isFoldersEnabled() ? "visible" : "excluded");
+
+
+ const workspacesContainer = this.__workspacesContainer = new osparc.dashboard.ToggleButtonContainer();
+ this._add(workspacesContainer);
+ workspacesContainer.setVisibility(osparc.utils.DisabledPlugins.isFoldersEnabled() ? "visible" : "excluded");
+
- const folders = this.__foldersLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
- const folderHeader = this.__folderHeader = new osparc.dashboard.FolderHeader();
- folders.add(folderHeader);
const foldersContainer = this.__foldersContainer = new osparc.dashboard.ToggleButtonContainer();
- folders.add(foldersContainer);
- this._add(folders);
- folders.setVisibility(osparc.utils.DisabledPlugins.isFoldersEnabled() ? "visible" : "excluded");
+ this._add(foldersContainer);
+ foldersContainer.setVisibility(osparc.utils.DisabledPlugins.isFoldersEnabled() ? "visible" : "excluded");
const nonGroupedContainer = this.__nonGroupedContainer = new osparc.dashboard.ToggleButtonContainer();
[
@@ -47,9 +55,8 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
});
this._add(nonGroupedContainer);
- const groupedContainersLayout = this.__groupedContainersLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
- this._add(groupedContainersLayout);
- this.__groupedContainersList = [];
+ const groupedContainers = this.__groupedContainers = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
+ this._add(groupedContainers);
},
properties: {
@@ -80,6 +87,9 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
"folderSelected": "qx.event.type.Data",
"folderUpdated": "qx.event.type.Data",
"deleteFolderRequested": "qx.event.type.Data",
+ "workspaceSelected": "qx.event.type.Data",
+ "workspaceUpdated": "qx.event.type.Data",
+ "deleteWorkspaceRequested": "qx.event.type.Data",
},
statics: {
@@ -104,13 +114,15 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
members: {
__foldersList: null,
+ __workspacesList: null,
__resourcesList: null,
+ __groupedContainersList: null,
__foldersLayout: null,
- __folderHeader: null,
+ __containerHeader: null,
__foldersContainer: null,
+ __workspacesContainer: null,
__nonGroupedContainer: null,
- __groupedContainersList: null,
- __groupedContainersLayout: null,
+ __groupedContainers: null,
addNonResourceCard: function(card) {
if (card instanceof qx.ui.form.ToggleButton) {
@@ -151,8 +163,8 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
}
},
- getFolderHeader: function() {
- return this.__folderHeader;
+ getContainerHeader: function() {
+ return this.__containerHeader;
},
getFlatList: function() {
@@ -238,44 +250,41 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
return card;
},
- __createFolderCard: function(folder) {
- const card = new osparc.dashboard.FolderButtonItem(folder);
- card.subscribeToFilterGroup("searchBarFilter");
- [
- "folderSelected",
- "folderUpdated",
- "deleteFolderRequested",
- ].forEach(eName => card.addListener(eName, e => this.fireDataEvent(eName, e.getData())));
- return card;
- },
-
setResourcesToList: function(resourcesList) {
this.__resourcesList = resourcesList;
},
__cleanAll: function() {
+ if (this.__workspacesContainer) {
+ this.__workspacesContainer.removeAll();
+ }
if (this.__nonGroupedContainer) {
this.__nonGroupedContainer.removeAll();
this.__nonGroupedContainer = null;
}
- if (this.__groupedContainersLayout) {
- this.__groupedContainersLayout.removeAll();
+ if (this.__groupedContainers) {
+ this.__groupedContainers.removeAll();
}
- this.__groupedContainersList.forEach(groupedContainer => groupedContainer.getContentContainer().removeAll());
+ this.__groupedContainersList.forEach(groupedContainer => {
+ groupedContainer.getContentContainer().removeAll();
+ });
this.__groupedContainersList = [];
this._removeAll();
},
- reloadCards: function(listId) {
+ reloadCards: function(resourceType) {
this.__cleanAll();
- this._add(this.__foldersLayout);
+ if (resourceType === "studies") {
+ this._add(this.__containerHeader);
+ this._add(this.__foldersContainer);
+ }
if (this.getGroupBy()) {
const noGroupContainer = this.__createGroupContainer("no-group", "No Group", "transparent");
- this.__groupedContainersLayout.add(noGroupContainer);
- this._add(this.__groupedContainersLayout);
+ this.__groupedContainers.add(noGroupContainer);
+ this._add(this.__groupedContainers);
} else {
const flatList = this.__nonGroupedContainer = new osparc.dashboard.ToggleButtonContainer();
- osparc.utils.Utils.setIdToWidget(flatList, listId);
+ osparc.utils.Utils.setIdToWidget(flatList, resourceType + "List");
[
"changeSelection",
"changeVisibility"
@@ -309,6 +318,43 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
return newCards;
},
+ // WORKSPACES
+ setWorkspacesToList: function(workspacesList) {
+ this.__workspacesList = workspacesList;
+ },
+
+ reloadWorkspaces: function() {
+ this.__cleanAll();
+ this._add(this.__containerHeader);
+ this._add(this.__workspacesContainer);
+ let workspacesCards = [];
+ this.__workspacesList.forEach(workspaceData => workspacesCards.push(this.__workspaceToCard(workspaceData)));
+ return workspacesCards;
+ },
+
+ addNewWorkspaceCard: function(newWorkspaceCard) {
+ this.__workspacesContainer.addAt(newWorkspaceCard, 0);
+ },
+
+ __workspaceToCard: function(workspaceData) {
+ const card = this.__createWorkspaceCard(workspaceData);
+ this.__workspacesContainer.add(card);
+ return card;
+ },
+
+ __createWorkspaceCard: function(workspace) {
+ const card = new osparc.dashboard.WorkspaceButtonItem(workspace);
+ card.subscribeToFilterGroup("searchBarFilter");
+ [
+ "workspaceSelected",
+ "workspaceUpdated",
+ "deleteWorkspaceRequested",
+ ].forEach(eName => card.addListener(eName, e => this.fireDataEvent(eName, e.getData())));
+ return card;
+ },
+ // /WORKSPACES
+
+ // FOLDERS
setFoldersToList: function(foldersList) {
this.__foldersList = foldersList;
},
@@ -326,10 +372,28 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
this.__foldersContainer.addAt(newFolderCard, 0);
},
+ __folderToCard: function(folderData) {
+ const card = this.__createFolderCard(folderData);
+ this.__foldersContainer.add(card);
+ return card;
+ },
+
+ __createFolderCard: function(folder) {
+ const card = new osparc.dashboard.FolderButtonItem(folder);
+ card.subscribeToFilterGroup("searchBarFilter");
+ [
+ "folderSelected",
+ "folderUpdated",
+ "deleteFolderRequested",
+ ].forEach(eName => card.addListener(eName, e => this.fireDataEvent(eName, e.getData())));
+ return card;
+ },
+ // /FOLDERS
+
__moveNoGroupToLast: function() {
- const idx = this.__groupedContainersLayout.getChildren().findIndex(grpContainer => grpContainer === this.__getGroupContainer("no-group"));
+ const idx = this.__groupedContainers.getChildren().findIndex(grpContainer => grpContainer === this.__getGroupContainer("no-group"));
if (idx > -1) {
- this.__groupedContainersLayout.getChildren().push(this.__groupedContainersLayout.getChildren().splice(idx, 1)[0]);
+ this.__groupedContainers.getChildren().push(this.__groupedContainers.getChildren().splice(idx, 1)[0]);
}
},
@@ -347,8 +411,8 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
if (groupContainer === null) {
groupContainer = this.__createGroupContainer(tag.id, tag.name, tag.color);
groupContainer.setHeaderIcon("@FontAwesome5Solid/tag/24");
- this.__groupedContainersLayout.add(groupContainer);
- this.__groupedContainersLayout.getChildren().sort((a, b) => a.getHeaderLabel().localeCompare(b.getHeaderLabel()));
+ this.__groupedContainers.add(groupContainer);
+ this.__groupedContainers.getChildren().sort((a, b) => a.getHeaderLabel().localeCompare(b.getHeaderLabel()));
this.__moveNoGroupToLast();
}
const card = this.__createCard(resourceData);
@@ -417,12 +481,6 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
this.self().sortListByPriority(this.__nonGroupedContainer);
}
return cardsCreated;
- },
-
- __folderToCard: function(folderData) {
- const card = this.__createFolderCard(folderData);
- this.__foldersContainer.add(card);
- return card;
}
}
});
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js b/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js
index 17d249b146b..7a32749e1b5 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js
@@ -257,7 +257,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
if (selection.length) {
const serviceVersion = selection[0].version;
if (serviceVersion !== this.__resourceData["version"]) {
- osparc.service.Store.getService(this.__resourceData["key"], serviceVersion)
+ osparc.store.Services.getService(this.__resourceData["key"], serviceVersion)
.then(serviceData => {
serviceData["resourceType"] = "service";
this.__resourceData = serviceData;
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 a325cec6123..0a47f4e12ec 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceFilter.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceFilter.js
@@ -26,6 +26,7 @@ qx.Class.define("osparc.dashboard.ResourceFilter", {
this.__resourceType = resourceType;
this.__sharedWithButtons = [];
+ this.__workspaceButtons = [];
this.__tagButtons = [];
this.__serviceTypeButtons = [];
@@ -35,6 +36,7 @@ qx.Class.define("osparc.dashboard.ResourceFilter", {
events: {
"changeSharedWith": "qx.event.type.Data",
+ "changeWorkspace": "qx.event.type.Data",
"changeSelectedTags": "qx.event.type.Data",
"changeServiceType": "qx.event.type.Data"
},
@@ -42,15 +44,19 @@ qx.Class.define("osparc.dashboard.ResourceFilter", {
members: {
__resourceType: null,
__sharedWithButtons: null,
+ __workspaceButtons: null,
__tagButtons: null,
__serviceTypeButtons: null,
__buildLayout: function() {
const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(40));
+
layout.add(this.__createSharedWithFilterLayout());
+
if (this.__resourceType !== "service") {
layout.add(this.__createTagsFilterLayout());
}
+
if (this.__resourceType === "service") {
layout.add(this.__createServiceTypeFilterLayout());
}
@@ -74,11 +80,23 @@ qx.Class.define("osparc.dashboard.ResourceFilter", {
if (this.__resourceType === "study" && option.id === "shared-with-everyone") {
return;
}
- const button = new qx.ui.toolbar.RadioButton(option.label, option.icon);
- button.id = option.id;
- button.set({
- appearance: "filter-toggle-button"
+ const button = new qx.ui.toolbar.RadioButton().set({
+ appearance: "filter-toggle-button",
+ label: option.label,
+ icon: option.icon,
});
+ if (this.__resourceType === "study") {
+ if (option.id === "show-all") {
+ button.set({
+ label: this.tr("My Workspace")
+ });
+ } else {
+ button.set({
+ marginLeft: 15
+ });
+ }
+ }
+ button.id = option.id;
layout.add(button);
radioGroup.add(button);
@@ -93,10 +111,56 @@ qx.Class.define("osparc.dashboard.ResourceFilter", {
this.__sharedWithButtons.push(button);
});
+ if (this.__resourceType === "study") {
+ this.__addWorkspaceButtons(layout, radioGroup);
+ }
+
return layout;
},
/* /SHARED WITH */
+ /* WORKSPACES */
+ __addWorkspaceButtons: function(layout, radioGroup) {
+ layout.add(new qx.ui.core.Spacer());
+ const workspacesButton = new qx.ui.toolbar.RadioButton(this.tr("Shared Workspaces"), osparc.store.Workspaces.iconPath(22));
+ workspacesButton.workspaceId = -1;
+ workspacesButton.set({
+ appearance: "filter-toggle-button"
+ });
+ layout.add(workspacesButton);
+ radioGroup.add(workspacesButton);
+ workspacesButton.addListener("execute", () => {
+ this.fireDataEvent("changeWorkspace", workspacesButton.workspaceId);
+ });
+
+ osparc.store.Workspaces.fetchWorkspaces()
+ .then(workspaces => {
+ workspaces.forEach(workspace => {
+ const workspaceButton = new qx.ui.toolbar.RadioButton(workspace.getName(), osparc.store.Workspaces.iconPath(22));
+ workspaceButton.workspaceId = workspace.getWorkspaceId();
+ this.__workspaceButtons.push(workspaceButton);
+ workspaceButton.set({
+ appearance: "filter-toggle-button",
+ marginLeft: 15,
+ });
+ layout.add(workspaceButton);
+ radioGroup.add(workspaceButton);
+ workspaceButton.addListener("execute", () => {
+ this.fireDataEvent("changeWorkspace", workspaceButton.workspaceId);
+ }, this);
+ });
+ })
+ .catch(console.error);
+ },
+
+ workspaceSelected: function(workspaceId) {
+ const foundButton = this.__workspaceButtons.find(workspaceButton => workspaceButton.workspaceId === workspaceId);
+ if (foundButton) {
+ foundButton.execute();
+ }
+ },
+ /* /WORKSPACES */
+
/* TAGS */
__createTagsFilterLayout: function() {
const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(5));
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/SearchBarFilter.js b/services/static-webserver/client/source/class/osparc/dashboard/SearchBarFilter.js
index 4be366fc05d..99ba301e236 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/SearchBarFilter.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/SearchBarFilter.js
@@ -287,6 +287,11 @@ qx.Class.define("osparc.dashboard.SearchBarFilter", {
});
},
+ resetSharedWithActiveFilter: function() {
+ this.__removeChips("shared-with");
+ this.__filter();
+ },
+
setSharedWithActiveFilter: function(optionId, optionLabel) {
this.__removeChips("shared-with");
if (optionId === "show-all") {
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 207b81956fc..81583c9b24f 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js
@@ -58,7 +58,7 @@ qx.Class.define("osparc.dashboard.ServiceBrowser", {
},
__loadServices: function() {
- osparc.service.Store.getServicesLatest()
+ osparc.store.Services.getServicesLatest()
.then(servicesLatest => {
const servicesList = [];
Object.keys(servicesLatest).forEach(key => {
@@ -100,7 +100,7 @@ qx.Class.define("osparc.dashboard.ServiceBrowser", {
_reloadCards: function() {
this._resourcesContainer.setResourcesToList(this._resourcesList);
- const cards = this._resourcesContainer.reloadCards("servicesList");
+ const cards = this._resourcesContainer.reloadCards("services");
cards.forEach(card => {
card.setMultiSelectionMode(this.getMultiSelection());
card.addListener("execute", () => this.__itemClicked(card), this);
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 2e174d99229..e9b61fadca7 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js
@@ -49,6 +49,14 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
},
properties: {
+ currentWorkspaceId: {
+ check: "Number",
+ nullable: true,
+ init: null,
+ event: "changeCurrentWorkspaceId",
+ apply: "__applyCurrentWorkspaceId"
+ },
+
currentFolderId: {
check: "Number",
nullable: true,
@@ -94,6 +102,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
},
members: {
+ __workspacesList: null,
__foldersList: null,
// overridden
@@ -141,13 +150,13 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
reloadResources: function() {
if (osparc.data.Permissions.getInstance().canDo("studies.user.read")) {
- this.__reloadResources();
+ this.__reloadFoldersAndStudies();
} else {
this.__resetStudiesList();
}
},
- __reloadResources: function() {
+ __reloadFoldersAndStudies: function() {
this.__reloadFolders();
this.__reloadStudies();
},
@@ -156,6 +165,15 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
this.__reloadFilteredStudies();
},
+ __reloadWorkspaces: function() {
+ osparc.store.Workspaces.fetchWorkspaces()
+ .then(workspaces => {
+ this.__workspacesList = workspaces;
+ workspaces.forEach(workspace => workspace["resourceType"] = "workspace");
+ this.__reloadWorkspaceCards();
+ });
+ },
+
__reloadFolders: function() {
const folders = osparc.store.Folders.getInstance().getFolders(this.getCurrentFolderId())
this.__setFoldersToList(folders);
@@ -186,7 +204,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
if (nStudies === 0) {
const promises = [
osparc.store.Store.getInstance().getTemplates(),
- osparc.service.Store.getServicesLatest(),
+ osparc.store.Services.getServicesLatest(),
];
if (osparc.utils.DisabledPlugins.isFoldersEnabled()) {
promises.push(osparc.store.Folders.getInstance().fetchFolders());
@@ -345,7 +363,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
const visibility = this._loadingResourcesBtn ? this._loadingResourcesBtn.getVisibility() : "excluded";
this._resourcesContainer.setResourcesToList(this._resourcesList);
- const cards = this._resourcesContainer.reloadCards("studiesList");
+ const cards = this._resourcesContainer.reloadCards("studies");
this.__configureCards(cards);
this.__addNewStudyButtons();
@@ -369,6 +387,66 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
osparc.filter.UIFilterController.dispatch("searchBarFilter");
},
+ __applyCurrentWorkspaceId: function(workspaceId) {
+ if (osparc.utils.DisabledPlugins.isFoldersEnabled()) {
+ if (workspaceId === -1) {
+ this._resourcesContainer.setResourcesToList([]);
+ this._resourcesList = [];
+
+ this.__reloadWorkspaces();
+ } else {
+ this._resourcesContainer.setResourcesToList([]);
+ this._resourcesList = [];
+ this.invalidateStudies();
+
+ this.__reloadFoldersAndStudies();
+ }
+ }
+ },
+
+ // WORKSPACES
+ __reloadWorkspaceCards: function() {
+ this._resourcesContainer.setWorkspacesToList(this.__workspacesList);
+ this._resourcesContainer.reloadWorkspaces();
+
+ const newWorkspaceCard = new osparc.dashboard.WorkspaceButtonNew();
+ newWorkspaceCard.setCardKey("new-workspace");
+ newWorkspaceCard.subscribeToFilterGroup("searchBarFilter");
+ newWorkspaceCard.addListener("createWorkspace", () => this.__reloadWorkspaces());
+ newWorkspaceCard.addListener("updateWorkspace", () => this.__reloadWorkspaces());
+ this._resourcesContainer.addNewWorkspaceCard(newWorkspaceCard);
+ },
+
+ _workspaceSelected: function(workspaceId) {
+ this.setCurrentWorkspaceId(workspaceId);
+ },
+
+ _workspaceUpdated: function() {
+ this.__reloadWorkspaceCards();
+ },
+
+ _deleteWorkspaceRequested: function(workspaceId) {
+ osparc.store.Workspaces.deleteWorkspace(workspaceId)
+ .then(() => this.__reloadWorkspaceCards())
+ .catch(err => console.error(err));
+ },
+ // /WORKSPACES
+
+ // FOLDERS
+ __applyCurrentFolderId: function(currentFolderId) {
+ if (osparc.utils.DisabledPlugins.isFoldersEnabled()) {
+ osparc.store.Folders.getInstance().fetchFolders(currentFolderId)
+ .then(() => {
+ this._resourcesContainer.setResourcesToList([]);
+ this._resourcesList = [];
+ this.invalidateStudies();
+
+ this.__reloadFoldersAndStudies();
+ })
+ .catch(console.error);
+ }
+ },
+
__reloadFolderCards: function() {
this._resourcesContainer.setFoldersToList(this.__foldersList);
this._resourcesContainer.reloadFolders();
@@ -392,20 +470,6 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
this.setCurrentFolderId(folderId);
},
- __applyCurrentFolderId: function(currentFolderId) {
- if (osparc.utils.DisabledPlugins.isFoldersEnabled()) {
- osparc.store.Folders.getInstance().fetchFolders(currentFolderId)
- .then(() => {
- this._resourcesContainer.setResourcesToList([]);
- this._resourcesList = [];
- this.invalidateStudies();
-
- this.__reloadResources();
- })
- .catch(console.error);
- }
- },
-
_folderUpdated: function() {
this.__reloadFolders();
},
@@ -415,6 +479,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
.then(() => this.__reloadFolders())
.catch(err => console.error(err));
},
+ // /FOLDERS
__configureCards: function(cards) {
cards.forEach(card => {
@@ -671,7 +736,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
// scale to latest compatible
const latestVersion = versions[0];
const latestCompatible = osparc.service.Utils.getLatestCompatible(key, latestVersion);
- osparc.service.Store.getService(latestCompatible["key"], latestCompatible["version"])
+ osparc.store.Services.getService(latestCompatible["key"], latestCompatible["version"])
.then(latestMetadata => {
const title = newButtonInfo.title + " " + osparc.service.Utils.extractVersionDisplay(latestMetadata);
const desc = newButtonInfo.description;
@@ -707,10 +772,12 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
_createLayout: function() {
this._createResourcesLayout();
- const folderHeader = this._resourcesContainer.getFolderHeader();
- if (folderHeader) {
- this.bind("currentFolderId", folderHeader, "currentFolderId");
- folderHeader.addListener("changeCurrentFolderId", e => this.setCurrentFolderId(e.getData()));
+ const containerHeader = this._resourcesContainer.getContainerHeader();
+ if (containerHeader) {
+ this.bind("currentWorkspaceId", containerHeader, "currentWorkspaceId");
+ containerHeader.bind("currentWorkspaceId", this, "currentWorkspaceId");
+ this.bind("currentFolderId", containerHeader, "currentFolderId");
+ containerHeader.bind("currentFolderId", this, "currentFolderId");
}
const list = this._resourcesContainer.getFlatList();
if (list) {
@@ -795,7 +862,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
if (filterData.text) {
this.__reloadFilteredResources(filterData.text);
} else {
- this.__reloadResources();
+ this.__reloadFoldersAndStudies();
}
sharedWithButton.filterChanged(filterData);
}, this);
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 d9ba8b01296..6a5e516ce9e 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js
@@ -111,7 +111,7 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", {
_reloadCards: function() {
this._resourcesContainer.setResourcesToList(this._resourcesList);
- const cards = this._resourcesContainer.reloadCards("templatesList");
+ const cards = this._resourcesContainer.reloadCards("templates");
cards.forEach(card => {
card.setMultiSelectionMode(this.getMultiSelection());
card.addListener("tap", () => this.__itemClicked(card), this);
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonBase.js b/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonBase.js
new file mode 100644
index 00000000000..fbcf92b3bf7
--- /dev/null
+++ b/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonBase.js
@@ -0,0 +1,252 @@
+/* ************************************************************************
+
+ 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.dashboard.WorkspaceButtonBase", {
+ extend: qx.ui.form.ToggleButton,
+ implement: [qx.ui.form.IModel, osparc.filter.IFilterable],
+ include: [qx.ui.form.MModelProperty, osparc.filter.MFilterable],
+ type: "abstract",
+
+ construct: function() {
+ this.base(arguments);
+
+ this.set({
+ width: this.self().ITEM_WIDTH,
+ height: this.self().ITEM_HEIGHT,
+ padding: 0
+ });
+
+ this._setLayout(new qx.ui.layout.Canvas());
+
+ this.getChildControl("main-layout");
+
+ [
+ "pointerover",
+ "focus"
+ ].forEach(e => this.addListener(e, this._onPointerOver, this));
+
+ [
+ "pointerout",
+ "focusout"
+ ].forEach(e => this.addListener(e, this._onPointerOut, this));
+ },
+
+ properties: {
+ cardKey: {
+ check: "String",
+ nullable: true
+ },
+
+ resourceType: {
+ check: ["workspace"],
+ init: "workspace",
+ nullable: false
+ },
+
+ priority: {
+ check: "Number",
+ init: null,
+ nullable: false
+ }
+ },
+
+ statics: {
+ ITEM_WIDTH: 190,
+ ITEM_HEIGHT: 190,
+ PADDING: 10,
+ SPACING_IN: 5,
+ SPACING: 15,
+ HEADER_MAX_HEIGHT: 40, // two lines in Manrope
+ ICON_SIZE: 60,
+ POS: {
+ HEADER: 0,
+ BODY: 1,
+ FOOTER: 2
+ },
+ HPOS: {
+ SHARED: 0,
+ TITLE: 1,
+ MENU: 2,
+ },
+ FPOS: {
+ MODIFIED: 0
+ }
+ },
+
+ events: {
+ /** (Fired by {@link qx.ui.form.List}) */
+ "action": "qx.event.type.Event"
+ },
+
+ members: { // eslint-disable-line qx-rules/no-refs-in-members
+ // overridden
+ _forwardStates: {
+ focused : true,
+ hovered : true,
+ selected : true,
+ dragover : true
+ },
+
+ // overridden
+ _createChildControlImpl: function(id) {
+ let layout;
+ let control;
+ switch (id) {
+ case "main-layout": {
+ control = new qx.ui.container.Composite(new qx.ui.layout.VBox(this.self().SPACING_IN));
+ const header = this.getChildControl("header");
+ const body = this.getChildControl("body");
+ const footer = this.getChildControl("footer");
+ control.addAt(header, this.self().POS.HEADER);
+ control.addAt(body, this.self().POS.BODY, {
+ flex: 1
+ });
+ control.addAt(footer, this.self().POS.FOOTER);
+ this._add(control, {
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0
+ });
+ break;
+ }
+ case "header":
+ control = new qx.ui.container.Composite(new qx.ui.layout.HBox(5)).set({
+ backgroundColor: "background-card-overlay",
+ anonymous: true,
+ maxWidth: this.self().ITEM_WIDTH,
+ maxHeight: this.self().HEADER_MAX_HEIGHT,
+ padding: this.self().PADDING,
+ alignY: "middle",
+ });
+ break;
+ case "body":
+ control = new qx.ui.container.Composite(new qx.ui.layout.VBox(5)).set({
+ decorator: "main",
+ allowGrowY: true,
+ allowGrowX: true,
+ allowShrinkX: true,
+ padding: this.self().PADDING
+ });
+ control.getContentElement().setStyles({
+ "border-width": 0
+ });
+ break;
+ case "footer": {
+ control = new qx.ui.container.Composite(new qx.ui.layout.HBox(5)).set({
+ backgroundColor: "background-card-overlay",
+ anonymous: true,
+ maxWidth: this.self().ITEM_WIDTH,
+ maxHeight: this.self().ITEM_HEIGHT,
+ padding: this.self().PADDING,
+ alignY: "middle",
+ });
+ break;
+ }
+ case "title":
+ control = new qx.ui.basic.Label().set({
+ textColor: "contrasted-text-light",
+ font: "text-14",
+ allowGrowX: true,
+ maxHeight: this.self().HEADER_MAX_HEIGHT
+ });
+ layout = this.getChildControl("header");
+ layout.addAt(control, this.self().HPOS.TITLE, {
+ flex: 1
+ });
+ break;
+ case "icon": {
+ layout = this.getChildControl("body");
+ const maxWidth = this.self().ITEM_WIDTH;
+ control = new osparc.ui.basic.Thumbnail(null, maxWidth, 124);
+ control.getChildControl("image").set({
+ anonymous: true,
+ alignY: "middle",
+ alignX: "center",
+ allowGrowX: true,
+ allowGrowY: true
+ });
+ layout.getContentElement().setStyles({
+ "border-width": "0px"
+ });
+ layout.add(control, {flex: 1});
+ break;
+ }
+ }
+ return control || this.base(arguments, id);
+ },
+
+ // overridden
+ _applyIcon: function(value) {
+ if (
+ value.includes("@FontAwesome5Solid/") ||
+ value.includes("@MaterialIcons/")
+ ) {
+ value += this.self().ICON_SIZE;
+ const image = this.getChildControl("icon").getChildControl("image");
+ image.set({
+ source: value
+ });
+ } else {
+ this.getContentElement().setStyles({
+ "background-image": `url(${value})`,
+ "background-repeat": "no-repeat",
+ "background-size": "cover", // auto width, 85% height
+ "background-position": "center center",
+ "background-origin": "border-box"
+ });
+ }
+ },
+
+ /**
+ * Event handler for the pointer over event.
+ */
+ _onPointerOver: function() {
+ this.addState("hovered");
+ },
+
+ /**
+ * Event handler for the pointer out event.
+ */
+ _onPointerOut : function() {
+ this.removeState("hovered");
+ },
+
+ _filter: function() {
+ this.exclude();
+ },
+
+ _unfilter: function() {
+ this.show();
+ },
+
+ _shouldApplyFilter: function(data) {
+ console.log("_shouldApplyFilter", data);
+ return false;
+ },
+
+ _shouldReactToFilter: function(data) {
+ console.log("_shouldReactToFilter", data);
+ return false;
+ }
+ },
+
+ destruct: function() {
+ this.removeListener("pointerover", this._onPointerOver, this);
+ this.removeListener("pointerout", this._onPointerOut, this);
+ }
+});
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonItem.js b/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonItem.js
new file mode 100644
index 00000000000..176d2775f46
--- /dev/null
+++ b/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonItem.js
@@ -0,0 +1,283 @@
+/* ************************************************************************
+
+ 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)
+
+************************************************************************ */
+
+/**
+ * Widget used for displaying a Workspace in the Study Browser
+ *
+ */
+
+qx.Class.define("osparc.dashboard.WorkspaceButtonItem", {
+ extend: osparc.dashboard.WorkspaceButtonBase,
+
+ /**
+ * @param workspace {osparc.data.model.Workspace}
+ */
+ construct: function(workspace) {
+ this.base(arguments);
+
+ this.set({
+ appearance: "pb-listitem"
+ });
+
+ this.addListener("changeValue", e => this.__itemSelected(e.getData()), this);
+
+ this.setPriority(osparc.dashboard.CardBase.CARD_PRIORITY.ITEM);
+
+ this.set({
+ workspace: workspace
+ });
+ },
+
+ events: {
+ "workspaceSelected": "qx.event.type.Data",
+ "workspaceUpdated": "qx.event.type.Data",
+ "deleteWorkspaceRequested": "qx.event.type.Data"
+ },
+
+ properties: {
+ workspace: {
+ check: "osparc.data.model.Workspace",
+ nullable: false,
+ init: null,
+ apply: "__applyWorkspace"
+ },
+
+ workspaceId: {
+ check: "Number",
+ nullable: false
+ },
+
+ title: {
+ check: "String",
+ nullable: true,
+ apply: "__applyTitle"
+ },
+
+ description: {
+ check: "String",
+ nullable: true,
+ apply: "__applyDescription"
+ },
+
+ myAccessRights: {
+ check: "Object",
+ nullable: true,
+ apply: "__applyMyAccessRights"
+ },
+
+ accessRights: {
+ check: "Object",
+ nullable: true,
+ apply: "__applyAccessRights"
+ },
+
+ lastModified: {
+ check: "Date",
+ nullable: true,
+ apply: "__applyLastModified"
+ }
+ },
+
+ statics: {
+ MENU_BTN_DIMENSIONS: 24
+ },
+
+ members: {
+ _createChildControlImpl: function(id) {
+ let control;
+ let layout;
+ switch (id) {
+ case "shared-icon":
+ control = new qx.ui.basic.Image().set({
+ alignY: "middle",
+ allowGrowX: false,
+ allowShrinkX: false
+ });
+ layout = this.getChildControl("header");
+ layout.addAt(control, osparc.dashboard.WorkspaceButtonBase.HPOS.SHARED);
+ break;
+ case "menu-button":
+ control = new qx.ui.form.MenuButton().set({
+ appearance: "form-button-outlined",
+ minWidth: this.self().MENU_BTN_DIMENSIONS,
+ minHeight: this.self().MENU_BTN_DIMENSIONS,
+ width: this.self().MENU_BTN_DIMENSIONS,
+ height: this.self().MENU_BTN_DIMENSIONS,
+ padding: [0, 8, 0, 8],
+ alignX: "center",
+ alignY: "middle",
+ icon: "@FontAwesome5Solid/ellipsis-v/14",
+ focusable: false
+ });
+ // make it circular
+ control.getContentElement().setStyles({
+ "border-radius": `${this.self().MENU_BTN_DIMENSIONS / 2}px`
+ });
+ layout = this.getChildControl("header");
+ layout.addAt(control, osparc.dashboard.WorkspaceButtonBase.HPOS.MENU);
+ break;
+ case "modified-text":
+ control = new qx.ui.basic.Label().set({
+ textColor: "contrasted-text-dark",
+ alignY: "middle",
+ rich: true,
+ anonymous: true,
+ font: "text-12",
+ allowGrowY: false
+ });
+ layout = this.getChildControl("footer");
+ layout.addAt(control, osparc.dashboard.WorkspaceButtonBase.FPOS.MODIFIED);
+ break;
+ }
+ return control || this.base(arguments, id);
+ },
+
+ __applyWorkspace: function(workspace) {
+ this.set({
+ cardKey: "workspace-" + workspace.getWorkspaceId()
+ });
+ workspace.bind("workspaceId", this, "workspaceId");
+ workspace.bind("name", this, "title");
+ workspace.bind("description", this, "description");
+ workspace.bind("thumbnail", this, "icon", {
+ converter: thumbnail => thumbnail ? thumbnail : osparc.store.Workspaces.iconPath(-1)
+ });
+ workspace.bind("accessRights", this, "accessRights");
+ workspace.bind("lastModified", this, "lastModified");
+ workspace.bind("myAccessRights", this, "myAccessRights");
+ },
+
+ __applyTitle: function(value) {
+ const label = this.getChildControl("title");
+ label.setValue(value);
+ this.__updateTooltip();
+ },
+
+ __applyDescription: function() {
+ this.__updateTooltip();
+ },
+
+ __applyMyAccessRights: function(value) {
+ if (value && value["delete"]) {
+ const menuButton = this.getChildControl("menu-button");
+ menuButton.setVisibility("visible");
+
+ const menu = new qx.ui.menu.Menu().set({
+ position: "bottom-right"
+ });
+
+ const editButton = new qx.ui.menu.Button(this.tr("Rename..."), "@FontAwesome5Solid/pencil-alt/12");
+ editButton.addListener("execute", () => {
+ const workspace = this.getWorkspace();
+ const newWorkspace = false;
+ const workspaceEditor = new osparc.editor.WorkspaceEditor(newWorkspace).set({
+ label: workspace.getName(),
+ description: workspace.getDescription()
+ });
+ const title = this.tr("Edit Workspace");
+ const win = osparc.ui.window.Window.popUpInWindow(workspaceEditor, title, 300, 200);
+ workspaceEditor.addListener("updateWorkspace", () => {
+ const newName = workspaceEditor.getLabel();
+ const newDescription = workspaceEditor.getDescription();
+ const updateData = {
+ "name": newName,
+ "description": newDescription
+ };
+ osparc.data.model.Workspace.putWorkspace(this.getWorkspaceId(), updateData)
+ .then(() => {
+ workspace.set({
+ name: newName,
+ description: newDescription
+ });
+ this.fireDataEvent("workspaceUpdated", workspace.getWorkspaceId());
+ })
+ .catch(err => console.error(err));
+ win.close();
+ });
+ workspaceEditor.addListener("cancel", () => win.close());
+ });
+ menu.add(editButton);
+
+ const shareButton = new qx.ui.menu.Button(this.tr("Share..."), "@FontAwesome5Solid/share-alt/12");
+ shareButton.addListener("execute", () => this.__openShareWith(), this);
+ menu.add(shareButton);
+
+ menu.addSeparator();
+
+ const deleteButton = new qx.ui.menu.Button(this.tr("Delete"), "@FontAwesome5Solid/trash/12");
+ deleteButton.addListener("execute", () => this.__deleteWorkspaceRequested(), this);
+ menu.add(deleteButton);
+
+ menuButton.setMenu(menu);
+ }
+ },
+
+ __applyAccessRights: function(value) {
+ if (value && Object.keys(value).length) {
+ const shareIcon = this.getChildControl("shared-icon");
+ shareIcon.addListener("tap", e => {
+ e.stopPropagation();
+ this.__openShareWith();
+ }, this);
+ shareIcon.addListener("pointerdown", e => e.stopPropagation());
+ osparc.dashboard.CardBase.populateShareIcon(shareIcon, value);
+ }
+ },
+
+ __applyLastModified: function(value) {
+ const label = this.getChildControl("modified-text");
+ label.setValue(osparc.utils.Utils.formatDateAndTime(value));
+ },
+
+ __updateTooltip: function() {
+ const toolTipText = this.getTitle() + (this.getDescription() ? "
" + this.getDescription() : "");
+ this.set({
+ toolTipText
+ })
+ },
+
+ __itemSelected: function(newVal) {
+ if (newVal) {
+ this.fireDataEvent("workspaceSelected", this.getWorkspaceId());
+ }
+ this.setValue(false);
+ },
+
+ __openShareWith: function() {
+ const permissionsView = new osparc.share.CollaboratorsWorkspace(this.getWorkspace());
+ const title = this.tr("Share Workspace");
+ osparc.ui.window.Window.popUpInWindow(permissionsView, title, 500, 400);
+ permissionsView.addListener("updateAccessRights", () => this.__applyAccessRights(this.getWorkspace().getAccessRights()), this);
+ },
+
+ __deleteWorkspaceRequested: function() {
+ let msg = this.tr("Are you sure you want to delete") + " " + this.getTitle() + "?";
+ msg += "
" + this.tr("All the content of the workspace will be deleted.");
+ const confirmationWin = new osparc.ui.window.Confirmation(msg).set({
+ confirmText: this.tr("Delete"),
+ confirmAction: "delete"
+ });
+ confirmationWin.center();
+ confirmationWin.open();
+ confirmationWin.addListener("close", () => {
+ if (confirmationWin.getConfirmed()) {
+ this.fireDataEvent("deleteWorkspaceRequested", this.getWorkspaceId());
+ }
+ }, this);
+ }
+ }
+});
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonNew.js b/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonNew.js
new file mode 100644
index 00000000000..b06dd548529
--- /dev/null
+++ b/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceButtonNew.js
@@ -0,0 +1,78 @@
+/* ************************************************************************
+
+ 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)
+
+************************************************************************ */
+
+/**
+ * Widget used for displaying a New Workspace in the Study Browser
+ *
+ */
+
+qx.Class.define("osparc.dashboard.WorkspaceButtonNew", {
+ extend: osparc.dashboard.WorkspaceButtonBase,
+
+ construct: function() {
+ this.base(arguments);
+
+ this.set({
+ appearance: "pb-new"
+ });
+
+ this.addListener("changeValue", e => this.__itemSelected(e.getData()), this);
+
+ this.setPriority(osparc.dashboard.CardBase.CARD_PRIORITY.NEW);
+
+ const title = this.getChildControl("title");
+ title.setValue(this.tr("New Workspace"));
+
+ this.setIcon(osparc.dashboard.CardBase.NEW_ICON);
+
+ this.getChildControl("footer").exclude();
+ },
+
+ events: {
+ "createWorkspace": "qx.event.type.Data",
+ "updateWorkspace": "qx.event.type.Data"
+ },
+
+ members: {
+ __itemSelected: function(newVal) {
+ if (newVal) {
+ const workspaceEditor = new osparc.editor.WorkspaceEditor(true);
+ const title = this.tr("New Workspace");
+ const win = osparc.ui.window.Window.popUpInWindow(workspaceEditor, title, 300, 200);
+ workspaceEditor.addListener("createWorkspace", () => {
+ const newWorkspaceData = {
+ name: workspaceEditor.getLabel(),
+ description: workspaceEditor.getDescription(),
+ thumbnail: workspaceEditor.getThumbnail(),
+ };
+ osparc.store.Workspaces.postWorkspace(newWorkspaceData)
+ .then(newWorkspace => {
+ this.fireDataEvent("createWorkspace");
+ const permissionsView = new osparc.share.CollaboratorsWorkspace(newWorkspace);
+ const title2 = qx.locale.Manager.tr("Share Workspace");
+ osparc.ui.window.Window.popUpInWindow(permissionsView, title2, 500, 500);
+ permissionsView.addListener("updateAccessRights", () => this.fireDataEvent("updateWorkspace", newWorkspace.getWorkspaceId()), this);
+ })
+ .catch(console.error)
+ .finally(() => win.close());
+ });
+ workspaceEditor.addListener("cancel", () => win.close());
+ }
+ this.setValue(false);
+ }
+ }
+});
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/FolderWithSharedIcon.js b/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceWithSharedIcon.js
similarity index 95%
rename from services/static-webserver/client/source/class/osparc/dashboard/FolderWithSharedIcon.js
rename to services/static-webserver/client/source/class/osparc/dashboard/WorkspaceWithSharedIcon.js
index af6573fb16f..2e3b8a88d89 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/FolderWithSharedIcon.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/WorkspaceWithSharedIcon.js
@@ -15,7 +15,7 @@
************************************************************************ */
-qx.Class.define("osparc.dashboard.FolderWithSharedIcon", {
+qx.Class.define("osparc.dashboard.WorkspaceWithSharedIcon", {
extend: qx.ui.core.Widget,
construct: function() {
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 44ea7b20671..098d3239bfa 100644
--- a/services/static-webserver/client/source/class/osparc/data/Resources.js
+++ b/services/static-webserver/client/source/class/osparc/data/Resources.js
@@ -319,6 +319,42 @@ qx.Class.define("osparc.data.Resources", {
}
}
},
+ "workspaces": {
+ endpoints: {
+ getPage: {
+ method: "GET",
+ url: statics.API + "/workspaces?workspace_id={workspaceId}&offset={offset}&limit={limit}"
+ },
+ getOne: {
+ method: "GET",
+ url: statics.API + "/workspaces/{workspaceId}"
+ },
+ post: {
+ method: "POST",
+ url: statics.API + "/workspaces"
+ },
+ update: {
+ method: "PUT",
+ url: statics.API + "/workspaces/{workspaceId}"
+ },
+ delete: {
+ method: "DELETE",
+ url: statics.API + "/workspaces/{workspaceId}"
+ },
+ postAccessRights: {
+ method: "POST",
+ url: statics.API + "/workspaces/{workspaceId}/groups/{groupId}"
+ },
+ putAccessRights: {
+ method: "PUT",
+ url: statics.API + "/workspaces/{workspaceId}/groups/{groupId}"
+ },
+ deleteAccessRights: {
+ method: "DELETE",
+ url: statics.API + "/workspaces/{workspaceId}/groups/{groupId}"
+ },
+ }
+ },
"resourceUsage": {
useCache: false,
endpoints: {
@@ -470,7 +506,7 @@ qx.Class.define("osparc.data.Resources", {
* SERVICES V2 (web-api >=0.42.0)
*/
"servicesV2": {
- useCache: false, // handled in osparc.service.Store
+ useCache: false, // handled in osparc.store.Services
idField: ["key", "version"],
endpoints: {
get: {
diff --git a/services/static-webserver/client/source/class/osparc/data/Roles.js b/services/static-webserver/client/source/class/osparc/data/Roles.js
index 5d5a1d7c017..ccb66ffb7d7 100644
--- a/services/static-webserver/client/source/class/osparc/data/Roles.js
+++ b/services/static-webserver/client/source/class/osparc/data/Roles.js
@@ -135,7 +135,7 @@ qx.Class.define("osparc.data.Roles", {
}
},
- FOLDERS: {
+ WORKSPACE: {
1: {
id: "read",
label: qx.locale.Manager.tr("Viewer"),
@@ -158,7 +158,7 @@ qx.Class.define("osparc.data.Roles", {
label: qx.locale.Manager.tr("Owner"),
longLabel: qx.locale.Manager.tr("Owner: Read/Write/Delete access"),
canDo: [
- qx.locale.Manager.tr("- can rename folder"),
+ qx.locale.Manager.tr("- can rename workspace"),
qx.locale.Manager.tr("- can share it"),
qx.locale.Manager.tr("- can delete it")
]
@@ -216,8 +216,8 @@ qx.Class.define("osparc.data.Roles", {
return this.__createIntoFromRoles(osparc.data.Roles.SERVICES);
},
- createRolesFolderInfo: function(showWording = true) {
- return this.__createIntoFromRoles(osparc.data.Roles.FOLDERS, showWording);
+ createRolesWorkspaceInfo: function(showWording = true) {
+ return this.__createIntoFromRoles(osparc.data.Roles.WORKSPACE, showWording);
}
}
});
diff --git a/services/static-webserver/client/source/class/osparc/data/model/Folder.js b/services/static-webserver/client/source/class/osparc/data/model/Folder.js
index 9b8f7bcc630..a3e1eb7ca90 100644
--- a/services/static-webserver/client/source/class/osparc/data/model/Folder.js
+++ b/services/static-webserver/client/source/class/osparc/data/model/Folder.js
@@ -16,7 +16,7 @@
************************************************************************ */
/**
- * Class that stores Service data.
+ * Class that stores Folder data.
*/
qx.Class.define("osparc.data.model.Folder", {
diff --git a/services/static-webserver/client/source/class/osparc/data/model/Node.js b/services/static-webserver/client/source/class/osparc/data/model/Node.js
index a6cf28b8af3..6373d8835ca 100644
--- a/services/static-webserver/client/source/class/osparc/data/model/Node.js
+++ b/services/static-webserver/client/source/class/osparc/data/model/Node.js
@@ -382,7 +382,7 @@ qx.Class.define("osparc.data.model.Node", {
__applyNewMetaData: function(newV, oldV) {
if (oldV !== null) {
- const metadata = osparc.service.Store.getMetadata(this.getKey(), this.getVersion());
+ const metadata = osparc.store.Services.getMetadata(this.getKey(), this.getVersion());
if (metadata) {
this.__metaData = metadata;
}
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 6c16d1a9851..8fd40a67a28 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
@@ -299,7 +299,7 @@ qx.Class.define("osparc.data.model.Study", {
let nCompNodes = 0;
let overallProgress = 0;
Object.values(nodes).forEach(node => {
- const metadata = osparc.service.Store.getMetadata(node["key"], node["version"]);
+ const metadata = osparc.store.Services.getMetadata(node["key"], node["version"]);
if (metadata && osparc.data.model.Node.isComputational(metadata)) {
const progress = "progress" in node ? node["progress"] : 0;
overallProgress += progress;
diff --git a/services/static-webserver/client/source/class/osparc/data/model/Workbench.js b/services/static-webserver/client/source/class/osparc/data/model/Workbench.js
index 1110d55b736..3120a22f7f1 100644
--- a/services/static-webserver/client/source/class/osparc/data/model/Workbench.js
+++ b/services/static-webserver/client/source/class/osparc/data/model/Workbench.js
@@ -295,7 +295,7 @@ qx.Class.define("osparc.data.model.Workbench", {
};
try {
- const metadata = await osparc.service.Store.getService(key, version);
+ const metadata = await osparc.store.Services.getService(key, version);
const resp = await osparc.data.Resources.fetch("studies", "addNode", params);
const nodeId = resp["node_id"];
@@ -679,7 +679,7 @@ qx.Class.define("osparc.data.model.Workbench", {
const metadataPromises = [];
nodeIds.forEach(nodeId => {
const nodeData = workbenchData[nodeId];
- metadataPromises.push(osparc.service.Store.getService(nodeData.key, nodeData.version));
+ metadataPromises.push(osparc.store.Services.getService(nodeData.key, nodeData.version));
});
return Promise.all(metadataPromises)
diff --git a/services/static-webserver/client/source/class/osparc/data/model/Workspace.js b/services/static-webserver/client/source/class/osparc/data/model/Workspace.js
new file mode 100644
index 00000000000..ea4c324e9aa
--- /dev/null
+++ b/services/static-webserver/client/source/class/osparc/data/model/Workspace.js
@@ -0,0 +1,121 @@
+/* ************************************************************************
+
+ 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)
+
+************************************************************************ */
+
+/**
+ * Class that stores Workspace data.
+ */
+
+qx.Class.define("osparc.data.model.Workspace", {
+ extend: qx.core.Object,
+
+ /**
+ * @param workspaceData {Object} Object containing the serialized Workspace Data
+ */
+ construct: function(workspaceData) {
+ this.base(arguments);
+
+ this.set({
+ workspaceId: workspaceData.workspaceId,
+ name: workspaceData.name,
+ description: workspaceData.description,
+ thumbnail: workspaceData.thumbnail,
+ myAccessRights: workspaceData.myAccessRights,
+ accessRights: workspaceData.accessRights,
+ createdAt: new Date(workspaceData.createdAt),
+ lastModified: new Date(workspaceData.lastModified),
+ });
+ },
+
+ properties: {
+ workspaceId: {
+ check: "Number",
+ nullable: false,
+ init: null,
+ event: "changeId"
+ },
+
+ name: {
+ check: "String",
+ nullable: false,
+ init: null,
+ event: "changeName"
+ },
+
+ description: {
+ check: "String",
+ nullable: true,
+ init: null,
+ event: "changeDescription"
+ },
+
+ thumbnail: {
+ check: "String",
+ nullable: true,
+ init: null,
+ event: "changeThumbnail"
+ },
+
+ myAccessRights: {
+ check: "Object",
+ nullable: false,
+ init: null,
+ event: "changeMyAccessRights"
+ },
+
+ accessRights: {
+ check: "Object",
+ nullable: false,
+ init: null,
+ event: "changeAccessRights"
+ },
+
+ createdAt: {
+ check: "Date",
+ nullable: true,
+ init: null,
+ event: "changeCreatedAt"
+ },
+
+ lastModified: {
+ check: "Date",
+ nullable: true,
+ init: null,
+ event: "changeLastModified"
+ }
+ },
+
+ statics: {
+ putWorkspace: function(workspaceId, propKey, value) {
+ return osparc.store.Workspaces.putWorkspace(workspaceId, propKey, value);
+ },
+
+ getProperties: function() {
+ return Object.keys(qx.util.PropertyUtil.getProperties(osparc.data.model.Workspace));
+ }
+ },
+
+ members: {
+ serialize: function() {
+ const jsonObject = {};
+ const propertyKeys = this.self().getProperties();
+ propertyKeys.forEach(key => {
+ jsonObject[key] = this.get(key);
+ });
+ return jsonObject;
+ }
+ }
+});
diff --git a/services/static-webserver/client/source/class/osparc/desktop/organizations/ServicesList.js b/services/static-webserver/client/source/class/osparc/desktop/organizations/ServicesList.js
index d6655889ed7..6a212375312 100644
--- a/services/static-webserver/client/source/class/osparc/desktop/organizations/ServicesList.js
+++ b/services/static-webserver/client/source/class/osparc/desktop/organizations/ServicesList.js
@@ -115,7 +115,7 @@ qx.Class.define("osparc.desktop.organizations.ServicesList", {
}
const gid = orgModel.getGid();
- osparc.service.Store.getServicesLatest()
+ osparc.store.Services.getServicesLatest()
.then(servicesLatest => {
const orgServices = [];
Object.keys(servicesLatest).forEach(key => {
diff --git a/services/static-webserver/client/source/class/osparc/editor/ThumbnailSuggestions.js b/services/static-webserver/client/source/class/osparc/editor/ThumbnailSuggestions.js
index ff496032568..ba361f12f46 100644
--- a/services/static-webserver/client/source/class/osparc/editor/ThumbnailSuggestions.js
+++ b/services/static-webserver/client/source/class/osparc/editor/ThumbnailSuggestions.js
@@ -138,7 +138,7 @@ qx.Class.define("osparc.editor.ThumbnailSuggestions", {
}
const promises = [];
- queryParams.forEach(qP => promises.push(osparc.service.Store.getService(qP.key, qP.version)));
+ queryParams.forEach(qP => promises.push(osparc.store.Services.getService(qP.key, qP.version)));
return Promise.all(promises)
.then(values => {
const suggestions = new Set([]);
diff --git a/services/static-webserver/client/source/class/osparc/editor/WorkspaceEditor.js b/services/static-webserver/client/source/class/osparc/editor/WorkspaceEditor.js
new file mode 100644
index 00000000000..3a654307006
--- /dev/null
+++ b/services/static-webserver/client/source/class/osparc/editor/WorkspaceEditor.js
@@ -0,0 +1,162 @@
+/* ************************************************************************
+
+ 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.editor.WorkspaceEditor", {
+ extend: qx.ui.core.Widget,
+
+ construct: function(newWorkspace = true) {
+ this.base(arguments);
+
+ this._setLayout(new qx.ui.layout.VBox(8));
+
+ const manager = this.__validator = new qx.ui.form.validation.Manager();
+ const title = this.getChildControl("title");
+ title.setRequired(true);
+ manager.add(title);
+ this.getChildControl("description");
+ this.getChildControl("thumbnail");
+ newWorkspace ? this.getChildControl("create") : this.getChildControl("save");
+
+ this.addListener("appear", this.__onAppear, this);
+ },
+
+ properties: {
+ label: {
+ check: "String",
+ init: "",
+ nullable: false,
+ event: "changeLabel"
+ },
+
+ description: {
+ check: "String",
+ init: "",
+ nullable: false,
+ event: "changeDescription"
+ },
+
+ thumbnail: {
+ check: "String",
+ init: "",
+ nullable: false,
+ event: "changeThumbnail"
+ },
+
+ accessRights: {
+ check: "Object",
+ init: {},
+ nullable: false,
+ event: "changeAccessRights",
+ apply: "applyAccessRights"
+ }
+ },
+
+ events: {
+ "createWorkspace": "qx.event.type.Event",
+ "updateWorkspace": "qx.event.type.Event",
+ "cancel": "qx.event.type.Event"
+ },
+
+ members: {
+ _createChildControlImpl: function(id) {
+ let control;
+ switch (id) {
+ case "title": {
+ control = new qx.ui.form.TextField().set({
+ font: "text-14",
+ backgroundColor: "background-main",
+ placeholder: this.tr("Title"),
+ });
+ this.bind("label", control, "value");
+ control.bind("value", this, "label");
+ this._add(control);
+ break;
+ }
+ case "description": {
+ control = new qx.ui.form.TextArea().set({
+ font: "text-14",
+ placeholder: this.tr("Description"),
+ autoSize: true,
+ minHeight: 70,
+ });
+ this.bind("description", control, "value");
+ control.bind("value", this, "description");
+ this._add(control);
+ break;
+ }
+ case "thumbnail": {
+ control = new qx.ui.form.TextField().set({
+ font: "text-14",
+ placeholder: this.tr("Thumbnail"),
+ });
+ this.bind("thumbnail", control, "value");
+ control.bind("value", this, "thumbnail");
+ this._add(control);
+ break;
+ }
+ case "create": {
+ const buttons = this.getChildControl("buttonsLayout");
+ control = new osparc.ui.form.FetchButton(this.tr("Create")).set({
+ appearance: "form-button"
+ });
+ control.addListener("execute", () => {
+ if (this.__validator.validate()) {
+ control.setFetching(true);
+ this.fireEvent("createWorkspace");
+ }
+ }, this);
+ buttons.addAt(control, 1);
+ break;
+ }
+ case "save": {
+ const buttons = this.getChildControl("buttonsLayout");
+ control = new osparc.ui.form.FetchButton(this.tr("Save")).set({
+ appearance: "form-button"
+ });
+ control.addListener("execute", () => {
+ if (this.__validator.validate()) {
+ control.setFetching(true);
+ this.fireEvent("updateWorkspace");
+ }
+ }, this);
+ buttons.addAt(control, 1);
+ break;
+ }
+ case "buttonsLayout": {
+ control = new qx.ui.container.Composite(new qx.ui.layout.HBox(8).set({
+ alignX: "right"
+ }));
+ const cancelButton = new qx.ui.form.Button(this.tr("Cancel")).set({
+ appearance: "form-button-text"
+ });
+ cancelButton.addListener("execute", () => this.fireEvent("cancel"), this);
+ control.addAt(cancelButton, 0);
+ this._add(control);
+ break;
+ }
+ }
+
+ return control || this.base(arguments, id);
+ },
+
+ __onAppear: function() {
+ const title = this.getChildControl("title");
+ title.focus();
+ title.activate();
+ }
+ }
+});
diff --git a/services/static-webserver/client/source/class/osparc/info/MergedLarge.js b/services/static-webserver/client/source/class/osparc/info/MergedLarge.js
index cefe7e01c9a..d85ffef353d 100644
--- a/services/static-webserver/client/source/class/osparc/info/MergedLarge.js
+++ b/services/static-webserver/client/source/class/osparc/info/MergedLarge.js
@@ -325,7 +325,7 @@ qx.Class.define("osparc.info.MergedLarge", {
};
promise = osparc.data.Resources.get("nodesInStudyResources", params);
} else {
- promise = osparc.service.Store.getResources(this.getNode().getKey(), this.getNode().getVersion())
+ promise = osparc.store.Services.getResources(this.getNode().getKey(), this.getNode().getVersion())
}
promise
.then(serviceResources => {
diff --git a/services/static-webserver/client/source/class/osparc/info/ServiceLarge.js b/services/static-webserver/client/source/class/osparc/info/ServiceLarge.js
index efdccc3ad7d..9eb0bddf435 100644
--- a/services/static-webserver/client/source/class/osparc/info/ServiceLarge.js
+++ b/services/static-webserver/client/source/class/osparc/info/ServiceLarge.js
@@ -360,7 +360,7 @@ qx.Class.define("osparc.info.ServiceLarge", {
};
promise = osparc.data.Resources.get("nodesInStudyResources", params);
} else {
- promise = osparc.service.Store.getResources(this.getService()["key"], this.getService()["version"])
+ promise = osparc.store.Services.getResources(this.getService()["key"], this.getService()["version"])
}
promise
.then(serviceResources => {
@@ -474,7 +474,7 @@ qx.Class.define("osparc.info.ServiceLarge", {
__patchService: function(key, value) {
const serviceDataCopy = osparc.utils.Utils.deepCloneObject(this.getService());
- osparc.service.Store.patchServiceData(serviceDataCopy, key, value)
+ osparc.store.Services.patchServiceData(serviceDataCopy, key, value)
.then(() => {
this.setService(serviceDataCopy);
this.fireDataEvent("updateService", this.getService());
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 eb1f70913c5..abbee546dae 100644
--- a/services/static-webserver/client/source/class/osparc/info/StudyUtils.js
+++ b/services/static-webserver/client/source/class/osparc/info/StudyUtils.js
@@ -370,7 +370,7 @@ qx.Class.define("osparc.info.StudyUtils", {
openAccessRights: function(studyData) {
const permissionsView = new osparc.share.CollaboratorsStudy(studyData);
const title = qx.locale.Manager.tr("Share with Editors and Organizations");
- osparc.ui.window.Window.popUpInWindow(permissionsView, title, 500, 400);
+ osparc.ui.window.Window.popUpInWindow(permissionsView, title, 500, 500);
return permissionsView;
},
diff --git a/services/static-webserver/client/source/class/osparc/metadata/ClassifiersEditor.js b/services/static-webserver/client/source/class/osparc/metadata/ClassifiersEditor.js
index ee9c7328b46..3f66e39d7ec 100644
--- a/services/static-webserver/client/source/class/osparc/metadata/ClassifiersEditor.js
+++ b/services/static-webserver/client/source/class/osparc/metadata/ClassifiersEditor.js
@@ -158,7 +158,7 @@ qx.Class.define("osparc.metadata.ClassifiersEditor", {
});
} else {
const serviceDataCopy = osparc.utils.Utils.deepCloneObject(this.__resourceData);
- osparc.service.Store.patchServiceData(serviceDataCopy, "classifiers", newClassifiers)
+ osparc.store.Services.patchServiceData(serviceDataCopy, "classifiers", newClassifiers)
.then(() => {
osparc.FlashMessenger.getInstance().logAs(this.tr("Classifiers successfully edited"));
saveBtn.setFetching(false);
diff --git a/services/static-webserver/client/source/class/osparc/metadata/QualityEditor.js b/services/static-webserver/client/source/class/osparc/metadata/QualityEditor.js
index 5ac435dcea7..1b1000e5d68 100644
--- a/services/static-webserver/client/source/class/osparc/metadata/QualityEditor.js
+++ b/services/static-webserver/client/source/class/osparc/metadata/QualityEditor.js
@@ -457,7 +457,7 @@ qx.Class.define("osparc.metadata.QualityEditor", {
btn.setFetching(true);
if (osparc.utils.Resources.isService(this.__resourceData)) {
const serviceDataCopy = osparc.utils.Utils.deepCloneObject(this.__resourceData);
- osparc.service.Store.patchServiceData(serviceDataCopy, "quality", newQuality)
+ osparc.store.Services.patchServiceData(serviceDataCopy, "quality", newQuality)
.then(() => {
this.__initResourceData(serviceDataCopy);
this.fireDataEvent("updateQuality", serviceDataCopy);
diff --git a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js
index 03802472180..9f1dbe17600 100644
--- a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js
+++ b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js
@@ -45,7 +45,7 @@ qx.Class.define("osparc.metadata.ServicesInStudy", {
const servicesInStudy = osparc.study.Utils.extractServices(this._studyData["workbench"]);
if (servicesInStudy.length) {
const promises = [];
- servicesInStudy.forEach(srv => promises.push(osparc.service.Store.getService(srv.key, srv.version)));
+ servicesInStudy.forEach(srv => promises.push(osparc.store.Services.getService(srv.key, srv.version)));
Promise.all(promises)
.then(() => this._populateLayout());
} else {
@@ -137,7 +137,7 @@ qx.Class.define("osparc.metadata.ServicesInStudy", {
const infoButton = new qx.ui.form.Button(null, "@MaterialIcons/info_outline/14");
infoButton.addListener("execute", () => {
- const metadata = osparc.service.Store.getMetadata(node["key"], node["version"]);
+ const metadata = osparc.store.Services.getMetadata(node["key"], node["version"]);
if (metadata === null) {
osparc.FlashMessenger.logAs(this.tr("Service information could not be retrieved"), "WARNING");
return;
@@ -167,7 +167,7 @@ qx.Class.define("osparc.metadata.ServicesInStudy", {
});
this.__grid.setRowHeight(i, 24);
- const nodeMetadata = osparc.service.Store.getMetadata(node["key"], node["version"]);
+ const nodeMetadata = osparc.store.Services.getMetadata(node["key"], node["version"]);
if (nodeMetadata === null) {
osparc.FlashMessenger.logAs(this.tr("Some service information could not be retrieved"), "WARNING");
break;
diff --git a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyBootOpts.js b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyBootOpts.js
index 5f3802d1267..72ad2d4530e 100644
--- a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyBootOpts.js
+++ b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyBootOpts.js
@@ -25,7 +25,7 @@ qx.Class.define("osparc.metadata.ServicesInStudyBootOpts", {
if ("workbench" in studyData) {
for (const nodeId in studyData["workbench"]) {
const node = studyData["workbench"][nodeId];
- const metadata = osparc.service.Store.getMetadata(node["key"], node["version"]);
+ const metadata = osparc.store.Services.getMetadata(node["key"], node["version"]);
if (metadata && osparc.data.model.Node.hasBootModes(metadata)) {
return true;
}
@@ -74,7 +74,7 @@ qx.Class.define("osparc.metadata.ServicesInStudyBootOpts", {
for (const nodeId in workbench) {
i++;
const node = workbench[nodeId];
- const nodeMetadata = osparc.service.Store.getMetadata(node["key"], node["version"]);
+ const nodeMetadata = osparc.store.Services.getMetadata(node["key"], node["version"]);
if (nodeMetadata === null) {
osparc.FlashMessenger.logAs(this.tr("Some service information could not be retrieved"), "WARNING");
break;
diff --git a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js
index 3ab2f4b87a1..bbd9685bfec 100644
--- a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js
+++ b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js
@@ -205,7 +205,7 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
for (const nodeId in workbench) {
i++;
const node = workbench[nodeId];
- const metadata = osparc.service.Store.getMetadata(node["key"], node["version"]);
+ const metadata = osparc.store.Services.getMetadata(node["key"], node["version"]);
const currentVersionLabel = new qx.ui.basic.Label(osparc.service.Utils.extractVersionDisplay(metadata)).set({
font: "text-14"
});
@@ -221,7 +221,7 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
const latestCompatible = osparc.service.Utils.getLatestCompatible(node["key"], node["version"]);
if (latestCompatible) {
// updatable
- osparc.service.Store.getService(latestCompatible["key"], latestCompatible["version"])
+ osparc.store.Services.getService(latestCompatible["key"], latestCompatible["version"])
.then(latestMetadata => {
let label = osparc.service.Utils.extractVersionDisplay(latestMetadata)
if (node["key"] !== latestMetadata["key"]) {
diff --git a/services/static-webserver/client/source/class/osparc/pricing/ServicesList.js b/services/static-webserver/client/source/class/osparc/pricing/ServicesList.js
index f3b5c60949b..eb215da3c76 100644
--- a/services/static-webserver/client/source/class/osparc/pricing/ServicesList.js
+++ b/services/static-webserver/client/source/class/osparc/pricing/ServicesList.js
@@ -83,7 +83,7 @@ qx.Class.define("osparc.pricing.ServicesList", {
services.forEach(service => {
const key = service["serviceKey"];
const version = service["serviceVersion"];
- metadataPromises.push(osparc.service.Store.getService(key, version));
+ metadataPromises.push(osparc.store.Services.getService(key, version));
});
Promise.all(metadataPromises)
.catch(err => console.error(err))
@@ -92,7 +92,7 @@ qx.Class.define("osparc.pricing.ServicesList", {
services.forEach(service => {
const key = service["serviceKey"];
const version = service["serviceVersion"];
- const serviceMetadata = osparc.service.Store.getMetadata(key, version);
+ const serviceMetadata = osparc.store.Services.getMetadata(key, version);
if (serviceMetadata) {
sList.push(new osparc.data.model.Service(serviceMetadata));
}
diff --git a/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js b/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js
index 543e3d0b11a..059dd840170 100644
--- a/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js
+++ b/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js
@@ -158,7 +158,7 @@ qx.Class.define("osparc.service.ServiceListItem", {
if (version === this.self().LATEST) {
version = this.__versionsBox.getChildrenContainer().getSelectables()[1].version;
}
- osparc.service.Store.getService(key, version)
+ osparc.store.Services.getService(key, version)
.then(serviceMetadata => {
const serviceDetails = new osparc.info.ServiceLarge(serviceMetadata);
const title = this.tr("Service information");
diff --git a/services/static-webserver/client/source/class/osparc/service/Utils.js b/services/static-webserver/client/source/class/osparc/service/Utils.js
index 38ce2b31905..b47f3a5b5fa 100644
--- a/services/static-webserver/client/source/class/osparc/service/Utils.js
+++ b/services/static-webserver/client/source/class/osparc/service/Utils.js
@@ -65,8 +65,6 @@ qx.Class.define("osparc.service.Utils", {
}
},
- servicesCached: {},
-
getTypes: function() {
return Object.keys(this.TYPES);
},
@@ -133,7 +131,7 @@ qx.Class.define("osparc.service.Utils", {
},
getVersions: function(key, filterDeprecated = true) {
- const services = osparc.service.Store.servicesCached;
+ const services = osparc.store.Services.servicesCached;
let versions = [];
if (key in services) {
const serviceVersions = services[key];
@@ -152,7 +150,7 @@ qx.Class.define("osparc.service.Utils", {
},
getLatest: function(key) {
- const services = osparc.service.Store.servicesCached;
+ const services = osparc.store.Services.servicesCached;
if (key in services) {
const versions = this.getVersions(key, true);
if (versions.length) {
@@ -163,7 +161,7 @@ qx.Class.define("osparc.service.Utils", {
},
getLatestCompatible: function(key, version) {
- const services = osparc.service.Store.servicesCached;
+ const services = osparc.store.Services.servicesCached;
if (key in services && version in services[key]) {
const serviceMD = services[key][version];
if (serviceMD["compatibility"] && serviceMD["compatibility"]["canUpdateTo"]) {
@@ -183,7 +181,7 @@ qx.Class.define("osparc.service.Utils", {
},
getVersionDisplay: function(key, version) {
- const services = osparc.service.Store.servicesCached;
+ const services = osparc.store.Services.servicesCached;
if (key in services && version in services[key]) {
return this.extractVersionDisplay(services[key][version]);
}
@@ -195,7 +193,7 @@ qx.Class.define("osparc.service.Utils", {
},
getReleasedDate: function(key, version) {
- const services = osparc.service.Store.servicesCached;
+ const services = osparc.store.Services.servicesCached;
if (
key in services &&
version in services[key] &&
@@ -262,7 +260,8 @@ qx.Class.define("osparc.service.Utils", {
getParametersMetadata: function() {
const parametersMetadata = [];
- for (const key in this.servicesCached) {
+ const services = osparc.store.Services.servicesCached;
+ for (const key in services) {
if (key.includes("simcore/services/frontend/parameter/")) {
const latest = this.self().getLatest(key);
if (latest) {
diff --git a/services/static-webserver/client/source/class/osparc/share/Collaborators.js b/services/static-webserver/client/source/class/osparc/share/Collaborators.js
index 47163863b82..c315c7d26d3 100644
--- a/services/static-webserver/client/source/class/osparc/share/Collaborators.js
+++ b/services/static-webserver/client/source/class/osparc/share/Collaborators.js
@@ -199,8 +199,8 @@ qx.Class.define("osparc.share.Collaborators", {
case "service":
fullOptions = osparc.service.Utils.canIWrite(this._serializedDataCopy["accessRights"]);
break;
- case "folder":
- fullOptions = osparc.share.CollaboratorsFolder.canIDelete(this._serializedDataCopy["myAccessRights"]);
+ case "workspace":
+ fullOptions = osparc.share.CollaboratorsWorkspace.canIDelete(this._serializedDataCopy["myAccessRights"]);
break;
}
return fullOptions;
@@ -212,8 +212,8 @@ qx.Class.define("osparc.share.Collaborators", {
case "service":
rolesLayout = osparc.data.Roles.createRolesServicesInfo();
break;
- case "folder":
- rolesLayout = osparc.data.Roles.createRolesFolderInfo();
+ case "workspace":
+ rolesLayout = osparc.data.Roles.createRolesWorkspaceInfo();
break;
default:
rolesLayout = osparc.data.Roles.createRolesStudyInfo();
diff --git a/services/static-webserver/client/source/class/osparc/share/CollaboratorsService.js b/services/static-webserver/client/source/class/osparc/share/CollaboratorsService.js
index 7379a512b9b..4f540ebb211 100644
--- a/services/static-webserver/client/source/class/osparc/share/CollaboratorsService.js
+++ b/services/static-webserver/client/source/class/osparc/share/CollaboratorsService.js
@@ -90,7 +90,7 @@ qx.Class.define("osparc.share.CollaboratorsService", {
gids.forEach(gid => {
newAccessRights[gid] = this.self().getCollaboratorAccessRight();
});
- osparc.service.Store.patchServiceData(this._serializedDataCopy, "accessRights", newAccessRights)
+ osparc.store.Services.patchServiceData(this._serializedDataCopy, "accessRights", newAccessRights)
.then(() => {
this.fireDataEvent("updateAccessRights", this._serializedDataCopy);
let text = this.tr("Editor(s) successfully added.");
@@ -119,7 +119,7 @@ qx.Class.define("osparc.share.CollaboratorsService", {
return;
}
- osparc.service.Store.patchServiceData(this._serializedDataCopy, "accessRights", this._serializedDataCopy["accessRights"])
+ osparc.store.Services.patchServiceData(this._serializedDataCopy, "accessRights", this._serializedDataCopy["accessRights"])
.then(() => {
this.fireDataEvent("updateAccessRights", this._serializedDataCopy);
osparc.FlashMessenger.getInstance().logAs(this.tr("Member successfully removed"));
@@ -139,7 +139,7 @@ qx.Class.define("osparc.share.CollaboratorsService", {
__make: function(collaboratorGId, newAccessRights, successMsg, failureMsg, item) {
item.setEnabled(false);
this._serializedDataCopy["accessRights"][collaboratorGId] = newAccessRights;
- osparc.service.Store.patchServiceData(this._serializedDataCopy, "accessRights", this._serializedDataCopy["accessRights"])
+ osparc.store.Services.patchServiceData(this._serializedDataCopy, "accessRights", this._serializedDataCopy["accessRights"])
.then(() => {
this.fireDataEvent("updateAccessRights", this._serializedDataCopy);
osparc.FlashMessenger.getInstance().logAs(successMsg);
diff --git a/services/static-webserver/client/source/class/osparc/share/CollaboratorsFolder.js b/services/static-webserver/client/source/class/osparc/share/CollaboratorsWorkspace.js
similarity index 69%
rename from services/static-webserver/client/source/class/osparc/share/CollaboratorsFolder.js
rename to services/static-webserver/client/source/class/osparc/share/CollaboratorsWorkspace.js
index d68df6a9dde..202d86b5e5d 100644
--- a/services/static-webserver/client/source/class/osparc/share/CollaboratorsFolder.js
+++ b/services/static-webserver/client/source/class/osparc/share/CollaboratorsWorkspace.js
@@ -16,18 +16,18 @@
************************************************************************ */
-qx.Class.define("osparc.share.CollaboratorsFolder", {
+qx.Class.define("osparc.share.CollaboratorsWorkspace", {
extend: osparc.share.Collaborators,
/**
- * @param folder {osparc.data.model.Folder}
+ * @param workspace {osparc.data.model.Workspace}
*/
- construct: function(folder) {
- this.__folder = folder;
- this._resourceType = "folder";
+ construct: function(workspace) {
+ this.__workspace = workspace;
+ this._resourceType = "workspace";
- const folderDataCopy = folder.serialize();
- this.base(arguments, folderDataCopy, []);
+ const workspaceDataCopy = workspace.serialize();
+ this.base(arguments, workspaceDataCopy, []);
},
statics: {
@@ -61,7 +61,7 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
},
members: {
- __folder: null,
+ __workspace: null,
_addEditors: function(gids) {
if (gids.length === 0) {
@@ -70,9 +70,9 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
const newCollaborators = {};
gids.forEach(gid => newCollaborators[gid] = this.self().getCollaboratorAccessRight());
- osparc.store.Folders.getInstance().addCollaborators(this.__folder.getFolderId(), newCollaborators)
+ osparc.store.Workspaces.addCollaborators(this.__workspace.getWorkspaceId(), newCollaborators)
.then(() => {
- this.fireDataEvent("updateAccessRights", this.__folder.serialize());
+ this.fireDataEvent("updateAccessRights", this.__workspace.serialize());
const text = this.tr("User(s) successfully added.");
osparc.FlashMessenger.getInstance().logAs(text);
this._reloadCollaboratorsList();
@@ -88,9 +88,9 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
item.setEnabled(false);
}
- osparc.store.Folders.getInstance().removeCollaborator(this.__folder.getFolderId(), collaborator["gid"])
+ osparc.store.Workspaces.removeCollaborator(this.__workspace.getWorkspaceId(), collaborator["gid"])
.then(() => {
- this.fireDataEvent("updateAccessRights", this.__folder.serialize());
+ this.fireDataEvent("updateAccessRights", this.__workspace.serialize());
osparc.FlashMessenger.getInstance().logAs(this.tr("Member successfully removed"));
this._reloadCollaboratorsList();
})
@@ -108,9 +108,9 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
__make: function(collaboratorGId, newAccessRights, successMsg, failureMsg, item) {
item.setEnabled(false);
- osparc.store.Folders.getInstance().updateCollaborator(this.__folder.getFolderId(), collaboratorGId, newAccessRights)
+ osparc.store.Workspaces.updateCollaborator(this.__workspace.getWorkspaceId(), collaboratorGId, newAccessRights)
.then(() => {
- this.fireDataEvent("updateAccessRights", this.__folder.serialize());
+ this.fireDataEvent("updateAccessRights", this.__workspace.serialize());
osparc.FlashMessenger.getInstance().logAs(successMsg);
this._reloadCollaboratorsList();
})
@@ -129,8 +129,8 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
this.__make(
collaborator["gid"],
this.self().getCollaboratorAccessRight(),
- this.tr(`${osparc.data.Roles.FOLDERS[1].label} successfully changed ${osparc.data.Roles.FOLDERS[2].label}`),
- this.tr(`Something went wrong changing ${osparc.data.Roles.FOLDERS[1].label} to ${osparc.data.Roles.FOLDERS[2].label}`),
+ this.tr(`${osparc.data.Roles.WORKSPACE[1].label} successfully changed ${osparc.data.Roles.WORKSPACE[2].label}`),
+ this.tr(`Something went wrong changing ${osparc.data.Roles.WORKSPACE[1].label} to ${osparc.data.Roles.WORKSPACE[2].label}`),
item
);
},
@@ -139,8 +139,8 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
this.__make(
collaborator["gid"],
this.self().getOwnerAccessRight(),
- this.tr(`${osparc.data.Roles.FOLDERS[2].label} successfully changed to ${osparc.data.Roles.FOLDERS[3].label}`),
- this.tr(`Something went wrong changing ${osparc.data.Roles.FOLDERS[2].label} to ${osparc.data.Roles.FOLDERS[3].label}`),
+ this.tr(`${osparc.data.Roles.WORKSPACE[2].label} successfully changed to ${osparc.data.Roles.WORKSPACE[3].label}`),
+ this.tr(`Something went wrong changing ${osparc.data.Roles.WORKSPACE[2].label} to ${osparc.data.Roles.WORKSPACE[3].label}`),
item
);
},
@@ -151,8 +151,8 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
this.__make(
gid,
this.self().getViewerAccessRight(),
- this.tr(`${osparc.data.Roles.FOLDERS[2].label} successfully changed to ${osparc.data.Roles.FOLDERS[1].label}`),
- this.tr(`Something went wrong changing ${osparc.data.Roles.FOLDERS[2].label} to ${osparc.data.Roles.FOLDERS[1].label}`),
+ this.tr(`${osparc.data.Roles.WORKSPACE[2].label} successfully changed to ${osparc.data.Roles.WORKSPACE[1].label}`),
+ this.tr(`Something went wrong changing ${osparc.data.Roles.WORKSPACE[2].label} to ${osparc.data.Roles.WORKSPACE[1].label}`),
itm
);
};
@@ -160,7 +160,7 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
const groupData = await osparc.store.Store.getInstance().getGroup(groupId);
const isOrganization = (groupData && !("id" in groupData));
if (isOrganization) {
- const msg = this.tr(`Demoting to ${osparc.data.Roles.FOLDERS[1].label} will remove write access to all the members of the Organization. Are you sure?`);
+ const msg = this.tr(`Demoting to ${osparc.data.Roles.WORKSPACE[1].label} will remove write access to all the members of the Organization. Are you sure?`);
const win = new osparc.ui.window.Confirmation(msg).set({
confirmAction: "delete",
confirmText: this.tr("Yes")
@@ -181,8 +181,8 @@ qx.Class.define("osparc.share.CollaboratorsFolder", {
this.__make(
collaborator["gid"],
this.self().getCollaboratorAccessRight(),
- this.tr(`${osparc.data.Roles.FOLDERS[3].label} successfully changed to ${osparc.data.Roles.FOLDERS[2].label}`),
- this.tr(`Something went wrong changing ${osparc.data.Roles.FOLDERS[3].label} to ${osparc.data.Roles.FOLDERS[2].label}`),
+ this.tr(`${osparc.data.Roles.WORKSPACE[3].label} successfully changed to ${osparc.data.Roles.WORKSPACE[2].label}`),
+ this.tr(`Something went wrong changing ${osparc.data.Roles.WORKSPACE[3].label} to ${osparc.data.Roles.WORKSPACE[2].label}`),
item
);
}
diff --git a/services/static-webserver/client/source/class/osparc/share/ShareePermissions.js b/services/static-webserver/client/source/class/osparc/share/ShareePermissions.js
index 4df66b06ca6..c0c4a4c6b89 100644
--- a/services/static-webserver/client/source/class/osparc/share/ShareePermissions.js
+++ b/services/static-webserver/client/source/class/osparc/share/ShareePermissions.js
@@ -51,7 +51,7 @@ qx.Class.define("osparc.share.ShareePermissions", {
const label = new qx.ui.basic.Label();
hBox.add(infoButton);
hBox.add(label);
- osparc.service.Store.getService(inaccessibleService.key, inaccessibleService.version)
+ osparc.store.Services.getService(inaccessibleService.key, inaccessibleService.version)
.then(metadata => {
label.setValue(metadata["name"] + " : " + metadata["version"])
infoButton.addListener("execute", () => {
diff --git a/services/static-webserver/client/source/class/osparc/service/Store.js b/services/static-webserver/client/source/class/osparc/store/Services.js
similarity index 99%
rename from services/static-webserver/client/source/class/osparc/service/Store.js
rename to services/static-webserver/client/source/class/osparc/store/Services.js
index 8158eb836bc..1fb2c1b0959 100644
--- a/services/static-webserver/client/source/class/osparc/service/Store.js
+++ b/services/static-webserver/client/source/class/osparc/store/Services.js
@@ -15,7 +15,7 @@
************************************************************************ */
-qx.Class.define("osparc.service.Store", {
+qx.Class.define("osparc.store.Services", {
type: "static",
statics: {
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 c6c25606acc..1c03b85ea44 100644
--- a/services/static-webserver/client/source/class/osparc/store/Store.js
+++ b/services/static-webserver/client/source/class/osparc/store/Store.js
@@ -74,6 +74,10 @@ qx.Class.define("osparc.store.Store", {
check: "Array",
init: []
},
+ workspaces: {
+ check: "Array",
+ init: []
+ },
studyComments: {
check: "Array",
init: []
diff --git a/services/static-webserver/client/source/class/osparc/store/Workspaces.js b/services/static-webserver/client/source/class/osparc/store/Workspaces.js
new file mode 100644
index 00000000000..6d0664abb0a
--- /dev/null
+++ b/services/static-webserver/client/source/class/osparc/store/Workspaces.js
@@ -0,0 +1,317 @@
+/* ************************************************************************
+
+ 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.store.Workspaces", {
+ type: "static",
+
+ statics: {
+ workspacesCached: [],
+
+ iconPath: function(iconsSize = 18) {
+ const source = "@MaterialIcons/folder_shared/";
+ if (iconsSize === -1) {
+ return source;
+ }
+ return source+iconsSize;
+ },
+
+ FAKE_WORKSPACES: [{
+ workspaceId: 1,
+ name: "Workspace 1",
+ description: "Workspace 1 desc",
+ thumbnail: "https://images.ctfassets.net/hrltx12pl8hq/01rJn4TormMsGQs1ZRIpzX/16a1cae2440420d0fd0a7a9a006f2dcb/Artboard_Copy_231.jpg?fit=fill&w=600&h=600",
+ myAccessRights: {
+ read: true,
+ write: true,
+ delete: true,
+ },
+ accessRights: {
+ 3: {
+ read: true,
+ write: true,
+ delete: true,
+ },
+ 5: {
+ read: true,
+ write: true,
+ delete: false,
+ },
+ 9: {
+ read: true,
+ write: false,
+ delete: false,
+ },
+ },
+ createdAt: "2024-03-04 15:59:51.579217",
+ lastModified: "2024-03-05 15:18:21.515403",
+ }, {
+ workspaceId: 2,
+ name: "Workspace 2",
+ description: "Workspace 2 desc",
+ thumbnail: "",
+ myAccessRights: {
+ read: true,
+ write: true,
+ delete: false,
+ },
+ accessRights: {
+ 3: {
+ read: true,
+ write: true,
+ delete: false,
+ },
+ 5: {
+ read: true,
+ write: true,
+ delete: true,
+ },
+ 9: {
+ read: true,
+ write: false,
+ delete: false,
+ },
+ },
+ createdAt: "2024-03-05 15:18:21.515403",
+ lastModified: "2024-04-24 12:03:05.15249",
+ }, {
+ workspaceId: 3,
+ name: "Workspace 3",
+ description: "Workspace 3 desc",
+ thumbnail: "https://media.springernature.com/lw703/springer-static/image/art%3A10.1038%2F528452a/MediaObjects/41586_2015_Article_BF528452a_Figg_HTML.jpg",
+ myAccessRights: {
+ read: true,
+ write: false,
+ delete: false,
+ },
+ accessRights: {
+ 3: {
+ read: true,
+ write: false,
+ delete: false,
+ },
+ 5: {
+ read: true,
+ write: true,
+ delete: false,
+ },
+ 9: {
+ read: true,
+ write: true,
+ delete: true,
+ },
+ },
+ createdAt: "2024-04-24 12:03:05.15249",
+ lastModified: "2024-06-21 13:00:40.33769",
+ }],
+
+ fetchWorkspaces: function() {
+ if (osparc.auth.Data.getInstance().isGuest()) {
+ return new Promise(resolve => {
+ resolve([]);
+ });
+ }
+
+ /*
+ return osparc.data.Resources.getInstance().getAllPages("workspaces", params)
+ .then(workspacesData => {
+ const workspaces = [];
+ workspacesData.forEach(workspaceData => {
+ const workspace = new osparc.data.model.Workspace(workspaceData);
+ this.__addToCache(workspace);
+ workspaces.push(workspace);
+ });
+ return workspaces;
+ });
+ */
+
+ return new Promise(resolve => {
+ if (this.workspacesCached.length === 0) {
+ this.self().FAKE_WORKSPACES.forEach(workspaceData => {
+ const workspace = new osparc.data.model.Workspace(workspaceData);
+ this.__addToCache(workspace);
+ });
+ }
+ resolve(this.workspacesCached);
+ });
+ },
+
+ createNewWorkspaceData: function(name, description = "", thumbnail = "") {
+ return {
+ name,
+ description,
+ thumbnail,
+ };
+ },
+
+ postWorkspace: function(newWorkspaceData) {
+ /*
+ const params = {
+ data: newWorkspaceData
+ };
+ return osparc.data.Resources.getInstance().fetch("workspaces", "post", params)
+ .then(workspaceData => {
+ const newWorkspace = new osparc.data.model.Workspace(workspaceData);
+ this.__addToCache(newWorkspace);
+ return newWorkspace;
+ });
+ */
+ const workspaceData = newWorkspaceData;
+ workspaceData["workspaceId"] = Math.floor(Math.random() * 100) + 100;
+ workspaceData["myAccessRights"] = osparc.share.CollaboratorsWorkspace.getOwnerAccessRight();
+ const myGroupId = osparc.auth.Data.getInstance().getGroupId();
+ workspaceData["accessRights"] = {};
+ workspaceData["accessRights"][myGroupId] = osparc.share.CollaboratorsWorkspace.getOwnerAccessRight();
+ workspaceData["createdAt"] = new Date().toISOString();
+ workspaceData["lastModified"] = new Date().toISOString();
+ return new Promise(resolve => {
+ const workspace = new osparc.data.model.Workspace(workspaceData);
+ this.__addToCache(workspace);
+ resolve(workspace);
+ });
+ },
+
+ deleteWorkspace: function(workspaceId) {
+ return new Promise((resolve, reject) => {
+ if (this.__deleteFromCache(workspaceId)) {
+ resolve();
+ } else {
+ reject();
+ }
+ /*
+ const params = {
+ "url": {
+ workspaceId
+ }
+ };
+ osparc.data.Resources.getInstance().fetch("workspaces", "delete", params)
+ .then(() => {
+ if (this.__deleteFromCache(workspaceId)) {
+ resolve();
+ } else {
+ reject();
+ }
+ })
+ .catch(err => reject(err));
+ */
+ });
+ },
+
+ putWorkspace: function(workspaceId, updateData) {
+ return new Promise((resolve, reject) => {
+ const params = {
+ "url": {
+ workspaceId
+ },
+ data: updateData
+ };
+ osparc.data.Resources.getInstance().fetch("workspaces", "update", params)
+ .then(() => {
+ const workspace = this.getWorkspace(workspaceId);
+ Object.keys(updateData).forEach(propKey => {
+ const upKey = qx.lang.String.firstUp(propKey);
+ const setter = "set" + upKey;
+ if (workspace && setter in workspace) {
+ workspace[setter](updateData[propKey]);
+ }
+ });
+ workspace.setLastModified(new Date());
+ this.__deleteFromCache(workspaceId);
+ this.__addToCache(workspace);
+ resolve();
+ })
+ .catch(err => reject(err));
+ });
+ },
+
+ addCollaborators: function(workspaceId, newCollaborators) {
+ return new Promise((resolve, reject) => {
+ const workspace = this.getWorkspace(workspaceId);
+ if (workspace) {
+ const accessRights = workspace.getAccessRights();
+ const newAccessRights = Object.assign(accessRights, newCollaborators);
+ workspace.set({
+ accessRights: newAccessRights,
+ lastModified: new Date()
+ })
+ resolve();
+ } else {
+ reject();
+ }
+ });
+ },
+
+ removeCollaborator: function(workspaceId, gid) {
+ return new Promise((resolve, reject) => {
+ const workspace = this.getWorkspace(workspaceId);
+ if (workspace) {
+ const accessRights = workspace.getAccessRights();
+ delete accessRights[gid];
+ workspace.set({
+ accessRights: accessRights,
+ lastModified: new Date()
+ })
+ resolve();
+ } else {
+ reject();
+ }
+ });
+ },
+
+ updateCollaborator: function(workspaceId, gid, newPermissions) {
+ return new Promise((resolve, reject) => {
+ const workspace = this.getWorkspace(workspaceId);
+ if (workspace) {
+ const accessRights = workspace.getAccessRights();
+ if (gid in accessRights) {
+ accessRights[gid] = newPermissions;
+ workspace.set({
+ accessRights: accessRights,
+ lastModified: new Date()
+ })
+ resolve();
+ return;
+ }
+ }
+ reject();
+ });
+ },
+
+ getWorkspaces: function(parentId = null) {
+ return this.workspacesCached.filter(f => f.getParentId() === parentId);
+ },
+
+ getWorkspace: function(workspaceId = null) {
+ return this.workspacesCached.find(f => f.getWorkspaceId() === workspaceId);
+ },
+
+ __addToCache: function(workspace) {
+ const found = this.workspacesCached.find(f => f.getWorkspaceId() === workspace.getWorkspaceId());
+ if (!found) {
+ this.workspacesCached.unshift(workspace);
+ }
+ },
+
+ __deleteFromCache: function(workspaceId) {
+ const idx = this.workspacesCached.findIndex(f => f.getWorkspaceId() === workspaceId);
+ if (idx > -1) {
+ this.workspacesCached.splice(idx, 1);
+ return true;
+ }
+ return false;
+ }
+ }
+});
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 a1f4fc76f31..3855cf01f96 100644
--- a/services/static-webserver/client/source/class/osparc/study/Utils.js
+++ b/services/static-webserver/client/source/class/osparc/study/Utils.js
@@ -35,7 +35,7 @@ qx.Class.define("osparc.study.Utils", {
},
getInaccessibleServices: function(workbench) {
- const allServices = osparc.service.Store.servicesCached;
+ const allServices = osparc.store.Services.servicesCached;
const unaccessibleServices = [];
const wbServices = new Set(this.extractServices(workbench));
wbServices.forEach(srv => {
@@ -70,7 +70,7 @@ qx.Class.define("osparc.study.Utils", {
},
isWorkbenchRetired: function(workbench) {
- const allServices = osparc.service.Store.servicesCached;
+ const allServices = osparc.store.Services.servicesCached;
const services = new Set(this.extractServices(workbench));
const isRetired = Array.from(services).some(srv => {
if (srv.key in allServices && srv.version in allServices[srv.key]) {
@@ -88,7 +88,7 @@ qx.Class.define("osparc.study.Utils", {
},
isWorkbenchDeprecated: function(workbench) {
- const allServices = osparc.service.Store.servicesCached;
+ const allServices = osparc.store.Services.servicesCached;
const services = new Set(this.extractServices(workbench));
const isRetired = Array.from(services).some(srv => {
if (srv.key in allServices && srv.version in allServices[srv.key]) {
@@ -107,7 +107,7 @@ qx.Class.define("osparc.study.Utils", {
createStudyFromService: function(key, version, existingStudies, newStudyLabel) {
return new Promise((resolve, reject) => {
- osparc.service.Store.getService(key, version)
+ osparc.store.Services.getService(key, version)
.then(metadata => {
const newUuid = osparc.utils.Utils.uuidV4();
const minStudyData = osparc.data.model.Study.createMyNewStudyObject();
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 dfba86b6b8c..6dd098e5bb3 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
@@ -83,8 +83,8 @@ qx.Class.define("osparc.ui.list.CollaboratorListItem", {
return osparc.data.Roles.STUDY[i];
} else if (resource === "service") {
return osparc.data.Roles.SERVICES[i];
- } else if (resource === "folder") {
- return osparc.data.Roles.FOLDERS[i];
+ } else if (resource === "workspace") {
+ return osparc.data.Roles.WORKSPACE[i];
}
return undefined;
},
diff --git a/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js b/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js
index 1684b780fc6..a1b4db10cb1 100644
--- a/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js
+++ b/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js
@@ -197,7 +197,7 @@ qx.Class.define("osparc.workbench.ServiceCatalog", {
__populateList: function() {
this.__servicesLatest = [];
- osparc.service.Store.getServicesLatest()
+ osparc.store.Services.getServicesLatest()
.then(servicesLatest => {
Object.keys(servicesLatest).forEach(key => {
this.__servicesLatest.push(servicesLatest[key]);
@@ -293,7 +293,7 @@ qx.Class.define("osparc.workbench.ServiceCatalog", {
if (version == this.self(arguments).LATEST.toString()) {
version = this.__versionsBox.getChildrenContainer().getSelectables()[1].version;
}
- const serviceMetadata = await osparc.service.Store.getService(key, version);
+ const serviceMetadata = await osparc.store.Services.getService(key, version);
return serviceMetadata;
},