Skip to content

Commit 65af25b

Browse files
committed
Merge branch 'master' into is468/empty-trash
2 parents 3a5d39b + ee36743 commit 65af25b

File tree

8 files changed

+158
-120
lines changed

8 files changed

+158
-120
lines changed

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

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ qx.Class.define("osparc.dashboard.CardBase", {
148148
return false;
149149
},
150150

151-
populateShareIcon: async function(shareIcon, accessRights) {
151+
populateShareIcon: function(shareIcon, accessRights) {
152152
const gids = Object.keys(accessRights).map(key => parseInt(key));
153153

154154
const groupsStore = osparc.store.Groups.getInstance();
@@ -169,6 +169,17 @@ qx.Class.define("osparc.dashboard.CardBase", {
169169
}
170170

171171
// Tooltip
172+
const canIWrite = osparc.data.model.Study.canIWrite(accessRights);
173+
const myGroupId = groupsStore.getMyGroupId();
174+
if (gids.length === 0 || (gids.length === 1 && gids[0] === myGroupId)) {
175+
if (canIWrite) {
176+
shareIcon.set({
177+
toolTipText: qx.locale.Manager.tr("Share")
178+
});
179+
}
180+
return;
181+
}
182+
172183
const sharedGrps = [];
173184
const groups = [];
174185
groups.push(groupEveryone);
@@ -181,43 +192,44 @@ qx.Class.define("osparc.dashboard.CardBase", {
181192
gids.splice(idx, 1);
182193
}
183194
});
184-
// once the groups were removed, the remaining group ids are users' primary groups ids
185-
const usersStore = osparc.store.Users.getInstance();
186-
const myGroupId = groupsStore.getMyGroupId();
187-
for (let i=0; i<gids.length; i++) {
188-
const gid = gids[i];
189-
if (myGroupId !== gid) {
190-
const user = await usersStore.getUser(gid);
191-
if (user) {
192-
sharedGrps.push(user);
195+
196+
const hint = new osparc.ui.hint.Hint(shareIcon);
197+
shareIcon.addListener("mouseover", async () => {
198+
hint.show();
199+
200+
// lazy load tooltip, this can be an expensive call
201+
202+
// once the groups were removed, the remaining group ids are users' primary groups ids
203+
const usersStore = osparc.store.Users.getInstance();
204+
for (let i=0; i<gids.length; i++) {
205+
const gid = gids[i];
206+
if (myGroupId !== gid) {
207+
const user = await usersStore.getUser(gid);
208+
if (user) {
209+
sharedGrps.push(user);
210+
}
193211
}
194212
}
195-
}
196213

197-
const canIWrite = osparc.data.model.Study.canIWrite(accessRights);
198-
if (sharedGrps.length === 0) {
199-
if (canIWrite) {
200-
shareIcon.set({
201-
toolTipText: qx.locale.Manager.tr("Share")
202-
});
203-
}
204-
return;
205-
}
206-
const sharedGrpLabels = [];
207-
const maxItems = 6;
208-
for (let i=0; i<sharedGrps.length; i++) {
209-
if (i > maxItems) {
210-
sharedGrpLabels.push("...");
211-
break;
212-
}
213-
const sharedGrpLabel = sharedGrps[i].getLabel();
214-
if (!sharedGrpLabels.includes(sharedGrpLabel)) {
215-
sharedGrpLabels.push(sharedGrpLabel);
214+
if (hint.getText() === "") {
215+
const sharedGrpLabels = [];
216+
const maxItems = 6;
217+
for (let i=0; i<sharedGrps.length; i++) {
218+
if (i > maxItems) {
219+
sharedGrpLabels.push("...");
220+
break;
221+
}
222+
const sharedGrpLabel = sharedGrps[i].getLabel();
223+
if (!sharedGrpLabels.includes(sharedGrpLabel)) {
224+
sharedGrpLabels.push(sharedGrpLabel);
225+
}
226+
}
227+
const hintText = sharedGrpLabels.join("<br>");
228+
if (hintText) {
229+
hint.setText(hintText);
230+
}
216231
}
217-
}
218-
const hintText = sharedGrpLabels.join("<br>");
219-
const hint = new osparc.ui.hint.Hint(shareIcon, hintText);
220-
shareIcon.addListener("mouseover", () => hint.show(), this);
232+
}, this);
221233
shareIcon.addListener("mouseout", () => hint.exclude(), this);
222234
},
223235
},

services/static-webserver/client/source/class/osparc/desktop/wallets/MembersList.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,15 @@ qx.Class.define("osparc.desktop.wallets.MembersList", {
208208

209209
const myGroupId = osparc.auth.Data.getInstance().getGroupId();
210210
const membersList = [];
211-
const potentialCollaborators = osparc.store.Groups.getInstance().getPotentialCollaborators(true);
212211
const canIWrite = wallet.getMyAccessRights()["write"];
213-
wallet.getAccessRights().forEach(accessRights => {
212+
const accessRightss = wallet.getAccessRights();
213+
const usersStore = osparc.store.Users.getInstance();
214+
for (let i=0; i<Object.keys(accessRightss).length; i++) {
215+
const accessRights = accessRightss[i];
214216
const gid = parseInt(accessRights["gid"]);
215-
if (Object.prototype.hasOwnProperty.call(potentialCollaborators, gid)) {
216-
// only users or groupMe
217-
const collab = potentialCollaborators[gid];
217+
// only users or groupMe
218+
const collab = await usersStore.getUser(gid);
219+
if (collab) {
218220
const collaborator = {};
219221
collaborator["userId"] = gid === myGroupId ? osparc.auth.Data.getInstance().getUserId() : collab.getUserId();
220222
collaborator["groupId"] = collab.getGroupId();
@@ -250,7 +252,7 @@ qx.Class.define("osparc.desktop.wallets.MembersList", {
250252
collaborator["showOptions"] = Boolean(options.length);
251253
membersList.push(collaborator);
252254
}
253-
});
255+
}
254256
membersList.sort(this.self().sortWalletMembers);
255257
membersList.forEach(member => membersModel.append(qx.data.marshal.Json.createModel(member)));
256258
},

services/static-webserver/client/source/class/osparc/file/FileLabelWithActions.js

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
4949

5050
const deleteBtn = this.getChildControl("delete-button");
5151
deleteBtn.addListener("execute", () => this.__deleteSelected(), this);
52+
53+
this.__selection = [];
5254
},
5355

5456
events: {
@@ -61,13 +63,12 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
6163
init: false,
6264
nullable: false,
6365
event: "changeMultiSelect",
64-
apply: "__enableMultiSelection",
66+
apply: "__changeMultiSelection",
6567
},
6668
},
6769

6870
members: {
6971
__selection: null,
70-
__multiSelection: null,
7172

7273
_createChildControlImpl: function(id) {
7374
let control;
@@ -99,9 +100,10 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
99100
return control || this.base(arguments, id);
100101
},
101102

102-
__enableMultiSelection: function() {
103-
this.resetItemSelected();
104-
this.__multiSelection = [];
103+
__changeMultiSelection: function() {
104+
if (this.__selection.length > 1) {
105+
this.resetSelection();
106+
}
105107
},
106108

107109
setItemSelected: function(selectedItem) {
@@ -111,25 +113,25 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
111113
this.getChildControl("delete-button").setEnabled(isFile);
112114
const selectedLabel = this.getChildControl("selected-label");
113115
if (isFile) {
114-
this.__selection = selectedItem;
116+
this.__selection = [selectedItem];
115117
selectedLabel.set({
116118
value: selectedItem.getLabel(),
117119
toolTipText: selectedItem.getFileId()
118120
});
119121
} else {
120-
this.__selection = null;
122+
this.__selection = [];
121123
selectedLabel.set({
122124
value: "",
123125
toolTipText: ""
124126
});
125127
}
126128
} else {
127-
this.resetItemSelected();
129+
this.resetSelection();
128130
}
129131
},
130132

131133
setMultiItemSelected: function(multiSelectionData) {
132-
this.__multiSelection = multiSelectionData;
134+
this.__selection = multiSelectionData;
133135
if (multiSelectionData && multiSelectionData.length) {
134136
if (multiSelectionData.length === 1) {
135137
this.setItemSelected(multiSelectionData[0]);
@@ -140,34 +142,27 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
140142
});
141143
}
142144
} else {
143-
this.resetItemSelected();
145+
this.resetSelection();
144146
}
145147
},
146148

147-
resetItemSelected: function() {
148-
this.__selection = null;
149-
this.__multiSelection = [];
149+
resetSelection: function() {
150+
this.__selection = [];
150151
this.getChildControl("download-button").setEnabled(false);
151152
this.getChildControl("delete-button").setEnabled(false);
152153
this.getChildControl("selected-label").resetValue();
153154
},
154155

155-
getItemSelected: function() {
156-
const selectedItem = this.__selection;
157-
if (selectedItem && osparc.file.FilesTree.isFile(selectedItem)) {
158-
return selectedItem;
159-
}
160-
return null;
161-
},
162-
163156
__retrieveURLAndDownloadSelected: function() {
164157
if (this.isMultiSelect()) {
165-
this.__multiSelection.forEach(selection => {
166-
this.__retrieveURLAndDownloadFile(selection);
158+
this.__selection.forEach(selection => {
159+
if (selection && osparc.file.FilesTree.isFile(selection)) {
160+
this.__retrieveURLAndDownloadFile(selection);
161+
}
167162
});
168-
} else {
169-
const selection = this.getItemSelected();
170-
if (selection) {
163+
} else if (this.__selection.length) {
164+
const selection = this.__selection[0];
165+
if (selection && osparc.file.FilesTree.isFile(selection)) {
171166
this.__retrieveURLAndDownloadFile(selection);
172167
}
173168
}
@@ -176,10 +171,12 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
176171
__deleteSelected: function() {
177172
if (this.isMultiSelect()) {
178173
const requests = [];
179-
this.__multiSelection.forEach(selection => {
180-
const request = this.__deleteFile(selection);
181-
if (request) {
182-
requests.push(request);
174+
this.__selection.forEach(selection => {
175+
if (selection && osparc.file.FilesTree.isFile(selection)) {
176+
const request = this.__deleteFile(selection);
177+
if (request) {
178+
requests.push(request);
179+
}
183180
}
184181
});
185182
Promise.all(requests)
@@ -190,9 +187,9 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
190187
}
191188
});
192189
requests
193-
} else {
194-
const selection = this.getItemSelected();
195-
if (selection) {
190+
} else if (this.__selection.length) {
191+
const selection = this.__selection[0];
192+
if (selection && osparc.file.FilesTree.isFile(selection)) {
196193
const request = this.__deleteFile(selection);
197194
if (request) {
198195
request

services/static-webserver/client/source/class/osparc/file/FolderContent.js

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ qx.Class.define("osparc.file.FolderContent", {
4747
init: false,
4848
nullable: false,
4949
event: "changeMultiSelect",
50-
apply: "__reloadFolderContent"
50+
apply: "__changeMultiSelect"
5151
},
5252
},
5353

@@ -227,26 +227,43 @@ qx.Class.define("osparc.file.FolderContent", {
227227
} else if (this.getMode() === "icons") {
228228
const iconsLayout = this.getChildControl("icons-layout");
229229
iconsLayout.removeAll();
230-
const iconsGroup = new qx.ui.form.RadioGroup().set({
231-
allowEmptySelection: true
232-
});
233230
entries.forEach(entry => {
234-
if (!this.isMultiSelect()) {
235-
iconsGroup.add(entry);
236-
}
237231
iconsLayout.add(entry);
238232
});
239233
}
240234
this.setSelection([this.getSelectables()[this.getMode() === "icons" ? 0 : 1]]);
241235
},
242236

243-
__itemTapped: function(entry, buttonSelected) {
237+
__changeMultiSelect: function() {
238+
if (this.getMode() === "icons" && this.getMultiSelect() === false) {
239+
const iconsLayout = this.getChildControl("icons-layout");
240+
const selectedButtons = iconsLayout.getChildren().filter(btn => btn.getValue());
241+
if (selectedButtons.length > 1) {
242+
// reset selection
243+
selectedButtons.forEach(btn => btn.setValue(false));
244+
}
245+
} else if (this.getMode() === "list") {
246+
const selectionModel = this.getChildControl("table").getSelectionModel();
247+
let selection = null;
248+
if (selectionModel.getSelectedCount() === 1) {
249+
// keep selection
250+
selection = selectionModel.getSelectedRanges()[0];
251+
}
252+
selectionModel.setSelectionMode(this.isMultiSelect() ?
253+
qx.ui.table.selection.Model.MULTIPLE_INTERVAL_SELECTION_TOGGLE :
254+
qx.ui.table.selection.Model.SINGLE_SELECTION
255+
);
256+
if (selection) {
257+
selectionModel.setSelectionInterval(selection.minIndex, selection.maxIndex);
258+
}
259+
}
260+
},
261+
262+
__selectionChanged: function(selection) {
244263
if (this.isMultiSelect()) {
245-
this.fireDataEvent("multiSelectionChanged", entry);
246-
} else if (buttonSelected === false) {
247-
this.fireDataEvent("selectionChanged", null);
264+
this.fireDataEvent("multiSelectionChanged", selection);
248265
} else {
249-
this.fireDataEvent("selectionChanged", entry);
266+
this.fireDataEvent("selectionChanged", (selection && selection.length) ? selection[0] : null);
250267
}
251268
},
252269

@@ -255,7 +272,10 @@ qx.Class.define("osparc.file.FolderContent", {
255272
},
256273

257274
__attachListenersToGridItem: function(gridItem) {
258-
gridItem.addListener("tap", () => {
275+
gridItem.addListener("tap", e => {
276+
if (e.getNativeEvent().ctrlKey) {
277+
this.setMultiSelect(true);
278+
}
259279
if (this.isMultiSelect()) {
260280
// pass all buttons that are selected
261281
const selectedFiles = [];
@@ -265,9 +285,14 @@ qx.Class.define("osparc.file.FolderContent", {
265285
selectedFiles.push(btn.entry);
266286
}
267287
});
268-
this.__itemTapped(selectedFiles, gridItem.getValue());
288+
this.__selectionChanged(selectedFiles);
269289
} else {
270-
this.__itemTapped(gridItem.entry, gridItem.getValue());
290+
// unselect the other items
291+
const iconsLayout = this.getChildControl("icons-layout");
292+
iconsLayout.getChildren().forEach(btn => {
293+
btn.setValue(btn === gridItem);
294+
});
295+
this.__selectionChanged(gridItem.getValue() ? [gridItem.entry] : null);
271296
}
272297
// folders can't be selected
273298
if (osparc.file.FilesTree.isDir(gridItem.entry)) {
@@ -281,11 +306,20 @@ qx.Class.define("osparc.file.FolderContent", {
281306

282307
__attachListenersToTableItem: function(table) {
283308
table.addListener("cellTap", e => {
284-
const selectedRow = e.getRow();
285-
const rowData = table.getTableModel().getRowData(selectedRow);
286-
if ("entry" in rowData) {
287-
this.__itemTapped(rowData.entry);
309+
if (e.getNativeEvent().ctrlKey) {
310+
this.setMultiSelect(true);
288311
}
312+
const selectedFiles = [];
313+
const selectionRanges = table.getSelectionModel().getSelectedRanges();
314+
selectionRanges.forEach(range => {
315+
for (let i=range.minIndex; i<=range.maxIndex; i++) {
316+
const row = table.getTableModel().getRowData(i);
317+
if (osparc.file.FilesTree.isFile(row.entry)) {
318+
selectedFiles.push(row.entry);
319+
}
320+
}
321+
});
322+
this.__selectionChanged(selectedFiles);
289323
}, this);
290324
table.addListener("cellDbltap", e => {
291325
const selectedRow = e.getRow();

0 commit comments

Comments
 (0)