Skip to content

Commit 4fa6ee2

Browse files
authoredFeb 5, 2025··
🎨 [Frontend] UI/UX Data handling: Larger window and list view by default (#7160)
1 parent aed987d commit 4fa6ee2

29 files changed

+208
-247
lines changed
 

‎services/static-webserver/client/source/class/osparc/DownloadLinkTracker.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ qx.Class.define("osparc.DownloadLinkTracker", {
3333
downloadAnchorNode.setAttribute("href", url);
3434
downloadAnchorNode.setAttribute("download", fileName);
3535
downloadAnchorNode.setAttribute("osparc", "downloadFile");
36+
document.body.appendChild(downloadAnchorNode);
3637
this.setDownloading(true);
3738
downloadAnchorNode.click();
38-
downloadAnchorNode.remove();
39+
document.body.removeChild(downloadAnchorNode);
3940
// This is needed to make it work in Firefox
4041
setTimeout(() => this.setDownloading(false), 100);
4142
}

‎services/static-webserver/client/source/class/osparc/admin/AdminCenter.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ qx.Class.define("osparc.admin.AdminCenter", {
2424
const miniProfile = osparc.desktop.account.MyAccount.createMiniProfileView().set({
2525
paddingRight: 10
2626
});
27-
this.addWidgetOnTopOfTheTabs(miniProfile);
27+
this.addWidgetToTabs(miniProfile);
2828

2929
this.__addPricingPlansPage();
3030
this.__addMaintenancePage();

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -963,8 +963,8 @@ qx.Class.define("osparc.dashboard.CardBase", {
963963
},
964964

965965
openData: function() {
966-
const moreOpts = this.__openMoreOptions();
967-
moreOpts.openData();
966+
const resourceData = this.getResourceData();
967+
osparc.widget.StudyDataManager.popUpInWindow(resourceData["uuid"]);
968968
},
969969

970970
openBilling: function() {

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

+22-33
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
9393
__resourceData: null,
9494
__resourceModel: null,
9595
__infoPage: null,
96-
__dataPage: null,
9796
__servicesUpdatePage: null,
9897
__permissionsPage: null,
9998
__tagsPage: null,
@@ -216,10 +215,6 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
216215
this._openPage(this.__infoPage);
217216
},
218217

219-
openData: function() {
220-
this._openPage(this.__dataPage);
221-
},
222-
223218
openUpdateServices: function() {
224219
this._openPage(this.__servicesUpdatePage);
225220
},
@@ -306,7 +301,6 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
306301
this.__getBillingPage,
307302
this.__getServicesUpdatePage,
308303
this.__getServicesBootOptionsPage,
309-
this.__getDataPage,
310304
this.__getCommentsPage,
311305
this.__getPermissionsPage,
312306
this.__getSaveAsTemplatePage,
@@ -323,6 +317,28 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
323317
}
324318
});
325319

320+
const resourceData = this.__resourceData;
321+
if (!osparc.utils.Resources.isService(resourceData)) {
322+
const title = osparc.product.Utils.getStudyAlias({firstUpperCase: true}) + this.tr(" Files...");
323+
const iconSrc = "@FontAwesome5Solid/file/22";
324+
const dataAccess = new qx.ui.basic.Atom().set({
325+
label: title,
326+
icon: iconSrc,
327+
font: "text-14",
328+
padding: 8,
329+
paddingLeft: 12,
330+
gap: 14,
331+
cursor: "pointer",
332+
});
333+
dataAccess.addListener("tap", () => osparc.widget.StudyDataManager.popUpInWindow(resourceData["uuid"]));
334+
this.addWidgetToTabs(dataAccess);
335+
336+
if (resourceData["resourceType"] === "study") {
337+
const canShowData = osparc.study.Utils.canShowStudyData(resourceData);
338+
dataAccess.setEnabled(canShowData);
339+
}
340+
}
341+
326342
if (selectedTabId) {
327343
const pageFound = tabsView.getChildren().find(page => page.tabId === selectedTabId);
328344
if (pageFound) {
@@ -486,33 +502,6 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
486502
return page;
487503
},
488504

489-
__getDataPage: function() {
490-
const resourceData = this.__resourceData;
491-
if (osparc.utils.Resources.isService(resourceData)) {
492-
return null;
493-
}
494-
495-
const id = "Data";
496-
const title = osparc.product.Utils.getStudyAlias({firstUpperCase: true}) + this.tr(" Files");
497-
const iconSrc = "@FontAwesome5Solid/file/22";
498-
const page = this.__dataPage = new osparc.dashboard.resources.pages.BasePage(title, iconSrc, id);
499-
this.__addOpenButton(page);
500-
501-
if (this.__resourceData["resourceType"] === "study") {
502-
const studyData = this.__resourceData;
503-
const canBeOpened = osparc.study.Utils.canShowStudyData(studyData);
504-
page.setEnabled(canBeOpened);
505-
}
506-
507-
const lazyLoadContent = () => {
508-
const studyDataManager = new osparc.widget.NodeDataManager(resourceData["uuid"]);
509-
page.addToContent(studyDataManager);
510-
}
511-
page.addListenerOnce("appear", lazyLoadContent, this);
512-
513-
return page;
514-
},
515-
516505
__getPermissionsPage: function() {
517506
const id = "Permissions";
518507
const title = this.tr("Sharing");

‎services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ qx.Class.define("osparc.desktop.StudyEditor", {
722722
this.__workbenchView.showPipeline();
723723
} else {
724724
const currentNodeId = this.getStudy().getUi().getCurrentNodeId();
725-
if (currentNodeId) {
725+
if (currentNodeId && this.getStudy().getWorkbench().getNode(currentNodeId)) {
726726
const node = this.getStudy().getWorkbench().getNode(currentNodeId);
727727
if (node && node.isDynamic()) {
728728
this.__workbenchView.fullscreenNode(currentNodeId);

‎services/static-webserver/client/source/class/osparc/desktop/WorkbenchView.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,8 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
5454
});
5555
},
5656

57-
openNodeDataManager: function(node) {
58-
const nodeDataManager = new osparc.widget.NodeDataManager(null, node.getNodeId());
59-
const win = osparc.ui.window.Window.popUpInWindow(nodeDataManager, node.getLabel(), 900, 600).set({
60-
appearance: "service-window"
61-
});
57+
openStudyDataManager: function(node) {
58+
const win = osparc.widget.StudyDataManager.popUpInWindow(null, node.getNodeId(), node.getLabel());
6259
const closeBtn = win.getChildControl("close-button");
6360
osparc.utils.Utils.setIdToWidget(closeBtn, "nodeDataManagerCloseBtn");
6461
}
@@ -1049,7 +1046,7 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
10491046
allowGrowY: false
10501047
});
10511048
osparc.utils.Utils.setIdToWidget(nodeFilesBtn, "nodeFilesBtn");
1052-
nodeFilesBtn.addListener("execute", () => this.self().openNodeDataManager(node));
1049+
nodeFilesBtn.addListener("execute", () => this.self().openStudyDataManager(node));
10531050
outputsBox.add(nodeFilesBtn);
10541051

10551052
const outputs = new osparc.desktop.PanelView(this.tr("Outputs"), outputsBox);

‎services/static-webserver/client/source/class/osparc/desktop/account/MyAccount.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ qx.Class.define("osparc.desktop.account.MyAccount", {
2424
const miniProfile = osparc.desktop.account.MyAccount.createMiniProfileView().set({
2525
paddingRight: 10
2626
});
27-
this.addWidgetOnTopOfTheTabs(miniProfile);
27+
this.addWidgetToTabs(miniProfile);
2828

2929
this.__profilePage = this.__addProfilePage();
3030

‎services/static-webserver/client/source/class/osparc/desktop/credits/BillingCenter.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ qx.Class.define("osparc.desktop.credits.BillingCenter", {
2424
const miniWallet = this.self().createMiniWalletView().set({
2525
paddingRight: 10
2626
});
27-
this.addWidgetOnTopOfTheTabs(miniWallet);
27+
this.addWidgetToTabs(miniWallet);
2828

2929
this.__walletsPage = this.__addWalletsPage();
3030
this.__paymentMethodsPage = this.__addPaymentMethodsPage();

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

+63-49
Original file line numberDiff line numberDiff line change
@@ -108,23 +108,11 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
108108

109109
setItemSelected: function(selectedItem) {
110110
if (selectedItem) {
111+
this.__selection = [selectedItem];
111112
const isFile = osparc.file.FilesTree.isFile(selectedItem);
112113
this.getChildControl("download-button").setEnabled(isFile);
113-
this.getChildControl("delete-button").setEnabled(isFile);
114-
const selectedLabel = this.getChildControl("selected-label");
115-
if (isFile) {
116-
this.__selection = [selectedItem];
117-
selectedLabel.set({
118-
value: selectedItem.getLabel(),
119-
toolTipText: selectedItem.getFileId()
120-
});
121-
} else {
122-
this.__selection = [];
123-
selectedLabel.set({
124-
value: "",
125-
toolTipText: ""
126-
});
127-
}
114+
this.getChildControl("delete-button").setEnabled(true); // folders can also be deleted
115+
this.getChildControl("selected-label").setValue(selectedItem.getLabel());
128116
} else {
129117
this.resetSelection();
130118
}
@@ -138,7 +126,7 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
138126
} else {
139127
const selectedLabel = this.getChildControl("selected-label");
140128
selectedLabel.set({
141-
value: multiSelectionData.length + " files"
129+
value: multiSelectionData.length + " items"
142130
});
143131
}
144132
} else {
@@ -168,60 +156,86 @@ qx.Class.define("osparc.file.FileLabelWithActions", {
168156
}
169157
},
170158

159+
__retrieveURLAndDownloadFile: function(file) {
160+
const fileId = file.getFileId();
161+
const locationId = file.getLocation();
162+
osparc.utils.Utils.retrieveURLAndDownload(locationId, fileId)
163+
.then(data => {
164+
if (data) {
165+
osparc.DownloadLinkTracker.getInstance().downloadLinkUnattended(data.link, data.fileName);
166+
}
167+
});
168+
},
169+
171170
__deleteSelected: function() {
171+
const toBeDeleted = [];
172+
let isFolderSelected = false;
172173
if (this.isMultiSelect()) {
173-
const requests = [];
174174
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);
175+
if (selection) {
176+
toBeDeleted.push(selection);
177+
if (osparc.file.FilesTree.isDir(selection)) {
178+
isFolderSelected = true;
179179
}
180180
}
181181
});
182-
Promise.all(requests)
183-
.then(datas => {
184-
if (datas.length) {
185-
this.fireDataEvent("fileDeleted", datas[0]);
186-
osparc.FlashMessenger.getInstance().logAs(this.tr("Files successfully deleted"), "INFO");
187-
}
188-
});
189-
requests
190182
} else if (this.__selection.length) {
191183
const selection = this.__selection[0];
192-
if (selection && osparc.file.FilesTree.isFile(selection)) {
193-
const request = this.__deleteFile(selection);
194-
if (request) {
195-
request
196-
.then(data => {
197-
this.fireDataEvent("fileDeleted", data);
198-
osparc.FlashMessenger.getInstance().logAs(this.tr("File successfully deleted"), "INFO");
199-
});
184+
if (selection) {
185+
if (osparc.file.FilesTree.isDir(selection)) {
186+
isFolderSelected = true;
200187
}
201188
}
202189
}
190+
191+
let msg = this.tr("This operation cannot be undone.");
192+
msg += isFolderSelected ? ("<br>"+this.tr("All the content of the folders will be deleted.")) : "";
193+
msg += "<br>" + this.tr("Do you want to proceed?");
194+
const confirmationWin = new osparc.ui.window.Confirmation(msg).set({
195+
caption: this.tr("Delete"),
196+
confirmText: this.tr("Delete"),
197+
confirmAction: "delete"
198+
});
199+
confirmationWin.center();
200+
confirmationWin.open();
201+
confirmationWin.addListener("close", () => {
202+
if (confirmationWin.getConfirmed()) {
203+
this.__doDeleteSelected(toBeDeleted);
204+
}
205+
}, this);
203206
},
204207

205-
__retrieveURLAndDownloadFile: function(file) {
206-
const fileId = file.getFileId();
207-
const locationId = file.getLocation();
208-
osparc.utils.Utils.retrieveURLAndDownload(locationId, fileId)
209-
.then(data => {
210-
if (data) {
211-
osparc.DownloadLinkTracker.getInstance().downloadLinkUnattended(data.link, data.fileName);
208+
__doDeleteSelected: function(toBeDeleted) {
209+
const requests = [];
210+
toBeDeleted.forEach(selection => {
211+
if (selection) {
212+
let request = null;
213+
if (osparc.file.FilesTree.isFile(selection)) {
214+
request = this.__deleteItem(selection.getFileId(), selection.getLocation());
215+
} else {
216+
request = this.__deleteItem(selection.getPath(), selection.getLocation());
217+
}
218+
if (request) {
219+
requests.push(request);
220+
}
221+
}
222+
});
223+
Promise.all(requests)
224+
.then(datas => {
225+
if (datas.length) {
226+
this.fireDataEvent("fileDeleted", datas[0]);
227+
osparc.FlashMessenger.getInstance().logAs(this.tr("Items successfully deleted"), "INFO");
212228
}
213229
});
214230
},
215231

216-
__deleteFile: function(file) {
217-
const fileId = file.getFileId();
218-
const locationId = file.getLocation();
232+
__deleteItem: function(itemId, locationId) {
219233
if (locationId !== 0 && locationId !== "0") {
220-
osparc.FlashMessenger.getInstance().logAs(this.tr("Only files in simcore.s3 can be deleted"));
234+
osparc.FlashMessenger.getInstance().logAs(this.tr("Only items in simcore.s3 can be deleted"));
221235
return null;
222236
}
223237
const dataStore = osparc.store.Data.getInstance();
224-
return dataStore.deleteFile(locationId, fileId);
238+
return dataStore.deleteFile(locationId, itemId);
225239
},
226240
}
227241
});

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

+3-31
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ qx.Class.define("osparc.file.FileTreeItem", {
7979
itemId: {
8080
check: "String",
8181
event: "changeItemId",
82-
apply: "_applyItemId",
82+
apply: "__applyItemId",
8383
nullable: true
8484
},
8585

@@ -144,7 +144,6 @@ qx.Class.define("osparc.file.FileTreeItem", {
144144

145145
// Add lastModified
146146
const lastModifiedWidget = new qx.ui.basic.Label().set({
147-
width: 140,
148147
maxWidth: 140,
149148
textAlign: "right"
150149
});
@@ -162,7 +161,6 @@ qx.Class.define("osparc.file.FileTreeItem", {
162161

163162
// Add size
164163
const sizeWidget = new qx.ui.basic.Label().set({
165-
width: 70,
166164
maxWidth: 70,
167165
textAlign: "right"
168166
});
@@ -175,39 +173,13 @@ qx.Class.define("osparc.file.FileTreeItem", {
175173
}
176174
});
177175
this.addWidget(sizeWidget);
178-
179-
180-
const permissions = osparc.data.Permissions.getInstance();
181-
// Add Path
182-
const pathWidget = new qx.ui.basic.Label().set({
183-
width: 300,
184-
maxWidth: 300,
185-
textAlign: "right"
186-
});
187-
this.bind("path", pathWidget, "value");
188-
this.addWidget(pathWidget);
189-
permissions.bind("role", pathWidget, "visibility", {
190-
converter: () => permissions.canDo("study.nodestree.uuid.read") ? "visible" : "excluded"
191-
});
192-
193-
// Add NodeId
194-
const fileIdWidget = new qx.ui.basic.Label().set({
195-
width: 300,
196-
maxWidth: 300,
197-
textAlign: "right"
198-
});
199-
this.bind("fileId", fileIdWidget, "value");
200-
this.addWidget(fileIdWidget);
201-
permissions.bind("role", fileIdWidget, "visibility", {
202-
converter: () => permissions.canDo("study.nodestree.uuid.read") ? "visible" : "excluded"
203-
});
204176
},
205177

206-
// override
207-
_applyItemId: function(value, old) {
178+
__applyItemId: function(value, old) {
208179
osparc.utils.Utils.setIdToWidget(this, "fileTreeItem_" + value);
209180
},
210181

182+
// override
211183
_applyIcon: function(value, old) {
212184
this.base(arguments, value, old);
213185
const icon = this.getChildControl("icon", true);

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ qx.Class.define("osparc.file.FilesTree", {
163163
}
164164
studyModel = this.getModel();
165165
this.__filesToDataset("0", studyId, files, studyModel);
166+
167+
// select study item
168+
this.setSelection(new qx.data.Array([studyModel]));
169+
this.__selectionChanged();
166170
});
167171
},
168172

@@ -189,8 +193,8 @@ qx.Class.define("osparc.file.FilesTree", {
189193
}
190194
this.openNode(rootNodeModel);
191195

192-
const selected = new qx.data.Array([rootNodeModel]);
193-
this.setSelection(selected);
196+
// select node item
197+
this.setSelection(new qx.data.Array([rootNodeModel]));
194198
this.__selectionChanged();
195199
} else {
196200
rootModel.getChildren().removeAll();

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

+18-16
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ qx.Class.define("osparc.file.FolderContent", {
3636

3737
mode: {
3838
check: ["list", "icons"],
39-
init: "icons",
39+
init: "list",
4040
nullable: false,
4141
event: "changeMode",
4242
apply: "__reloadFolderContent"
@@ -80,7 +80,7 @@ qx.Class.define("osparc.file.FolderContent", {
8080
T_POS: {
8181
TYPE: 0,
8282
NAME: 1,
83-
DATE: 2,
83+
MODIFIED_DATE: 2,
8484
SIZE: 3,
8585
ID: 4
8686
}
@@ -105,9 +105,9 @@ qx.Class.define("osparc.file.FolderContent", {
105105
});
106106
control.getTableColumnModel().setDataCellRenderer(this.self().T_POS.TYPE, new qx.ui.table.cellrenderer.Image());
107107
control.setColumnWidth(this.self().T_POS.TYPE, 30);
108-
control.setColumnWidth(this.self().T_POS.NAME, 360);
109-
control.setColumnWidth(this.self().T_POS.DATE, 170);
110-
control.setColumnWidth(this.self().T_POS.SIZE, 70);
108+
control.setColumnWidth(this.self().T_POS.NAME, 250);
109+
control.setColumnWidth(this.self().T_POS.MODIFIED_DATE, 125);
110+
control.setColumnWidth(this.self().T_POS.SIZE, 80);
111111
this.bind("mode", control, "visibility", {
112112
converter: mode => mode === "list" ? "visible" : "excluded"
113113
});
@@ -144,6 +144,8 @@ qx.Class.define("osparc.file.FolderContent", {
144144
};
145145
datas.push(data);
146146
});
147+
// folders first
148+
datas.sort((a, b) => osparc.file.FilesTree.isFile(a.entry) - osparc.file.FilesTree.isFile(b.entry));
147149
const items = [];
148150
if (this.getMode() === "list") {
149151
datas.forEach(data => {
@@ -278,14 +280,14 @@ qx.Class.define("osparc.file.FolderContent", {
278280
}
279281
if (this.isMultiSelect()) {
280282
// pass all buttons that are selected
281-
const selectedFiles = [];
283+
const selectedItems = [];
282284
const iconsLayout = this.getChildControl("icons-layout");
283285
iconsLayout.getChildren().forEach(btn => {
284-
if (osparc.file.FilesTree.isFile(btn.entry) && btn.getValue()) {
285-
selectedFiles.push(btn.entry);
286+
if (btn.getValue() && "entry" in btn) {
287+
selectedItems.push(btn.entry);
286288
}
287289
});
288-
this.__selectionChanged(selectedFiles);
290+
this.__selectionChanged(selectedItems);
289291
} else {
290292
// unselect the other items
291293
const iconsLayout = this.getChildControl("icons-layout");
@@ -309,23 +311,23 @@ qx.Class.define("osparc.file.FolderContent", {
309311
if (e.getNativeEvent().ctrlKey) {
310312
this.setMultiSelect(true);
311313
}
312-
const selectedFiles = [];
314+
const selectedItems = [];
313315
const selectionRanges = table.getSelectionModel().getSelectedRanges();
314316
selectionRanges.forEach(range => {
315317
for (let i=range.minIndex; i<=range.maxIndex; i++) {
316318
const row = table.getTableModel().getRowData(i);
317-
if (osparc.file.FilesTree.isFile(row.entry)) {
318-
selectedFiles.push(row.entry);
319+
if (row && "entry" in row) {
320+
selectedItems.push(row.entry);
319321
}
320322
}
321323
});
322-
this.__selectionChanged(selectedFiles);
324+
this.__selectionChanged(selectedItems);
323325
}, this);
324326
table.addListener("cellDbltap", e => {
325327
const selectedRow = e.getRow();
326-
const rowData = table.getTableModel().getRowData(selectedRow);
327-
if ("entry" in rowData) {
328-
this.__itemDblTapped(rowData.entry);
328+
const row = table.getTableModel().getRowData(selectedRow);
329+
if (row && "entry" in row) {
330+
this.__itemDblTapped(row.entry);
329331
}
330332
}, this);
331333
}

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

+8-7
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
qx.Class.define("osparc.file.FolderViewer", {
2323
extend: qx.ui.core.Widget,
2424

25-
construct: function(allowMultiselection = true) {
25+
construct: function(allowMultiSelection = true) {
2626
this.base(arguments);
2727

2828
this._setLayout(new qx.ui.layout.VBox(10));
@@ -33,11 +33,11 @@ qx.Class.define("osparc.file.FolderViewer", {
3333
folderUpBtn.addListener("execute", () => this.fireDataEvent("folderUp", this.getFolder()), this);
3434
this.getChildControl("folder-path");
3535
let multiSelectButton = null;
36-
if (allowMultiselection) {
36+
if (allowMultiSelection) {
3737
multiSelectButton = this.getChildControl("multi-select-button");
3838
}
39-
const gridViewButton = this.getChildControl("view-options-icons");
4039
const listViewButton = this.getChildControl("view-options-list");
40+
const gridViewButton = this.getChildControl("view-options-icons");
4141
const folderContent = this.getChildControl("folder-content");
4242
const selectedFileLayout = this.getChildControl("selected-file-layout");
4343

@@ -51,7 +51,7 @@ qx.Class.define("osparc.file.FolderViewer", {
5151

5252
this.bind("folder", folderContent, "folder");
5353

54-
if (allowMultiselection) {
54+
if (allowMultiSelection) {
5555
multiSelectButton.bind("value", folderContent, "multiSelect");
5656
folderContent.bind("multiSelect", multiSelectButton, "value");
5757
multiSelectButton.addListener("changeValue", e => {
@@ -142,20 +142,21 @@ qx.Class.define("osparc.file.FolderViewer", {
142142
header.addAt(control, 2);
143143
break;
144144
}
145-
case "view-options-rgroup":
145+
case "view-options-radio-group":
146146
control = new qx.ui.form.RadioGroup();
147147
break;
148148
case "view-options-icons": {
149149
control = new qx.ui.form.ToggleButton(null, "@MaterialIcons/apps/18");
150-
const group = this.getChildControl("view-options-rgroup");
150+
osparc.utils.Utils.setIdToWidget(control, "folderGridView");
151+
const group = this.getChildControl("view-options-radio-group");
151152
group.add(control);
152153
const header = this.getChildControl("header");
153154
header.addAt(control, 3);
154155
break;
155156
}
156157
case "view-options-list": {
157158
control = new qx.ui.form.ToggleButton(null, "@MaterialIcons/reorder/18");
158-
const group = this.getChildControl("view-options-rgroup");
159+
const group = this.getChildControl("view-options-radio-group");
159160
group.add(control);
160161
const header = this.getChildControl("header");
161162
header.addAt(control, 4);

‎services/static-webserver/client/source/class/osparc/info/StudyLarge.js

+10-24
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,9 @@ qx.Class.define("osparc.info.StudyLarge", {
6262

6363
const vBox = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
6464

65-
const mainHBox = new qx.ui.container.Composite(new qx.ui.layout.VBox(5));
66-
67-
const leftVBox = new qx.ui.container.Composite(new qx.ui.layout.VBox(5));
68-
mainHBox.add(leftVBox, {
69-
flex: 1
70-
});
71-
72-
vBox.add(mainHBox);
73-
74-
const extraInfo = this.__extraInfo();
75-
const extraInfoLayout = this.__createExtraInfo(extraInfo);
76-
77-
leftVBox.add(extraInfoLayout);
65+
const infoElements = this.__infoElements();
66+
const infoLayout = osparc.info.StudyUtils.infoElementsToLayout(infoElements);
67+
vBox.add(infoLayout);
7868

7969
let text = osparc.product.Utils.getStudyAlias({firstUpperCase: true}) + " Id";
8070
if (this.__isTemplate) {
@@ -87,7 +77,7 @@ qx.Class.define("osparc.info.StudyLarge", {
8777
allowGrowX: false
8878
});
8979
copyIdButton.addListener("execute", () => osparc.utils.Utils.copyTextToClipboard(this.getStudy().getUuid()));
90-
leftVBox.add(copyIdButton);
80+
vBox.add(copyIdButton);
9181

9282
const scrollContainer = new qx.ui.container.Scroll();
9383
scrollContainer.add(vBox);
@@ -97,8 +87,8 @@ qx.Class.define("osparc.info.StudyLarge", {
9787
});
9888
},
9989

100-
__extraInfo: function() {
101-
const extraInfo = {
90+
__infoElements: function() {
91+
const infoLayout = {
10292
"TITLE": {
10393
label: this.tr("Title:"),
10494
view: osparc.info.StudyUtils.createTitle(this.getStudy()),
@@ -166,7 +156,7 @@ qx.Class.define("osparc.info.StudyLarge", {
166156
this.getStudy().getQuality() &&
167157
osparc.metadata.Quality.isEnabled(this.getStudy().getQuality())
168158
) {
169-
extraInfo["QUALITY"] = {
159+
infoLayout["QUALITY"] = {
170160
label: this.tr("Quality:"),
171161
view: osparc.info.StudyUtils.createQuality(this.getStudy()),
172162
action: {
@@ -178,7 +168,7 @@ qx.Class.define("osparc.info.StudyLarge", {
178168
}
179169

180170
if (osparc.product.Utils.showClassifiers()) {
181-
extraInfo["CLASSIFIERS"] = {
171+
infoLayout["CLASSIFIERS"] = {
182172
label: this.tr("Classifiers:"),
183173
view: osparc.info.StudyUtils.createClassifiers(this.getStudy()),
184174
action: (this.getStudy().getClassifiers().length || this.__canIWrite()) ? {
@@ -192,18 +182,14 @@ qx.Class.define("osparc.info.StudyLarge", {
192182
if (!this.__isTemplate) {
193183
const pathLabel = new qx.ui.basic.Label();
194184
pathLabel.setValue(this.getStudy().getLocationString());
195-
extraInfo["LOCATION"] = {
185+
infoLayout["LOCATION"] = {
196186
label: this.tr("Location:"),
197187
view: pathLabel,
198188
action: null
199189
};
200190
}
201191

202-
return extraInfo;
203-
},
204-
205-
__createExtraInfo: function(extraInfo) {
206-
return osparc.info.StudyUtils.createExtraInfoGrid(extraInfo);
192+
return infoLayout;
207193
},
208194

209195
__createStudyId: function() {

‎services/static-webserver/client/source/class/osparc/info/StudyUtils.js

+19-17
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ qx.Class.define("osparc.info.StudyUtils", {
252252
return titleLayout;
253253
},
254254

255-
createExtraInfoGrid: function(extraInfos) {
255+
infoElementsToLayout: function(extraInfos) {
256256
const positions = {
257257
TITLE: {
258258
column: 0,
@@ -308,18 +308,15 @@ qx.Class.define("osparc.info.StudyUtils", {
308308
},
309309
};
310310

311-
const grid = new qx.ui.layout.Grid(15, 5);
311+
const grid1 = new qx.ui.layout.Grid(15, 5);
312+
grid1.setColumnAlign(0, "left", "top");
313+
grid1.setColumnFlex(0, 1);
314+
const mainInfoLayout = new qx.ui.container.Composite(grid1);
315+
312316
const grid2 = new qx.ui.layout.Grid(15, 5);
313-
grid.setColumnAlign(0, "left", "top");
314-
const container = new qx.ui.container.Composite(new qx.ui.layout.VBox());
315-
const moreInfo = new qx.ui.container.Composite(grid);
316-
const otherInfo = new qx.ui.container.Composite(grid2);
317-
grid.setColumnFlex(0, 1);
317+
const extraInfoLayout = new qx.ui.container.Composite(grid2);
318318
grid2.setColumnFlex(0, 1);
319319

320-
const box = this.__createSectionBox(qx.locale.Manager.tr("Details"));
321-
const box2 = this.__createSectionBox(qx.locale.Manager.tr("Meta details"));
322-
323320
let row = 0;
324321
let row2 = 0;
325322
Object.keys(positions).forEach(key => {
@@ -335,7 +332,7 @@ qx.Class.define("osparc.info.StudyUtils", {
335332
});
336333
}
337334
titleLayout.add(extraInfo.view);
338-
otherInfo.add(titleLayout, {
335+
extraInfoLayout.add(titleLayout, {
339336
row: row2,
340337
column: gridInfo.column
341338
});
@@ -344,25 +341,30 @@ qx.Class.define("osparc.info.StudyUtils", {
344341
row2++;
345342
} else {
346343
const titleLayout = this.__titleWithEditLayout(extraInfo);
347-
moreInfo.add(titleLayout, {
344+
mainInfoLayout.add(titleLayout, {
348345
row,
349346
column: gridInfo.column
350347
});
351348
row++;
352-
moreInfo.add(extraInfo.view, {
349+
mainInfoLayout.add(extraInfo.view, {
353350
row,
354351
column: gridInfo.column
355352
});
356353
row++;
357-
grid.setRowHeight(row, 5); // spacer
354+
grid1.setRowHeight(row, 5); // spacer
358355
row++;
359356
}
360357
}
361358
});
362359

363-
box.add(moreInfo);
364-
box2.add(otherInfo);
365-
container.addAt(box, 0);
360+
361+
const container = new qx.ui.container.Composite(new qx.ui.layout.VBox());
362+
const box1 = this.__createSectionBox(qx.locale.Manager.tr("Details"));
363+
box1.add(mainInfoLayout);
364+
container.addAt(box1, 0);
365+
366+
const box2 = this.__createSectionBox(qx.locale.Manager.tr("Meta details"));
367+
box2.add(extraInfoLayout);
366368
container.addAt(box2, 1);
367369

368370
return container;

‎services/static-webserver/client/source/class/osparc/po/POCenter.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ qx.Class.define("osparc.po.POCenter", {
2424
const miniProfile = osparc.desktop.account.MyAccount.createMiniProfileView().set({
2525
paddingRight: 10
2626
});
27-
this.addWidgetOnTopOfTheTabs(miniProfile);
27+
this.addWidgetToTabs(miniProfile);
2828

2929
this.__addUsersPage();
3030
this.__addPreRegistrationPage();

‎services/static-webserver/client/source/class/osparc/store/Data.js

+1
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ qx.Class.define("osparc.store.Data", {
283283
return true;
284284
},
285285

286+
// if folder path is provided as fileUuid, it can also be deleted
286287
deleteFile: function(locationId, fileUuid) {
287288
if (!osparc.data.Permissions.getInstance().canDo("study.node.data.delete", true)) {
288289
return null;

‎services/static-webserver/client/source/class/osparc/study/Utils.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ qx.Class.define("osparc.study.Utils", {
330330

331331
canShowStudyData: function(studyData) {
332332
const blocked = this.__getBlockedState(studyData);
333-
return [false].includes(blocked);
333+
return ["UNKNOWN_SERVICES", false].includes(blocked);
334334
},
335335

336336
canShowPreview: function(studyData) {

‎services/static-webserver/client/source/class/osparc/tester/TesterCenter.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ qx.Class.define("osparc.tester.TesterCenter", {
2424
const miniProfile = osparc.desktop.account.MyAccount.createMiniProfileView().set({
2525
paddingRight: 10
2626
});
27-
this.addWidgetOnTopOfTheTabs(miniProfile);
27+
this.addWidgetToTabs(miniProfile);
2828

2929
this.__addSocketMessagesPage();
3030
this.__addConsoleErrorsPage();

‎services/static-webserver/client/source/class/osparc/theme/ColorDark.js

-22
Original file line numberDiff line numberDiff line change
@@ -122,28 +122,6 @@ qx.Theme.define("osparc.theme.ColorDark", {
122122
"tooltip": "flash_message_bg",
123123
"tooltip-text": "text",
124124

125-
// table
126-
"table-header": "background-main",
127-
"table-header-foreground": "c09",
128-
"table-header-border": "c07",
129-
"table-focus-indicator": "background-main-5",
130-
131-
// used in table code
132-
"table-header-cell": "background-main",
133-
"table-row-background-even": "background-main",
134-
"table-row-background-odd": "background-main",
135-
"table-row-background-focused": "background-main-1",
136-
"table-row-background-focused-selected": "background-main-2",
137-
"table-row-background-selected": "background-main-2",
138-
139-
// foreground
140-
"table-row-selected": "c12",
141-
"table-row": "c09",
142-
143-
// table grid color
144-
"table-row-line": "background-main",
145-
"table-column-line": "background-main",
146-
147125
// used in progressive code
148126
"progressive-table-header": "c08",
149127
"progressive-table-row-background-even": "background-main",

‎services/static-webserver/client/source/class/osparc/theme/ColorLight.js

-22
Original file line numberDiff line numberDiff line change
@@ -124,28 +124,6 @@ qx.Theme.define("osparc.theme.ColorLight", {
124124
"tooltip-text": "text",
125125

126126

127-
// table
128-
"table-header": "background-main",
129-
"table-header-foreground": "c09",
130-
"table-header-border": "c07",
131-
"table-focus-indicator": "background-main-5",
132-
133-
// used in table code
134-
"table-header-cell": "background-main",
135-
"table-row-background-even": "background-main",
136-
"table-row-background-odd": "background-main",
137-
"table-row-background-focused": "background-main-1",
138-
"table-row-background-focused-selected": "background-main-2",
139-
"table-row-background-selected": "background-main-2",
140-
141-
// foreground
142-
"table-row-selected": "c12",
143-
"table-row": "c09",
144-
145-
// table grid color
146-
"table-row-line": "background-main",
147-
"table-column-line": "background-main",
148-
149127
// used in progressive code
150128
"progressive-table-header": "c08",
151129
"progressive-table-row-background-even": "background-main",

‎services/static-webserver/client/source/class/osparc/theme/mixin/Color.js

+24-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,29 @@ qx.Theme.define("osparc.theme.mixin.Color", {
5454
"logger-warning-message": "warning-yellow",
5555
"logger-error-message": "failed-red",
5656

57-
"workbench-edge-selected": "busy-orange"
57+
"workbench-edge-selected": "busy-orange",
58+
59+
60+
// table
61+
"table-header": "transparent",
62+
"table-header-foreground": "text", // text color
63+
"table-header-border": "text", // header underline
64+
"table-header-cell": "transparent",
65+
66+
// used in table code
67+
"table-focus-indicator": "transparent",
68+
"table-row-background-even": "transparent",
69+
"table-row-background-odd": "transparent",
70+
"table-row-background-focused": "transparent",
71+
"table-row-background-focused-selected": "background-main-2",
72+
"table-row-background-selected": "background-main-2",
73+
74+
// foreground
75+
"table-row-selected": "text",
76+
"table-row": "text",
77+
78+
// table grid color
79+
"table-row-line": "transparent",
80+
"table-column-line": "transparent",
5881
}
5982
});

‎services/static-webserver/client/source/class/osparc/ui/window/TabbedView.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ qx.Class.define("osparc.ui.window.TabbedView", {
7979
return control || this.base(arguments, id);
8080
},
8181

82-
addWidgetOnTopOfTheTabs: function(widget) {
82+
addWidgetToTabs: function(widget) {
8383
this.getChildControl("tabs-view").getChildControl("bar").add(widget);
8484
},
8585

‎services/static-webserver/client/source/class/osparc/vipMarket/Market.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ qx.Class.define("osparc.vipMarket.Market", {
2525
paddingRight: 10,
2626
minWidth: 150,
2727
});
28-
this.addWidgetOnTopOfTheTabs(miniWallet);
28+
this.addWidgetToTabs(miniWallet);
2929

3030
const store = osparc.store.Store.getInstance();
3131
const contextWallet = store.getContextWallet();

‎services/static-webserver/client/source/class/osparc/widget/ProgressSequence.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ qx.Class.define("osparc.widget.ProgressSequence", {
2525

2626
this.set({
2727
backgroundColor: "window-popup-background",
28-
paddingBottom: 8
28+
paddingBottom: 8,
29+
minWidth: 400,
2930
});
3031

3132
this.__initLayout(title);

‎services/static-webserver/client/source/class/osparc/widget/NodeDataManager.js ‎services/static-webserver/client/source/class/osparc/widget/StudyDataManager.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525
* Here is a little example of how to use the widget.
2626
*
2727
* <pre class='javascript'>
28-
* let dataManager = new osparc.widget.NodeDataManager(null, nodeId);
28+
* let dataManager = new osparc.widget.StudyDataManager(null, nodeId);
2929
* this.getRoot().add(dataManager);
3030
* </pre>
3131
*/
3232

33-
qx.Class.define("osparc.widget.NodeDataManager", {
33+
qx.Class.define("osparc.widget.StudyDataManager", {
3434
extend: qx.ui.core.Widget,
3535

3636
/**
@@ -58,6 +58,16 @@ qx.Class.define("osparc.widget.NodeDataManager", {
5858
this.__reloadTree();
5959
},
6060

61+
statics: {
62+
popUpInWindow: function(studyId, nodeId, title) {
63+
const studyDataManager = new osparc.widget.StudyDataManager(studyId, nodeId);
64+
if (!title) {
65+
title = osparc.product.Utils.getStudyAlias({firstUpperCase: true}) + qx.locale.Manager.tr(" Files");
66+
}
67+
return osparc.ui.window.Window.popUpInWindow(studyDataManager, title, osparc.dashboard.ResourceDetails.WIDTH, osparc.dashboard.ResourceDetails.HEIGHT);
68+
},
69+
},
70+
6171
properties: {
6272
studyId: {
6373
check: "String",

‎tests/e2e-playwright/tests/sleepers/test_sleepers.py

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def _get_expected_file_names_for_version(version: Version) -> list[str]:
6767
)
6868
def _get_file_names(page: Page) -> list[str]:
6969
file_names_found = []
70+
page.get_by_test_id("folderGridView").click()
7071
for file in page.get_by_test_id("FolderViewerItem").all():
7172
file_name = file.text_content()
7273
assert file_name

‎tests/e2e/tutorials/tutorialBase.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ class TutorialBase {
484484

485485
async __checkNItemsInFolder(fileNames, openOutputsFolder = false) {
486486
await this.takeScreenshot("checkNodeOutputs_before");
487+
await this.waitAndClick("folderGridView");
487488
console.log("N items in folder. Expected:", fileNames);
488489
if (openOutputsFolder) {
489490
const itemTexts = await this.__page.$$eval('[osparc-test-id="FolderViewerItem"]',
@@ -506,8 +507,7 @@ class TutorialBase {
506507
}
507508
if (outputsFound) {
508509
await this.takeScreenshot("outputs_folder");
509-
}
510-
else {
510+
} else {
511511
throw ("outputs folder not found");
512512
}
513513
}

‎tests/e2e/utils/auto.js

+1
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ async function openNodeFilesAppMode(page) {
363363

364364
async function checkDataProducedByNode(page, nFiles = 1) {
365365
console.log("checking Data produced by Node. Expecting", nFiles, "file(s)");
366+
await utils.waitAndClick(page, '[osparc-test-id="folderGridView"]');
366367
const iconsContent = await page.waitForSelector('[osparc-test-id="FolderViewerIconsContent"]', {
367368
timeout: 5000
368369
});

0 commit comments

Comments
 (0)
Please sign in to comment.