Skip to content

Commit fc18d82

Browse files
authored
✨ [Frontend] Feature: Let users open a project if it's in use if isSimultaneousAccessEnabled (ITISFoundation#8100)
1 parent d6de2b6 commit fc18d82

File tree

11 files changed

+308
-102
lines changed

11 files changed

+308
-102
lines changed

services/static-webserver/client/source/class/osparc/dashboard/CardBase.js

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ qx.Class.define("osparc.dashboard.CardBase", {
2424
construct: function() {
2525
this.base(arguments);
2626

27+
if (osparc.utils.DisabledPlugins.isSimultaneousAccessEnabled()) {
28+
// "IN_USE" is not a blocker anymore
29+
const inUseIdx = qx.util.PropertyUtil.getProperties(osparc.dashboard.CardBase).blocked.check.indexOf("IN_USE");
30+
if (inUseIdx > -1) {
31+
qx.util.PropertyUtil.getProperties(osparc.dashboard.CardBase).blocked.check.splice(inUseIdx, 1);
32+
}
33+
}
34+
2735
[
2836
"pointerover",
2937
"focus"
@@ -768,13 +776,22 @@ qx.Class.define("osparc.dashboard.CardBase", {
768776
},
769777

770778
__applyState: function(state) {
771-
let lockInUse = false;
779+
let projectInUse = false;
772780
if ("locked" in state && "value" in state["locked"]) {
773-
lockInUse = state["locked"]["value"];
781+
projectInUse = state["locked"]["value"];
774782
}
775-
this.setBlocked(lockInUse ? "IN_USE" : false);
776-
if (lockInUse) {
777-
this.__showBlockedCardFromStatus("IN_USE", state["locked"]);
783+
784+
if (osparc.utils.DisabledPlugins.isSimultaneousAccessEnabled()) {
785+
if (projectInUse && state["locked"]["status"] === "OPENED") {
786+
this.__showWhoIsIn(state["locked"]["owner"]);
787+
} else {
788+
this.__showWhoIsIn(null);
789+
}
790+
} else {
791+
this.setBlocked(projectInUse ? "IN_USE" : false);
792+
if (projectInUse) {
793+
this.__showBlockedCardFromStatus("IN_USE", state["locked"]);
794+
}
778795
}
779796

780797
const pipelineState = ("state" in state) ? state["state"]["value"] : undefined;
@@ -854,6 +871,30 @@ qx.Class.define("osparc.dashboard.CardBase", {
854871
});
855872
},
856873

874+
__showWhoIsIn: function(whoIsIn) {
875+
let users = [];
876+
if (whoIsIn) {
877+
// replace this once the backend returns a list of group__ids
878+
const allUsers = [
879+
{ name: "Alice", avatar: "https://i.pravatar.cc/150?img=1" },
880+
{ name: "Bob", avatar: "https://i.pravatar.cc/150?img=2" },
881+
{ name: "Charlie", avatar: "https://i.pravatar.cc/150?img=3" },
882+
{ name: "Dana", avatar: "https://i.pravatar.cc/150?img=4" },
883+
{ name: "Eve", avatar: "https://i.pravatar.cc/150?img=5" },
884+
{ name: "Frank", avatar: "https://i.pravatar.cc/150?img=6" },
885+
];
886+
// Random number of users between 1 and 6
887+
const randomCount = Math.floor(Math.random() * 6) + 1;
888+
// Shuffle the array and take the first randomCount users
889+
const shuffled = allUsers.sort(() => 0.5 - Math.random());
890+
users = shuffled.slice(0, randomCount);
891+
}
892+
if (osparc.utils.DisabledPlugins.isSimultaneousAccessEnabled() && this.getResourceType() === "study") {
893+
const avatarGroup = this.getChildControl("avatar-group");
894+
avatarGroup.setUsers(users);
895+
}
896+
},
897+
857898
__showBlockedCardFromStatus: function(reason, moreInfo) {
858899
switch (reason) {
859900
case "IN_USE":

services/static-webserver/client/source/class/osparc/dashboard/GridButtonBase.js

Lines changed: 38 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -43,35 +43,41 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
4343
statics: {
4444
ITEM_WIDTH: 190,
4545
ITEM_HEIGHT: 220,
46-
PADDING: 10,
47-
TITLE_PADDING: 6,
48-
SPACING_IN: 5,
46+
PADDING: 6,
4947
SPACING: 15,
5048
THUMBNAIL_SIZE: 50,
5149
POS: {
5250
TITLE: {
5351
row: 0,
5452
column: 0,
55-
rowSpan: 1,
56-
colSpan: 4
5753
},
58-
THUMBNAIL: {
59-
row: 2,
54+
BODY: {
55+
row: 1,
6056
column: 0,
61-
rowSpan: 1,
62-
colSpan: 4
63-
},
64-
TAGS: {
65-
row: 3,
66-
column: 0
6757
},
6858
FOOTER: {
69-
row: 4,
59+
row: 2,
7060
column: 0,
71-
rowSpan: 1,
72-
colSpan: 4
7361
}
7462
},
63+
HPOS: {
64+
ICON: {
65+
column: 0,
66+
row: 0,
67+
},
68+
TITLE: {
69+
column: 1,
70+
row: 0,
71+
},
72+
SUBTITLE_ICON: {
73+
column: 0,
74+
row: 1,
75+
},
76+
SUBTITLE_TEXT: {
77+
column: 1,
78+
row: 1,
79+
},
80+
},
7581
FPOS: {
7682
MODIFIED: {
7783
row: 0,
@@ -97,7 +103,7 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
97103
row: 1,
98104
column: 2,
99105
}
100-
}
106+
},
101107
},
102108

103109
events: {
@@ -113,20 +119,21 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
113119
switch (id) {
114120
case "main-layout": {
115121
const grid = new qx.ui.layout.Grid();
116-
grid.setSpacing(this.self().SPACING_IN);
117-
grid.setRowFlex(2, 1);
122+
grid.setRowFlex(this.self().POS.BODY.row, 1);
118123
grid.setColumnFlex(0, 1);
119124

120125
control = new qx.ui.container.Composite().set({
126+
minWidth: this.self().ITEM_WIDTH,
127+
minHeight: this.self().ITEM_HEIGHT,
121128
maxWidth: this.self().ITEM_WIDTH,
122-
maxHeight: this.self().ITEM_HEIGHT
129+
maxHeight: this.self().ITEM_HEIGHT,
123130
});
124131
control.setLayout(grid);
125132
const header = this.getChildControl("header");
126133
const body = this.getChildControl("body");
127134
const footer = this.getChildControl("footer");
128135
control.add(header, this.self().POS.TITLE);
129-
control.add(body, this.self().POS.THUMBNAIL);
136+
control.add(body, this.self().POS.BODY);
130137
control.add(footer, this.self().POS.FOOTER);
131138
this._add(control, {
132139
top: 0,
@@ -140,8 +147,8 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
140147
const hGrid = new qx.ui.layout.Grid().set({
141148
spacing: 6,
142149
});
143-
hGrid.setRowFlex(0, 1);
144-
hGrid.setColumnFlex(1, 1);
150+
hGrid.setRowFlex(this.self().HPOS.TITLE.row, 1);
151+
hGrid.setColumnFlex(this.self().HPOS.TITLE.column, 1);
145152
hGrid.setColumnAlign(0, "right", "middle");
146153
hGrid.setColumnAlign(1, "left", "middle");
147154
hGrid.setColumnAlign(2, "center", "middle");
@@ -157,24 +164,17 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
157164
break;
158165
}
159166
case "body":
160-
control = new qx.ui.container.Composite(new qx.ui.layout.VBox(5)).set({
161-
decorator: "main",
162-
allowGrowY: true,
163-
allowGrowX: true,
164-
allowShrinkX: true,
165-
padding: this.self().PADDING
166-
});
167-
control.getContentElement().setStyles({
168-
"border-width": 0
167+
control = new qx.ui.container.Composite(new qx.ui.layout.VBox(6)).set({
168+
padding: this.self().PADDING,
169169
});
170170
break;
171171
case "footer": {
172172
const fGrid = new qx.ui.layout.Grid();
173173
fGrid.setSpacing(2);
174-
fGrid.setColumnFlex(0, 1);
174+
fGrid.setColumnFlex(this.self().FPOS.MODIFIED.row, 1);
175175
control = new qx.ui.container.Composite().set({
176176
backgroundColor: "background-card-overlay",
177-
padding: this.self().PADDING - 2,
177+
padding: this.self().PADDING,
178178
maxWidth: this.self().ITEM_WIDTH,
179179
maxHeight: this.self().ITEM_HEIGHT
180180
});
@@ -184,10 +184,7 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
184184
case "icon": {
185185
control = osparc.dashboard.CardBase.createCardIcon();
186186
layout = this.getChildControl("header");
187-
layout.add(control, {
188-
column: 0,
189-
row: 0,
190-
});
187+
layout.add(control, this.self().HPOS.ICON);
191188
break;
192189
}
193190
case "title":
@@ -196,21 +193,15 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
196193
font: "text-14",
197194
});
198195
layout = this.getChildControl("header");
199-
layout.add(control, {
200-
column: 1,
201-
row: 0,
202-
});
196+
layout.add(control, this.self().HPOS.TITLE);
203197
break;
204198
case "subtitle-icon": {
205199
control = new qx.ui.basic.Image().set({
206200
allowGrowX: false,
207201
allowShrinkX: false,
208202
});
209203
layout = this.getChildControl("header");
210-
layout.add(control, {
211-
column: 0,
212-
row: 1,
213-
});
204+
layout.add(control, this.self().HPOS.SUBTITLE_ICON);
214205
break;
215206
}
216207
case "subtitle-text": {
@@ -225,10 +216,7 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
225216
allowGrowY: false
226217
});
227218
layout = this.getChildControl("header");
228-
layout.add(control, {
229-
column: 1,
230-
row: 1,
231-
});
219+
layout.add(control, this.self().HPOS.SUBTITLE_TEXT);
232220
break;
233221
}
234222
case "thumbnail": {
@@ -322,32 +310,6 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
322310
return;
323311
},
324312

325-
__fitThumbnailHeight: function() {
326-
const thumbnailLayout = this.getChildControl("thumbnail");
327-
let maxHeight = this.getHeight() - this.getPaddingTop() - this.getPaddingBottom() - 5;
328-
const checkThis = [
329-
"title",
330-
"body",
331-
"footer",
332-
"tags"
333-
];
334-
const layout = this.getChildControl("main-layout");
335-
// eslint-disable-next-line no-underscore-dangle
336-
layout._getChildren().forEach(child => {
337-
if (checkThis.includes(child.getSubcontrolId()) && child.getBounds()) {
338-
maxHeight -= (child.getBounds().height + this.self().SPACING_IN);
339-
if (child.getSubcontrolId() === "tags") {
340-
maxHeight -= 8;
341-
}
342-
}
343-
});
344-
// maxHeight -= 4; // for Roboto
345-
maxHeight -= 18; // for Manrope
346-
thumbnailLayout.getChildControl("image").setMaxHeight(maxHeight);
347-
thumbnailLayout.setMaxHeight(maxHeight);
348-
thumbnailLayout.recheckSize();
349-
},
350-
351313
/**
352314
* Event handler for the pointer over event.
353315
*/

services/static-webserver/client/source/class/osparc/dashboard/GridButtonItem.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ qx.Class.define("osparc.dashboard.GridButtonItem", {
3434
},
3535

3636
statics: {
37-
MENU_BTN_DIMENSIONS: 24
37+
MENU_BTN_DIMENSIONS: 24,
38+
39+
BODY_POS: {
40+
AVATAR_GROUP: 0,
41+
TAGS: 1,
42+
},
3843
},
3944

4045
members: {
@@ -81,16 +86,25 @@ qx.Class.define("osparc.dashboard.GridButtonItem", {
8186
layout = this.getChildControl("footer");
8287
layout.add(control, osparc.dashboard.GridButtonBase.FPOS.HITS);
8388
break;
84-
case "tags":
85-
control = new qx.ui.container.Composite(new qx.ui.layout.Flow(5, 3)).set({
89+
case "avatar-group": {
90+
const maxWidth = osparc.dashboard.GridButtonBase.ITEM_WIDTH - osparc.dashboard.GridButtonBase.PADDING * 2;
91+
control = new osparc.ui.basic.AvatarGroup(24, "left", maxWidth);
92+
this.getChildControl("body").addAt(control, this.self().BODY_POS.AVATAR_GROUP);
93+
break;
94+
}
95+
case "tags": {
96+
const wrapper = new qx.ui.container.Composite(new qx.ui.layout.VBox());
97+
// Add spacer to push tags to bottom
98+
wrapper.add(new qx.ui.core.Spacer(), {flex: 1});
99+
control = new qx.ui.container.Composite(new qx.ui.layout.Flow(4, 4)).set({
86100
anonymous: true,
87-
paddingLeft: osparc.dashboard.GridButtonBase.PADDING,
88-
paddingRight: osparc.dashboard.GridButtonBase.PADDING,
89-
paddingBottom: osparc.dashboard.GridButtonBase.PADDING / 2
90101
});
91-
layout = this.getChildControl("main-layout");
92-
layout.add(control, osparc.dashboard.GridButtonBase.POS.TAGS);
102+
wrapper.add(control);
103+
this.getChildControl("body").addAt(wrapper, this.self().BODY_POS.TAGS, {
104+
flex: 1,
105+
});
93106
break;
107+
}
94108
case "menu-selection-stack":
95109
control = new qx.ui.container.Stack();
96110
control.set({
@@ -261,7 +275,7 @@ qx.Class.define("osparc.dashboard.GridButtonItem", {
261275
const tagsContainer = this.getChildControl("tags");
262276
tagsContainer.setVisibility(tags.length ? "visible" : "excluded");
263277
tagsContainer.removeAll();
264-
for (let i=0; i<=tags.length && i<maxTags; i++) {
278+
for (let i=0; i<tags.length && i<maxTags; i++) {
265279
const tag = tags[i];
266280
const tagUI = new osparc.ui.basic.Tag(tag, "searchBarFilter");
267281
tagUI.set({

services/static-webserver/client/source/class/osparc/dashboard/ListButtonBase.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,15 @@ qx.Class.define("osparc.dashboard.ListButtonBase", {
5050
TITLE: 2,
5151
SPACER: 3,
5252
PROGRESS: 4,
53-
TAGS: 5,
54-
ICONS_LAYOUT: 6,
55-
OWNER: 7,
56-
SHARED: 8,
57-
LAST_CHANGE: 9,
58-
TSR: 10,
59-
HITS: 11,
60-
OPTIONS: 12
53+
AVATAR_GROUP: 5,
54+
TAGS: 6,
55+
ICONS_LAYOUT: 7,
56+
OWNER: 8,
57+
SHARED: 9,
58+
LAST_CHANGE: 10,
59+
TSR: 11,
60+
HITS: 12,
61+
OPTIONS: 13,
6162
}
6263
},
6364

services/static-webserver/client/source/class/osparc/dashboard/ListButtonItem.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ qx.Class.define("osparc.dashboard.ListButtonItem", {
4545
column: osparc.dashboard.ListButtonBase.POS.LOCK_STATUS
4646
});
4747
break;
48+
case "avatar-group":
49+
control = new osparc.ui.basic.AvatarGroup(24, "right", 100).set({
50+
paddingTop: 4, // to align it in the middle
51+
});
52+
this._add(control, {
53+
row: 0,
54+
column: osparc.dashboard.ListButtonBase.POS.AVATAR_GROUP
55+
});
56+
break;
4857
case "tags":
4958
control = new qx.ui.container.Composite(new qx.ui.layout.HBox(3).set({
5059
alignY: "middle"
@@ -236,8 +245,8 @@ qx.Class.define("osparc.dashboard.ListButtonItem", {
236245
const label = this.getChildControl("owner");
237246
const user = this.__createOwner(value);
238247
label.setValue(user);
248+
239249
this.__makeItemResponsive(label);
240-
return;
241250
},
242251

243252
_applyAccessRights: function(value) {

0 commit comments

Comments
 (0)