Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
[
this.__getInfoPage,
this.__getBillingPage,
this.__getActivityOverviewPage,
this.__getServicesUpdatePage,
this.__getServicesBootOptionsPage,
this.__getConversationsPage,
Expand Down Expand Up @@ -494,6 +495,31 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
return null;
},

__getActivityOverviewPage: function() {
const resourceData = this.__resourceData;
if (
!osparc.desktop.credits.Utils.areWalletsEnabled() ||
!osparc.utils.Resources.isStudy(resourceData)
) {
return null;
}

const id = "ActivityOverview";
const title = this.tr("Activity Overview");
const iconSrc = "@FontAwesome5Solid/tasks/22";
const page = this.__billingSettings = new osparc.dashboard.resources.pages.BasePage(title, iconSrc, id);
this.__addOpenButton(page);

const lazyLoadContent = () => {
const activityOverview = new osparc.jobs.ActivityOverview(resourceData);
const billingScroll = new qx.ui.container.Scroll(activityOverview);
page.addToContent(billingScroll);
}
page.addListenerOnce("appear", lazyLoadContent, this);

return page;
},

__getPreviewPage: function() {
const resourceData = this.__resourceData;
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"]) {
Expand Down Expand Up @@ -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,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
},

Expand Down Expand Up @@ -666,15 +666,16 @@ qx.Class.define("osparc.desktop.StudyEditor", {
},

__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();

this.getStudyLogger().info(null, "Stopping pipeline");
return true;

const params = {
url: {
"studyId": studyId
},
};
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 ------------------

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* ************************************************************************

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);
},

members: {
__buildLayout: function(projectData) {
const subRunsTable = new osparc.jobs.SubRunsTable(projectData["uuid"]);
this._add(subRunsTable);
},
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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();
},
}
});
Loading
Loading