diff --git a/services/static-webserver/client/source/class/osparc/auth/ui/RequestAccount.js b/services/static-webserver/client/source/class/osparc/auth/ui/RequestAccount.js index ce4adcec697b..385d8b3c6d2d 100644 --- a/services/static-webserver/client/source/class/osparc/auth/ui/RequestAccount.js +++ b/services/static-webserver/client/source/class/osparc/auth/ui/RequestAccount.js @@ -83,27 +83,12 @@ qx.Class.define("osparc.auth.ui.RequestAccount", { this._form.add(phone, this.tr("Phone Number"), null, "phone"); - const organization = new qx.ui.form.TextField(); - doubleSpaced.push(organization); - switch (osparc.product.Utils.getProductName()) { - case "s4l": - this._form.add(organization, this.tr("Company Name"), null, "company"); - organization.setRequired(true); - break; - case "s4lacad": - case "s4ldesktopacad": - this._form.add(organization, this.tr("University"), null, "university"); - organization.setRequired(true); - break; - case "tiplite": - this._form.add(organization, this.tr("University"), null, "university"); - break; - case "tis": - this._form.add(organization, this.tr("Organization"), null, "organization"); - break; - case "osparc": - this._form.add(organization, this.tr("Research Group/Organization"), null, "organization"); - break; + const institution = new qx.ui.form.TextField(); + doubleSpaced.push(institution); + const institutionAlias = osparc.product.Utils.getInstitutionAlias(); + this._form.add(institution, institutionAlias.label, null, institutionAlias.key); + if (institutionAlias.required) { + institution.setRequired(true); } diff --git a/services/static-webserver/client/source/class/osparc/conversation/AddMessage.js b/services/static-webserver/client/source/class/osparc/conversation/AddMessage.js index 41837171a7ac..0e9ee0e108d7 100644 --- a/services/static-webserver/client/source/class/osparc/conversation/AddMessage.js +++ b/services/static-webserver/client/source/class/osparc/conversation/AddMessage.js @@ -70,11 +70,9 @@ qx.Class.define("osparc.conversation.AddMessage", { } case "thumbnail": { control = osparc.utils.Utils.createThumbnail(32); - const authData = osparc.auth.Data.getInstance(); - const myUsername = authData.getUsername(); - const myEmail = authData.getEmail(); + const meGroup = osparc.store.Groups.getInstance().getGroupMe(); control.set({ - source: osparc.utils.Avatar.emailToThumbnail(myEmail, myUsername, 32), + source: meGroup.getThumbnail(), alignX: "center", alignY: "middle", marginRight: 8, diff --git a/services/static-webserver/client/source/class/osparc/data/model/User.js b/services/static-webserver/client/source/class/osparc/data/model/User.js index 6d571b98aba5..538fd41c3692 100644 --- a/services/static-webserver/client/source/class/osparc/data/model/User.js +++ b/services/static-webserver/client/source/class/osparc/data/model/User.js @@ -44,13 +44,6 @@ qx.Class.define("osparc.data.model.User", { } else if (userData["lastName"]) { lastName = userData["lastName"]; } - let description = [firstName, lastName].join(" ").trim(); // the null values will be replaced by empty strings - if (email) { - if (description) { - description += " - " - } - description += email; - } this.set({ userId, @@ -60,10 +53,32 @@ qx.Class.define("osparc.data.model.User", { lastName, email, phoneNumber: userData["phone"] || null, + }); + + let description = this.getFullName(); + if (email) { + if (description) { + description += " - " + } + description += email; + } + this.set({ label: userData["userName"] || description, description, }); + if (userData["contact"]) { + const contact = userData["contact"]; + this.set({ + institution: contact["institution"] || null, + address: contact["address"] || null, + city: contact["city"] || null, + state: contact["state"] || null, + country: contact["country"] || null, + postalCode: contact["postalCode"] || null, + }); + } + // create the thumbnail after setting email and username this.set({ thumbnail: this.createThumbnail(), @@ -140,11 +155,74 @@ qx.Class.define("osparc.data.model.User", { init: "", event: "changeThumbnail", }, + + institution: { + check: "String", + nullable: true, + init: null, + event: "changeInstitution", + }, + + address: { + check: "String", + nullable: true, + init: null, + event: "changeAddress", + }, + + city: { + check: "String", + nullable: true, + init: null, + event: "changeCity", + }, + + state: { + check: "String", + nullable: true, + init: null, + event: "changeState", + }, + + country: { + check: "String", + nullable: true, + init: null, + event: "changeCountry", + }, + + postalCode: { + check: "String", + nullable: true, + init: null, + event: "changePostalCode", + }, + }, + + statics: { + concatFullName: function(firstName, lastName) { + return [firstName, lastName].filter(Boolean).join(" "); + }, + + userDataToDescription: function(firstName, lastName, email) { + let description = this.concatFullName(firstName, lastName); + if (email) { + if (description) { + description += " - " + } + description += email; + } + return description; + }, }, members: { createThumbnail: function(size) { return osparc.utils.Avatar.emailToThumbnail(this.getEmail(), this.getUsername(), size); }, + + getFullName: function() { + return this.self().concatFullName(this.getFirstName(), this.getLastName()); + }, }, }); diff --git a/services/static-webserver/client/source/class/osparc/desktop/account/MyAccount.js b/services/static-webserver/client/source/class/osparc/desktop/account/MyAccount.js index a77f891f3287..619ad99a6d14 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/account/MyAccount.js +++ b/services/static-webserver/client/source/class/osparc/desktop/account/MyAccount.js @@ -46,16 +46,18 @@ qx.Class.define("osparc.desktop.account.MyAccount", { }, statics: { - createMiniProfileView: function(withSpacer = true) { + createMiniProfileView: function(userData) { const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(6)).set({ alignX: "center", minWidth: 120, maxWidth: 150 }); - const authData = osparc.auth.Data.getInstance(); - const username = authData.getUsername(); - const email = authData.getEmail(); + if (!userData) { + userData = osparc.auth.Data.getInstance(); + } + const username = userData.getUsername(); + const email = userData.getEmail(); const avatarSize = 80; const img = new qx.ui.basic.Image().set({ source: osparc.utils.Avatar.emailToThumbnail(email, username, avatarSize), @@ -73,7 +75,7 @@ qx.Class.define("osparc.desktop.account.MyAccount", { font: "text-14", alignX: "center" }); - authData.bind("username", usernameLabel, "value"); + userData.bind("username", usernameLabel, "value"); layout.add(usernameLabel); const fullNameLabel = new qx.ui.basic.Label().set({ @@ -81,15 +83,15 @@ qx.Class.define("osparc.desktop.account.MyAccount", { alignX: "center" }); layout.add(fullNameLabel); - authData.bind("firstName", fullNameLabel, "value", { - converter: () => authData.getFullName() + userData.bind("firstName", fullNameLabel, "value", { + converter: () => userData.getFullName() }); - authData.bind("lastName", fullNameLabel, "value", { - converter: () => authData.getFullName() + userData.bind("lastName", fullNameLabel, "value", { + converter: () => userData.getFullName() }); - if (authData.getRole() !== "user") { - const role = authData.getFriendlyRole(); + if (userData.getRole() !== "user") { + const role = userData.getFriendlyRole(); const roleLabel = new qx.ui.basic.Label(role).set({ font: "text-13", alignX: "center" @@ -97,9 +99,7 @@ qx.Class.define("osparc.desktop.account.MyAccount", { layout.add(roleLabel); } - if (withSpacer) { - layout.add(new qx.ui.core.Spacer(15, 15)); - } + layout.add(new qx.ui.core.Spacer(15, 15)); return layout; } diff --git a/services/static-webserver/client/source/class/osparc/desktop/account/ProfilePage.js b/services/static-webserver/client/source/class/osparc/desktop/account/ProfilePage.js index 8668cd1da889..e08e0f6241d0 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/account/ProfilePage.js +++ b/services/static-webserver/client/source/class/osparc/desktop/account/ProfilePage.js @@ -37,6 +37,7 @@ qx.Class.define("osparc.desktop.account.ProfilePage", { this._add(this.__create2FASection()); } this._add(this.__createPasswordSection()); + this._add(this.__createContactSection()); this._add(this.__createDeleteAccount()); this.__userProfileData = {}; @@ -55,29 +56,42 @@ qx.Class.define("osparc.desktop.account.ProfilePage", { PHONE: 4, }, }, + + createSectionBox: function(title) { + const box = osparc.ui.window.TabbedView.createSectionBox(title).set({ + alignX: "left", + maxWidth: 500 + }); + return box; + }, }, members: { __userProfileData: null, __userProfileModel: null, + __userProfileForm: null, __userProfileRenderer: null, - __privacyRenderer: null, __updateProfileBtn: null, __userPrivacyData: null, __userPrivacyModel: null, + __privacyRenderer: null, __updatePrivacyBtn: null, - __userProfileForm: null, __sms2FAItem: null, + __personalInfoModel: null, + __personalInfoRenderer: null, __fetchProfile: function() { this.__userProfileRenderer.setEnabled(false); this.__privacyRenderer.setEnabled(false); + this.__personalInfoRenderer.setEnabled(false); + osparc.data.Resources.getOne("profile", {}, null, false) .then(profile => { this.__setDataToProfile(profile); this.__setDataToPrivacy(profile["privacy"]); this.__userProfileRenderer.setEnabled(true); this.__privacyRenderer.setEnabled(true); + this.__personalInfoRenderer.setEnabled(true); }) .catch(err => console.error(err)); }, @@ -93,6 +107,17 @@ qx.Class.define("osparc.desktop.account.ProfilePage", { "phone": data["phone"] || "-", "expirationDate": data["expirationDate"] || null, }); + if (data["contact"]) { + const contact = data["contact"]; + this.__personalInfoModel.set({ + "institution": contact["institution"] || "", + "address": contact["address"] || "", + "city": contact["city"] || "", + "state": contact["state"] || "", + "country": contact["country"] || "", + "postalCode": contact["postalCode"] || "", + }); + } } this.__updateProfileBtn.setEnabled(false); @@ -137,13 +162,17 @@ qx.Class.define("osparc.desktop.account.ProfilePage", { this.__updatePrivacyBtn.setEnabled(false); }, + __resetUserData: function() { + this.__setDataToProfile(this.__userProfileData); + }, + + __resetPrivacyData: function() { + this.__setDataToPrivacy(this.__userPrivacyData); + }, + __createProfileUser: function() { // layout - const box = osparc.ui.window.TabbedView.createSectionBox(this.tr("User")); - box.set({ - alignX: "left", - maxWidth: 500 - }); + const box = this.self().createSectionBox(this.tr("User")); const username = new qx.ui.form.TextField().set({ placeholder: this.tr("username") @@ -307,13 +336,9 @@ qx.Class.define("osparc.desktop.account.ProfilePage", { const privacyModel = this.__userPrivacyModel = qx.data.marshal.Json.createModel(defaultModel, true); - const box = osparc.ui.window.TabbedView.createSectionBox(this.tr("Privacy")); - box.set({ - alignX: "left", - maxWidth: 500 - }); + const box = this.self().createSectionBox(this.tr("Privacy")); - const label = osparc.ui.window.TabbedView.createHelpLabel(this.tr("For Privacy reasons, you might want to hide some personal data.")); + const label = osparc.ui.window.TabbedView.createHelpLabel(this.tr("Choose what others see.")); box.add(label); const hideUsername = new qx.ui.form.CheckBox().set({ @@ -427,7 +452,7 @@ qx.Class.define("osparc.desktop.account.ProfilePage", { }, __create2FASection: function() { - const box = osparc.ui.window.TabbedView.createSectionBox(this.tr("Two-Factor Authentication")); + const box = this.self().createSectionBox(this.tr("Two-Factor Authentication")); const label = osparc.ui.window.TabbedView.createHelpLabel(this.tr("Set your preferred method to use for two-factor authentication when signing in:")); box.add(label); @@ -497,21 +522,9 @@ qx.Class.define("osparc.desktop.account.ProfilePage", { return box; }, - __resetUserData: function() { - this.__setDataToProfile(this.__userProfileData); - }, - - __resetPrivacyData: function() { - this.__setDataToPrivacy(this.__userPrivacyData); - }, - __createPasswordSection: function() { // layout - const box = osparc.ui.window.TabbedView.createSectionBox(this.tr("Password")); - box.set({ - alignX: "left", - maxWidth: 500 - }); + const box = this.self().createSectionBox(this.tr("Password")); const currentPassword = new osparc.ui.form.PasswordField().set({ required: true, @@ -577,13 +590,79 @@ qx.Class.define("osparc.desktop.account.ProfilePage", { return box; }, - __createDeleteAccount: function() { + __createContactSection: function() { // layout - const box = osparc.ui.window.TabbedView.createSectionBox(this.tr("Danger Zone")).set({ - alignX: "left", - maxWidth: 500 + const box = this.self().createSectionBox(this.tr("Contact")); + + const institution = new qx.ui.form.TextField().set({ + placeholder: osparc.product.Utils.getInstitutionAlias().label, + readOnly: true, + }); + + const address = new qx.ui.form.TextField().set({ + placeholder: this.tr("Address"), + readOnly: true, + }); + const city = new qx.ui.form.TextField().set({ + placeholder: this.tr("City"), + readOnly: true, + }); + + const state = new qx.ui.form.TextField().set({ + placeholder: this.tr("State"), + readOnly: true, + }); + + const country = new qx.ui.form.TextField().set({ + placeholder: this.tr("Country"), + readOnly: true, + }); + + const postalCode = new qx.ui.form.TextField().set({ + placeholder: this.tr("Postal Code"), + readOnly: true, }); + const personalInfoForm = new qx.ui.form.Form(); + personalInfoForm.add(institution, osparc.product.Utils.getInstitutionAlias().label, null, "institution"); + personalInfoForm.add(address, this.tr("Address"), null, "address"); + personalInfoForm.add(city, this.tr("City"), null, "city"); + personalInfoForm.add(state, this.tr("State"), null, "state"); + personalInfoForm.add(country, this.tr("Country"), null, "country"); + personalInfoForm.add(postalCode, this.tr("Postal Code"), null, "postalCode"); + this.__personalInfoRenderer = new qx.ui.form.renderer.Single(personalInfoForm); + box.add(this.__personalInfoRenderer); + + // binding to a model + const raw = { + "institution": null, + "address": null, + "city": null, + "state": null, + "country": null, + "postalCode": null, + }; + + const model = this.__personalInfoModel = qx.data.marshal.Json.createModel(raw); + const controller = new qx.data.controller.Object(model); + + controller.addTarget(institution, "value", "institution", true); + controller.addTarget(address, "value", "address", true); + controller.addTarget(city, "value", "city", true); + controller.addTarget(state, "value", "state", true); + controller.addTarget(country, "value", "country", true); + controller.addTarget(postalCode, "value", "postalCode", true); + + return box; + }, + + __createDeleteAccount: function() { + // layout + const box = this.self().createSectionBox(this.tr("Delete Account")); + + const label = osparc.ui.window.TabbedView.createHelpLabel(this.tr("Request the deletion of your account.")); + box.add(label); + const deleteBtn = new qx.ui.form.Button(this.tr("Delete Account")).set({ appearance: "danger-button", alignX: "right", diff --git a/services/static-webserver/client/source/class/osparc/product/Utils.js b/services/static-webserver/client/source/class/osparc/product/Utils.js index d6ca69d2456f..68bbedbe17e4 100644 --- a/services/static-webserver/client/source/class/osparc/product/Utils.js +++ b/services/static-webserver/client/source/class/osparc/product/Utils.js @@ -155,6 +155,39 @@ qx.Class.define("osparc.product.Utils", { return resourceType; }, + getInstitutionAlias: function() { + switch (osparc.product.Utils.getProductName()) { + case "s4l": + return { + label: qx.locale.Manager.tr("Company Name"), + key: "company", + required: true, + }; + case "s4lacad": + case "s4ldesktopacad": + return { + label: qx.locale.Manager.tr("University"), + key: "university", + required: true, + }; + case "tiplite": + return { + label: qx.locale.Manager.tr("University"), + key: "university", + }; + case "tis": + return { + label: qx.locale.Manager.tr("Organization"), + key: "organization", + }; + case "osparc": + return { + label: qx.locale.Manager.tr("Research Group/Organization"), + key: "organization", + }; + } + }, + getLogoPath: function(longLogo = true) { let logosPath = null; const colorManager = qx.theme.manager.Color.getInstance();