diff --git a/services/static-webserver/client/source/class/osparc/dashboard/CardBase.js b/services/static-webserver/client/source/class/osparc/dashboard/CardBase.js index 610f40e5e23..5df1eef59a0 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/CardBase.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/CardBase.js @@ -489,7 +489,7 @@ qx.Class.define("osparc.dashboard.CardBase", { lastChangeDate: resourceData.lastChangeDate ? new Date(resourceData.lastChangeDate) : null, trashedAt: resourceData.trashedAt ? new Date(resourceData.trashedAt) : null, trashedBy: resourceData.trashedBy || null, - icon: ["study", "template"].includes(resourceData.resourceType) ? osparc.study.Utils.guessIcon(resourceData) : null, + icon: ["study", "template"].includes(resourceData.resourceType) ? osparc.study.Utils.guessIcon(resourceData) : osparc.dashboard.CardBase.PRODUCT_ICON, thumbnail: resourceData.thumbnail || this.self().PRODUCT_THUMBNAIL, state: resourceData.state ? resourceData.state : {}, classifiers: resourceData.classifiers && resourceData.classifiers ? resourceData.classifiers : [], diff --git a/services/static-webserver/client/source/class/osparc/dashboard/GridButtonBase.js b/services/static-webserver/client/source/class/osparc/dashboard/GridButtonBase.js index 8f6933c189c..56050879c73 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/GridButtonBase.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/GridButtonBase.js @@ -44,6 +44,7 @@ qx.Class.define("osparc.dashboard.GridButtonBase", { ITEM_WIDTH: 190, ITEM_HEIGHT: 220, PADDING: 10, + TITLE_PADDING: 6, SPACING_IN: 5, SPACING: 15, ICON_SIZE: 32, @@ -202,8 +203,8 @@ qx.Class.define("osparc.dashboard.GridButtonBase", { control = new qx.ui.basic.Label().set({ textColor: "contrasted-text-light", font: "text-14", - padding: this.self().PADDING, - maxWidth: this.self().ITEM_WIDTH - 2*this.self().PADDING, + padding: this.self().TITLE_PADDING, + maxWidth: this.self().ITEM_WIDTH, maxHeight: this.self().TITLE_MAX_HEIGHT, }); layout = this.getChildControl("header"); @@ -368,14 +369,6 @@ qx.Class.define("osparc.dashboard.GridButtonBase", { thumbnailLayout.recheckSize(); }, - replaceIcon: function(newIcon) { - const plusIcon = this.getChildControl("icon"); - plusIcon.exclude(); - - const bodyLayout = this.getChildControl("body"); - bodyLayout.add(newIcon, {flex: 1}); - }, - /** * Event handler for the pointer over event. */ diff --git a/services/static-webserver/client/source/class/osparc/dashboard/GridButtonItem.js b/services/static-webserver/client/source/class/osparc/dashboard/GridButtonItem.js index 92eba66bd6e..7e776c86e8b 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/GridButtonItem.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/GridButtonItem.js @@ -93,8 +93,7 @@ qx.Class.define("osparc.dashboard.GridButtonItem", { break; case "menu-button": this.getChildControl("title").set({ - maxWidth: osparc.dashboard.GridButtonBase.ITEM_WIDTH - osparc.dashboard.GridButtonBase.ICON_SIZE - this.self().MENU_BTN_DIMENSIONS - 6, - padding: 4, + maxWidth: osparc.dashboard.GridButtonBase.ITEM_WIDTH - osparc.dashboard.GridButtonBase.ICON_SIZE - this.self().MENU_BTN_DIMENSIONS, }); control = new qx.ui.form.MenuButton().set({ appearance: "form-button-outlined", @@ -245,10 +244,12 @@ qx.Class.define("osparc.dashboard.GridButtonItem", { _applyTags: function(tags) { if (osparc.data.Permissions.getInstance().canDo("study.tag")) { + const maxTags = 2; const tagsContainer = this.getChildControl("tags"); tagsContainer.setVisibility(tags.length ? "visible" : "excluded"); tagsContainer.removeAll(); - tags.forEach(tag => { + for (let i=0; i<=tags.length && i this.fireDataEvent("tagClicked", tag)); tagsContainer.add(tagUI); - }); + } + if (tags.length > maxTags) { + const moreButton = new qx.ui.basic.Label(this.tr("More...")).set({ + font: "text-12", + backgroundColor: "strong-main", + appearance: "tag", + }); + tagsContainer.add(moreButton); + } } }, diff --git a/services/static-webserver/client/source/class/osparc/dashboard/GridButtonLoadMore.js b/services/static-webserver/client/source/class/osparc/dashboard/GridButtonLoadMore.js index af3bf1ae666..47ccb900cbd 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/GridButtonLoadMore.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/GridButtonLoadMore.js @@ -39,12 +39,12 @@ qx.Class.define("osparc.dashboard.GridButtonLoadMore", { members: { _applyFetching: function(value) { - this.setIcon(osparc.dashboard.CardBase.LOADING_ICON); + this.setThumbnail(osparc.dashboard.CardBase.LOADING_ICON); if (value) { - this.getChildControl("icon").getChildControl("image").getContentElement() + this.getChildControl("thumbnail").getChildControl("image").getContentElement() .addClass("rotate"); } else { - this.getChildControl("icon").getChildControl("image").getContentElement() + this.getChildControl("thumbnail").getChildControl("image").getContentElement() .removeClass("rotate"); } this.setEnabled(!value); diff --git a/services/static-webserver/client/source/class/osparc/dashboard/GridButtonPlaceholder.js b/services/static-webserver/client/source/class/osparc/dashboard/GridButtonPlaceholder.js index a946d8832d2..4c2c933042b 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/GridButtonPlaceholder.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/GridButtonPlaceholder.js @@ -105,7 +105,7 @@ qx.Class.define("osparc.dashboard.GridButtonPlaceholder", { title.setValue(titleText); } if (icon) { - this.setIcon(icon); + this.setThumbnail(icon); } const stateLabel = this.getChildControl("state-label"); diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ListButtonItem.js b/services/static-webserver/client/source/class/osparc/dashboard/ListButtonItem.js index f7c34780fa1..2bf551a20e6 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/ListButtonItem.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/ListButtonItem.js @@ -253,9 +253,11 @@ qx.Class.define("osparc.dashboard.ListButtonItem", { _applyTags: function(tags) { if (osparc.data.Permissions.getInstance().canDo("study.tag")) { + const maxTags = 2; const tagsContainer = this.getChildControl("tags"); tagsContainer.removeAll(); - tags.forEach(tag => { + for (let i=0; i<=tags.length && i this.fireDataEvent("tagClicked", tag)); tagsContainer.add(tagUI); - }); + } + if (tags.length > maxTags) { + const moreButton = new qx.ui.basic.Label(this.tr("More...")).set({ + font: "text-12", + backgroundColor: "strong-main", + appearance: "tag", + }); + tagsContainer.add(moreButton); + } this.__makeItemResponsive(tagsContainer); } }, 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 a2a69c32940..f0bed4d36c6 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceFilter.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceFilter.js @@ -54,19 +54,29 @@ qx.Class.define("osparc.dashboard.ResourceFilter", { __buildLayout: function() { const filtersSpacer = new qx.ui.core.Spacer(10, 10); switch (this.__resourceType) { - case "study": + case "study": { this._add(this.__createWorkspacesAndFoldersTree()); this._add(this.__createTrashBin()); this._add(this.__createResourceTypeContextButtons()); this._add(filtersSpacer); - this._add(this.__createTagsFilterLayout()); + const scrollView = new qx.ui.container.Scroll(); + scrollView.add(this.__createTagsFilterLayout()); + this._add(scrollView, { + flex: 1 + }); break; - case "template": + } + case "template": { this._add(this.__createResourceTypeContextButtons()); this._add(filtersSpacer); this._add(this.__createSharedWithFilterLayout()); - this._add(this.__createTagsFilterLayout()); + const scrollView = new qx.ui.container.Scroll(); + scrollView.add(this.__createTagsFilterLayout()); + this._add(scrollView, { + flex: 1 + }); break; + } case "service": this._add(this.__createResourceTypeContextButtons()); this._add(filtersSpacer); @@ -350,15 +360,15 @@ qx.Class.define("osparc.dashboard.ResourceFilter", { /* TAGS */ __createTagsFilterLayout: function() { - const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(2)); - osparc.utils.Utils.setIdToWidget(layout, this.__resourceType + "-tagsFilter"); + const tagsLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(2)); + osparc.utils.Utils.setIdToWidget(tagsLayout, this.__resourceType + "-tagsFilter"); - this.__populateTags(layout, []); + this.__populateTags(tagsLayout, []); osparc.store.Tags.getInstance().addListener("tagsChanged", () => { - this.__populateTags(layout, this.__getSelectedTagIds()); + this.__populateTags(tagsLayout, this.__getSelectedTagIds()); }, this); - return layout; + return tagsLayout; }, __getSelectedTagIds: function() { @@ -366,10 +376,10 @@ qx.Class.define("osparc.dashboard.ResourceFilter", { return selectedTagIds; }, - __populateTags: function(layout, selectedTagIds) { + __populateTags: function(tagsLayout, selectedTagIds) { const maxTags = 5; this.__tagButtons = []; - layout.removeAll(); + tagsLayout.removeAll(); osparc.store.Tags.getInstance().getTags().forEach((tag, idx) => { const button = new qx.ui.form.ToggleButton(null, "@FontAwesome5Solid/tag/16"); button.id = tag.getTagId(); @@ -381,7 +391,7 @@ qx.Class.define("osparc.dashboard.ResourceFilter", { value: selectedTagIds.includes(tag.getTagId()) }); - layout.add(button); + tagsLayout.add(button); button.addListener("execute", () => { const selection = this.__getSelectedTagIds(); @@ -411,7 +421,7 @@ qx.Class.define("osparc.dashboard.ResourceFilter", { showAllButton.showingAll = true; } }); - layout.add(showAllButton); + tagsLayout.add(showAllButton); } const editTagsButton = new qx.ui.form.Button(this.tr("Edit Tags..."), "@FontAwesome5Solid/pencil-alt/14"); @@ -422,10 +432,10 @@ qx.Class.define("osparc.dashboard.ResourceFilter", { const myAccountWindow = osparc.desktop.account.MyAccountWindow.openWindow(); myAccountWindow.openTags(); }); - layout.add(editTagsButton); + tagsLayout.add(editTagsButton); if (this.__resourceType === "study") { - layout.getChildren().forEach(item => item.setPaddingLeft(10)); // align them with the context + tagsLayout.getChildren().forEach(item => item.setPaddingLeft(10)); // align them with the context } }, /* /TAGS */ diff --git a/services/static-webserver/client/source/class/osparc/desktop/preferences/pages/TagsPage.js b/services/static-webserver/client/source/class/osparc/desktop/preferences/pages/TagsPage.js index f69ae38e4ee..6493ef91f3a 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/preferences/pages/TagsPage.js +++ b/services/static-webserver/client/source/class/osparc/desktop/preferences/pages/TagsPage.js @@ -26,64 +26,60 @@ qx.Class.define("osparc.desktop.preferences.pages.TagsPage", { this._add(new qx.ui.core.Spacer(null, 10)); - this.__container = new qx.ui.container.Composite(new qx.ui.layout.VBox(10)); - this.__container.set({ - paddingLeft: 10 - }); - const scroll = new qx.ui.container.Scroll(this.__container); - this._add(scroll); - - this.__createComponents(); + this.__renderLayout(); }, members: { - __container: null, - __addTagButton: null, - __tagItems: null, + __tagsContainer: null, + + __renderLayout: function() { + // Tags + this.__tagsContainer = new qx.ui.container.Composite(new qx.ui.layout.VBox(10)); + this.__tagsContainer.set({ + paddingLeft: 10 + }); + const tagContainerScroll = new qx.ui.container.Scroll(this.__tagsContainer); + this._add(tagContainerScroll, { + flex: 1 + }); + + const tags = osparc.store.Tags.getInstance().getTags(); + const tagItems = tags.map(tag => new osparc.form.tag.TagItem().set({tag})); + tagItems.forEach(tagItem => { + this.__tagsContainer.add(tagItem); + this.__attachTagItemEvents(tagItem); + }); - __createComponents: function() { - this.__addTagButton = new qx.ui.form.Button().set({ + // New tag Button + const addTagButton = new qx.ui.form.Button().set({ appearance: "form-button-outlined", label: this.tr("New Tag"), icon: "@FontAwesome5Solid/plus/14" }); - osparc.utils.Utils.setIdToWidget(this.__addTagButton, "addTagBtn"); - const tags = osparc.store.Tags.getInstance().getTags(); - this.__tagItems = tags.map(tag => new osparc.form.tag.TagItem().set({tag})); - this.__renderLayout(); - this.__attachEventHandlers(); - }, - - __renderLayout: function() { - this.__container.removeAll(); + osparc.utils.Utils.setIdToWidget(addTagButton, "addTagBtn"); + addTagButton.addListener("execute", () => { + const newItem = new osparc.form.tag.TagItem().set({ + mode: osparc.form.tag.TagItem.modes.EDIT + }); + this.__tagsContainer.add(newItem); + this.__attachTagItemEvents(newItem); - // Print tag items - this.__tagItems.forEach(tagItem => this.__container.add(tagItem)); + // scroll down + const height = tagContainerScroll.getSizeHint().height; + tagContainerScroll.scrollToY(height); + }); // New tag button const buttonContainer = new qx.ui.container.Composite(new qx.ui.layout.HBox().set({ alignX: "center" })); - buttonContainer.add(new qx.ui.core.Spacer(null, 10)); - buttonContainer.add(this.__addTagButton); - this.__container.add(buttonContainer); - }, - - __attachEventHandlers: function() { - this.__addTagButton.addListener("execute", () => { - const itemCount = this.__container.getChildren().length; - const newItem = new osparc.form.tag.TagItem().set({ - mode: osparc.form.tag.TagItem.modes.EDIT - }); - this.__attachTagItemEvents(newItem); - this.__container.addAt(newItem, Math.max(0, itemCount - 1)); - }); - this.__tagItems.forEach(tagItem => this.__attachTagItemEvents(tagItem)); + buttonContainer.add(addTagButton); + this._add(buttonContainer); }, __attachTagItemEvents: function(tagItem) { - tagItem.addListener("cancelNewTag", e => this.__container.remove(e.getTarget()), this); - tagItem.addListener("deleteTag", e => this.__container.remove(e.getTarget())); + tagItem.addListener("cancelNewTag", e => this.__tagsContainer.remove(e.getTarget()), this); + tagItem.addListener("deleteTag", e => this.__tagsContainer.remove(e.getTarget())); } } }); diff --git a/services/static-webserver/client/source/class/osparc/form/tag/TagManager.js b/services/static-webserver/client/source/class/osparc/form/tag/TagManager.js index 111c020fda6..04b6c06c393 100644 --- a/services/static-webserver/client/source/class/osparc/form/tag/TagManager.js +++ b/services/static-webserver/client/source/class/osparc/form/tag/TagManager.js @@ -70,7 +70,9 @@ qx.Class.define("osparc.form.tag.TagManager", { this._add(filter); const tagsContainer = this.__tagsContainer = new qx.ui.container.Composite(new qx.ui.layout.VBox()); - this._add(tagsContainer, { + const scrollTags = new qx.ui.container.Scroll(); + scrollTags.add(tagsContainer); + this._add(scrollTags, { flex: 1 }); @@ -90,6 +92,10 @@ qx.Class.define("osparc.form.tag.TagManager", { newItem.addListener("cancelNewTag", e => tagsContainer.remove(e.getTarget()), this); newItem.addListener("deleteTag", e => tagsContainer.remove(e.getTarget()), this); tagsContainer.add(newItem); + + // scroll down + const height = scrollTags.getSizeHint().height; + scrollTags.scrollToY(height); }); this._add(addTagButton); @@ -120,7 +126,11 @@ qx.Class.define("osparc.form.tag.TagManager", { __repopulateTags: function() { this.__tagsContainer.removeAll(); const tags = osparc.store.Tags.getInstance().getTags(); - tags.forEach(tag => this.__tagsContainer.add(this.__tagButton(tag))); + const tagButtons = []; + tags.forEach(tag => tagButtons.push(this.__tagButton(tag))); + // list the selected tags first + tagButtons.sort((a, b) => b.getValue() - a.getValue()); + tagButtons.forEach(tagButton => this.__tagsContainer.add(tagButton)); }, __tagButton: function(tag) { 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 9d2ef3bf7bc..386a3958d18 100644 --- a/services/static-webserver/client/source/class/osparc/info/StudyUtils.js +++ b/services/static-webserver/client/source/class/osparc/info/StudyUtils.js @@ -205,7 +205,9 @@ qx.Class.define("osparc.info.StudyUtils", { * @param study {osparc.data.model.Study} Study Model */ createTags: function(study) { - const tagsContainer = new qx.ui.container.Composite(new qx.ui.layout.HBox(5)); + const tagsContainer = new qx.ui.container.Composite(new qx.ui.layout.Flow(5, 5)).set({ + maxWidth: 420 + }); const addTags = model => { tagsContainer.removeAll(); @@ -308,14 +310,14 @@ qx.Class.define("osparc.info.StudyUtils", { }, }; - const grid1 = new qx.ui.layout.Grid(15, 5); - grid1.setColumnAlign(0, "left", "top"); - grid1.setColumnFlex(0, 1); - const mainInfoLayout = new qx.ui.container.Composite(grid1); + const mainInfoGrid = new qx.ui.layout.Grid(15, 5); + mainInfoGrid.setColumnAlign(0, "left", "top"); + mainInfoGrid.setColumnFlex(0, 1); + const mainInfoLayout = new qx.ui.container.Composite(mainInfoGrid); - const grid2 = new qx.ui.layout.Grid(15, 5); - const extraInfoLayout = new qx.ui.container.Composite(grid2); - grid2.setColumnFlex(0, 1); + const extraInfoGrid = new qx.ui.layout.Grid(15, 5); + const extraInfoLayout = new qx.ui.container.Composite(extraInfoGrid); + extraInfoGrid.setColumnFlex(0, 1); let row = 0; let row2 = 0; @@ -331,13 +333,15 @@ qx.Class.define("osparc.info.StudyUtils", { marginRight: 15 }); } - titleLayout.add(extraInfo.view); + titleLayout.add(extraInfo.view, { + flex: 1 + }); extraInfoLayout.add(titleLayout, { row: row2, column: gridInfo.column }); row2++; - grid2.setRowHeight(row2, 5); // spacer + extraInfoGrid.setRowHeight(row2, 5); // spacer row2++; } else { const titleLayout = this.__titleWithEditLayout(extraInfo); @@ -351,7 +355,7 @@ qx.Class.define("osparc.info.StudyUtils", { column: gridInfo.column }); row++; - grid1.setRowHeight(row, 5); // spacer + mainInfoGrid.setRowHeight(row, 5); // spacer row++; } }