Skip to content
Merged
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
5be0c8f
NewPlusButton
odeimaiz Jan 24, 2025
3e4eb8b
NewPlusMenu
odeimaiz Jan 24, 2025
dfb2e9d
[skip ci] minor
odeimaiz Jan 24, 2025
c256011
[skip ci] newStudyFromTemplateClicked
odeimaiz Jan 24, 2025
78795a0
createFolder
odeimaiz Jan 24, 2025
8a54535
[skip ci] minor
odeimaiz Jan 24, 2025
6db331f
[skip ci] changeTab
odeimaiz Jan 24, 2025
6fa1e4b
Merge branch 'master' into feature/new-plus-button
odeimaiz Jan 27, 2025
d2440fa
minors
odeimaiz Jan 27, 2025
7b1f592
unused
odeimaiz Jan 27, 2025
5aea20e
Products store
odeimaiz Jan 27, 2025
23d95f1
[skip ci] refactor
odeimaiz Jan 27, 2025
df9a54a
minor
odeimaiz Jan 27, 2025
fc6fc09
aesthetics
odeimaiz Jan 27, 2025
1e71c7b
[skip ci] categories
odeimaiz Jan 27, 2025
9414da5
[skip ci] category headers
odeimaiz Jan 27, 2025
c04ff70
group by categories
odeimaiz Jan 27, 2025
86ca800
prettify menu
odeimaiz Jan 27, 2025
f27c907
[minor] skip ci
odeimaiz Jan 27, 2025
20aa37f
[skip ci] less style
odeimaiz Jan 27, 2025
73e3971
minor
odeimaiz Jan 27, 2025
711eda1
minor
odeimaiz Jan 27, 2025
8a73abe
scale icon
odeimaiz Jan 27, 2025
a56f929
minor
odeimaiz Jan 27, 2025
bd32496
refactoring
odeimaiz Jan 27, 2025
43176dd
hasNewPlusButton
odeimaiz Jan 27, 2025
2c03ead
start sim4life from menu
odeimaiz Jan 27, 2025
0410df5
minors
odeimaiz Jan 27, 2025
e6366df
__addIcon
odeimaiz Jan 27, 2025
073f8f6
Merge branch 'master' into feature/new-plus-button
odeimaiz Jan 28, 2025
64307fd
support icon
odeimaiz Jan 28, 2025
6e224b8
support both modes
odeimaiz Jan 28, 2025
e20f074
all products supported
odeimaiz Jan 28, 2025
b552d30
minor
odeimaiz Jan 28, 2025
ef75db4
larger icon
odeimaiz Jan 28, 2025
6ed9027
[skip ci] aesthetics
odeimaiz Jan 28, 2025
1bb904b
update tests
odeimaiz Jan 28, 2025
0714b28
Merge branch 'master' into feature/new-plus-button
odeimaiz Jan 28, 2025
3ef95b0
remove studiesTabBtn
odeimaiz Jan 28, 2025
62c9d09
hide dashboard buttons
odeimaiz Jan 28, 2025
586d2b3
tutorials and services buttons
odeimaiz Jan 28, 2025
5b7d46e
remote buttons
odeimaiz Jan 28, 2025
a25dc3b
minor
odeimaiz Jan 28, 2025
8685cbb
minor
odeimaiz Jan 28, 2025
a912b84
connect empty study
odeimaiz Jan 28, 2025
383aa41
pop up service info
odeimaiz Jan 28, 2025
56a2bc3
[skip ci] minors
odeimaiz Jan 28, 2025
b228f7d
minor
odeimaiz Jan 28, 2025
203c308
Merge branch 'master' into feature/new-plus-button
odeimaiz Jan 28, 2025
a57a0f7
minor
odeimaiz Jan 28, 2025
d993cc4
[skip ci] connect Tutorials and Service buttons
odeimaiz Jan 28, 2025
78ab79f
createResourceTypeContextButtons
odeimaiz Jan 28, 2025
7345e01
context changing works
odeimaiz Jan 28, 2025
af97312
minor
odeimaiz Jan 28, 2025
79562b6
filtersSpacer
odeimaiz Jan 28, 2025
b91cc17
Merge branch 'master' into feature/new-plus-button
odeimaiz Jan 29, 2025
f9498e0
fix test
odeimaiz Jan 29, 2025
0d36246
renaming
odeimaiz Jan 29, 2025
1ad11ec
[skip ci] reason and refactoring
odeimaiz Jan 29, 2025
c4200bc
reason to NewStudies
odeimaiz Jan 29, 2025
0c477c3
replace_me_product_name
odeimaiz Jan 29, 2025
56192b9
Merge branch 'master' into feature/new-plus-button
odeimaiz Jan 29, 2025
d34d377
categories more differentiable
odeimaiz Jan 29, 2025
9de1fb8
Open -> New Project
odeimaiz Jan 29, 2025
0ff6b24
Open ->New
odeimaiz Jan 29, 2025
1616c0d
Merge branch 'master' into feature/new-plus-button
mergify[bot] Jan 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ qx.Class.define("osparc.dashboard.Dashboard", {
construct: function() {
this.base(arguments);

osparc.utils.Utils.setIdToWidget(this.getChildControl("bar"), "dashboardTabs");
osparc.utils.Utils.setIdToWidget(this, "dashboard");
this.getChildControl("bar").set({
visibility: "excluded",
});

this.set({
contentPadding: this.self().PADDING,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* ************************************************************************

osparc - the simcore frontend

https://osparc.io

Copyright:
2025 IT'IS Foundation, https://itis.swiss

License:
MIT: https://opensource.org/licenses/MIT

Authors:
* Odei Maiz (odeimaiz)

************************************************************************ */

qx.Class.define("osparc.dashboard.NewPlusButton", {
extend: qx.ui.form.MenuButton,

construct: function() {
this.base(arguments);

this.set({
appearance: "strong-button",
icon: osparc.dashboard.CardBase.NEW_ICON + "20",
label: this.tr("New"),
font: "text-16",
gap: 15,
padding: 15,
paddingRight: 20,
allowGrowX: false,
});

osparc.utils.Utils.setIdToWidget(this, "newPlusBtn");

this.setMenu(new osparc.dashboard.NewPlusMenu());
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
/* ************************************************************************

osparc - the simcore frontend

https://osparc.io

Copyright:
2025 IT'IS Foundation, https://itis.swiss

License:
MIT: https://opensource.org/licenses/MIT

Authors:
* Odei Maiz (odeimaiz)

************************************************************************ */

qx.Class.define("osparc.dashboard.NewPlusMenu", {
extend: qx.ui.menu.Menu,

construct: function() {
this.base(arguments);

osparc.utils.Utils.prettifyMenu(this);

this.set({
position: "bottom-left",
spacingX: 20,
});

this.__categoryHeaders = [];

this.__addItems();
},

events: {
"createFolder": "qx.event.type.Data",
"newEmptyStudyClicked": "qx.event.type.Data",
"newStudyFromTemplateClicked": "qx.event.type.Data",
"newStudyFromServiceClicked": "qx.event.type.Data",
},

statics: {
createMenuButton: function(icon, title, infoText) {
title = osparc.utils.Utils.replaceTokens(
title,
"replace_me_product_name",
osparc.store.StaticInfo.getInstance().getDisplayName()
);
const menuButton = new qx.ui.menu.Button().set({
icon: icon || null,
label: title,
font: "text-16",
allowGrowX: true,
});
menuButton.getChildControl("icon").set({
alignX: "center",
});
menuButton.getChildControl("label").set({
rich: true,
marginRight: 20,
});
if (infoText) {
infoText = osparc.utils.Utils.replaceTokens(
title,
"replace_me_product_name",
osparc.store.StaticInfo.getInstance().getDisplayName()
);
const infoHint = new osparc.ui.hint.InfoHint(infoText).set({
source: osparc.ui.hint.InfoHint.INFO_ICON + "/16",
});
// where the shortcut is supposed to go
// eslint-disable-next-line no-underscore-dangle
menuButton._add(infoHint, {column: 2});
}
return menuButton;
},

createHeader: function(icon, label, infoText) {
return this.createMenuButton(icon, label, infoText).set({
anonymous: true,
cursor: "default",
font: "text-14",
textColor: "text-darker",
});
},
},

members: {
__categoryHeaders: null,

_createChildControlImpl: function(id) {
let control;
switch (id) {
case "new-folder":
control = this.self().createMenuButton(
osparc.dashboard.CardBase.NEW_ICON + "16",
this.tr("New Folder"),
);
osparc.utils.Utils.setIdToWidget(control, "newFolderButton");
control.addListener("tap", () => this.__createNewFolder());
this.add(control);
break;
}
return control || this.base(arguments, id);
},

__addItems: async function() {
this.getChildControl("new-folder");
this.addSeparator();
await this.__addNewStudyItems();
},

__addNewStudyItems: async function() {
await Promise.all([
osparc.store.Products.getInstance().getNewStudyConfig(),
osparc.data.Resources.get("templates")
]).then(values => {
const newStudiesData = values[0];
const templates = values[1];
if (newStudiesData["categories"]) {
this.__addCategories(newStudiesData["categories"]);
}
newStudiesData["resources"].forEach(newStudyData => {
if (newStudyData["showDisabled"]) {
this.__addDisabledButton(newStudyData);
} else if (newStudyData["resourceType"] === "study") {
this.__addEmptyStudyButton(newStudyData);
} else if (newStudyData["resourceType"] === "template") {
this.__addFromTemplateButton(newStudyData, templates);
} else if (newStudyData["resourceType"] === "service") {
this.__addFromServiceButton(newStudyData);
}
});
});
},

__getLastIdxFromCategory: function(categoryId) {
for (let i=this.getChildren().length-1; i>=0; i--) {
const child = this.getChildren()[i];
if (child && child["categoryId"] && child["categoryId"] === categoryId) {
return i;
}
}
return null;
},

__addCategories: function(categories) {
categories.forEach(category => {
const categoryHeader = this.self().createHeader(null, category["title"], category["description"]);
categoryHeader["categoryId"] = category["id"];
if (this.__categoryHeaders.length) {
// add spacing between categories
categoryHeader.setMarginTop(10);
}
this.__categoryHeaders.push(categoryHeader);
this.add(categoryHeader);
});
},

__addIcon: function(menuButton, resourceInfo, resourceMetadata) {
let source = null;
if (resourceInfo && "icon" in resourceInfo) {
// first the one set in the new_studies
source = resourceInfo["icon"];
} else if (resourceMetadata && "thumbnail" in resourceMetadata) {
// second the one from the resource
source = resourceMetadata["thumbnail"];
}

if (source) {
const thumbnail = new osparc.ui.basic.Thumbnail(source, 24, 24).set({
minHeight: 24,
minWidth: 24,
});
thumbnail.getChildControl("image").set({
anonymous: true,
decorator: "rounded",
});
// eslint-disable-next-line no-underscore-dangle
menuButton._add(thumbnail, {column: 0});
}
},

__addFromResourceButton: function(menuButton, category) {
let idx = null;
if (category) {
idx = this.__getLastIdxFromCategory(category);
}
if (idx) {
menuButton["categoryId"] = category;
this.addAt(menuButton, idx+1);
} else {
this.add(menuButton);
}
},

__addDisabledButton: function(newStudyData) {
const menuButton = this.self().createMenuButton(null, newStudyData.title, newStudyData.reason);
osparc.utils.Utils.setIdToWidget(menuButton, newStudyData.idToWidget);
menuButton.setEnabled(false);

this.__addIcon(menuButton, newStudyData);
this.__addFromResourceButton(menuButton, newStudyData.category);
},

__addEmptyStudyButton: function(newStudyData) {
const menuButton = this.self().createMenuButton(null, newStudyData.title);
osparc.utils.Utils.setIdToWidget(menuButton, newStudyData.idToWidget);

menuButton.addListener("tap", () => {
this.fireDataEvent("newEmptyStudyClicked", {
newStudyLabel: newStudyData.newStudyLabel,
});
});

this.__addIcon(menuButton, newStudyData);
this.__addFromResourceButton(menuButton, newStudyData.category);
},

__addFromTemplateButton: function(newStudyData, templates) {
const menuButton = this.self().createMenuButton(null, newStudyData.title);
osparc.utils.Utils.setIdToWidget(menuButton, newStudyData.idToWidget);
// disable it until found in templates store
menuButton.setEnabled(false);

let templateMetadata = templates.find(t => t.name === newStudyData.expectedTemplateLabel);
if (templateMetadata) {
menuButton.setEnabled(true);
menuButton.addListener("tap", () => {
this.fireDataEvent("newStudyFromTemplateClicked", {
templateData: templateMetadata,
newStudyLabel: newStudyData.newStudyLabel,
});
});
this.__addIcon(menuButton, newStudyData, templateMetadata);
this.__addFromResourceButton(menuButton, newStudyData.category);
}
},

__addFromServiceButton: function(newStudyData) {
const menuButton = this.self().createMenuButton(null, newStudyData.title);
osparc.utils.Utils.setIdToWidget(menuButton, newStudyData.idToWidget);
// disable it until found in services store
menuButton.setEnabled(false);

const key = newStudyData.expectedKey;
// Include deprecated versions, they should all be updatable to a non deprecated version
const versions = osparc.service.Utils.getVersions(key, false);
if (versions.length && newStudyData) {
// scale to latest compatible
const latestVersion = versions[0];
const latestCompatible = osparc.service.Utils.getLatestCompatible(key, latestVersion);
osparc.store.Services.getService(latestCompatible["key"], latestCompatible["version"])
.then(latestMetadata => {
// make sure this one is not deprecated
if (osparc.service.Utils.isDeprecated(latestMetadata)) {
return;
}
menuButton.setEnabled(true);
menuButton.addListener("tap", () => {
this.fireDataEvent("newStudyFromServiceClicked", {
serviceMetadata: latestMetadata,
newStudyLabel: newStudyData.newStudyLabel,
});
});

const cb = e => {
this.hide();
// so that is not consumed by the menu button itself
e.stopPropagation();
latestMetadata["resourceType"] = "service";
const resourceDetails = new osparc.dashboard.ResourceDetails(latestMetadata);
osparc.dashboard.ResourceDetails.popUpInWindow(resourceDetails);
}
const infoButton = new osparc.ui.basic.IconButton(osparc.ui.hint.InfoHint.INFO_ICON + "/16", cb);
// where the shortcut is supposed to go
// eslint-disable-next-line no-underscore-dangle
menuButton._add(infoButton, {column: 2});

this.__addIcon(menuButton, newStudyData, latestMetadata);
this.__addFromResourceButton(menuButton, newStudyData.category);
})
}
},

__createNewFolder: function() {
const newFolder = true;
const folderEditor = new osparc.editor.FolderEditor(newFolder);
const title = this.tr("New Folder");
const win = osparc.ui.window.Window.popUpInWindow(folderEditor, title, 300, 120);
folderEditor.addListener("createFolder", () => {
const name = folderEditor.getLabel();
this.fireDataEvent("createFolder", {
name,
});
win.close();
});
folderEditor.addListener("cancel", () => win.close());
},
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ qx.Class.define("osparc.dashboard.NewStudies", {
this._add(noGroupContainer);

Array.from(this.__groups).forEach(group => {
const groupContainer = this.__createGroupContainer(group.id, group.label, "transparent");
let headerLabel = group.title;
headerLabel += "description" in group ? (". " + group["description"]) : "";
const groupContainer = this.__createGroupContainer(group.id, headerLabel, "transparent");
this._add(groupContainer);
});
} else {
Expand All @@ -106,7 +108,18 @@ qx.Class.define("osparc.dashboard.NewStudies", {
this.__newStudies.forEach(resourceData => {
const cards = this.__resourceToCards(resourceData);
cards.forEach(newCard => {
newCard.setEnabled(!(resourceData.showDisabled));
if (resourceData.showDisabled) {
newCard.setEnabled(false);
if (resourceData.reason) {
const reason = osparc.utils.Utils.replaceTokens(
resourceData.reason,
"replace_me_product_name",
osparc.store.StaticInfo.getInstance().getDisplayName()
);
const descLabel = newCard.getChildControl("subtitle-text");
descLabel.setValue(reason.toString());
}
}
newCards.push(newCard);
});
});
Expand Down
Loading
Loading