Skip to content

Commit a37a9a9

Browse files
authored
✨ Service Catalog card redesign (ITISFoundation#3019)
1 parent 86b0ad7 commit a37a9a9

33 files changed

+290
-103
lines changed

services/web/client/source/class/osparc/Application.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ qx.Class.define("osparc.Application", {
4949
this.base();
5050

5151
// Load user preferred theme if present
52-
if (window.localStorage.getItem("themeName") &&
53-
window.localStorage.getItem("themeName") !== qx.theme.manager.Meta.getInstance().getTheme().name) {
54-
const preferredTheme = qx.Theme.getByName(window.localStorage.getItem("themeName"));
52+
const themeName = osparc.utils.Utils.localCache.getTheme();
53+
if (themeName && themeName !== qx.theme.manager.Meta.getInstance().getTheme().name) {
54+
const preferredTheme = qx.Theme.getByName(themeName);
5555
const themes = qx.Theme.getAll();
5656
if (preferredTheme && Object.keys(themes).includes(preferredTheme.name)) {
5757
qx.theme.manager.Meta.getInstance().setTheme(preferredTheme);

services/web/client/source/class/osparc/component/service/ServiceButtonSmall.js renamed to services/web/client/source/class/osparc/component/service/ServiceButtonGrid.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* Big button representing a service. It shows its name and icon and description as tooltip.
2020
* It also adds filtering capabilities.
2121
*/
22-
qx.Class.define("osparc.component.service.ServiceButtonSmall", {
22+
qx.Class.define("osparc.component.service.ServiceButtonGrid", {
2323
extend: osparc.dashboard.GridButtonBase,
2424

2525
construct: function(serviceModel) {
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/* ************************************************************************
2+
3+
osparc - the simcore frontend
4+
5+
https://osparc.io
6+
7+
Copyright:
8+
2022 IT'IS Foundation, https://itis.swiss
9+
10+
License:
11+
MIT: https://opensource.org/licenses/MIT
12+
13+
Authors:
14+
* Odei Maiz (odeimaiz)
15+
16+
************************************************************************ */
17+
18+
/**
19+
* Big button representing a service. It shows its name and icon and description as tooltip.
20+
* It also adds filtering capabilities.
21+
*/
22+
qx.Class.define("osparc.component.service.ServiceButtonList", {
23+
extend: osparc.dashboard.ListButtonBase,
24+
25+
construct: function(serviceModel) {
26+
this.base(arguments);
27+
28+
this.set({
29+
width: this.self().ITEM_WIDTH,
30+
height: this.self().ITEM_HEIGHT,
31+
allowGrowX: true
32+
});
33+
34+
if (serviceModel) {
35+
this.setServiceModel(serviceModel);
36+
}
37+
38+
this.subscribeToFilterGroup("serviceCatalog");
39+
},
40+
41+
properties: {
42+
serviceModel: {
43+
check: "qx.core.Object",
44+
nullable: false,
45+
apply: "__applyServiceModel"
46+
}
47+
},
48+
49+
statics: {
50+
ITEM_WIDTH: 550,
51+
ITEM_HEIGHT: 40,
52+
SERVICE_ICON: "@FontAwesome5Solid/paw/24"
53+
},
54+
55+
members: {
56+
_createChildControlImpl: function(id) {
57+
let control;
58+
switch (id) {
59+
case "hits":
60+
control = new qx.ui.basic.Label().set({
61+
anonymous: true,
62+
font: "text-13",
63+
allowGrowY: false,
64+
minWidth: 120,
65+
alignY: "middle"
66+
});
67+
this._addAt(control, osparc.dashboard.ListButtonBase.POS.LAST_CHANGE);
68+
break;
69+
}
70+
return control || this.base(arguments, id);
71+
},
72+
73+
__applyServiceModel: function(serviceModel) {
74+
// BASE
75+
if (serviceModel.getThumbnail()) {
76+
this.getChildControl("icon").setSource(serviceModel.getThumbnail());
77+
} else {
78+
this.getChildControl("icon").setSource(this.self().SERVICE_ICON);
79+
}
80+
serviceModel.bind("name", this.getChildControl("title"), "value");
81+
serviceModel.bind("description", this.getChildControl("description-md"), "value");
82+
83+
// ITEM
84+
this.__applyLatestVersion(serviceModel);
85+
this.__applyHits(serviceModel);
86+
},
87+
88+
__applyLatestVersion: function(serviceModel) {
89+
const latestVLabel = new qx.ui.basic.Label("v" + serviceModel.getVersion()).set({
90+
alignY: "middle"
91+
});
92+
this._addAt(latestVLabel, osparc.dashboard.ListButtonBase.POS.LAST_CHANGE);
93+
},
94+
95+
__applyHits: function(serviceModel) {
96+
const hitsLabel = new qx.ui.basic.Label(this.tr("Latest: ") + String(serviceModel.hits)).set({
97+
alignY: "middle",
98+
toolTipText: this.tr("Number of times it was instantiated")
99+
});
100+
this._addAt(hitsLabel, osparc.dashboard.ListButtonBase.POS.TSR);
101+
},
102+
103+
_filterText: function(text) {
104+
const checks = [
105+
this.getServiceModel().getName(),
106+
this.getServiceModel().getDescription(),
107+
this.getServiceModel().getContact()
108+
];
109+
return osparc.dashboard.CardBase.filterText(checks, text);
110+
},
111+
112+
_filterTags: function(tags) {
113+
if (tags && tags.length) {
114+
const type = this.getServiceModel().getType() || "";
115+
if (!tags.includes(osparc.utils.Utils.capitalize(type.trim()))) {
116+
return true;
117+
}
118+
}
119+
return false;
120+
},
121+
122+
_filterClassifiers: function(classifiers) {
123+
const checks = this.getServiceModel().getClassifiers();
124+
return osparc.dashboard.CardBase.filterText(checks, classifiers);
125+
}
126+
}
127+
});

services/web/client/source/class/osparc/component/service/ServiceList.js

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
************************************************************************ */
1717

1818
/**
19-
* This is a view to display the available services in a flowing fashion. Creates a ServiceButtonSmall button
19+
* This is a view to display the available services in a flowing fashion. Creates a ServiceButtonGrid button
2020
* for every service in the model and subscribes it to the filter group.
2121
*/
2222
qx.Class.define("osparc.component.service.ServiceList", {
@@ -25,7 +25,7 @@ qx.Class.define("osparc.component.service.ServiceList", {
2525
/**
2626
* If the optional parameter is given, the elements will be subscribed to the filter group of the given id.
2727
*
28-
* @param {String} [filterGroupId] Id of the filter group the ServiceButtonSmall buttons will be subscribed to.
28+
* @param {String} [filterGroupId] Id of the filter group the ServiceButtonGrid buttons will be subscribed to.
2929
*/
3030
construct: function(filterGroupId) {
3131
this.base(arguments);
@@ -61,24 +61,25 @@ qx.Class.define("osparc.component.service.ServiceList", {
6161
const group = this.__buttonGroup = new qx.ui.form.RadioGroup().set({
6262
allowEmptySelection: true
6363
});
64-
model.toArray()
65-
.sort((a, b) => a.getName().localeCompare(b.getName()))
66-
.forEach(service => {
67-
const button = new osparc.component.service.ServiceButtonSmall(service);
68-
if (this.__filterGroup !== null) {
69-
button.subscribeToFilterGroup(this.__filterGroup);
70-
}
71-
group.add(button);
72-
this._add(button);
73-
button.addListener("dbltap", e => {
64+
65+
osparc.utils.Services.sortBasedOnFav(model);
66+
model.toArray().forEach(service => {
67+
const button = new osparc.component.service.ServiceButtonList(service);
68+
if (this.__filterGroup !== null) {
69+
button.subscribeToFilterGroup(this.__filterGroup);
70+
}
71+
group.add(button);
72+
this._add(button);
73+
button.addListener("dbltap", () => {
74+
this.fireDataEvent("serviceAdd", button.getServiceModel());
75+
}, this);
76+
button.addListener("keypress", e => {
77+
if (e.getKeyIdentifier() === "Enter") {
7478
this.fireDataEvent("serviceAdd", button.getServiceModel());
75-
}, this);
76-
button.addListener("keypress", e => {
77-
if (e.getKeyIdentifier() === "Enter") {
78-
this.fireDataEvent("serviceAdd", button.getServiceModel());
79-
}
80-
}, this);
81-
});
79+
}
80+
}, this);
81+
});
82+
8283
group.addListener("changeValue", e => this.dispatchEvent(e.clone()), this);
8384
},
8485

services/web/client/source/class/osparc/component/workbench/BaseNodeUI.js

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,15 @@ qx.Class.define("osparc.component.workbench.BaseNodeUI", {
4444

4545
this.subscribeToFilterGroup("workbench");
4646

47-
this.getChildControl("captionbar").set({
47+
const captionBar = this.getChildControl("captionbar");
48+
captionBar.set({
4849
cursor: "move",
4950
paddingRight: 0,
5051
paddingLeft: this.self().PORT_WIDTH
5152
});
5253

5354
const menuBtn = this.__getMenuButton();
54-
this.getChildControl("captionbar").add(menuBtn, {
55+
captionBar.add(menuBtn, {
5556
row: 0,
5657
column: this.self().CAPTION_POS.MENU
5758
});
@@ -92,8 +93,8 @@ qx.Class.define("osparc.component.workbench.BaseNodeUI", {
9293
statics: {
9394
PORT_HEIGHT: 18,
9495
PORT_WIDTH: 11,
95-
NODE_CONNECTED: "@FontAwesome5Regular/dot-circle/18",
96-
NODE_DISCONNECTED: "@FontAwesome5Regular/circle/18",
96+
PORT_CONNECTED: "@FontAwesome5Regular/dot-circle/18",
97+
PORT_DISCONNECTED: "@FontAwesome5Regular/circle/18",
9798

9899
CAPTION_POS: {
99100
ICON: 0, // from qooxdoo
@@ -129,13 +130,6 @@ qx.Class.define("osparc.component.workbench.BaseNodeUI", {
129130
_optionsMenu: null,
130131
__nodeMoving: null,
131132

132-
/**
133-
* @abstract
134-
*/
135-
_createWindowLayout: function() {
136-
throw new Error("Abstract method called!");
137-
},
138-
139133
__getMenuButton: function() {
140134
const optionsMenu = this._optionsMenu = new qx.ui.menu.Menu().set({
141135
position: "bottom-right"
@@ -190,13 +184,6 @@ qx.Class.define("osparc.component.workbench.BaseNodeUI", {
190184
return this._outputLayout;
191185
},
192186

193-
/**
194-
* @abstract
195-
*/
196-
_createPorts: function() {
197-
throw new Error("Abstract method called!");
198-
},
199-
200187
_createPort: function(isInput, placeholder = false) {
201188
let port = null;
202189
const width = this.self().PORT_HEIGHT;
@@ -205,7 +192,7 @@ qx.Class.define("osparc.component.workbench.BaseNodeUI", {
205192
port = new qx.ui.core.Spacer(width, width);
206193
} else {
207194
port = new qx.ui.basic.Image().set({
208-
source: this.self().NODE_DISCONNECTED, // disconnected by default
195+
source: this.self().PORT_DISCONNECTED, // disconnected by default
209196
height: width,
210197
draggable: true,
211198
droppable: true,
@@ -238,27 +225,6 @@ qx.Class.define("osparc.component.workbench.BaseNodeUI", {
238225
return port;
239226
},
240227

241-
/**
242-
* @abstract
243-
*/
244-
_createDragDropEventData: function(e, isInput) {
245-
throw new Error("Abstract method called!");
246-
},
247-
248-
_addDragDropMechanism: function(port, isInput) {
249-
[
250-
["dragstart", "edgeDragStart"],
251-
["dragover", "edgeDragOver"],
252-
["drop", "edgeDrop"],
253-
["dragend", "edgeDragEnd"]
254-
].forEach(eventPair => {
255-
port.addListener(eventPair[0], e => {
256-
const eData = this._createDragDropEventData(e, isInput);
257-
this.fireDataEvent(eventPair[1], eData);
258-
}, this);
259-
}, this);
260-
},
261-
262228
getEdgePoint: function(port) {
263229
const bounds = this.getCurrentBounds();
264230
const captionHeight = Math.max(this.getChildControl("captionbar").getSizeHint().height, this.self().captionHeight());

0 commit comments

Comments
 (0)