Skip to content

Commit 3d866c0

Browse files
author
Andrei Neagu
committed
Merge remote-tracking branch 'upstream/master' into pr-osparc-expose-list-service-for-ops
2 parents e859ad0 + 3a4bf81 commit 3d866c0

File tree

19 files changed

+223
-62
lines changed

19 files changed

+223
-62
lines changed

packages/notifications-library/src/notifications_library/_models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,17 @@ class UserData:
1313
email: str
1414

1515

16+
@dataclass(frozen=True)
17+
class ProductUIData:
18+
logo_url: str
19+
strong_color: str
20+
21+
1622
@dataclass(frozen=True)
1723
class ProductData:
1824
product_name: ProductName
1925
display_name: str
2026
vendor_display_inline: str
2127
support_email: str
28+
homepage_url: str
29+
ui: ProductUIData
Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,110 @@
1+
{% set default_strong_color = "rgb(131, 0, 191)" %}
2+
{% set default_logo = "https://raw.githubusercontent.com/ITISFoundation/osparc-simcore/refs/heads/master/services/static-webserver/client/source/resource/osparc/osparc-black.svg" %}
3+
{% set default_homepage = "https://osparc.io/" %}
4+
15
<!DOCTYPE html>
26
<html lang="en">
37
<head>
48
<meta charset="UTF-8">
59
<meta name="viewport" content="width=device-width, initial-scale=1.0">
610
<title>{% block title %}{% endblock %}</title>
711
<style>
8-
body {
9-
font-family: Arial, sans-serif;
10-
margin: 0;
11-
padding: 20px;
12-
color: #333;
13-
}
14-
.container {
15-
background-color: #f9f9f9;
16-
padding: 20px;
17-
border-radius: 5px;
18-
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
19-
}
20-
a {
21-
color: #007bff;
22-
text-decoration: none;
23-
}
12+
body {
13+
font-family: Manrope, sans-serif;
14+
margin: 0;
15+
padding: 0;
16+
background-color: #f4f4f4;
17+
}
18+
.email-container {
19+
max-width: 600px;
20+
margin: 20px auto;
21+
background-color: #ffffff;
22+
padding: 20px;
23+
border-radius: 8px;
24+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
25+
}
26+
.header {
27+
display: flex;
28+
align-items: center;
29+
border-bottom: 2px solid #ddd;
30+
padding-bottom: 10px;
31+
margin-bottom: 20px;
32+
}
33+
.logo {
34+
height: 40px;
35+
}
36+
.content {
37+
color: #333;
38+
font-size: 16px;
39+
line-height: 1.5;
40+
}
41+
a {
42+
color: #007bff;
43+
text-decoration: none;
44+
}
45+
.strong-button {
46+
cursor: pointer;
47+
background-color: {{ product.ui.strong_color | default(default_strong_color) }};
48+
color: white;
49+
padding: 10px;
50+
border: none;
51+
border-radius: 4px;
52+
overflow: hidden;
53+
white-space: nowrap;
54+
user-select: none;
55+
touch-action: none;
56+
outline: none;
57+
}
58+
.strong-button a {
59+
font-size: 16px;
60+
color: white;
61+
text-decoration: none;
62+
display: block;
63+
width: 100%;
64+
height: 100%;
65+
text-align: center;
66+
}
67+
.footer {
68+
margin-top: 20px;
69+
padding-top: 15px;
70+
border-top: 2px solid #ddd;
71+
font-size: 14px;
72+
text-align: center;
73+
color: #666;
74+
}
75+
.footer a {
76+
color: #007bff;
77+
text-decoration: none;
78+
}
79+
.github-logo {
80+
height: 20px;
81+
vertical-align: bottom;
82+
}
2483
</style>
2584
</head>
2685
<body>
27-
<div class="container">
28-
{% block content %}
29-
{% endblock %}
86+
<div class="email-container">
87+
<div class="header">
88+
<a href="{{ product.homepage_url | default(default_homepage) }}" target="_blank" rel="noopener noreferrer">
89+
<img src="{{ product.ui.logo_url | default(default_logo) }}" alt="Logo" class="logo">
90+
</a>
91+
</div>
92+
93+
<div class="content">
94+
{% block content %}
95+
{% endblock %}
96+
</div>
97+
98+
<div class="footer">
99+
<p>
100+
Visit the <a href="{{ product.homepage_url | default(default_homepage) }}" target="_blank" rel="noopener noreferrer">Platform</a> |
101+
Need help? <a href="mailto:{{ product.support_email }}">Support</a> |
102+
Powered by oSPARC
103+
<a href="https://github.com/ITISFoundation/osparc-simcore" target="_blank" rel="noopener noreferrer">
104+
<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" alt="GitHub" class="github-logo">
105+
</a>
106+
</p>
107+
</div>
30108
</div>
31109
</body>
32110
</html>

packages/notifications-library/src/notifications_library/templates/on_change_email.email.content.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
</p>
99

1010
<p>
11-
<a href="{{ link }}">{{ link }}</a>
11+
<!-- Many email clients strip or ignore certain CSS properties, including them inline -->
12+
<button class="strong-button" style="border-radius: 4px;">
13+
<a href="{{ link }}" style="color: white;">Change email</a>
14+
</button>
1215
</p>
1316

1417
<p>Please don't hesitate to contact us at {{ product.support_email }} if you need further help.

packages/notifications-library/src/notifications_library/templates/on_new_invitation.email.content.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
{% block content %}
44
<p>Dear {{ user.first_name }},</p>
55
<p>Thank you for your interest in {{ product.display_name }}. We are pleased to provide you with a one-time invitation link to register on the platform.</p>
6-
<p>Click <a href="{{ link }}">here</a> to access the registration page.</p>
6+
<p>
7+
<!-- Many email clients strip or ignore certain CSS properties, including them inline -->
8+
<button class="strong-button" style="border-radius: 4px;">
9+
<a href="{{ link }}" style="color: white;">Register</a>
10+
</button>
11+
</p>
712
<p>Please follow the on-screen information and proceed with your registration.</p>
813
<p>If any problem should occur, please feel free to contact us at {{ product.support_email }}.</p>
914
<p>Enjoy {{ product.display_name }}!</p>

packages/notifications-library/src/notifications_library/templates/on_registered.email.content.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
<p>Dear {{ user.first_name }},</p>
55
<p>Thank you for your interest in {{ product.display_name }}. You have successfully registered for {{ host }}.</p>
66
<p>Please activate your account via the link below:</p>
7-
<p><a href="{{ link }}">{{ link }}</a></p>
7+
<p>
8+
<button class="strong-button" style="border-radius: 4px;">
9+
<a href="{{ link }}" style="color: white;">Activate</a>
10+
</button>
11+
</p>
812
<p>Please don't hesitate to contact us at {{ product.support_email }} if you need further help.</p>
913
<p>Best Regards,</p>
1014
<p>The <i>{{ product.display_name }}</i> Team</p>

packages/notifications-library/src/notifications_library/templates/on_reset_password.email.content.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
{% if success %}
88

99
<p>To complete the process, please click the link below:</p>
10-
<p><a href="{{ link }}">{{ link }}</a></p>
10+
<p>
11+
<button class="strong-button" style="border-radius: 4px;">
12+
<a href="{{ link }}" style="color: white;">Reset Password</a>
13+
</button>
14+
</p>
1115

1216
{% else %}
1317

@@ -16,7 +20,7 @@
1620

1721
{% endif %}
1822

19-
<p>If you did not request this, please contact us immediatly at {{ product.support_email }} for security reasons.</p>
23+
<p>If you did not request this, please contact us immediately at {{ product.support_email }} for security reasons.</p>
2024

2125
<p>Best Regards,</p>
2226
<p>The <i>{{ product.display_name }}</i> Team</p>

packages/notifications-library/tests/conftest.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import notifications_library
1111
import pytest
1212
from models_library.products import ProductName
13-
from notifications_library._models import ProductData, UserData
13+
from notifications_library._models import ProductData, ProductUIData, UserData
1414
from notifications_library.payments import PaymentData
1515
from pydantic import EmailStr
1616
from pytest_simcore.helpers.typing_env import EnvVarsDict
@@ -44,7 +44,7 @@ def external_envfile_dict(external_envfile_dict: EnvVarsDict) -> EnvVarsDict:
4444

4545

4646
#
47-
# mock data for templaes
47+
# mock data for templates
4848
#
4949

5050

@@ -55,11 +55,21 @@ def product_data(
5555
) -> ProductData:
5656
vendor: Vendor = product["vendor"]
5757

58+
product_ui = ProductUIData(
59+
logo_url=vendor.get("ui", {}).get(
60+
"logo_url",
61+
"https://raw.githubusercontent.com/ITISFoundation/osparc-simcore/refs/heads/master/services/static-webserver/client/source/resource/osparc/osparc-white.svg",
62+
),
63+
strong_color=vendor.get("ui", {}).get("strong_color", "rgb(131, 0, 191)"),
64+
)
65+
5866
return ProductData( # type: ignore
5967
product_name=product_name,
6068
display_name=product["display_name"],
6169
vendor_display_inline=f"{vendor.get('name','')}, {vendor.get('address','')}",
6270
support_email=product["support_email"],
71+
homepage_url=vendor.get("url", "https://osparc.io/"),
72+
ui=product_ui,
6373
)
6474

6575

packages/notifications-library/tests/test__render.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
from pathlib import Path
33

44
from models_library.products import ProductName
5+
from notifications_library._models import ProductData
56
from notifications_library._render import (
67
create_render_env_from_folder,
78
create_render_env_from_package,
89
)
910
from notifications_library._templates import _print_tree, _templates_dir
1011

1112

12-
def test_render_env_from_folder(tmp_path: Path, product_name: ProductName):
13+
def test_render_env_from_folder(
14+
tmp_path: Path, product_name: ProductName, product_data: ProductData
15+
):
1316

1417
pkg_env = create_render_env_from_package()
1518

@@ -27,4 +30,5 @@ def test_render_env_from_folder(tmp_path: Path, product_name: ProductName):
2730
product_template = consolidated_env.get_template(f"{product_name}/base.html")
2831
common_template = pkg_env.get_template("base.html")
2932

30-
assert product_template.render() == common_template.render()
33+
data = {"product": product_data}
34+
assert product_template.render(data) == common_template.render(data)

packages/postgres-database/src/simcore_postgres_database/models/products.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
""" Products table
1+
"""Products table
22
3-
- List of products served by the simcore platform
4-
- Products have a name and an associated host (defined by a regex)
5-
- Every product has a front-end with exactly the same name
3+
- List of products served by the simcore platform
4+
- Products have a name and an associated host (defined by a regex)
5+
- Every product has a front-end with exactly the same name
66
"""
77

88
import json
@@ -29,6 +29,11 @@
2929
#
3030

3131

32+
class VendorUI(TypedDict, total=True):
33+
logo_url: str # vendor logo url
34+
strong_color: str # vendor main color
35+
36+
3237
class Vendor(TypedDict, total=False):
3338
"""
3439
Brand information about the vendor
@@ -47,6 +52,8 @@ class Vendor(TypedDict, total=False):
4752

4853
release_notes_url_template: str # a template url where `{vtag}` will be replaced, eg: "http://example.com/{vtag}.md"
4954

55+
ui: VendorUI
56+
5057

5158
class IssueTracker(TypedDict, total=True):
5259
"""Link to actions in an online issue tracker (e.g. in fogbugz, github, gitlab ...)

packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
"""
2-
Collection of functions that create fake raw data that can be used
3-
to populate postgres DATABASE, create datasets with consistent values, etc
2+
Collection of functions that create fake raw data that can be used
3+
to populate postgres DATABASE, create datasets with consistent values, etc
44
5-
Built on top of the idea of Faker library (https://faker.readthedocs.io/en/master/),
6-
that generate fake data to bootstrap a database, fill-in stress tests, anonymize data ...
7-
etc
5+
Built on top of the idea of Faker library (https://faker.readthedocs.io/en/master/),
6+
that generate fake data to bootstrap a database, fill-in stress tests, anonymize data ...
7+
etc
88
9-
NOTE: all outputs MUST be Dict-like or built-in data structures that fit at least
10-
required fields in postgres_database.models tables or pydantic models.
9+
NOTE: all outputs MUST be Dict-like or built-in data structures that fit at least
10+
required fields in postgres_database.models tables or pydantic models.
1111
12-
NOTE: to reduce coupling, please import simcore_postgres_database inside of the functions
12+
NOTE: to reduce coupling, please import simcore_postgres_database inside of the functions
1313
"""
1414

1515
import itertools
@@ -232,7 +232,7 @@ def random_product(
232232
- group_id: product group ID. SEE get_or_create_product_group to produce `group_id`
233233
- registration_email_template
234234
"""
235-
from simcore_postgres_database.models.products import Vendor, products
235+
from simcore_postgres_database.models.products import Vendor, VendorUI, products
236236

237237
name = overrides.get("name")
238238
suffix = fake.unique.word() if name is None else name
@@ -257,6 +257,10 @@ def random_product(
257257
invitation_url=fake.url(),
258258
invitation_form=fake.boolean(),
259259
address=fake.address().replace("\n", ". "),
260+
ui=VendorUI(
261+
logo_url=fake.url(),
262+
strong_color=fake.color(),
263+
),
260264
),
261265
"registration_email_template": registration_email_template,
262266
"created": fake.date_time_this_decade(),

services/static-webserver/client/source/class/osparc/auth/LoginWithDecorators.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ qx.Class.define("osparc.auth.LoginWithDecorators", {
219219
if (urlFragment.nav && urlFragment.nav.length) {
220220
if (urlFragment.nav[0] === "registration") {
221221
pages.setSelection([registration]);
222-
} else if (urlFragment.nav[0] === "request-account" && requestAccount) {
223-
pages.setSelection([requestAccount]);
222+
} else if (urlFragment.nav[0] === "request-account") {
223+
requestAccount ? pages.setSelection([requestAccount]) : pages.setSelection([registration]);
224224
} else if (urlFragment.nav[0] === "reset-password") {
225225
pages.setSelection([resetPassword]);
226226
}

services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,16 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
500500
return taskCard;
501501
},
502502

503+
_removeTaskCard: function(task) {
504+
if (task) {
505+
const taskPlaceholders = this._resourcesContainer.getCards().filter(card => osparc.dashboard.ResourceBrowserBase.isCardTaskPlaceholder(card));
506+
const taskCard = taskPlaceholders.find(taskPlaceholder => taskPlaceholder.getTask() === task);
507+
if (taskCard) {
508+
this._resourcesContainer.removeNonResourceCard(taskCard);
509+
}
510+
}
511+
},
512+
503513
_populateCardMenu: function(card) {
504514
throw new Error("Abstract method called!");
505515
},

0 commit comments

Comments
 (0)