Skip to content

Commit

Permalink
Merge branch 'master' into feature/share-tags
Browse files Browse the repository at this point in the history
  • Loading branch information
odeimaiz authored Jan 7, 2025
2 parents 82855c0 + 208de24 commit 7b21119
Show file tree
Hide file tree
Showing 22 changed files with 463 additions and 255 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""add deprecated submit column
Revision ID: 307017ee1a49
Revises: 1e3c9c804fec
Create Date: 2025-01-06 12:53:51.604189+00:00
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '307017ee1a49'
down_revision = '1e3c9c804fec'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('comp_tasks', sa.Column('submit', sa.DateTime(timezone=True), server_default=sa.text("'1900-01-01T00:00:00Z'::timestamptz"), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('comp_tasks', 'submit')
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
""" Computational Tasks Table
"""
"""Computational Tasks Table"""

import enum

Expand Down Expand Up @@ -102,6 +100,14 @@ class NodeClass(enum.Enum):
nullable=True,
doc="Harware information of this task",
),
# deprecated columns must be kept due to legacy services
# utc timestamps for submission/start/end
sa.Column(
"submit",
sa.DateTime(timezone=True),
server_default=sa.text("'1900-01-01T00:00:00Z'::timestamptz"),
doc="[DEPRECATED unused but kept for legacy services and must be filled with a default value of 1 January 1900]",
),
# ------
sa.UniqueConstraint("project_id", "node_id", name="project_node_uniqueness"),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ class CompTaskAtDB(BaseModel):
pricing_info: dict | None
hardware_info: HardwareInfo

submit: dt.datetime | None = Field(
default=None, deprecated=True, description="Required for legacy services"
)

@field_validator("state", mode="before")
@classmethod
def _convert_state_from_state_type_enum_if_needed(cls, v):
Expand Down Expand Up @@ -238,7 +242,9 @@ def to_db_model(self, **exclusion_rules) -> dict[str, Any]:
"pricing_unit_id": 1,
"pricing_unit_cost_id": 1,
},
"hardware_info": next(iter(HardwareInfo.model_config["json_schema_extra"]["examples"])), # type: ignore
"hardware_info": next(
iter(HardwareInfo.model_config["json_schema_extra"]["examples"]) # type: ignore
),
}
for image_example in Image.model_config["json_schema_extra"]["examples"] # type: ignore
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,54 +148,59 @@ qx.Class.define("osparc.dashboard.CardBase", {
return false;
},

// groups -> [orgMembs, orgs, [productEveryone], [everyone]];
setIconAndTooltip: function(shareIcon, accessRights, groups) {
shareIcon.setSource(osparc.dashboard.CardBase.SHARE_ICON);
if (osparc.data.model.Study.canIWrite(accessRights)) {
shareIcon.set({
toolTipText: qx.locale.Manager.tr("Share")
});
populateShareIcon: async function(shareIcon, accessRights) {
const gids = Object.keys(accessRights).map(key => parseInt(key));

const groupsStore = osparc.store.Groups.getInstance();

// Icon
const groupEveryone = groupsStore.getEveryoneGroup();
const groupProductEveryone = groupsStore.getEveryoneProductGroup();
const organizations = groupsStore.getOrganizations();
const organizationIds = Object.keys(organizations).map(key => parseInt(key));
if (gids.includes(groupEveryone.getGroupId()) || gids.includes(groupProductEveryone.getGroupId())) {
shareIcon.setSource(osparc.dashboard.CardBase.SHARED_ALL);
} else if (organizationIds.filter(value => gids.includes(value)).length) { // find intersection
shareIcon.setSource(osparc.dashboard.CardBase.SHARED_ORGS);
} else if (gids.length === 1) {
shareIcon.setSource(osparc.dashboard.CardBase.SHARE_ICON);
} else {
shareIcon.setSource(osparc.dashboard.CardBase.SHARED_USER);
}
let sharedGrps = [];
const myGroupId = osparc.auth.Data.getInstance().getGroupId();
for (let i=0; i<groups.length; i++) {
if (groups[i].length === 0) {
// user has no read access to the productEveryone
continue;

// Tooltip
const sharedGrps = [];
const groups = [];
groups.push(groupEveryone);
groups.push(groupProductEveryone);
groups.push(...Object.values(organizations));
groups.forEach(group => {
const idx = gids.indexOf(group.getGroupId());
if (idx > -1) {
sharedGrps.push(group);
gids.splice(idx, 1);
}
const sharedGrp = [];
const gids = Object.keys(accessRights);
for (let j=0; j<gids.length; j++) {
const gid = parseInt(gids[j]);
if (gid === myGroupId) {
continue;
}
const grp = groups[i].find(group => group.getGroupId() === gid);
if (grp) {
sharedGrp.push(grp);
});
// once the groups were removed, the remaining group ids are users' primary groups ids
const usersStore = osparc.store.Users.getInstance();
const myGroupId = groupsStore.getMyGroupId();
for (let i=0; i<gids.length; i++) {
const gid = gids[i];
if (myGroupId !== gid) {
const user = await usersStore.getUser(gid);
if (user) {
sharedGrps.push(user);
}
}
if (sharedGrp.length === 0) {
continue;
} else {
sharedGrps = sharedGrps.concat(sharedGrp);
}
switch (i) {
case 0:
shareIcon.setSource(osparc.dashboard.CardBase.SHARED_USER);
break;
case 1:
shareIcon.setSource(osparc.dashboard.CardBase.SHARED_ORGS);
break;
case 2:
case 3:
shareIcon.setSource(osparc.dashboard.CardBase.SHARED_ALL);
break;
}
}

// tooltip
const canIWrite = osparc.data.model.Study.canIWrite(accessRights);
if (sharedGrps.length === 0) {
if (canIWrite) {
shareIcon.set({
toolTipText: qx.locale.Manager.tr("Share")
});
}
return;
}
const sharedGrpLabels = [];
Expand All @@ -215,17 +220,6 @@ qx.Class.define("osparc.dashboard.CardBase", {
shareIcon.addListener("mouseover", () => hint.show(), this);
shareIcon.addListener("mouseout", () => hint.exclude(), this);
},

// groups -> [orgMembs, orgs, [productEveryone], [everyone]];
populateShareIcon: function(shareIcon, accessRights) {
const groupsStore = osparc.store.Groups.getInstance();
const orgMembs = Object.values(groupsStore.getReachableUsers());
const orgs = Object.values(groupsStore.getOrganizations());
const productEveryone = [groupsStore.getEveryoneProductGroup()];
const everyone = [groupsStore.getEveryoneGroup()];
const groups = [orgMembs, orgs, productEveryone, everyone];
osparc.dashboard.CardBase.setIconAndTooltip(shareIcon, accessRights, groups);
},
},

properties: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,22 @@ qx.Class.define("osparc.data.Resources", {
}
}
},
/*
* USERS
*/
"users": {
useCache: false, // osparc.store.Groups handles the cache
endpoints: {
get: {
method: "GET",
url: statics.API + "/groups/{gid}/users"
},
search: {
method: "POST",
url: statics.API + "/users:search"
}
}
},
/*
* WALLETS
*/
Expand Down Expand Up @@ -958,7 +974,7 @@ qx.Class.define("osparc.data.Resources", {
}
}
},
"users": {
"poUsers": {
endpoints: {
search: {
method: "GET",
Expand Down
25 changes: 18 additions & 7 deletions services/static-webserver/client/source/class/osparc/data/Roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ qx.Class.define("osparc.data.Roles", {
}
},

__createIntoFromRoles: function(roles, showWording = true) {
__createRolesLayout: function(roles, showWording = true) {
const rolesLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(5)).set({
alignY: "middle",
paddingRight: 10
Expand Down Expand Up @@ -202,23 +202,34 @@ qx.Class.define("osparc.data.Roles", {
},

createRolesOrgInfo: function() {
return this.__createIntoFromRoles(osparc.data.Roles.ORG);
return this.__createRolesLayout(osparc.data.Roles.ORG);
},

createRolesWalletInfo: function() {
return this.__createIntoFromRoles(osparc.data.Roles.WALLET);
return this.__createRolesLayout(osparc.data.Roles.WALLET);
},

createRolesStudyInfo: function() {
return this.__createIntoFromRoles(osparc.data.Roles.STUDY);
return this.__createRolesLayout(osparc.data.Roles.STUDY);
},

createRolesServicesInfo: function() {
return this.__createIntoFromRoles(osparc.data.Roles.SERVICES);
return this.__createRolesLayout(osparc.data.Roles.SERVICES);
},

createRolesWorkspaceInfo: function(showWording = true) {
return this.__createIntoFromRoles(osparc.data.Roles.WORKSPACE, showWording);
}
return this.__createRolesLayout(osparc.data.Roles.WORKSPACE, showWording);
},

replaceSpacerWithWidget: function(rolesLayout, widget) {
if (rolesLayout && rolesLayout.getChildren()) {
// remove spacer
rolesLayout.remove(rolesLayout.getChildren()[0]);
// add widget
rolesLayout.addAt(widget, 0, {
flex: 1
});
}
},
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -274,21 +274,19 @@ qx.Class.define("osparc.data.model.Study", {
},

canIWrite: function(studyAccessRights) {
const myGroupId = osparc.auth.Data.getInstance().getGroupId();
const groupsStore = osparc.store.Groups.getInstance();
const orgIDs = groupsStore.getOrganizationIds();
orgIDs.push(myGroupId);
orgIDs.push(groupsStore.getMyGroupId());
if (orgIDs.length) {
return osparc.share.CollaboratorsStudy.canGroupsWrite(studyAccessRights, (orgIDs));
}
return false;
},

canIDelete: function(studyAccessRights) {
const myGroupId = osparc.auth.Data.getInstance().getGroupId();
const groupsStore = osparc.store.Groups.getInstance();
const orgIDs = groupsStore.getOrganizationIds();
orgIDs.push(myGroupId);
orgIDs.push(groupsStore.getMyGroupId());
if (orgIDs.length) {
return osparc.share.CollaboratorsStudy.canGroupsDelete(studyAccessRights, (orgIDs));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,30 @@ qx.Class.define("osparc.data.model.User", {
construct: function(userData) {
this.base(arguments);

let description = "";
if (userData["first_name"]) {
description = userData["first_name"];
if (userData["last_name"]) {
description += " " + userData["last_name"];
const userId = ("id" in userData) ? parseInt(userData["id"]) : parseInt(userData["userId"]);
const groupId = ("gid" in userData) ? parseInt(userData["gid"]) : parseInt(userData["groupId"]);
const username = userData["userName"];
const email = ("login" in userData) ? userData["login"] : userData["email"];
const firstName = ("first_name" in userData) ? userData["first_name"] : userData["firstName"];
const lastName = ("last_name" in userData) ? userData["last_name"] : userData["lastName"];
let description = [firstName, lastName].join(" ").trim(); // the null values will be replaced by empty strings
if (email) {
if (description) {
description += " - "
}
description += " - ";
description += email;
}
if (userData["login"]) {
description += userData["login"];
}
const thumbnail = osparc.utils.Avatar.emailToThumbnail(userData["login"], userData["userName"]);
const thumbnail = osparc.utils.Avatar.emailToThumbnail(email, username);
this.set({
userId: parseInt(userData["id"]),
groupId: parseInt(userData["gid"]),
username: userData["userName"],
firstName: userData["first_name"],
lastName: userData["last_name"],
email: userData["login"],
label: userData["userName"],
description,
userId,
groupId,
username,
firstName,
lastName,
email,
thumbnail,
label: username,
description,
});
},

Expand Down
Loading

0 comments on commit 7b21119

Please sign in to comment.