diff --git a/packages/postgres-database/src/simcore_postgres_database/models/products.py b/packages/postgres-database/src/simcore_postgres_database/models/products.py index 664627ac020..913c929e04c 100644 --- a/packages/postgres-database/src/simcore_postgres_database/models/products.py +++ b/packages/postgres-database/src/simcore_postgres_database/models/products.py @@ -32,12 +32,17 @@ class Vendor(TypedDict, total=False): """ name: str # e.g. IT'IS Foundation - copyright: str - url: str + address: str # e.g. Zeughausstrasse 43, 8004 Zurich, Switzerland + copyright: str # copyright message + + url: str # vendor website license_url: str # Which are the license terms? (if applies) + invitation_url: str # How to request a trial invitation? (if applies) - has_landing_page: bool # Landing page enabled - address: str # e.g. Zeughausstrasse 43, 8004 Zurich, Switzerland + invitation_form: bool # If True, it takes precendence over invitation_url and asks the FE to show the form (if defined) + + has_landing_page: bool # Is Landing page enabled + release_notes_url_template: str # a template url where `{vtag}` will be replaced, eg: "http://example.com/{vtag}.md" diff --git a/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py b/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py index 79da716b515..250db1c86b2 100644 --- a/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py +++ b/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py @@ -234,6 +234,7 @@ def random_product( url=fake.url(), license_url=fake.url(), invitation_url=fake.url(), + invitation_form=fake.boolean(), has_landing_page=fake.boolean(), address=fake.address().replace("\n", ". "), ), diff --git a/services/static-webserver/client/source/class/osparc/Application.js b/services/static-webserver/client/source/class/osparc/Application.js index c611d3cd09a..68d6cb37436 100644 --- a/services/static-webserver/client/source/class/osparc/Application.js +++ b/services/static-webserver/client/source/class/osparc/Application.js @@ -518,20 +518,16 @@ qx.Class.define("osparc.Application", { case "s4ldesktop": case "s4ldesktopacad": view = new osparc.auth.LoginPageS4L(); - this.__loadView(view); break; case "tis": view = new osparc.auth.LoginPageTI(); - this.__loadView(view); break; default: { view = new osparc.auth.LoginPageOsparc(); - this.__loadView(view, { - top: "15%" - }); break; } } + this.__loadView(view); view.addListener("done", () => this.__restart(), this); }, diff --git a/services/static-webserver/client/source/class/osparc/auth/LoginPage.js b/services/static-webserver/client/source/class/osparc/auth/LoginPage.js index f177f56c011..a972fce24d6 100644 --- a/services/static-webserver/client/source/class/osparc/auth/LoginPage.js +++ b/services/static-webserver/client/source/class/osparc/auth/LoginPage.js @@ -210,9 +210,8 @@ qx.Class.define("osparc.auth.LoginPage", { const login = this.getChildControl("login-view"); const registration = this.getChildControl("registration-view"); - const config = osparc.store.Store.getInstance().get("config"); let requestAccount = null; - if (config["invitation_required"] && osparc.desktop.credits.Utils.areWalletsEnabled()) { + if (osparc.product.Utils.getCreateAccountAction() === "REQUEST_ACCOUNT_FORM") { requestAccount = this.getChildControl("request-account"); } const verifyPhoneNumber = this.getChildControl("verify-phone-number-view"); diff --git a/services/static-webserver/client/source/class/osparc/auth/ui/LoginView.js b/services/static-webserver/client/source/class/osparc/auth/ui/LoginView.js index 2d14e799beb..1c18a4a3aed 100644 --- a/services/static-webserver/client/source/class/osparc/auth/ui/LoginView.js +++ b/services/static-webserver/client/source/class/osparc/auth/ui/LoginView.js @@ -89,20 +89,18 @@ qx.Class.define("osparc.auth.ui.LoginView", { const grp = new qx.ui.container.Composite(new qx.ui.layout.HBox(20)); const createAccountBtn = new osparc.ui.form.LinkButton(this.tr("Create Account")); - const config = osparc.store.Store.getInstance().get("config"); - if (config["invitation_required"]) { + const createAccountAction = osparc.product.Utils.getCreateAccountAction(); + if (["REQUEST_ACCOUNT_FORM", "REQUEST_ACCOUNT_INSTRUCTIONS"].includes(createAccountAction)) { createAccountBtn.setLabel(this.tr("Request Account")); } createAccountBtn.addListener("execute", () => { createAccountBtn.setEnabled(false); - if (config["invitation_required"]) { - if (osparc.desktop.credits.Utils.areWalletsEnabled()) { - this.fireEvent("toRequestAccount"); - } else { - osparc.store.Support.openInvitationRequiredDialog(); - } - } else { + if (createAccountAction === "REGISTER") { this.fireEvent("toRegister"); + } else if (createAccountAction === "REQUEST_ACCOUNT_FORM") { + this.fireEvent("toRequestAccount"); + } else if (createAccountAction === "REQUEST_ACCOUNT_FORM") { + osparc.store.Support.openInvitationRequiredDialog(); } createAccountBtn.setEnabled(true); }, this); 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 13b022b26d1..5f2daa8c5ff 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 @@ -59,6 +59,7 @@ qx.Class.define("osparc.auth.ui.RequestAccount", { switch (osparc.product.Utils.getProductName()) { case "s4l": case "tis": + case "osparc": this._form.add(email, this.tr("Email"), qx.util.Validate.email(), "email"); break; case "s4lacad": @@ -84,6 +85,9 @@ qx.Class.define("osparc.auth.ui.RequestAccount", { 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; } @@ -127,84 +131,156 @@ qx.Class.define("osparc.auth.ui.RequestAccount", { this._form.add(country, this.tr("Country"), null, "country"); - if ( - osparc.product.Utils.isProduct("s4l") || - osparc.product.Utils.isProduct("s4lacad") || - osparc.product.Utils.isProduct("s4ldesktopacad") - ) { - const application = new qx.ui.form.SelectBox(); - [{ - id: "Antenna_Design_for_Wireless_Communication", - label: "Antenna Design for Wireless Communication" - }, { - id: "Bioelectronics,_Electroceuticals_and_Neuroprosthetics", - label: "Bioelectronics, Electroceuticals & Neuroprosthetics" - }, { - id: "Safety_and_Efficacy_Assessment", - label: "Safety & Efficacy Assessment" - }, { - id: "Exposure_and_Compliance", - label: "Exposure & Compliance" - }, { - id: "Focused_Ultrasound", - label: "Focused Ultrasound" - }, { - id: "In_Silico_Trials", - label: "In Silico Trials" - }, { - id: "Implant_Design", - label: "Implant Design" - }, { - id: "Magnetic_Resonance_Imaging", - label: "Magnetic Resonance Imaging" - }, { - id: "Neurostimulation", - label: "Neurostimulation" - }, { - id: "Personalized_Medicine", - label: "Personalized Medicine" - }, { - id: "Thermal_Therapies", - label: "Thermal Therapies" - }, { - id: "Wireless_Power_Transfer_Systems", - label: "Wireless Power Transfer Systems" - }, { - id: "Vascular_Flow_and_Perfusion", - label: "Vascular Flow & Perfusion" - }].forEach(appData => { - const lItem = new qx.ui.form.ListItem(appData.label, null, appData.id).set({ - rich: true + switch (osparc.product.Utils.getProductName()) { + case "s4l": + case "s4lacad": + case "s4ldesktopacad": { + const application = new qx.ui.form.SelectBox(); + [{ + id: "Antenna_Design_for_Wireless_Communication", + label: "Antenna Design for Wireless Communication" + }, { + id: "Bioelectronics,_Electroceuticals_and_Neuroprosthetics", + label: "Bioelectronics, Electroceuticals & Neuroprosthetics" + }, { + id: "Safety_and_Efficacy_Assessment", + label: "Safety & Efficacy Assessment" + }, { + id: "Exposure_and_Compliance", + label: "Exposure & Compliance" + }, { + id: "Focused_Ultrasound", + label: "Focused Ultrasound" + }, { + id: "In_Silico_Trials", + label: "In Silico Trials" + }, { + id: "Implant_Design", + label: "Implant Design" + }, { + id: "Magnetic_Resonance_Imaging", + label: "Magnetic Resonance Imaging" + }, { + id: "Neurostimulation", + label: "Neurostimulation" + }, { + id: "Personalized_Medicine", + label: "Personalized Medicine" + }, { + id: "Thermal_Therapies", + label: "Thermal Therapies" + }, { + id: "Wireless_Power_Transfer_Systems", + label: "Wireless Power Transfer Systems" + }, { + id: "Vascular_Flow_and_Perfusion", + label: "Vascular Flow & Perfusion" + }].forEach(appData => { + const lItem = new qx.ui.form.ListItem(appData.label, null, appData.id).set({ + rich: true + }); + application.add(lItem); }); - application.add(lItem); - }); - doubleSpaced.push(application); - this._form.add(application, this.tr("Application"), null, "application"); - + doubleSpaced.push(application); + this._form.add(application, this.tr("Application"), null, "application"); - const description = new qx.ui.form.TextField(); - doubleSpaced.push(description); - this._form.add(description, this.tr("Description"), null, "description"); + const description = new qx.ui.form.TextField(); + doubleSpaced.push(description); + this._form.add(description, this.tr("Description"), null, "description"); + break; + } + case "osparc": { + const application = new qx.ui.form.SelectBox(); + [{ + id: "other", + label: "Other" + }, { + id: "Reuse_Existing_Services_And_Models", + label: "Reuse Existing Services And Models" + }, { + id: "Data_Analysis", + label: "Data Analysis" + }, { + id: "Personalized_Medicine", + label: "Personalized Medicine" + }, { + id: "Neurostimulation", + label: "Neurostimulation" + }, { + id: "Safety_And_Efficacy_Assessment", + label: "Safety & Efficacy Assessment" + }, { + id: "Device_Design_And_Optimization", + label: "Device Design & Optimization" + }, { + id: "Magnetic_Resonance_Imaging", + label: "Magnetic Resonance Imaging" + }, { + id: "Bioelectromagnetics", + label: "Bioelectromagnetics" + }, { + id: "In_Silico_Trials", + label: "In Silico Trials" + }, { + id: "Image_based_Modeling", + label: "Image-based Modeling" + }].forEach(appData => { + const lItem = new qx.ui.form.ListItem(appData.label, null, appData.id).set({ + rich: true + }); + application.add(lItem); + }); + doubleSpaced.push(application); + this._form.add(application, this.tr("Application"), null, "application"); + break; + } } const hear = new qx.ui.form.SelectBox(); - [{ - id: "Search_Engine", - label: "Search Engine" - }, { - id: "Conference", - label: "Conference" - }, { - id: "Publication", - label: "Publication" - }, { - id: "Social_Media", - label: "Social Media" - }, { - id: "Other", - label: "Other" - }].forEach(hearData => { + let hearOptions = []; + switch (osparc.product.Utils.getProductName()) { + case "osparc": + hearOptions = [{ + id: "Other", + label: "Other" + }, { + id: "SPARC_Portal_Or_Event", + label: "SPARC Portal Or Event" + }, { + id: "Search_Engine", + label: "Search Engine" + }, { + id: "Conference", + label: "Conference" + }, { + id: "Publication", + label: "Publication" + }, { + id: "Social_Media", + label: "Social Media" + }]; + break; + default: + hearOptions = [{ + id: "Search_Engine", + label: "Search Engine" + }, { + id: "Conference", + label: "Conference" + }, { + id: "Publication", + label: "Publication" + }, { + id: "Social_Media", + label: "Social Media" + }, { + id: "Other", + label: "Other" + }]; + break; + } + hearOptions.forEach(hearData => { const lItem = new qx.ui.form.ListItem(hearData.label, null, hearData.id); hear.add(lItem); }); @@ -214,11 +290,17 @@ qx.Class.define("osparc.auth.ui.RequestAccount", { // accept links // Privacy Policy link - let ppLink = osparc.CookiePolicy.getS4LPrivacyPolicyLink("our privacy policy"); - if (osparc.product.Utils.isProduct("tis")) { - ppLink = osparc.CookiePolicy.getITISPrivacyPolicyLink("our privacy policy"); + let ppLink = ""; + switch (osparc.product.Utils.getProductName()) { + case "osparc": + case "tis": + ppLink = osparc.CookiePolicy.getITISPrivacyPolicyLink("our privacy policy"); + break; + default: + ppLink = osparc.CookiePolicy.getS4LPrivacyPolicyLink("our privacy policy"); + break; } - const ppText = this.tr("I acknowledge that data will be processed in accordance with ") + ppLink; + const ppText = this.tr("I acknowledge that data will be processed in accordance to ") + ppLink; const privacyPolicy = new qx.ui.form.CheckBox().set({ required: true, value: false @@ -227,14 +309,17 @@ qx.Class.define("osparc.auth.ui.RequestAccount", { this._form.add(privacyPolicy, ppText, null, "privacyPolicy") // Eula link - const eulaLink = osparc.CookiePolicy.getZMTEULALink("end users license agreement (EULA)"); - const eulaText = "I accept the " + eulaLink + " and I will use the product in accordance with it"; - const eula = new qx.ui.form.CheckBox().set({ - required: true, - value: false - }); - doubleSpaced.push(eula); - this._form.add(eula, eulaText, null, "eula"); + if (osparc.product.Utils.getProductName() !== "osparc") { + const eulaLink = osparc.CookiePolicy.getZMTEULALink("end users license agreement (EULA)"); + const eulaText = "I accept the " + eulaLink + " and I will use the product in accordance with it"; + const eula = new qx.ui.form.CheckBox().set({ + required: true, + value: false + }); + doubleSpaced.push(eula); + this._form.add(eula, eulaText, null, "eula"); + } + const content = new qx.ui.container.Composite(new qx.ui.layout.VBox(10)); const formRenderer = new osparc.ui.form.renderer.DoubleV(this._form, doubleSpaced); 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 c214337a3e2..e136eeb01dc 100644 --- a/services/static-webserver/client/source/class/osparc/product/Utils.js +++ b/services/static-webserver/client/source/class/osparc/product/Utils.js @@ -194,6 +194,28 @@ qx.Class.define("osparc.product.Utils", { return false; }, + /** + * @returns {String} ["REGISTER", "REQUEST_ACCOUNT_FORM", "REQUEST_ACCOUNT_INSTRUCTIONS"] + */ + getCreateAccountAction: function() { + if (osparc.utils.Utils.isDevelopmentPlatform()) { + // Allow registering in Development Platform + return "REGISTER"; + } + + const config = osparc.store.Store.getInstance().get("config"); + if (config["invitation_required"]) { + const vendor = osparc.store.VendorInfo.getInstance().getVendor(); + if (vendor["invitation_form"]) { + // If invitation_required (login_settings) and invitation_form (vendor) + return "REQUEST_ACCOUNT_FORM"; + } + // do not show request account form, pop up a dialog with instructions instead + return "REQUEST_ACCOUNT_INSTRUCTIONS"; + } + return "REGISTER"; + }, + // All products except oSPARC hasIdlingTrackerEnabled: function() { const product = this.getProductName(); diff --git a/services/web/server/src/simcore_service_webserver/products/_model.py b/services/web/server/src/simcore_service_webserver/products/_model.py index d9a93f3e286..de3955652a3 100644 --- a/services/web/server/src/simcore_service_webserver/products/_model.py +++ b/services/web/server/src/simcore_service_webserver/products/_model.py @@ -180,6 +180,7 @@ class Config: "vendor": { "url": "https://acme.com", "license_url": "https://acme.com/license", + "invitation_form": True, "name": "ACME", "copyright": "© ACME correcaminos", "has_landing_page": False, diff --git a/services/web/server/tests/unit/isolated/test_products_model.py b/services/web/server/tests/unit/isolated/test_products_model.py index 3444d1fef26..b3ee823a37e 100644 --- a/services/web/server/tests/unit/isolated/test_products_model.py +++ b/services/web/server/tests/unit/isolated/test_products_model.py @@ -51,6 +51,7 @@ def test_product_to_static(): "url": "https://acme.com", "license_url": "https://acme.com/license", "has_landing_page": False, + "invitation_form": True, }, "issues": [ {