diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js b/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js
index 5ff218af4518..8daed6a8036b 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js
@@ -483,6 +483,10 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
},
_addTaskCard: function(task, cardTitle, cardIcon) {
+ if (!this._resourcesContainer) {
+ return null;
+ }
+
if (task) {
const taskPlaceholders = this._resourcesContainer.getCards().filter(card => osparc.dashboard.ResourceBrowserBase.isCardTaskPlaceholder(card));
if (taskPlaceholders.find(taskPlaceholder => taskPlaceholder.getTask() === task)) {
@@ -505,6 +509,10 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
},
_removeTaskCard: function(task) {
+ if (!this._resourcesContainer) {
+ return;
+ }
+
if (task) {
const taskPlaceholders = this._resourcesContainer.getCards().filter(card => osparc.dashboard.ResourceBrowserBase.isCardTaskPlaceholder(card));
const taskCard = taskPlaceholders.find(taskPlaceholder => taskPlaceholder.getTask() === task);
diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js b/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js
index d066ff1ab103..6677e485689a 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js
@@ -356,27 +356,9 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
}
});
- const resourceData = this.__resourceData;
- if (!osparc.utils.Resources.isService(resourceData)) {
- const title = osparc.product.Utils.getStudyAlias({firstUpperCase: true}) + this.tr(" Files...");
- const iconSrc = "@FontAwesome5Solid/file/22";
- const dataAccess = new qx.ui.basic.Atom().set({
- label: title,
- icon: iconSrc,
- font: "text-14",
- padding: 8,
- paddingLeft: 12,
- gap: 14,
- cursor: "pointer",
- });
- dataAccess.addListener("tap", () => osparc.widget.StudyDataManager.popUpInWindow(resourceData["uuid"]));
- this.addWidgetToTabs(dataAccess);
- if (resourceData["resourceType"] === "study") {
- const canShowData = osparc.study.Utils.canShowStudyData(resourceData);
- dataAccess.setEnabled(canShowData);
- }
- }
+ this.__getActivityOverviewPopUp();
+ this.__getProjectFilesPopUp();
if (selectedTabId) {
const pageFound = tabsView.getChildren().find(page => page.tabId === selectedTabId);
@@ -814,6 +796,52 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
page.addToHeader(toolbar);
page.addToContent(createFunction);
return page;
- }
+ },
+
+ __getProjectFilesPopUp: function() {
+ const resourceData = this.__resourceData;
+ if (!osparc.utils.Resources.isService(resourceData)) {
+ const title = osparc.product.Utils.getStudyAlias({firstUpperCase: true}) + this.tr(" Files...");
+ const iconSrc = "@FontAwesome5Solid/file/22";
+ const dataAccess = new qx.ui.basic.Atom().set({
+ label: title,
+ icon: iconSrc,
+ font: "text-14",
+ padding: 8,
+ paddingLeft: 12,
+ gap: 14,
+ cursor: "pointer",
+ });
+ dataAccess.addListener("tap", () => osparc.widget.StudyDataManager.popUpInWindow(resourceData["uuid"]));
+ this.addWidgetToTabs(dataAccess);
+
+ if (resourceData["resourceType"] === "study") {
+ const canShowData = osparc.study.Utils.canShowStudyData(resourceData);
+ dataAccess.setEnabled(canShowData);
+ }
+ }
+ },
+
+ __getActivityOverviewPopUp: function() {
+ const resourceData = this.__resourceData;
+ if (
+ osparc.desktop.credits.Utils.areWalletsEnabled() &&
+ osparc.utils.Resources.isStudy(resourceData)
+ ) {
+ const title = this.tr("Activity Overview...");
+ const iconSrc = "@FontAwesome5Solid/tasks/22";
+ const dataAccess = new qx.ui.basic.Atom().set({
+ label: title,
+ icon: iconSrc,
+ font: "text-14",
+ padding: 8,
+ paddingLeft: 10,
+ gap: 12, // align with the rest of the tabs
+ cursor: "pointer",
+ });
+ dataAccess.addListener("tap", () => osparc.jobs.ActivityOverview.popUpInWindow(resourceData));
+ this.addWidgetToTabs(dataAccess);
+ }
+ },
}
});
diff --git a/services/static-webserver/client/source/class/osparc/data/Job.js b/services/static-webserver/client/source/class/osparc/data/Job.js
index 1a143cbff42e..34b7d1ec190c 100644
--- a/services/static-webserver/client/source/class/osparc/data/Job.js
+++ b/services/static-webserver/client/source/class/osparc/data/Job.js
@@ -23,11 +23,12 @@ qx.Class.define("osparc.data.Job", {
this.set({
projectUuid: jobData["projectUuid"],
- state: jobData["state"],
+ state: jobData["state"] || "UNKNOWN",
submittedAt: jobData["submittedAt"] ? new Date(jobData["submittedAt"]) : null,
startedAt: jobData["startedAt"] ? new Date(jobData["startedAt"]) : null,
endedAt: jobData["endedAt"] ? new Date(jobData["endedAt"]) : null,
info: jobData["info"] || null,
+ customMetadata: jobData["customMetadata"] || null,
});
if (jobData["info"] && jobData["info"]["project_name"]) {
@@ -76,11 +77,32 @@ qx.Class.define("osparc.data.Job", {
info: {
check: "Object",
- nullable: false,
+ nullable: true,
+ init: null,
+ },
+
+ customMetadata: {
+ check: "Object",
+ nullable: true,
init: null,
},
},
+ statics: {
+ STATUS_LABELS: {
+ "UNKNOWN": "Unknown",
+ "NOT_STARTED": "Not Started",
+ "PUBLISHED": "Published",
+ "PENDING": "Pending",
+ "RUNNING": "Running",
+ "SUCCESS": "Success",
+ "FAILED": "Failed",
+ "ABORTED": "Aborted",
+ "WAITING_FOR_RESOURCES": "Waiting for Resources",
+ "WAITING_FOR_CLUSTER": "Waiting for Cluster",
+ },
+ },
+
members: {
__subJobs: null,
diff --git a/services/static-webserver/client/source/class/osparc/data/Resources.js b/services/static-webserver/client/source/class/osparc/data/Resources.js
index f91a8a5062f4..dcffb8738285 100644
--- a/services/static-webserver/client/source/class/osparc/data/Resources.js
+++ b/services/static-webserver/client/source/class/osparc/data/Resources.js
@@ -334,13 +334,25 @@ qx.Class.define("osparc.data.Resources", {
},
}
},
- "jobs": {
+ "runPipeline": {
+ useCache: false,
+ endpoints: {
+ startPipeline: {
+ method: "POST",
+ url: statics.API + "/computations/{studyId}:start"
+ },
+ stopPipeline: {
+ method: "POST",
+ url: statics.API + "/computations/{studyId}:stop"
+ },
+ }
+ },
+ "jobsActive": {
useCache: false, // handled in osparc.store.Jobs
endpoints: {
getPage: {
method: "GET",
- // url: statics.API + "/computations/-/iterations/latest?offset={offset}&limit={limit}&order_by={orderBy}"
- url: statics.API + "/computations/-/iterations/latest?offset={offset}&limit={limit}&order_by=%7B%22field%22:%22submitted_at%22,%22direction%22:%22desc%22%7D"
+ 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"
},
}
},
diff --git a/services/static-webserver/client/source/class/osparc/data/SubJob.js b/services/static-webserver/client/source/class/osparc/data/SubJob.js
index 6642827635a5..7b7cbfd51e9a 100644
--- a/services/static-webserver/client/source/class/osparc/data/SubJob.js
+++ b/services/static-webserver/client/source/class/osparc/data/SubJob.js
@@ -29,7 +29,7 @@ qx.Class.define("osparc.data.SubJob", {
progress: subJobData["progress"],
startedAt: subJobData["startedAt"] ? new Date(subJobData["startedAt"]) : null,
endedAt: subJobData["endedAt"] ? new Date(subJobData["endedAt"]) : null,
- osparcCredits: subJobData["osparcCredits"] || null,
+ osparcCredits: subJobData["osparcCredits"] === null ? null : -1*parseFloat(subJobData["osparcCredits"]),
image: subJobData["image"] || {},
logDownloadLink: subJobData["logDownloadLink"] || null,
});
diff --git a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js
index 6d6095b2d4aa..2cf130e98716 100644
--- a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js
+++ b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js
@@ -69,7 +69,7 @@ qx.Class.define("osparc.desktop.MainPage", {
preloadPromises.push(osparc.store.Tags.getInstance().fetchTags());
preloadPromises.push(osparc.store.Products.getInstance().fetchUiConfig());
preloadPromises.push(osparc.store.PollTasks.getInstance().fetchTasks());
- preloadPromises.push(osparc.store.Jobs.getInstance().fetchJobs());
+ preloadPromises.push(osparc.store.Jobs.getInstance().fetchJobsActive());
Promise.all(preloadPromises)
.then(() => {
const mainStack = this.__createMainStack();
diff --git a/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js b/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js
index eaae2e78fb35..9110b9ca8140 100644
--- a/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js
+++ b/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js
@@ -569,64 +569,64 @@ qx.Class.define("osparc.desktop.StudyEditor", {
return;
}
- this.getStudy().setPipelineRunning(true);
this.updateStudyDocument()
.then(() => {
this.__requestStartPipeline(this.getStudy().getUuid(), partialPipeline);
})
.catch(() => {
this.getStudyLogger().error(null, "Run failed");
- this.getStudy().setPipelineRunning(false);
});
},
__requestStartPipeline: function(studyId, partialPipeline = [], forceRestart = false) {
- const url = "/computations/" + encodeURIComponent(studyId) + ":start";
- const req = new osparc.io.request.ApiRequest(url, "POST");
- req.addListener("success", this.__onPipelineSubmitted, this);
- req.addListener("error", () => {
- this.getStudyLogger().error(null, "Error submitting pipeline");
- this.getStudy().setPipelineRunning(false);
- }, this);
- req.addListener("fail", async e => {
- if (e.getTarget().getStatus() == "409") {
- this.getStudyLogger().error(null, "Pipeline is already running");
- } else if (e.getTarget().getStatus() == "422") {
- this.getStudyLogger().info(null, "The pipeline is up-to-date");
- const msg = this.tr("The pipeline is up-to-date. Do you want to re-run it?");
- const win = new osparc.ui.window.Confirmation(msg).set({
- caption: this.tr("Re-run"),
- confirmText: this.tr("Run"),
- confirmAction: "create"
- });
- win.center();
- win.open();
- win.addListener("close", () => {
- if (win.getConfirmed()) {
- this.__requestStartPipeline(studyId, partialPipeline, true);
- }
- }, this);
- } else if (e.getTarget().getStatus() == "402") {
- const msg = await e.getTarget().getResponse().error.errors[0].message;
- osparc.FlashMessenger.logAs(msg, "WARNING");
- } else {
- this.getStudyLogger().error(null, "Unsuccessful pipeline submission");
- }
- this.getStudy().setPipelineRunning(false);
- }, this);
+ this.getStudy().setPipelineRunning(true);
- const requestData = {
- "subgraph": partialPipeline,
- "force_restart": forceRestart
- };
- req.setRequestData(requestData);
- req.send();
if (partialPipeline.length) {
this.getStudyLogger().info(null, "Starting partial pipeline");
} else {
this.getStudyLogger().info(null, "Starting pipeline");
}
+ const params = {
+ url: {
+ "studyId": studyId
+ },
+ data: {
+ "subgraph": partialPipeline,
+ "force_restart": forceRestart,
+ }
+ };
+ osparc.data.Resources.fetch("runPipeline", "startPipeline", params)
+ .then(() => this.__onPipelineSubmitted())
+ .catch(err => {
+ let msg = err.message;
+ const errStatus = err.status;
+ if (errStatus == "409") {
+ this.getStudyLogger().error(null, "Pipeline is already running");
+ } else if (errStatus == "422") {
+ this.getStudyLogger().info(null, "The pipeline is up-to-date");
+ msg = this.tr("The pipeline is up-to-date. Do you want to re-run it?");
+ const win = new osparc.ui.window.Confirmation(msg).set({
+ caption: this.tr("Re-run"),
+ confirmText: this.tr("Run"),
+ confirmAction: "create"
+ });
+ win.center();
+ win.open();
+ win.addListener("close", () => {
+ if (win.getConfirmed()) {
+ this.__requestStartPipeline(studyId, partialPipeline, true);
+ }
+ }, this);
+ } else if (err.status == "402") {
+ osparc.FlashMessenger.logAs(msg, "WARNING");
+ } else {
+ osparc.FlashMessenger.logAs(msg, "WARNING");
+ this.getStudyLogger().error(null, "Unsuccessful pipeline submission");
+ }
+ this.getStudy().setPipelineRunning(false);
+ });
+
return true;
},
@@ -662,19 +662,20 @@ qx.Class.define("osparc.desktop.StudyEditor", {
return;
}
- this.__requestStopPipeline(this.getStudy().getUuid());
+ this.__requestStopPipeline();
},
- __requestStopPipeline: function(studyId) {
- const url = "/computations/" + encodeURIComponent(studyId) + ":stop";
- const req = new osparc.io.request.ApiRequest(url, "POST");
- req.addListener("success", () => this.getStudyLogger().debug(null, "Pipeline aborting"), this);
- req.addListener("error", () => this.getStudyLogger().error(null, "Error stopping pipeline"), this);
- req.addListener("fail", () => this.getStudyLogger().error(null, "Failed stopping pipeline"), this);
- req.send();
-
+ __requestStopPipeline: function() {
this.getStudyLogger().info(null, "Stopping pipeline");
- return true;
+
+ const params = {
+ url: {
+ "studyId": this.getStudy().getUuid()
+ },
+ };
+ osparc.data.Resources.fetch("runPipeline", "stopPipeline", params)
+ .then(() => this.getStudyLogger().debug(null, "Stopping pipeline"), this)
+ .catch(() => this.getStudyLogger().error(null, "Error stopping pipeline"), this);
},
// ------------------ START/STOP PIPELINE ------------------
diff --git a/services/static-webserver/client/source/class/osparc/jobs/ActivityCenterWindow.js b/services/static-webserver/client/source/class/osparc/jobs/ActivityCenterWindow.js
index cd56d3198f6d..7f2fe3b7b023 100644
--- a/services/static-webserver/client/source/class/osparc/jobs/ActivityCenterWindow.js
+++ b/services/static-webserver/client/source/class/osparc/jobs/ActivityCenterWindow.js
@@ -24,8 +24,8 @@ qx.Class.define("osparc.jobs.ActivityCenterWindow", {
this.set({
layout: new qx.ui.layout.VBox(),
modal: true,
- width: 1100,
- height: 500,
+ width: this.self().WIDTH,
+ height: this.self().HEIGHT,
showMaximize: false,
showMinimize: false,
});
@@ -34,6 +34,9 @@ qx.Class.define("osparc.jobs.ActivityCenterWindow", {
},
statics: {
+ WIDTH: 1000,
+ HEIGHT: 500,
+
openWindow: function() {
const runsWindow = new osparc.jobs.ActivityCenterWindow();
runsWindow.center();
diff --git a/services/static-webserver/client/source/class/osparc/jobs/ActivityOverview.js b/services/static-webserver/client/source/class/osparc/jobs/ActivityOverview.js
new file mode 100644
index 000000000000..0f985f4e03da
--- /dev/null
+++ b/services/static-webserver/client/source/class/osparc/jobs/ActivityOverview.js
@@ -0,0 +1,43 @@
+/* ************************************************************************
+
+ osparc - the simcore frontend
+
+ https://osparc.io
+
+ Copyright:
+ 2025 IT'IS Foundation, https://itis.swiss
+
+ License:
+ MIT: https://opensource.org/licenses/MIT
+
+ Authors:
+ * Odei Maiz (odeimaiz)
+
+************************************************************************ */
+
+qx.Class.define("osparc.jobs.ActivityOverview", {
+ extend: qx.ui.core.Widget,
+
+ construct: function(projectData) {
+ this.base(arguments);
+
+ this._setLayout(new qx.ui.layout.VBox(15));
+
+ this.__buildLayout(projectData);
+ },
+
+ statics: {
+ popUpInWindow: function(projectData) {
+ const activityOverview = new osparc.jobs.ActivityOverview(projectData);
+ const title = qx.locale.Manager.tr("Activity Overview");
+ return osparc.ui.window.Window.popUpInWindow(activityOverview, title, osparc.jobs.ActivityCenterWindow.WIDTH, osparc.jobs.ActivityCenterWindow.HEIGHT);
+ },
+ },
+
+ members: {
+ __buildLayout: function(projectData) {
+ const subRunsTable = new osparc.jobs.SubRunsTable(projectData["uuid"]);
+ this._add(subRunsTable);
+ },
+ }
+});
diff --git a/services/static-webserver/client/source/class/osparc/jobs/JobsButton.js b/services/static-webserver/client/source/class/osparc/jobs/JobsButton.js
index c0df3017ee9c..b5362ab59529 100644
--- a/services/static-webserver/client/source/class/osparc/jobs/JobsButton.js
+++ b/services/static-webserver/client/source/class/osparc/jobs/JobsButton.js
@@ -27,14 +27,14 @@ qx.Class.define("osparc.jobs.JobsButton", {
width: 30,
alignX: "center",
cursor: "pointer",
- visibility: "excluded",
toolTipText: this.tr("Activity Center"),
});
this.addListener("tap", () => osparc.jobs.ActivityCenterWindow.openWindow(), this);
const jobsStore = osparc.store.Jobs.getInstance();
- jobsStore.addListener("changeJobs", e => this.__updateJobsButton(), this);
+ jobsStore.addListener("changeJobsActive", e => this.__updateJobsButton(e.getData()), this);
+ jobsStore.fetchJobsActive();
},
members: {
@@ -71,14 +71,12 @@ qx.Class.define("osparc.jobs.JobsButton", {
return control || this.base(arguments, id);
},
- __updateJobsButton: function() {
+ __updateJobsButton: function(nActiveJobs) {
this.getChildControl("icon");
const number = this.getChildControl("number");
- const jobsStore = osparc.store.Jobs.getInstance();
- const nJobs = jobsStore.getJobs().length > 20 ? "20+" : jobsStore.getJobs().length;
+ const nJobs = nActiveJobs > osparc.store.Jobs.SERVER_MAX_LIMIT ? (osparc.store.Jobs.SERVER_MAX_LIMIT + "+") : nActiveJobs;
number.setValue(nJobs.toString());
- nJobs ? this.show() : this.exclude();
},
}
});
diff --git a/services/static-webserver/client/source/class/osparc/jobs/RunsTable.js b/services/static-webserver/client/source/class/osparc/jobs/RunsTable.js
index 41fc06821a0c..9d16c3225377 100644
--- a/services/static-webserver/client/source/class/osparc/jobs/RunsTable.js
+++ b/services/static-webserver/client/source/class/osparc/jobs/RunsTable.js
@@ -36,9 +36,13 @@ qx.Class.define("osparc.jobs.RunsTable", {
Object.values(this.self().COLS).forEach(col => columnModel.setColumnWidth(col.column, col.width));
- const iconPathStop = "osparc/circle-stop-text.svg";
- const fontButtonRendererStop = new osparc.ui.table.cellrenderer.ImageButtonRenderer("stop", iconPathStop);
- columnModel.setDataCellRenderer(this.self().COLS.ACTION_STOP.column, fontButtonRendererStop);
+ const iconPathStop = "osparc/icons/circle-xmark-text.svg";
+ const fontButtonRendererStop = new osparc.ui.table.cellrenderer.ImageButtonRenderer("cancel", iconPathStop);
+ columnModel.setDataCellRenderer(this.self().COLS.ACTION_CANCEL.column, fontButtonRendererStop);
+
+ const iconPathInfo = "osparc/icons/circle-info-text.svg";
+ const fontButtonRendererInfo = new osparc.ui.table.cellrenderer.ImageButtonRenderer("info", iconPathInfo);
+ columnModel.setDataCellRenderer(this.self().COLS.ACTION_INFO.column, fontButtonRendererInfo);
this.__attachHandlers();
},
@@ -53,20 +57,20 @@ qx.Class.define("osparc.jobs.RunsTable", {
id: "projectUuid",
column: 0,
label: qx.locale.Manager.tr("Project Id"),
- width: 170
+ width: 200
},
PROJECT_NAME: {
id: "projectName",
column: 1,
label: qx.locale.Manager.tr("Project"),
- width: 170,
+ width: 150,
sortable: true
},
STATE: {
id: "state",
column: 2,
label: qx.locale.Manager.tr("Status"),
- width: 170
+ width: 150
},
SUBMIT: {
id: "submit",
@@ -89,11 +93,17 @@ qx.Class.define("osparc.jobs.RunsTable", {
width: 130,
sortable: true
},
- ACTION_STOP: {
- id: "action_stop",
+ ACTION_CANCEL: {
+ id: "action_cancel",
column: 6,
- label: "",
- width: 40
+ label: qx.locale.Manager.tr("Cancel"),
+ width: 50
+ },
+ ACTION_INFO: {
+ id: "action_info",
+ column: 7,
+ label: qx.locale.Manager.tr("Info"),
+ width: 50
},
}
},
@@ -122,17 +132,35 @@ qx.Class.define("osparc.jobs.RunsTable", {
},
__handleButtonClick: function(action, row) {
+ this.resetSelection();
const rowData = this.getTableModel().getRowData(row);
switch (action) {
case "info": {
- this.fireDataEvent("runSelected", rowData);
+ const job = osparc.store.Jobs.getInstance().getJob(rowData["projectUuid"]);
+ if (!job) {
+ return;
+ }
+ const allInfo = {
+ "image": job.getInfo() ? osparc.utils.Utils.deepCloneObject(job.getInfo()) : {},
+ "customMetadata": job.getCustomMetadata() ? osparc.utils.Utils.deepCloneObject(job.getCustomMetadata()) : {},
+ }
+ const runInfo = new osparc.jobs.Info(allInfo);
+ const win = osparc.jobs.Info.popUpInWindow(runInfo);
+ win.setCaption(rowData["projectName"]);
break;
}
- case "run":
- case "stop":
- case "logs": {
- const msg = `I wish I could ${action} the job ${rowData["projectUuid"]}`;
- osparc.FlashMessenger.logAs(msg, "WARNING");
+ case "cancel": {
+ const params = {
+ url: {
+ "studyId": rowData["projectUuid"],
+ },
+ };
+ osparc.data.Resources.fetch("runPipeline", "stopPipeline", params)
+ .then(() => {
+ const msg = this.tr("Stopping pipeline");
+ osparc.FlashMessenger.logAs(msg, "INFO");
+ })
+ .catch(err => osparc.FlashMessenger.logError(err));
break;
}
default:
diff --git a/services/static-webserver/client/source/class/osparc/jobs/RunsTableModel.js b/services/static-webserver/client/source/class/osparc/jobs/RunsTableModel.js
index cd75159534aa..da829b670989 100644
--- a/services/static-webserver/client/source/class/osparc/jobs/RunsTableModel.js
+++ b/services/static-webserver/client/source/class/osparc/jobs/RunsTableModel.js
@@ -60,7 +60,7 @@ qx.Class.define("osparc.jobs.RunsTableModel", {
const offset = 0;
const limit = 1;
const resolveWResponse = true;
- osparc.store.Jobs.getInstance().fetchJobs(offset, limit, JSON.stringify(this.getOrderBy()), resolveWResponse)
+ osparc.store.Jobs.getInstance().fetchJobsActive(offset, limit, JSON.stringify(this.getOrderBy()), resolveWResponse)
.then(resp => {
this._onRowCountLoaded(resp["_meta"].total)
})
@@ -76,7 +76,7 @@ qx.Class.define("osparc.jobs.RunsTableModel", {
const lastRow = Math.min(qxLastRow, this._rowCount - 1);
// Returns a request promise with given offset and limit
const getFetchPromise = (offset, limit) => {
- return osparc.store.Jobs.getInstance().fetchJobs(offset, limit, JSON.stringify(this.getOrderBy()))
+ return osparc.store.Jobs.getInstance().fetchJobsActive(offset, limit, JSON.stringify(this.getOrderBy()))
.then(jobs => {
const data = [];
const jobsCols = osparc.jobs.RunsTable.COLS;
@@ -84,7 +84,7 @@ qx.Class.define("osparc.jobs.RunsTableModel", {
data.push({
[jobsCols.PROJECT_UUID.id]: job.getProjectUuid(),
[jobsCols.PROJECT_NAME.id]: job.getProjectName(),
- [jobsCols.STATE.id]: job.getState(),
+ [jobsCols.STATE.id]: osparc.data.Job.STATUS_LABELS[job.getState()] || job.getState(),
[jobsCols.SUBMIT.id]: job.getSubmittedAt() ? osparc.utils.Utils.formatDateAndTime(job.getSubmittedAt()) : "-",
[jobsCols.START.id]: job.getStartedAt() ? osparc.utils.Utils.formatDateAndTime(job.getStartedAt()) : "-",
[jobsCols.END.id]: job.getEndedAt() ? osparc.utils.Utils.formatDateAndTime(job.getEndedAt()) : "-",
diff --git a/services/static-webserver/client/source/class/osparc/jobs/SubRunsTable.js b/services/static-webserver/client/source/class/osparc/jobs/SubRunsTable.js
index 2f457bb3efbb..ecdb587ac827 100644
--- a/services/static-webserver/client/source/class/osparc/jobs/SubRunsTable.js
+++ b/services/static-webserver/client/source/class/osparc/jobs/SubRunsTable.js
@@ -37,11 +37,11 @@ qx.Class.define("osparc.jobs.SubRunsTable", {
Object.values(this.self().COLS).forEach(col => columnModel.setColumnWidth(col.column, col.width));
- const iconPathInfo = "osparc/circle-info-text.svg";
+ const iconPathInfo = "osparc/icons/circle-info-text.svg";
const fontButtonRendererInfo = new osparc.ui.table.cellrenderer.ImageButtonRenderer("info", iconPathInfo);
columnModel.setDataCellRenderer(this.self().COLS.INFO.column, fontButtonRendererInfo);
- const iconPathLogs = "osparc/logs-text.svg";
+ const iconPathLogs = "osparc/icons/logs-text.svg";
const fontButtonRendererLogs = new osparc.ui.table.cellrenderer.ImageButtonRenderer("logs", iconPathLogs);
columnModel.setDataCellRenderer(this.self().COLS.LOGS.column, fontButtonRendererLogs);
@@ -54,25 +54,25 @@ qx.Class.define("osparc.jobs.SubRunsTable", {
id: "projectUuid",
column: 0,
label: qx.locale.Manager.tr("Project Id"),
- width: 170
+ width: 200
},
NODE_ID: {
id: "nodeId",
column: 1,
label: qx.locale.Manager.tr("Node Id"),
- width: 170
+ width: 200
},
NODE_NAME: {
id: "nodeName",
column: 2,
label: qx.locale.Manager.tr("Node"),
- width: 170
+ width: 100
},
APP: {
id: "app",
column: 3,
label: qx.locale.Manager.tr("App"),
- width: 150
+ width: 100
},
STATE: {
id: "state",
@@ -108,7 +108,7 @@ qx.Class.define("osparc.jobs.SubRunsTable", {
id: "credits",
column: 9,
label: qx.locale.Manager.tr("Credits"),
- width: 70
+ width: 50
},
INFO: {
id: "info",
@@ -145,6 +145,7 @@ qx.Class.define("osparc.jobs.SubRunsTable", {
},
__handleButtonClick: function(action, row) {
+ this.resetSelection();
const rowData = this.getTableModel().getRowData(row);
switch (action) {
case "info": {
@@ -161,6 +162,23 @@ qx.Class.define("osparc.jobs.SubRunsTable", {
win.setCaption(rowData["nodeName"]);
break;
}
+ case "logs": {
+ const job = osparc.store.Jobs.getInstance().getJob(rowData["projectUuid"]);
+ if (!job) {
+ return;
+ }
+ const subJob = job.getSubJob(rowData["nodeId"]);
+ if (!subJob) {
+ return;
+ }
+ const logDownloadLink = subJob.getLogDownloadLink()
+ if (logDownloadLink) {
+ osparc.utils.Utils.downloadLink(logDownloadLink, "GET", rowData["nodeName"] + ".logs");
+ } else {
+ osparc.component.message.FlashMessenger.getInstance().logAsWarning(this.tr("No logs available"));
+ }
+ break;
+ }
default:
console.warn(`Unknown action: ${action}`);
break;
diff --git a/services/static-webserver/client/source/class/osparc/jobs/SubRunsTableModel.js b/services/static-webserver/client/source/class/osparc/jobs/SubRunsTableModel.js
index 33f65f03a85d..eeafa9ea2515 100644
--- a/services/static-webserver/client/source/class/osparc/jobs/SubRunsTableModel.js
+++ b/services/static-webserver/client/source/class/osparc/jobs/SubRunsTableModel.js
@@ -96,7 +96,7 @@ qx.Class.define("osparc.jobs.SubRunsTableModel", {
[subJobsCols.NODE_ID.id]: subJob.getNodeId(),
[subJobsCols.NODE_NAME.id]: subJob.getNodeName(),
[subJobsCols.APP.id]: appName + ":" + displayVersion,
- [subJobsCols.STATE.id]: subJob.getState(),
+ [subJobsCols.STATE.id]: osparc.data.Job.STATUS_LABELS[subJob.getState()] || subJob.getState(),
[subJobsCols.PROGRESS.id]: subJob.getProgress() * 100 + "%",
[subJobsCols.START.id]: startedAt ? osparc.utils.Utils.formatDateAndTime(startedAt) : "-",
[subJobsCols.END.id]: endedAt ? osparc.utils.Utils.formatDateAndTime(endedAt) : "-",
diff --git a/services/static-webserver/client/source/class/osparc/store/Jobs.js b/services/static-webserver/client/source/class/osparc/store/Jobs.js
index 183d25c621fb..87ea782e18a6 100644
--- a/services/static-webserver/client/source/class/osparc/store/Jobs.js
+++ b/services/static-webserver/client/source/class/osparc/store/Jobs.js
@@ -25,7 +25,11 @@ qx.Class.define("osparc.store.Jobs", {
init: [],
nullable: true,
event: "changeJobs"
- }
+ },
+ },
+
+ events: {
+ "changeJobsActive": "qx.event.type.Data",
},
statics: {
@@ -33,7 +37,7 @@ qx.Class.define("osparc.store.Jobs", {
},
members: {
- fetchJobs: function(
+ fetchJobsActive: function(
offset = 0,
limit = this.self().SERVER_MAX_LIMIT,
orderBy = {
@@ -52,18 +56,19 @@ qx.Class.define("osparc.store.Jobs", {
const options = {
resolveWResponse: true
};
- return osparc.data.Resources.fetch("jobs", "getPage", params, options)
+ return osparc.data.Resources.fetch("jobsActive", "getPage", params, options)
.then(jobsResp => {
- const jobs = [];
+ this.fireDataEvent("changeJobsActive", jobsResp["_meta"]["total"]);
+ const jobsActive = [];
if ("data" in jobsResp) {
- jobsResp["data"].forEach(jobData => {
- jobs.push(this.addJob(jobData));
+ jobsResp["data"].forEach(jobActiveData => {
+ jobsActive.push(this.__addJob(jobActiveData));
});
}
if (resolveWResponse) {
return jobsResp;
}
- return jobs;
+ return jobsActive;
})
.catch(err => console.error(err));
},
@@ -85,7 +90,7 @@ qx.Class.define("osparc.store.Jobs", {
.catch(err => console.error(err));
},
- addJob: function(jobData) {
+ __addJob: function(jobData) {
const jobs = this.getJobs();
const jobFound = jobs.find(job => job.getProjectUuid() === jobData["projectUuid"]);
if (jobFound) {
@@ -94,18 +99,20 @@ qx.Class.define("osparc.store.Jobs", {
}
const job = new osparc.data.Job(jobData);
jobs.push(job);
- this.fireDataEvent("changeJobs");
return job;
},
addSubJob: function(subJobData) {
- const jobs = this.getJobs();
- const jobFound = jobs.find(job => job.getProjectUuid() === subJobData["projectUuid"]);
- if (jobFound) {
- const subJob = jobFound.addSubJob(subJobData);
- return subJob;
+ let job = this.getJob(subJobData["projectUuid"]);
+ if (!job) {
+ const jobs = this.getJobs();
+ job = new osparc.data.Job({
+ "projectUuid": subJobData["projectUuid"],
+ });
+ jobs.push(job);
}
- return null;
+ const subJob = job.addSubJob(subJobData);
+ return subJob;
},
getJob: function(projectUuid) {
diff --git a/services/static-webserver/client/source/class/osparc/widget/logger/LoggerModel.js b/services/static-webserver/client/source/class/osparc/widget/logger/LoggerModel.js
index edca2766438e..953c4448cafb 100644
--- a/services/static-webserver/client/source/class/osparc/widget/logger/LoggerModel.js
+++ b/services/static-webserver/client/source/class/osparc/widget/logger/LoggerModel.js
@@ -83,13 +83,13 @@ qx.Class.define("osparc.widget.logger.LoggerModel", {
let iconSource = "";
switch (logLevel) {
case logLevels.INFO:
- iconSource = "osparc/circle-info-solid.svg";
+ iconSource = "osparc/icons/circle-info-solid.svg";
break;
case logLevels.WARNING:
- iconSource = "osparc/circle-exclamation-solid.svg";
+ iconSource = "osparc/icons/circle-exclamation-solid.svg";
break;
case logLevels.ERROR:
- iconSource = "osparc/circle-xmark-solid.svg";
+ iconSource = "osparc/icons/circle-xmark-solid.svg";
break;
}
return iconSource;
diff --git a/services/static-webserver/client/source/resource/osparc/circle-stop-text.svg b/services/static-webserver/client/source/resource/osparc/circle-stop-text.svg
deleted file mode 100644
index 1470fd0f2952..000000000000
--- a/services/static-webserver/client/source/resource/osparc/circle-stop-text.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/services/static-webserver/client/source/resource/osparc/circle-exclamation-solid.svg b/services/static-webserver/client/source/resource/osparc/icons/circle-exclamation-solid.svg
similarity index 87%
rename from services/static-webserver/client/source/resource/osparc/circle-exclamation-solid.svg
rename to services/static-webserver/client/source/resource/osparc/icons/circle-exclamation-solid.svg
index fa80fe70833c..8f3a586bfa80 100644
--- a/services/static-webserver/client/source/resource/osparc/circle-exclamation-solid.svg
+++ b/services/static-webserver/client/source/resource/osparc/icons/circle-exclamation-solid.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/services/static-webserver/client/source/resource/osparc/circle-info-solid.svg b/services/static-webserver/client/source/resource/osparc/icons/circle-info-solid.svg
similarity index 87%
rename from services/static-webserver/client/source/resource/osparc/circle-info-solid.svg
rename to services/static-webserver/client/source/resource/osparc/icons/circle-info-solid.svg
index 64e1e26721a3..5e28757f57f6 100644
--- a/services/static-webserver/client/source/resource/osparc/circle-info-solid.svg
+++ b/services/static-webserver/client/source/resource/osparc/icons/circle-info-solid.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/services/static-webserver/client/source/resource/osparc/circle-info-text.svg b/services/static-webserver/client/source/resource/osparc/icons/circle-info-text.svg
similarity index 87%
rename from services/static-webserver/client/source/resource/osparc/circle-info-text.svg
rename to services/static-webserver/client/source/resource/osparc/icons/circle-info-text.svg
index b753c59738b3..5b80476aa3a4 100644
--- a/services/static-webserver/client/source/resource/osparc/circle-info-text.svg
+++ b/services/static-webserver/client/source/resource/osparc/icons/circle-info-text.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/services/static-webserver/client/source/resource/osparc/circle-xmark-solid.svg b/services/static-webserver/client/source/resource/osparc/icons/circle-xmark-solid.svg
similarity index 97%
rename from services/static-webserver/client/source/resource/osparc/circle-xmark-solid.svg
rename to services/static-webserver/client/source/resource/osparc/icons/circle-xmark-solid.svg
index e7074e6aadf9..2844d4d2e155 100644
--- a/services/static-webserver/client/source/resource/osparc/circle-xmark-solid.svg
+++ b/services/static-webserver/client/source/resource/osparc/icons/circle-xmark-solid.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/services/static-webserver/client/source/resource/osparc/icons/circle-xmark-text.svg b/services/static-webserver/client/source/resource/osparc/icons/circle-xmark-text.svg
new file mode 100644
index 000000000000..134422e82d53
--- /dev/null
+++ b/services/static-webserver/client/source/resource/osparc/icons/circle-xmark-text.svg
@@ -0,0 +1 @@
+
diff --git a/services/static-webserver/client/source/resource/osparc/logs-text.svg b/services/static-webserver/client/source/resource/osparc/icons/logs-text.svg
similarity index 96%
rename from services/static-webserver/client/source/resource/osparc/logs-text.svg
rename to services/static-webserver/client/source/resource/osparc/icons/logs-text.svg
index 20dd82103ce4..115dfe4b2655 100644
--- a/services/static-webserver/client/source/resource/osparc/logs-text.svg
+++ b/services/static-webserver/client/source/resource/osparc/icons/logs-text.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/services/static-webserver/client/source/resource/osparc/trash-text.svg b/services/static-webserver/client/source/resource/osparc/trash-text.svg
deleted file mode 100644
index 0cbfe135be55..000000000000
--- a/services/static-webserver/client/source/resource/osparc/trash-text.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file