Skip to content

Commit 437adab

Browse files
authored
🎨 [Frontend] Show Runs history (#7681)
1 parent a8f1977 commit 437adab

File tree

8 files changed

+124
-21
lines changed

8 files changed

+124
-21
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
4444

4545
latestPromise
4646
.then(latestResourceData => {
47-
this.__resourceData = latestResourceData;
47+
if (!latestResourceData) {
48+
const msg = this.tr("Data not found, please try again");
49+
osparc.FlashMessenger.logAs(msg, "WARNING");
50+
return;
51+
}
52+
this.__resourceData = osparc.utils.Utils.deepCloneObject(latestResourceData);
4853
this.__resourceData["resourceType"] = resourceData["resourceType"];
4954
switch (resourceData["resourceType"]) {
5055
case "study":

services/static-webserver/client/source/class/osparc/data/Resources.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,19 +347,23 @@ qx.Class.define("osparc.data.Resources", {
347347
},
348348
}
349349
},
350-
"jobsActive": {
350+
"jobs": {
351351
useCache: false, // handled in osparc.store.Jobs
352352
endpoints: {
353-
getPage: {
353+
getPageLatestActive: {
354354
method: "GET",
355355
url: statics.API + "/computations/-/iterations/latest?offset={offset}&limit={limit}&order_by=%7B%22field%22:%22submitted_at%22,%22direction%22:%22desc%22%7D&filter_only_running=true"
356356
},
357+
getPageHistory: {
358+
method: "GET",
359+
url: statics.API + "/computations/{studyId}/iterations?offset={offset}&limit={limit}&order_by=%7B%22field%22:%22submitted_at%22,%22direction%22:%22desc%22%7D"
360+
},
357361
}
358362
},
359363
"subJobs": {
360364
useCache: false, // handled in osparc.store.Jobs
361365
endpoints: {
362-
getPage: {
366+
getPageLatest: {
363367
method: "GET",
364368
url: statics.API + "/computations/{studyId}/iterations/latest/tasks?offset={offset}&limit={limit}"
365369
},
@@ -608,7 +612,7 @@ qx.Class.define("osparc.data.Resources", {
608612
"functions": {
609613
useCache: false,
610614
endpoints: {
611-
getPage: {
615+
create: {
612616
method: "POST",
613617
url: statics.API + "/functions"
614618
}

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

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ qx.Class.define("osparc.jobs.ActivityOverview", {
2121
construct: function(projectData) {
2222
this.base(arguments);
2323

24-
this._setLayout(new qx.ui.layout.VBox(15));
24+
this._setLayout(new qx.ui.layout.VBox(10));
2525

2626
this.__buildLayout(projectData);
2727
},
@@ -30,13 +30,41 @@ qx.Class.define("osparc.jobs.ActivityOverview", {
3030
popUpInWindow: function(projectData) {
3131
const activityOverview = new osparc.jobs.ActivityOverview(projectData);
3232
const title = qx.locale.Manager.tr("Activity Overview");
33-
return osparc.ui.window.Window.popUpInWindow(activityOverview, title, osparc.jobs.ActivityCenterWindow.WIDTH, osparc.jobs.ActivityCenterWindow.HEIGHT);
33+
const win = osparc.ui.window.Window.popUpInWindow(activityOverview, title, osparc.jobs.ActivityCenterWindow.WIDTH, osparc.jobs.ActivityCenterWindow.HEIGHT);
34+
win.set({
35+
maxHeight: 700,
36+
});
37+
return win;
3438
},
3539
},
3640

3741
members: {
3842
__buildLayout: function(projectData) {
43+
this._add(new qx.ui.basic.Label(this.tr("Runs History")).set({
44+
font: "text-14"
45+
}));
46+
47+
const latestOnly = false;
48+
const projectUuid = projectData["uuid"];
49+
const runsTable = new osparc.jobs.RunsTable(latestOnly, projectUuid);
50+
const columnModel = runsTable.getTableColumnModel();
51+
// Hide project name column
52+
columnModel.setColumnVisible(osparc.jobs.RunsTable.COLS.PROJECT_NAME.column, false);
53+
// Hide cancel column
54+
columnModel.setColumnVisible(osparc.jobs.RunsTable.COLS.ACTION_CANCEL.column, false);
55+
runsTable.set({
56+
maxHeight: 250,
57+
})
58+
this._add(runsTable);
59+
60+
this._add(new qx.ui.basic.Label(this.tr("Latest Tasks")).set({
61+
font: "text-14"
62+
}));
63+
3964
const subRunsTable = new osparc.jobs.SubRunsTable(projectData["uuid"]);
65+
subRunsTable.set({
66+
maxHeight: 250,
67+
})
4068
this._add(subRunsTable);
4169
},
4270
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,14 @@ qx.Class.define("osparc.jobs.RunsBrowser", {
6060
flex: 1
6161
});
6262
break;
63-
case "runs-table":
64-
control = new osparc.jobs.RunsTable();
63+
case "runs-table": {
64+
const latestOnly = true;
65+
const projectUuid = null;
66+
control = new osparc.jobs.RunsTable(latestOnly, projectUuid);
6567
control.addListener("runSelected", e => this.fireDataEvent("runSelected", e.getData()));
6668
this._add(control);
6769
break;
70+
}
6871
}
6972

7073
return control || this.base(arguments, id);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
qx.Class.define("osparc.jobs.RunsTable", {
2020
extend: qx.ui.table.Table,
2121

22-
construct: function(filters) {
22+
construct: function(latestOnly = true, projectUuid = null) {
2323
this.base(arguments);
2424

25-
const model = new osparc.jobs.RunsTableModel(filters);
25+
const model = new osparc.jobs.RunsTableModel(latestOnly, projectUuid);
2626
this.setTableModel(model);
2727

2828
this.set({

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
qx.Class.define("osparc.jobs.RunsTableModel", {
2020
extend: qx.ui.table.model.Remote,
2121

22-
construct: function() {
22+
construct: function(latestOnly = true, projectUuid = null) {
2323
this.base(arguments);
2424

25+
this.__latestOnly = latestOnly;
26+
this.__projectUuid = projectUuid;
27+
2528
const jobsCols = osparc.jobs.RunsTable.COLS;
2629
const colLabels = Object.values(jobsCols).map(col => col.label);
2730
const colIDs = Object.values(jobsCols).map(col => col.id);
@@ -60,7 +63,13 @@ qx.Class.define("osparc.jobs.RunsTableModel", {
6063
const offset = 0;
6164
const limit = 1;
6265
const resolveWResponse = true;
63-
osparc.store.Jobs.getInstance().fetchJobsActive(offset, limit, JSON.stringify(this.getOrderBy()), resolveWResponse)
66+
let promise;
67+
if (this.__latestOnly && this.__projectUuid === null) {
68+
promise = osparc.store.Jobs.getInstance().fetchJobsActive(offset, limit, JSON.stringify(this.getOrderBy()), resolveWResponse);
69+
} else {
70+
promise = osparc.store.Jobs.getInstance().fetchJobsHistory(this.__projectUuid, offset, limit, JSON.stringify(this.getOrderBy()), resolveWResponse);
71+
}
72+
promise
6473
.then(resp => {
6574
this._onRowCountLoaded(resp["_meta"].total)
6675
})
@@ -76,7 +85,13 @@ qx.Class.define("osparc.jobs.RunsTableModel", {
7685
const lastRow = Math.min(qxLastRow, this._rowCount - 1);
7786
// Returns a request promise with given offset and limit
7887
const getFetchPromise = (offset, limit) => {
79-
return osparc.store.Jobs.getInstance().fetchJobsActive(offset, limit, JSON.stringify(this.getOrderBy()))
88+
let promise;
89+
if (this.__latestOnly && this.__projectUuid === null) {
90+
promise = osparc.store.Jobs.getInstance().fetchJobsActive(offset, limit, JSON.stringify(this.getOrderBy()));
91+
} else {
92+
promise = osparc.store.Jobs.getInstance().fetchJobsHistory(this.__projectUuid, offset, limit, JSON.stringify(this.getOrderBy()));
93+
}
94+
return promise
8095
.then(jobs => {
8196
const data = [];
8297
const jobsCols = osparc.jobs.RunsTable.COLS;

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

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ qx.Class.define("osparc.store.Jobs", {
5656
const options = {
5757
resolveWResponse: true
5858
};
59-
return osparc.data.Resources.fetch("jobsActive", "getPage", params, options)
59+
return osparc.data.Resources.fetch("jobs", "getPageLatestActive", params, options)
6060
.then(jobsResp => {
6161
this.fireDataEvent("changeJobsActive", jobsResp["_meta"]["total"]);
6262
const jobsActive = [];
@@ -73,13 +73,51 @@ qx.Class.define("osparc.store.Jobs", {
7373
.catch(err => console.error(err));
7474
},
7575

76+
fetchJobsHistory: function(
77+
studyId,
78+
offset = 0,
79+
limit = this.self().SERVER_MAX_LIMIT,
80+
orderBy = {
81+
field: "submitted_at",
82+
direction: "desc"
83+
},
84+
resolveWResponse = false
85+
) {
86+
const params = {
87+
url: {
88+
studyId,
89+
offset,
90+
limit,
91+
orderBy: JSON.stringify(orderBy),
92+
}
93+
};
94+
const options = {
95+
resolveWResponse: true
96+
};
97+
return osparc.data.Resources.fetch("jobs", "getPageHistory", params, options)
98+
.then(jobsResp => {
99+
if (resolveWResponse) {
100+
return jobsResp;
101+
}
102+
const jobs = [];
103+
if ("data" in jobsResp) {
104+
jobsResp["data"].forEach(jobData => {
105+
const job = new osparc.data.Job(jobData);
106+
jobs.push(job);
107+
});
108+
}
109+
return jobs;
110+
})
111+
.catch(err => console.error(err));
112+
},
113+
76114
fetchSubJobs: function(projectUuid) {
77115
const params = {
78116
url: {
79117
studyId: projectUuid,
80118
}
81119
};
82-
return osparc.data.Resources.getInstance().getAllPages("subJobs", params)
120+
return osparc.data.Resources.getInstance().getAllPages("subJobs", params, "getPageLatest")
83121
.then(subJobsData => {
84122
const subJobs = [];
85123
subJobsData.forEach(subJobData => {

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ qx.Class.define("osparc.store.Services", {
106106
return this.__servicesPromisesCached[key][version];
107107
}
108108

109-
return new Promise((resolve, reject) => {
109+
// Create a new promise
110+
const promise = new Promise((resolve, reject) => {
110111
if (
111112
useCache &&
112113
this.__isInCache(key, version) &&
@@ -133,17 +134,26 @@ qx.Class.define("osparc.store.Services", {
133134
this.__addServiceToCache(service);
134135
// Resolve the promise locally before deleting it
135136
resolve(service);
136-
// Remove the promise from the cache
137-
delete this.__servicesPromisesCached[key][version];
138137
})
139138
.catch(err => {
140-
// store it in cache to avoid asking again
139+
// Store null in cache to avoid repeated failed requests
141140
this.__addToCache(key, version, null);
142-
delete this.__servicesPromisesCached[key][version];
143141
console.error(err);
144142
reject(err);
143+
})
144+
.finally(() => {
145+
// Remove the promise from the cache
146+
delete this.__servicesPromisesCached[key][version];
145147
});
146148
});
149+
150+
// Store the promise in the cache
151+
// The point of keeping this assignment outside of the main Promise block is to
152+
// ensure that the promise is immediately stored in the cache before any asynchronous
153+
// operations (like fetch) are executed. This prevents duplicate requests for the
154+
// same key and version when multiple consumers call getService concurrently.
155+
this.__servicesPromisesCached[key][version] = promise;
156+
return promise;
147157
},
148158

149159
getStudyServices: function(studyId) {

0 commit comments

Comments
 (0)