Skip to content

Commit 0eb2563

Browse files
🐛 [Frontend] Fix: Runs listing (#8049)
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 34a9ef0 commit 0eb2563

File tree

6 files changed

+61
-37
lines changed

6 files changed

+61
-37
lines changed

services/static-webserver/client/source/class/osparc/jobs/ActivityCenterWindow.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ qx.Class.define("osparc.jobs.ActivityCenterWindow", {
7272
});
7373

7474
this.addListener("close", () => {
75-
runsBrowser.stopInterval();
7675
subRunsBrowser.stopInterval();
7776
});
7877
},

services/static-webserver/client/source/class/osparc/jobs/RunsBrowser.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ qx.Class.define("osparc.jobs.RunsBrowser", {
2424

2525
this._setLayout(new qx.ui.layout.VBox(10));
2626

27+
const reloadButton = this.getChildControl("reload-button");
28+
reloadButton.addListener("execute", () => this.reloadRuns());
2729
this.getChildControl("intro-label");
2830
const jobsFilter = this.getChildControl("jobs-filter");
2931
const runningCB = this.getChildControl("running-only-cb");
@@ -35,8 +37,6 @@ qx.Class.define("osparc.jobs.RunsBrowser", {
3537
});
3638

3739
runningCB.bind("value", runsTable, "runningOnly");
38-
39-
this.__reloadInterval = setInterval(() => this.reloadRuns(), 10*1000);
4040
},
4141

4242
events: {
@@ -49,13 +49,19 @@ qx.Class.define("osparc.jobs.RunsBrowser", {
4949
_createChildControlImpl: function(id) {
5050
let control;
5151
switch (id) {
52-
case "header-filter":
52+
case "header-toolbar":
5353
control = new qx.ui.container.Composite(new qx.ui.layout.HBox(5));
5454
this._add(control);
5555
break;
56+
case "reload-button":
57+
control = new qx.ui.form.Button(this.tr("Reload"), "@FontAwesome5Solid/sync-alt/14");
58+
this.getChildControl("header-toolbar").add(control);
59+
break;
5660
case "intro-label":
57-
control = new qx.ui.basic.Label(this.tr("Select a Run to check the details"));
58-
this.getChildControl("header-filter").add(control);
61+
control = new qx.ui.basic.Label(this.tr("Select a Run to check the details")).set({
62+
alignY: "middle",
63+
});
64+
this.getChildControl("header-toolbar").add(control);
5965
break;
6066
case "jobs-filter":
6167
control = new osparc.filter.TextFilter("text", "jobsList").set({
@@ -66,7 +72,7 @@ qx.Class.define("osparc.jobs.RunsBrowser", {
6672
placeholder: qx.locale.Manager.tr("Filter by name or ID"),
6773
});
6874
control.hide(); // @matusdrobuliak66: remove this when the backend is ready
69-
this.getChildControl("header-filter").add(control, {
75+
this.getChildControl("header-toolbar").add(control, {
7076
flex: 1
7177
});
7278
break;
@@ -75,7 +81,7 @@ qx.Class.define("osparc.jobs.RunsBrowser", {
7581
value: true,
7682
label: qx.locale.Manager.tr("Active only"),
7783
});
78-
this.getChildControl("header-filter").add(control);
84+
this.getChildControl("header-toolbar").add(control);
7985
break;
8086
case "runs-table": {
8187
const projectUuid = null;
@@ -95,11 +101,5 @@ qx.Class.define("osparc.jobs.RunsBrowser", {
95101
const runsTable = this.getChildControl("runs-table");
96102
runsTable.reloadRuns();
97103
},
98-
99-
stopInterval: function() {
100-
if (this.__reloadInterval) {
101-
clearInterval(this.__reloadInterval);
102-
}
103-
},
104104
}
105105
})

services/static-webserver/client/source/class/osparc/jobs/RunsTableModel.js

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,8 @@ qx.Class.define("osparc.jobs.RunsTableModel", {
7979
},
8080
},
8181

82-
statics: {
83-
SERVER_MAX_LIMIT: 49,
84-
},
85-
8682
members: {
87-
__includeChildren: false,
83+
__includeChildren: null,
8884

8985
// overridden
9086
sortByColumn(columnIndex, ascending) {
@@ -126,7 +122,7 @@ qx.Class.define("osparc.jobs.RunsTableModel", {
126122
const lastRow = Math.min(qxLastRow, this._rowCount - 1);
127123
// Returns a request promise with given offset and limit
128124
const getFetchPromise = (offset, limit) => {
129-
const orderBy = this.getOrderBy();
125+
const orderBy = this.getOrderBy();
130126
let promise;
131127
if (this.getProjectUuid()) {
132128
promise = osparc.store.Jobs.getInstance().fetchJobsHistory(this.getProjectUuid(), this.__includeChildren, offset, limit, orderBy);
@@ -153,15 +149,13 @@ qx.Class.define("osparc.jobs.RunsTableModel", {
153149
};
154150

155151
// Divides the model row request into several server requests to comply with the number of rows server limit
152+
const serverMaxLimit = osparc.store.Jobs.SERVER_MAX_LIMIT;
156153
const reqLimit = lastRow - firstRow + 1; // Number of requested rows
157-
let nRequests = Math.ceil(reqLimit / this.self().SERVER_MAX_LIMIT);
154+
let nRequests = Math.ceil(reqLimit / serverMaxLimit);
158155
if (nRequests > 1) {
159156
const requests = [];
160-
for (let i=firstRow; i <= lastRow; i += this.self().SERVER_MAX_LIMIT) {
161-
// fetch the first page only
162-
if (i < 1) {
163-
requests.push(getFetchPromise(i, i > lastRow - this.self().SERVER_MAX_LIMIT + 1 ? reqLimit % this.self().SERVER_MAX_LIMIT : this.self().SERVER_MAX_LIMIT))
164-
}
157+
for (let i=firstRow; i <= lastRow; i += serverMaxLimit) {
158+
requests.push(getFetchPromise(i, i > lastRow - serverMaxLimit + 1 ? reqLimit % serverMaxLimit : serverMaxLimit));
165159
}
166160
Promise.all(requests)
167161
.then(responses => this._onRowDataLoaded(responses.flat()))

services/static-webserver/client/source/class/osparc/jobs/SubRunsTableModel.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@ qx.Class.define("osparc.jobs.SubRunsTableModel", {
5757
},
5858
},
5959

60-
statics: {
61-
SERVER_MAX_LIMIT: 49,
62-
},
63-
6460
members: {
6561
// overridden
6662
sortByColumn(columnIndex, ascending) {
@@ -132,12 +128,13 @@ qx.Class.define("osparc.jobs.SubRunsTableModel", {
132128
};
133129

134130
// Divides the model row request into several server requests to comply with the number of rows server limit
131+
const serverMaxLimit = osparc.store.Jobs.SERVER_MAX_LIMIT;
135132
const reqLimit = lastRow - firstRow + 1; // Number of requested rows
136-
const nRequests = Math.ceil(reqLimit / this.self().SERVER_MAX_LIMIT);
133+
const nRequests = Math.ceil(reqLimit / serverMaxLimit);
137134
if (nRequests > 1) {
138135
const requests = [];
139-
for (let i=firstRow; i <= lastRow; i += this.self().SERVER_MAX_LIMIT) {
140-
requests.push(getFetchPromise(i, i > lastRow - this.self().SERVER_MAX_LIMIT + 1 ? reqLimit % this.self().SERVER_MAX_LIMIT : this.self().SERVER_MAX_LIMIT))
136+
for (let i=firstRow; i <= lastRow; i += serverMaxLimit) {
137+
requests.push(getFetchPromise(i, i > lastRow - serverMaxLimit + 1 ? reqLimit % serverMaxLimit : serverMaxLimit))
141138
}
142139
Promise.all(requests)
143140
.then(responses => this._onRowDataLoaded(responses.flat()))

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,8 +1192,8 @@ qx.Theme.define("osparc.theme.Appearance", {
11921192
padding: [5, 10],
11931193
// showTimeout is themeable so it can be tuned
11941194
// it was defaulted to 700 which was too short
1195-
showTimeout: 2000,
1196-
hideTimeout: 6000,
1195+
showTimeout: 1400,
1196+
hideTimeout: 5000,
11971197
})
11981198
},
11991199

services/static-webserver/client/source/class/osparc/ui/table/cellrenderer/ImageButtonRenderer.js

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ qx.Class.define("osparc.ui.table.cellrenderer.ImageButtonRenderer", {
2121
construct: function(clickAction, iconPath) {
2222
this.base(arguments, clickAction);
2323

24+
this.__imageCache = {};
25+
2426
this.setIconPath(iconPath);
2527
},
2628

@@ -34,11 +36,43 @@ qx.Class.define("osparc.ui.table.cellrenderer.ImageButtonRenderer", {
3436
},
3537

3638
members: {
39+
__imageCache: null,
40+
3741
__applyIconPath: function(iconPath) {
3842
const resMgr = qx.util.ResourceManager.getInstance();
39-
const iconUrl = resMgr.toUri(iconPath); // Resolves to the correct URL of the asset
43+
const iconUrl = resMgr.toUri(iconPath);
44+
45+
// Create a data URI or use a more cache-friendly approach
46+
// Use base64 encoding for small icons (best for caching)
47+
this.__loadImageAsDataUri(iconUrl, iconPath);
48+
},
49+
50+
__loadImageAsDataUri: function(iconUrl, iconPath) {
51+
if (this.__imageCache[iconPath]) {
52+
this.setButtonContent(this.__imageCache[iconPath]);
53+
return;
54+
}
55+
56+
// Fetch and convert to data URI for permanent caching
57+
fetch(iconUrl)
58+
.then(response => response.blob())
59+
.then(blob => {
60+
const reader = new FileReader();
61+
reader.onload = () => {
62+
const dataUri = reader.result;
63+
const content = `<img src="${dataUri}" style="width:14px; height:14px;" alt="icon"/>`;
4064

41-
this.setButtonContent(`<img src="${iconUrl}" style="width:14x; height:14px;" alt="icon"/>`);
65+
// Cache the data URI
66+
this.__imageCache[iconPath] = content;
67+
this.setButtonContent(content);
68+
};
69+
reader.readAsDataURL(blob);
70+
})
71+
.catch(err => {
72+
console.warn("Failed to cache icon as data URI:", iconPath, err);
73+
// Fallback to original method
74+
this.setButtonContent(`<img src="${iconUrl}" style="width:14px; height:14px;" alt="icon"/>`);
75+
});
4276
},
4377
}
4478
});

0 commit comments

Comments
 (0)