Compare commits
145 Commits
feature/ad
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
488dc9a3f3 | ||
|
|
1a65ba6150 | ||
|
|
9474238dee | ||
|
|
60e663316b | ||
|
|
770d05c72c | ||
|
|
ea75d8e832 | ||
|
|
145dda8c19 | ||
|
|
149a79cb2c | ||
|
|
69f77020b8 | ||
|
|
5ac481a4b4 | ||
|
|
56470eec01 | ||
|
|
9b4903b230 | ||
|
|
74c3946609 | ||
|
|
feabed6565 | ||
|
|
af13a3cc47 | ||
|
|
466e3e79b7 | ||
|
|
3f1ce7565b | ||
|
|
265ca4db8f | ||
|
|
5015c4aa43 | ||
|
|
465720c5b1 | ||
|
|
2a8e7ae72b | ||
|
|
449e345ee5 | ||
|
|
51798ecc43 | ||
|
|
1e15ef5fce | ||
|
|
0f41aa24d8 | ||
|
|
15516cdaa5 | ||
|
|
948e415dbd | ||
|
|
a3fcf7d1d4 | ||
|
|
65de73f1fe | ||
|
|
989fe7b5b6 | ||
|
|
4bc929e1ce | ||
|
|
5817b24c48 | ||
|
|
550526efc9 | ||
|
|
2a2e36ade2 | ||
|
|
22f7d6f36a | ||
|
|
2d42099017 | ||
|
|
2ff47c486a | ||
|
|
338ee0b278 | ||
|
|
64c6548a48 | ||
|
|
8c824149cc | ||
|
|
607863cfc4 | ||
|
|
13c5d44544 | ||
|
|
6407eb90db | ||
|
|
a8c6b1a70c | ||
|
|
67c94bb045 | ||
|
|
f4c1173a34 | ||
|
|
e39b0082b1 | ||
|
|
9eb187a951 | ||
|
|
b928e74a74 | ||
|
|
75c0f504d0 | ||
|
|
7c0310a141 | ||
|
|
5e2e645787 | ||
|
|
9b31894e85 | ||
|
|
a4472e1a44 | ||
|
|
b99cae84de | ||
|
|
1cac19e4c9 | ||
|
|
d4883765b2 | ||
|
|
041f26274b | ||
|
|
82db30ffd9 | ||
|
|
b8684329b4 | ||
|
|
7e26b5f994 | ||
|
|
4bdcb46a8a | ||
|
|
ed6f413c18 | ||
|
|
f63549ee87 | ||
|
|
bd71ab1449 | ||
|
|
220bf9994b | ||
|
|
33d28e5890 | ||
|
|
f0f0fa15c9 | ||
|
|
30a9a6816f | ||
|
|
970b8fa7f1 | ||
|
|
629d725ff5 | ||
|
|
6998e66b22 | ||
|
|
c668c4c56a | ||
|
|
a13fbd87a6 | ||
|
|
7ffcd76cea | ||
|
|
bda0f52320 | ||
|
|
5efc2a671e | ||
|
|
1578654816 | ||
|
|
e8ab33e12f | ||
|
|
712b0dc502 | ||
|
|
e56c0f9029 | ||
|
|
794b48a50b | ||
|
|
393b30cf5c | ||
|
|
97198a1da4 | ||
|
|
3ba1195fbe | ||
|
|
121f3eddb5 | ||
|
|
38ad81b0e2 | ||
|
|
ec94c64dbc | ||
|
|
28a9a33aa1 | ||
|
|
97eeb85032 | ||
|
|
ceef9f024c | ||
|
|
40c8b9cc36 | ||
|
|
95a8ac1387 | ||
|
|
4c6e26e66b | ||
|
|
ad2b351a99 | ||
|
|
3bda1f9863 | ||
|
|
f46d95db66 | ||
|
|
ddfdd2fd55 | ||
|
|
17d586e384 | ||
|
|
dbec07d149 | ||
|
|
ebf142b505 | ||
|
|
0539d0ab88 | ||
|
|
2736bff76b | ||
|
|
192601f387 | ||
|
|
bc9cfeabab | ||
|
|
b770086071 | ||
|
|
b2c1fdd23b | ||
|
|
906978556e | ||
|
|
274c8e4658 | ||
|
|
257a44dac2 | ||
|
|
f393a3980b | ||
|
|
badff7eed8 | ||
|
|
384e07c2a9 | ||
|
|
89724a9712 | ||
|
|
94f4325f40 | ||
|
|
af1285b650 | ||
|
|
52eba53d8e | ||
|
|
94f240687a | ||
|
|
1b2bdfa881 | ||
|
|
271f450c86 | ||
|
|
6186e8b635 | ||
|
|
dfc6c392c3 | ||
|
|
0ec9a2ae02 | ||
|
|
09fcf64818 | ||
|
|
c25db5c3ae | ||
|
|
c85fff7581 | ||
|
|
039f4b8210 | ||
|
|
7be7ee67c2 | ||
|
|
6f5fc14dbc | ||
|
|
65edd3a52b | ||
|
|
ab7149403a | ||
|
|
5b2f3db867 | ||
|
|
e12941eab0 | ||
|
|
eda3f4826c | ||
|
|
61161eb472 | ||
|
|
325826c19b | ||
|
|
587839f852 | ||
|
|
7411f4a9e1 | ||
|
|
d63ae4768a | ||
|
|
92a8da724f | ||
|
|
ea3a081b6c | ||
|
|
0647ba2601 | ||
|
|
2769036f94 | ||
|
|
c76befad1c | ||
|
|
74ecfb8653 |
6
.github/workflows/main.yaml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
pip install flake8 flake8-print
|
||||
- name: Linting
|
||||
run: |
|
||||
python -m flake8 snikket_web
|
||||
make flake8
|
||||
|
||||
translation-check:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -66,10 +66,10 @@ jobs:
|
||||
pip install flask-babel
|
||||
- name: Linting
|
||||
run: |
|
||||
sed -ri '/^"POT-Creation-Date: /d' snikket_web/translations/messages.pot
|
||||
sed -ri '/^"POT-Creation-Date: /d;/^"Generated-By: /d' snikket_web/translations/messages.pot
|
||||
git add snikket_web/translations/messages.pot
|
||||
make extract_translations
|
||||
sed -ri '/^"POT-Creation-Date: /d' snikket_web/translations/messages.pot
|
||||
sed -ri '/^"POT-Creation-Date: /d;/^"Generated-By: /d' snikket_web/translations/messages.pot
|
||||
git diff --exit-code --color -- snikket_web/translations/messages.pot
|
||||
|
||||
|
||||
|
||||
18
Makefile
@@ -5,6 +5,8 @@ generated_css_files = $(patsubst snikket_web/scss/%.scss,snikket_web/static/css/
|
||||
translation_basepath = snikket_web/translations
|
||||
pot_file = $(translation_basepath)/messages.pot
|
||||
|
||||
black_formatted_py = snikket_web/prosodyclient.py
|
||||
|
||||
PYTHON3 ?= python3
|
||||
SCSSC ?= sassc --load-path snikket_web/scss/
|
||||
|
||||
@@ -34,4 +36,20 @@ compile_translations:
|
||||
-pybabel compile -d $(translation_basepath)
|
||||
|
||||
|
||||
.PHONY: lint
|
||||
lint: format flake8
|
||||
|
||||
.PHONY: format
|
||||
format:
|
||||
$(PYTHON3) -m black $(black_formatted_py)
|
||||
|
||||
.PHONY: flake8
|
||||
flake8:
|
||||
$(PYTHON3) -m flake8 --exclude=$(subst $(space),$(comma),$(strip $(black_formatted_py))) snikket_web
|
||||
$(PYTHON3) -m flake8 --ignore=E501,W503 $(black_formatted_py)
|
||||
|
||||
.PHONY: mypy
|
||||
mypy:
|
||||
$(PYTHON3) -m mypy --python-version 3.11 snikket_web
|
||||
|
||||
.PHONY: build_css clean update_translations compile_translations extract_translations force_update_translations
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
aiohttp~=3.6
|
||||
quart~=0.17,<0.18
|
||||
flask-wtf~=1.0
|
||||
aiohttp~=3.8,<3.9
|
||||
quart~=0.18,<0.19
|
||||
flask-wtf~=1.1,<1.2
|
||||
hsluv~=5.0
|
||||
flask-babel~=1.0
|
||||
email-validator~=1.1
|
||||
flask-babel~=2.0,<3
|
||||
email-validator~=1.3
|
||||
environ-config~=20.0
|
||||
wtforms~=3.0
|
||||
wtforms~=3.0,<4
|
||||
typing-extensions
|
||||
werkzeug~=2.2,<3
|
||||
|
||||
@@ -158,7 +158,9 @@ class AppConfig:
|
||||
"id",
|
||||
"it",
|
||||
"pl",
|
||||
"ru",
|
||||
"sv",
|
||||
"uk",
|
||||
"zh_Hans_CN",
|
||||
], converter=autosplit)
|
||||
apple_store_url = environ.var(
|
||||
@@ -210,6 +212,8 @@ def create_app() -> quart.Quart:
|
||||
app.config["PRIVACY_URI"] = config.privacy_uri
|
||||
app.config["ABUSE_EMAIL"] = config.abuse_email
|
||||
app.config["SECURITY_EMAIL"] = config.security_email
|
||||
app.config["SESSION_COOKIE_SECURE"] = True
|
||||
app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
|
||||
|
||||
app.context_processor(proc)
|
||||
app.register_error_handler(
|
||||
|
||||
@@ -76,10 +76,11 @@ class EditUserForm(BaseForm):
|
||||
role = wtforms.RadioField(
|
||||
_l("Access Level"),
|
||||
choices=[
|
||||
("prosody:restricted", _("Limited")),
|
||||
("prosody:restricted", _l("Limited")),
|
||||
("prosody:registered", _l("Normal user")),
|
||||
("prosody:admin", _l("Administrator")),
|
||||
],
|
||||
default="prosody:registered",
|
||||
)
|
||||
|
||||
action_save = wtforms.SubmitField(
|
||||
@@ -290,6 +291,20 @@ class InvitePost(BaseForm):
|
||||
default="account",
|
||||
)
|
||||
|
||||
role = wtforms.RadioField(
|
||||
_l("Access Level"),
|
||||
choices=[
|
||||
("prosody:restricted", _l("Limited")),
|
||||
("prosody:registered", _l("Normal user")),
|
||||
("prosody:admin", _l("Administrator")),
|
||||
],
|
||||
default="prosody:registered",
|
||||
)
|
||||
|
||||
note = wtforms.StringField(
|
||||
_l("Comment (optional)"),
|
||||
)
|
||||
|
||||
action_create_invite = wtforms.SubmitField(
|
||||
_l("New invitation link")
|
||||
)
|
||||
@@ -369,12 +384,16 @@ async def create_invite() -> typing.Union[str, werkzeug.Response]:
|
||||
if form.type_.data == "group":
|
||||
invite = await client.create_group_invite(
|
||||
group_ids=form.circles.data,
|
||||
role_names=[form.role.data],
|
||||
ttl=form.lifetime.data,
|
||||
note=form.note.data,
|
||||
)
|
||||
else:
|
||||
invite = await client.create_account_invite(
|
||||
group_ids=form.circles.data,
|
||||
role_names=[form.role.data],
|
||||
ttl=form.lifetime.data,
|
||||
note=form.note.data,
|
||||
)
|
||||
await flash(
|
||||
_("Invitation created"),
|
||||
@@ -733,21 +752,21 @@ def get_system_stats() -> typing.MutableMapping[
|
||||
|
||||
class AnnouncementForm(BaseForm):
|
||||
text = wtforms.StringField(
|
||||
_("Message contents"),
|
||||
_l("Message contents"),
|
||||
widget=wtforms.widgets.TextArea(),
|
||||
validators=[wtforms.validators.DataRequired()],
|
||||
)
|
||||
|
||||
online_only = wtforms.BooleanField(
|
||||
_("Only send to online users"),
|
||||
_l("Only send to online users"),
|
||||
)
|
||||
|
||||
action_post_all = wtforms.SubmitField(
|
||||
_("Post to all users"),
|
||||
_l("Post to all users"),
|
||||
)
|
||||
|
||||
action_send_preview = wtforms.SubmitField(
|
||||
_("Send preview to yourself"),
|
||||
_l("Send preview to yourself"),
|
||||
)
|
||||
|
||||
|
||||
@@ -812,6 +831,11 @@ async def system() -> typing.Union[str, werkzeug.Response]:
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
metrics["users"] = prosody_metrics["users"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
for k in list(metrics.keys()):
|
||||
if metrics[k] is None:
|
||||
# so that defaulting in jinja works
|
||||
|
||||
@@ -53,7 +53,7 @@ def flatten(a: typing.Iterable, levels: int = 1) -> typing.Iterable:
|
||||
|
||||
def circle_name(c: typing.Any) -> str:
|
||||
if c.id_ == "default" and c.name == "default":
|
||||
return _("Main")
|
||||
return _l("Main")
|
||||
return c.name
|
||||
|
||||
|
||||
|
||||
@@ -47,10 +47,20 @@ def apple_store_badge() -> str:
|
||||
return url_for("static", filename="img/apple/en.svg")
|
||||
|
||||
|
||||
def play_store_badge() -> str:
|
||||
locale = selected_locale()
|
||||
filename = "{}_badge_web_generic.png".format(locale)
|
||||
static_path = pathlib.Path(__file__).parent / "static" / "img" / "google"
|
||||
if (static_path / filename).exists():
|
||||
return url_for("static", filename="img/google/{}".format(filename))
|
||||
return url_for("static", filename="img/google/en_badge_web_generic.png")
|
||||
|
||||
|
||||
@bp.context_processor
|
||||
def context() -> typing.Dict[str, typing.Any]:
|
||||
return {
|
||||
"apple_store_badge": apple_store_badge,
|
||||
"play_store_badge": play_store_badge,
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +126,10 @@ class RegisterForm(BaseForm):
|
||||
|
||||
password = wtforms.PasswordField(
|
||||
_l("Password"),
|
||||
validators=[
|
||||
wtforms.validators.InputRequired(),
|
||||
wtforms.validators.Length(min=10),
|
||||
],
|
||||
)
|
||||
|
||||
password_confirm = wtforms.PasswordField(
|
||||
@@ -184,6 +198,10 @@ async def register(id_: str) -> typing.Union[str, werkzeug.Response]:
|
||||
class ResetForm(BaseForm):
|
||||
password = wtforms.PasswordField(
|
||||
_l("Password"),
|
||||
validators=[
|
||||
wtforms.validators.InputRequired(),
|
||||
wtforms.validators.Length(min=10),
|
||||
],
|
||||
)
|
||||
|
||||
password_confirm = wtforms.PasswordField(
|
||||
|
||||
@@ -259,6 +259,13 @@ div.form.layout-expanded {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
fieldset.descriptive-radio-selection {
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: $w-s2;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="radio"] + label, input[type="checkbox"] + label {
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
@@ -363,6 +370,10 @@ div.form.layout-expanded {
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
.radio-button-ext {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
div.select-wrap {
|
||||
display: block;
|
||||
border-bottom: $w-s4 solid $primary-500;
|
||||
@@ -981,19 +992,18 @@ div.profile-card {
|
||||
}
|
||||
}
|
||||
|
||||
/* clipboard button */
|
||||
/* clipboard and share buttons */
|
||||
|
||||
.copy-to-clipboard {
|
||||
.copy-to-clipboard, .share-button {
|
||||
cursor: pointer;
|
||||
font-style: normal;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
body.no-copy .copy-to-clipboard {
|
||||
body.no-copy .copy-to-clipboard, body.no-share .share-button {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* magic */
|
||||
|
||||
pre.guru-meditation {
|
||||
@@ -1304,4 +1314,11 @@ pre.guru-meditation {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.user-display-name {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
.user-jid {
|
||||
font-size: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
snikket_web/static/img/google/da_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
snikket_web/static/img/google/de_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
snikket_web/static/img/google/en_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
snikket_web/static/img/google/es_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
snikket_web/static/img/google/fr_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
snikket_web/static/img/google/id_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
snikket_web/static/img/google/it_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
snikket_web/static/img/google/ja_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
snikket_web/static/img/google/pl_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
snikket_web/static/img/google/ru_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
snikket_web/static/img/google/sv_badge_web_generic.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
@@ -148,6 +148,11 @@ licensed under the terms of the Apache 2.0 License -->
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5s-3 1.34-3 3 1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V18c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-1.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05.02.01.03.03.04.04 1.14.83 1.93 1.94 1.93 3.41V18c0 .35-.07.69-.18 1H22c.55 0 1-.45 1-1v-1.5c0-2.33-4.67-3.5-7-3.5z" />
|
||||
</symbol>
|
||||
<!-- from: social/person/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-person" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v1c0 .55.45 1 1 1h14c.55 0 1-.45 1-1v-1c0-2.66-5.33-4-8-4z" />
|
||||
</symbol>
|
||||
<!-- from: social/group_add/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-create_group" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
@@ -188,4 +193,9 @@ licensed under the terms of the Apache 2.0 License -->
|
||||
<g><rect fill="none" height="24" width="24" /><rect fill="none" height="24" width="24" /></g>
|
||||
<g><g><path d="M21,8c-1.45,0-2.26,1.44-1.93,2.51l-3.55,3.56c-0.3-0.09-0.74-0.09-1.04,0l-2.55-2.55C12.27,10.45,11.46,9,10,9 c-1.45,0-2.27,1.44-1.93,2.52l-4.56,4.55C2.44,15.74,1,16.55,1,18c0,1.1,0.9,2,2,2c1.45,0,2.26-1.44,1.93-2.51l4.55-4.56 c0.3,0.09,0.74,0.09,1.04,0l2.55,2.55C12.73,16.55,13.54,18,15,18c1.45,0,2.27-1.44,1.93-2.52l3.56-3.55 C21.56,12.26,23,11.45,23,10C23,8.9,22.1,8,21,8z" /><polygon points="15,9 15.94,6.93 18,6 15.94,5.07 15,3 14.08,5.07 12,6 14.08,6.93" /><polygon points="3.5,11 4,9 6,8.5 4,8 3.5,6 3,8 1,8.5 3,9" /></g></g>
|
||||
</symbol>
|
||||
<!-- from: social/share/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-share" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92s2.92-1.31 2.92-2.92-1.31-2.92-2.92-2.92z" />
|
||||
</symbol>
|
||||
</defs></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@@ -1,19 +1,57 @@
|
||||
{% from "library.j2" import form_button, render_errors %}
|
||||
{% from "library.j2" import form_button,
|
||||
render_errors,
|
||||
access_level_description, access_level_icon,
|
||||
invite_type_description, invite_type_icon
|
||||
%}
|
||||
<form method="POST" action="{{ url_for(".create_invite") }}">
|
||||
{{- invite_form.csrf_token -}}
|
||||
<div class="form layout-expanded">
|
||||
<h2 class="form-title">{% trans %}Create new invitation{% endtrans %}</h2>
|
||||
<p class="form-descr weak">{% trans %}Create a new invitation link to invite more users to your Snikket service by clicking the button below.{% endtrans %}</p>
|
||||
|
||||
<!-- Invitation type -->
|
||||
<div class="f-ebox">
|
||||
<fieldset>{#- -#}
|
||||
<fieldset class="descriptive-radio-selection">{#- -#}
|
||||
<legend>{{ invite_form.type_.label.text }}</legend>
|
||||
{{- invite_form.type_ -}}
|
||||
<p>{% trans %}Choose whether this invitation link will allow more than one person to join.{% endtrans %}</p>
|
||||
|
||||
{%- for invite_type in invite_form.type_ -%}
|
||||
<div class="radio-button-ext">
|
||||
{{ invite_type }}<label for="{{ invite_type.id }}">
|
||||
{%- trans title=invite_type.label.text, icon=invite_type_icon(invite_type.data), description=invite_type_description(invite_type.data) -%}
|
||||
<span class="invite-type">{{ title }}{{ icon }}</span><p>{{ description }}</p>
|
||||
{%- endtrans -%}
|
||||
</label>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<!-- Access level -->
|
||||
<div class="f-ebox">
|
||||
<fieldset class="descriptive-radio-selection">{#- -#}
|
||||
<legend>{{ invite_form.role.label.text }}</legend>
|
||||
<p>{% trans %}The access level of a user determines what interactions are allowed for them on your Snikket service.{% endtrans %}</p>
|
||||
{%- for level in invite_form.role -%}
|
||||
<div class="radio-button-ext">
|
||||
{{ level }}<label for="{{ level.id }}">
|
||||
{%- trans title=level.label.text, icon=access_level_icon(level.data), description=access_level_description(level.data) -%}
|
||||
<span class="access-level">{{ title }}{{ icon }}</span><p>{{ description }}</p>
|
||||
{%- endtrans -%}
|
||||
</label>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Valid for -->
|
||||
<div class="f-ebox">
|
||||
{{ invite_form.lifetime.label }}
|
||||
<div class="select-wrap">{{ invite_form.lifetime }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Invite to circle -->
|
||||
<div class="f-ebox">
|
||||
{#
|
||||
NOTE: This is for when/if we ever support multi-group invites.
|
||||
@@ -27,6 +65,13 @@
|
||||
<div class="select-wrap">{{ invite_form.circles }}</div>
|
||||
{%- call render_errors(invite_form.circles) -%}{%- endcall -%}
|
||||
</div>
|
||||
|
||||
<!-- Comment -->
|
||||
<div class="f-ebox">
|
||||
{{ invite_form.note.label }}
|
||||
{{ invite_form.note }}
|
||||
</div>
|
||||
|
||||
<div class="f-bbox">
|
||||
{%- call form_button("create_link", invite_form.action_create_invite, class="primary") %}{% endcall -%}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "admin_app.html" %}
|
||||
{% from "library.j2" import form_button, standard_button, value_or_hint, custom_form_button, clipboard_button, icon %}
|
||||
{% from "library.j2" import form_button, standard_button, value_or_hint, custom_form_button, clipboard_button, icon, render_user with context %}
|
||||
{% block head_lead %}
|
||||
{{ super() }}
|
||||
{% include "copy-snippet.html" %}
|
||||
@@ -47,7 +47,7 @@
|
||||
<tbody>
|
||||
{%- for chat in circle_chats -%}
|
||||
<tr>
|
||||
<td class="collapsible">{% call value_or_hint(chat.name) %}{% endcall %}</td>
|
||||
<td>{% call value_or_hint(chat.name) %}{% endcall %}</td>
|
||||
<td class="nowrap">
|
||||
{%- call custom_form_button("delete", form.action_remove_group_chat.name, chat.id_, class="primary danger", slim=True) -%}
|
||||
{% trans name=chat.name %}Delete group chat '{{ name }}'{% endtrans %}
|
||||
@@ -71,7 +71,6 @@
|
||||
<div class="el-2 elevated"><table>
|
||||
<thead>
|
||||
<th>{% trans %}Login name{% endtrans %}</th>
|
||||
<th class="collapsible">{% trans %}Display name{% endtrans %}</th>
|
||||
<th>{% trans %}Actions{% endtrans %}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -79,13 +78,12 @@
|
||||
<tr>
|
||||
<td>
|
||||
{%- if member -%}
|
||||
{{ localpart }}
|
||||
{%- call render_user(member) -%}{%- endcall -%}
|
||||
{%- else -%}
|
||||
{{ localpart }}
|
||||
<span class="with-tooltip above" data-tooltip="{% trans %}The user has been deleted from the server.{% endtrans %}"><em> ({% trans %}deleted{% endtrans %})</em></span>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td class="collapsible">{% call value_or_hint(member.display_name) %}{% endcall %}</td>
|
||||
<td class="nowrap">
|
||||
{%- call custom_form_button("remove_user", form.action_remove_user.name, member.localpart, class="primary danger", slim=True) -%}
|
||||
{% trans username=member.localpart %}Remove user {{ username }} from circle{% endtrans %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "admin_app.html" %}
|
||||
{% from "library.j2" import showuri, form_button, standard_button, extract_circle_name, invite_type_description %}
|
||||
{% from "library.j2" import showuri, form_button, standard_button, extract_circle_name, invite_type_name, invite_type_description %}
|
||||
{% block head_lead %}
|
||||
{{ super() }}
|
||||
{% include "copy-snippet.html" %}
|
||||
@@ -13,9 +13,10 @@
|
||||
<dt>{% trans %}Valid until{% endtrans %}</dt>
|
||||
<dd>{{ invite.expires | format_date }}</dd>
|
||||
<dt><label for="link-field">{% trans %}Link{% endtrans %}</label></dt>
|
||||
<dd>{% call showuri(invite.landing_page, id_="link-field") %}{% endcall %}</dd>
|
||||
<dd>{% call showuri(invite.landing_page, id_="link-field") %}{% trans %}Invitation to Snikket{% endtrans %}{% endcall %}</dd>
|
||||
<dt>{% trans %}Invitation type{% endtrans %}</dt>
|
||||
<dd>{% call invite_type_description(invite) %}{% endcall %}</dd>
|
||||
{% set invite_type = invite.reusable and "group" or "account" %}
|
||||
<dd><span class="with-tooltip above" data-tooltip="{% call invite_type_description(invite_type) %}{% endcall %}">{% call invite_type_name(invite_type) %}{% endcall %}</span></dd>
|
||||
{%- set ngroups = invite.group_ids | length -%}
|
||||
{%- if ngroups > 1 -%}
|
||||
{#- not supported via the web UI, but we should still display it properly -#}
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
{% extends "admin_app.html" %}
|
||||
{% from "library.j2" import box, form_button, standard_button, icon %}
|
||||
{% macro access_level_description(role, caller=None) %}
|
||||
{%- if role == "prosody:restricted" -%}
|
||||
{% trans %}Limited users can interact with users on the same Snikket service and be members of circles.{% endtrans %}
|
||||
{%- elif role == "prosody:registered" -%}
|
||||
{% trans %}Like limited users and can also interact with users on other Snikket services.{% endtrans %}
|
||||
{%- elif role == "prosody:admin" -%}
|
||||
{% trans %}Like normal users and can access the admin panel in the web portal.{% endtrans %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro access_level_icon(role, caller=None) %}
|
||||
{%- if role == "prosody:restricted" -%}
|
||||
{% call icon("lock") %}{% endcall %}
|
||||
{%- elif role == "prosody:admin" -%}
|
||||
{% call icon("admin") %}{% endcall %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% from "library.j2" import box, form_button, standard_button, icon, access_level_description, access_level_icon %}
|
||||
{% block content %}
|
||||
<h1>{% trans user_name=target_user.localpart %}Edit user {{ user_name }}{% endtrans %}</h1>
|
||||
<form method="POST">{{ form.csrf_token }}<div class="form layout-expanded">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "admin_app.html" %}
|
||||
{% from "library.j2" import action_button, icon, clipboard_button, form_button, custom_form_button, extract_circle_name, invite_type_name, invite_type_description %}
|
||||
{% from "library.j2" import action_button, icon, clipboard_button, share_button, form_button, custom_form_button, extract_circle_name, invite_type_name, invite_type_description %}
|
||||
{% block head_lead %}
|
||||
{{ super() }}
|
||||
{% include "copy-snippet.html" %}
|
||||
@@ -18,17 +18,18 @@
|
||||
<col/>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans %}Expires{% endtrans %}</th>
|
||||
<th class="collapsible">{% trans %}Type{% endtrans %}</th>
|
||||
<th class="collapsible">{% trans %}Circle{% endtrans %}</th>
|
||||
<th>{% trans %}Expires{% endtrans %}</th>
|
||||
<th>{% trans %}Comment{% endtrans %}</th>
|
||||
<th>{% trans %}Actions{% endtrans %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for invite in invites %}
|
||||
{% set invite_type = invite.reusable and "group" or "account" %}
|
||||
<tr>
|
||||
<td>{{ (invite.expires - now) | format_timedelta(add_direction=True) }}</td>
|
||||
<td class="collapsible"><span class="with-tooltip above" data-tooltip="{% call invite_type_description(invite) %}{% endcall %}">{% call invite_type_name(invite) %}{% endcall %}</span></td>
|
||||
<td class="collapsible"><span class="with-tooltip above" data-tooltip="{% call invite_type_description(invite_type) %}{% endcall %}">{% call invite_type_name(invite_type) %}{% endcall %}</span></td>
|
||||
<td class="collapsible">
|
||||
{#- -#}
|
||||
<ul class="inline">
|
||||
@@ -38,6 +39,8 @@
|
||||
</ul>
|
||||
{#- -#}
|
||||
</td>
|
||||
<td>{{ (invite.expires - now) | format_timedelta(add_direction=True) }}</td>
|
||||
<td>{% if invite.note is not none %}{{ invite.note }}{% endif %}</td>
|
||||
<td class="nowrap">
|
||||
{%- call action_button("more", url_for(".edit_invite", id_=invite.id_), class="secondary") -%}
|
||||
{% trans %}Show invite details{% endtrans %}
|
||||
@@ -45,6 +48,9 @@
|
||||
{%- call clipboard_button(invite.landing_page, class="primary") -%}
|
||||
{% trans %}Copy invite link to clipboard{% endtrans %}
|
||||
{%- endcall -%}
|
||||
{%- call share_button("Invitation to Snikket", invite.landing_page, class="primary") -%}
|
||||
{% trans %}Share invitation link{% endtrans %}
|
||||
{%- endcall -%}
|
||||
{%- call custom_form_button("remove_link", form.action_revoke.name, invite.id_, class="secondary danger", slim=True) -%}
|
||||
{% trans %}Delete invitation{% endtrans %}
|
||||
{%- endcall -%}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<dt>{% trans %}Valid until{% endtrans %}</dt>
|
||||
<dd>{{ reset_link.expires | format_date }}</dd>
|
||||
<dt><label for="link-field">{% trans %}Link{% endtrans %}</label></dt>
|
||||
<dd>{% call showuri(reset_link.landing_page, id_="link-field") %}{% endcall %}</dd>
|
||||
<dd>{% call showuri(reset_link.landing_page, id_="link-field") %}Reset your Snikket password{% endcall %}</dd>
|
||||
</dd>
|
||||
<div class="f-bbox">
|
||||
{%- call custom_form_button("remove_link", form.action_revoke.name, reset_link.id_, class="secondary danger") -%}
|
||||
|
||||
@@ -76,13 +76,20 @@
|
||||
<em>{% trans %}unknown{% endtrans %}</em>
|
||||
{%- endif -%}
|
||||
</dd>
|
||||
<dt>{% trans %}Connected devices{% endtrans %}</dt>
|
||||
<dt>{% trans %}Active users{% endtrans %}</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
{%- if metrics.prosody_devices | default(None) is not none -%}
|
||||
{{ metrics.prosody_devices }}
|
||||
<li>{% trans %}Connected now:{% endtrans %} {{ metrics.prosody_devices }}</li>
|
||||
{%- else -%}
|
||||
<em>{% trans %}unknown{% endtrans %}</em>
|
||||
<li><em>{% trans %}unknown{% endtrans %}</em></li>
|
||||
{%- endif -%}
|
||||
{%- if metrics.users | default(None) is not none -%}
|
||||
<li>{% trans %}Past 24 hours:{% endtrans %} {{ metrics.users.active_1d }}</li>
|
||||
<li>{% trans %}Past 7 days:{% endtrans %} {{ metrics.users.active_7d }}</li>
|
||||
<li>{% trans %}Past 30 days:{% endtrans %} {{ metrics.users.active_30d }}</li>
|
||||
{%- endif -%}
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
{%- call action_button("edit", url_for(".edit_user", localpart=user.localpart), class="primary") -%}
|
||||
{% trans user_name=user.localpart %}Edit user {{ user_name }}{% endtrans %}
|
||||
{%- endcall -%}
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@@ -16,5 +16,5 @@
|
||||
<meta name="msapplication-TileColor" content="#fbd308">
|
||||
<meta name="theme-color" content="#fbd308">
|
||||
</head>
|
||||
<body{% if body_id | default(False) %} id="{{ body_id }}"{% endif %} class="{% if is_in_debug_mode %}debug{% endif %}{% if body_class | default(False) %} {{ body_class }}{% endif %}"{% if onload | default(False) %} onload="{{ onload }}"{% endif %}>{% block body %}{% endblock %}</body>
|
||||
<body{% if body_id | default(False) %} id="{{ body_id }}"{% endif %} class="{% if is_in_debug_mode %}debug{% endif %}{% if body_class | default(False) %} {{ body_class }}{% endif %} no-copy no-share"{% if onload | default(False) %} onload="{{ onload }}"{% endif %}>{% block body %}{% endblock %}</body>
|
||||
</html>
|
||||
|
||||
@@ -115,8 +115,63 @@ var copy_to_clipboard_btn = function(el) {
|
||||
});
|
||||
};
|
||||
|
||||
var copy_to_clipboard_btn = function(el) {
|
||||
var text = el.dataset.cliptext;
|
||||
if (!text) {
|
||||
console.error('copy_to_clipboard used on element without text to copy');
|
||||
}
|
||||
copyTextToClipboard(text, el, function(success) {
|
||||
var existing_result_el = document.getElementById("clipboard-result");
|
||||
if (existing_result_el !== null) {
|
||||
existing_result_el.parentNode.removeChild(existing_result_el);
|
||||
}
|
||||
|
||||
var icon = "done";
|
||||
if (!success) {
|
||||
icon = "cancel";
|
||||
}
|
||||
var icon_bak = get_current_icon(el.firstChild);
|
||||
change_icon(el.firstChild, icon);
|
||||
setTimeout(function() {
|
||||
change_icon(el.firstChild, icon_bak);
|
||||
el.blur();
|
||||
}, 1500);
|
||||
});
|
||||
};
|
||||
|
||||
var share_url_btn = function(el) {
|
||||
let data = {
|
||||
"title": el.dataset.shareTitle,
|
||||
"url": el.dataset.shareUrl,
|
||||
}
|
||||
|
||||
let icon_bak = get_current_icon(el.firstChild);
|
||||
|
||||
new Promise(function (resolve, reject) {
|
||||
if(!navigator.canShare || !navigator.canShare(data)) {
|
||||
return reject();
|
||||
}
|
||||
return resolve(navigator.share(data));
|
||||
}).then(function () {
|
||||
// Success
|
||||
change_icon(el.firstChild, "done");
|
||||
}, function () {
|
||||
// Failure
|
||||
change_icon(el.firstChild, "cancel");
|
||||
}).finally(function () {
|
||||
// Either way, clear status icon after 1.5s
|
||||
setTimeout(function() {
|
||||
change_icon(el.firstChild, icon_bak);
|
||||
el.blur();
|
||||
}, 1500);
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
document.body.classList.remove("no-copy");
|
||||
if(navigator.share) {
|
||||
document.body.classList.remove("no-share");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
{% block head_lead %}
|
||||
{{ super() }}
|
||||
<title>{% trans %}Reset your password | Snikket{% endtrans %}</title>
|
||||
<script async type="text/javascript" src="{{ url_for("static", filename="js/qrcode.min.js") }}"></script>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<form method="POST"><div class="form layout-expanded">
|
||||
@@ -27,9 +26,4 @@
|
||||
{%- call form_button("passwd", form.action_reset, class="primary") -%}{%- endcall -%}
|
||||
</div>
|
||||
</div></form>
|
||||
<script type="text/javascript">
|
||||
var onload = function() {
|
||||
apply_qr_code(document.getElementById("qr-uri"));
|
||||
};
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{%- endif -%}
|
||||
<div class="install-buttons">
|
||||
<ul>
|
||||
<li><a href="{{ play_store_url }}"><img alt='{% trans %}Get it on Google Play{% endtrans %}' src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png' class="play"/></a></li>
|
||||
<li><a href="{{ play_store_url }}"><img alt='{% trans %}Get it on Google Play{% endtrans %}' src='{{ play_store_badge() }}' class="play"/></a></li>
|
||||
{%- if apple_store_url -%}
|
||||
<li><a href="{{ apple_store_url }}" class="popover" data-popover-id="apple-popover"><img alt='{% trans %}Download on the App Store{% endtrans %}' src="{{ apple_store_badge() }}" class="apple"></a></li>
|
||||
{%- endif -%}
|
||||
@@ -134,7 +134,6 @@
|
||||
|
||||
var onload = function() {
|
||||
apply_qr_code(document.getElementById("qr-invite-page"));
|
||||
apply_qr_code(document.getElementById("qr-uri"));
|
||||
var popover_as = document.getElementsByClassName("popover");
|
||||
for (var i = 0; i < popover_as.length; ++i) {
|
||||
var a = popover_as[i];
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<div class="user-info-container">
|
||||
<div class="user-localpart">{{- user.localpart -}}</div>
|
||||
{%- if user.display_name %}
|
||||
<div class="user-display-name">{{- user.display_name -}}</div>
|
||||
{%- endif %}
|
||||
<div class="user-jid"><span class="user-jid-localpart">{{- user.localpart -}}</span><span class="user-jid-at">@</span><span class="user-jid-domain">{{- config["SNIKKET_DOMAIN"] -}}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
@@ -38,7 +38,10 @@
|
||||
<em>—</em>
|
||||
{%- else -%}
|
||||
<div><input type="text" {% if id_ %}id="{{ id_ }}" {% endif %}readonly="readonly" value="{{ uri }}"></div>
|
||||
<div>{% call clipboard_button(uri, show_label=True) %}{% trans %}Copy link{% endtrans %}{% endcall %}</div>
|
||||
<div>
|
||||
{% call clipboard_button(uri, show_label=True) %}{% trans %}Copy link{% endtrans %}{% endcall %}
|
||||
{% call share_button(caller() if caller is not none else None, uri, show_label=True) %}{% trans %}Share{% endtrans %}{% endcall %}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
@@ -82,7 +85,7 @@
|
||||
|
||||
{% macro clipboard_button(data, show_label=False, caller=None, class=None) -%}
|
||||
{%- set label = caller() -%}
|
||||
<a class="button{% if class %} {{ class }}{% endif %}"
|
||||
<a class="button copy-to-clipboard{% if class %} {{ class }}{% endif %}"
|
||||
href="#"
|
||||
{% if not show_label %}
|
||||
aria-label="{{ label }}"
|
||||
@@ -97,6 +100,24 @@
|
||||
</a>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro share_button(title, url, show_label=False, caller=None, class=None) -%}
|
||||
{%- set label = caller() -%}
|
||||
<a class="button share-button{% if class %} {{ class }}{% endif %}"
|
||||
href="#"
|
||||
{% if not show_label %}
|
||||
aria-label="{{ label }}"
|
||||
title="{{ label }}"
|
||||
{% endif %}
|
||||
data-share-title="{{ title }}"
|
||||
data-share-url="{{ url }}"
|
||||
onclick="share_url_btn(this); return false;">
|
||||
{%- call icon("share") %}{% endcall -%}
|
||||
{%- if show_label %}
|
||||
<span>{{ label }}</span>
|
||||
{% endif -%}
|
||||
</a>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro render_errors(field, caller=None) -%}
|
||||
{%- set error_list = field.errors if field.errors is not mapping else (field.errors.values() | flatten | list) -%}
|
||||
{%- if error_list -%}
|
||||
@@ -132,18 +153,44 @@
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{%- macro invite_type_name(invite_info, caller=None) -%}
|
||||
{%- if invite_info.reusable -%}
|
||||
{% trans %}Group{% endtrans %}
|
||||
{%- else -%}
|
||||
{%- macro invite_type_name(invite_type, caller=None) -%}
|
||||
{%- if invite_type == "account" -%}
|
||||
{% trans %}Individual{% endtrans %}
|
||||
{%- else -%}
|
||||
{% trans %}Group{% endtrans %}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro invite_type_description(invite_info, caller=None) -%}
|
||||
{%- if invite_info.reusable -%}
|
||||
{% trans %}Can be used multiple times to create accounts on this Snikket service.{% endtrans %}
|
||||
{%- else -%}
|
||||
{% trans %}Can be used once to create an account on this Snikket service.{% endtrans %}
|
||||
{% macro access_level_description(role, caller=None) %}
|
||||
{%- if role == "prosody:restricted" -%}
|
||||
{% trans %}Limited users can interact with users on the same Snikket service and be members of circles.{% endtrans %}
|
||||
{%- elif role == "prosody:registered" -%}
|
||||
{% trans %}Like limited users and can also interact with users on other Snikket services.{% endtrans %}
|
||||
{%- elif role == "prosody:admin" -%}
|
||||
{% trans %}Like normal users and can access the admin panel in the web portal.{% endtrans %}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro access_level_icon(role, caller=None) %}
|
||||
{%- if role == "prosody:restricted" -%}
|
||||
{% call icon("lock") %}{% endcall %}
|
||||
{%- elif role == "prosody:admin" -%}
|
||||
{% call icon("admin") %}{% endcall %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro invite_type_description(invite_type, caller=None) %}
|
||||
{%- if invite_type == "account" -%}
|
||||
{% trans %}Invite a single person (invitation link can only be used once).{% endtrans %}
|
||||
{%- elif invite_type == "group" -%}
|
||||
{% trans %}Invite a group of people (invitation link can be used multiple times).{% endtrans %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro invite_type_icon(invite_type, caller=None) %}
|
||||
{%- if invite_type == "account" -%}
|
||||
{% call icon("person") %}{% endcall %}
|
||||
{%- elif invite_type == "group" -%}
|
||||
{% call icon("people") %}{% endcall %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<div class="f-bbox">
|
||||
{%- call form_button("login", form.action_signin, class="primary") -%}{% endcall -%}
|
||||
</div>
|
||||
</from>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
var domainCheck = function() {
|
||||
var form = document.getElementById("login-form");
|
||||
|
||||
@@ -6,8 +6,13 @@
|
||||
{% include "copy-snippet.html" %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans %}Welcome!{% endtrans %}</h1>
|
||||
<p>{% trans user_name=user_info.display_name %}Welcome home, {{ user_name }}.{% endtrans %}</p>
|
||||
{% if user_info.is_admin and metrics.users and metrics.users.active_1d <= 1 %}
|
||||
<aside class="box hint">
|
||||
<header>{% trans %}Welcome to Snikket!{% endtrans %}</header>
|
||||
<p>{% trans %}Now your Snikket instance is up and running, the next step is to invite people to join it. Family, friends, colleagues... you choose!{% endtrans %}</p>
|
||||
<a href="/admin/invitations">{% trans %}Create new invitation{% endtrans %}</a>
|
||||
</aside>
|
||||
{% endif %}
|
||||
<nav class="welcome">
|
||||
<ul>
|
||||
<li class="wide">
|
||||
|
||||
BIN
snikket_web/translations/es/LC_MESSAGES/messages.mo
Normal file
1939
snikket_web/translations/es/LC_MESSAGES/messages.po
Normal file
@@ -1,21 +1,21 @@
|
||||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2023 ORGANIZATION
|
||||
# Copyright (C) 2025 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2025.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2023-12-08 12:08+0000\n"
|
||||
"POT-Creation-Date: 2025-04-12 20:21+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.13.1\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#: snikket_web/admin.py:69 snikket_web/templates/admin_delete_user.html:10
|
||||
#: snikket_web/templates/admin_edit_circle.html:73
|
||||
@@ -23,229 +23,234 @@ msgid "Login name"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:73 snikket_web/templates/admin_delete_user.html:12
|
||||
#: snikket_web/templates/admin_edit_circle.html:74 snikket_web/user.py:63
|
||||
#: snikket_web/user.py:69
|
||||
msgid "Display name"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:77 snikket_web/templates/admin_edit_user.html:53
|
||||
#: snikket_web/admin.py:77 snikket_web/admin.py:295
|
||||
#: snikket_web/templates/admin_edit_user.html:37
|
||||
msgid "Access Level"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:79
|
||||
#: snikket_web/admin.py:79 snikket_web/admin.py:297
|
||||
msgid "Limited"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:80
|
||||
#: snikket_web/admin.py:80 snikket_web/admin.py:298
|
||||
msgid "Normal user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:81
|
||||
#: snikket_web/admin.py:81 snikket_web/admin.py:299
|
||||
msgid "Administrator"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:86
|
||||
#: snikket_web/admin.py:87
|
||||
msgid "Update user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:90
|
||||
#: snikket_web/admin.py:91
|
||||
msgid "Restore account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:94
|
||||
#: snikket_web/admin.py:95
|
||||
msgid "Unlock account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:98
|
||||
#: snikket_web/admin.py:99
|
||||
msgid "Create password reset link"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:116
|
||||
#: snikket_web/admin.py:117
|
||||
msgid "Password reset link created"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:128
|
||||
#: snikket_web/admin.py:129
|
||||
msgid "User account restored"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:133
|
||||
#: snikket_web/admin.py:134
|
||||
msgid "User account unlocked"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:140
|
||||
#: snikket_web/admin.py:141
|
||||
msgid "Could not restore user account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:145
|
||||
#: snikket_web/admin.py:146
|
||||
msgid "Could not unlock user account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:157
|
||||
#: snikket_web/admin.py:158
|
||||
msgid "User information updated."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:179
|
||||
#: snikket_web/admin.py:180
|
||||
msgid "Delete user permanently"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:192
|
||||
#: snikket_web/admin.py:193
|
||||
msgid "User deleted"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:230
|
||||
#: snikket_web/admin.py:231
|
||||
msgid "Password reset link not found"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:242
|
||||
#: snikket_web/admin.py:243
|
||||
msgid "Password reset link deleted"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:262
|
||||
#: snikket_web/admin.py:263
|
||||
msgid "Invite to circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:268
|
||||
#: snikket_web/admin.py:269
|
||||
msgid "At least one circle must be selected"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:273
|
||||
#: snikket_web/admin.py:274
|
||||
msgid "Valid for"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:275
|
||||
#: snikket_web/admin.py:276
|
||||
msgid "One hour"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:276
|
||||
#: snikket_web/admin.py:277
|
||||
msgid "Twelve hours"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:277
|
||||
#: snikket_web/admin.py:278
|
||||
msgid "One day"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:278
|
||||
#: snikket_web/admin.py:279
|
||||
msgid "One week"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:279
|
||||
#: snikket_web/admin.py:280
|
||||
msgid "Four weeks"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:285 snikket_web/templates/admin_edit_invite.html:17
|
||||
#: snikket_web/admin.py:286 snikket_web/templates/admin_edit_invite.html:17
|
||||
msgid "Invitation type"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:287 snikket_web/templates/library.j2:139
|
||||
#: snikket_web/admin.py:288 snikket_web/templates/library.j2:158
|
||||
msgid "Individual"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:288 snikket_web/templates/library.j2:137
|
||||
#: snikket_web/admin.py:289 snikket_web/templates/library.j2:160
|
||||
msgid "Group"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:294
|
||||
#: snikket_web/admin.py:305
|
||||
msgid "Comment (optional)"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:309
|
||||
msgid "New invitation link"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:356
|
||||
#: snikket_web/admin.py:371
|
||||
msgid "Revoke"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:380
|
||||
#: snikket_web/admin.py:399
|
||||
msgid "Invitation created"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:396
|
||||
#: snikket_web/admin.py:415
|
||||
msgid "No such invitation exists"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:411
|
||||
#: snikket_web/admin.py:430
|
||||
msgid "Invitation revoked"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:428 snikket_web/admin.py:476
|
||||
#: snikket_web/admin.py:447 snikket_web/admin.py:495
|
||||
#: snikket_web/templates/admin_delete_circle.html:10
|
||||
#: snikket_web/templates/admin_edit_circle.html:44
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:433 snikket_web/templates/admin_circles.html:47
|
||||
#: snikket_web/admin.py:452 snikket_web/templates/admin_circles.html:47
|
||||
msgid "Create circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:463
|
||||
#: snikket_web/admin.py:482
|
||||
msgid "Circle created"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:481
|
||||
#: snikket_web/admin.py:500
|
||||
msgid "Select user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:486
|
||||
#: snikket_web/admin.py:505
|
||||
msgid "Update circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:492
|
||||
#: snikket_web/admin.py:511
|
||||
msgid "Add user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:510 snikket_web/admin.py:609 snikket_web/admin.py:657
|
||||
#: snikket_web/admin.py:529 snikket_web/admin.py:628 snikket_web/admin.py:676
|
||||
msgid "No such circle exists"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:547
|
||||
#: snikket_web/admin.py:566
|
||||
msgid "Circle data updated"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:557
|
||||
#: snikket_web/admin.py:576
|
||||
msgid "User added to circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:566
|
||||
#: snikket_web/admin.py:585
|
||||
msgid "User removed from circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:575
|
||||
#: snikket_web/admin.py:594
|
||||
msgid "Chat removed from circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:593
|
||||
#: snikket_web/admin.py:612
|
||||
msgid "Delete circle permanently"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:620
|
||||
#: snikket_web/admin.py:639
|
||||
msgid "Circle deleted"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:634
|
||||
#: snikket_web/admin.py:653
|
||||
msgid "Group chat name"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:639
|
||||
#: snikket_web/admin.py:658
|
||||
msgid "Create group chat"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:669
|
||||
#: snikket_web/admin.py:688
|
||||
msgid "New group chat added to circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:736
|
||||
#: snikket_web/admin.py:755
|
||||
msgid "Message contents"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:742
|
||||
#: snikket_web/admin.py:761
|
||||
msgid "Only send to online users"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:746
|
||||
#: snikket_web/admin.py:765
|
||||
msgid "Post to all users"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:750
|
||||
#: snikket_web/admin.py:769
|
||||
msgid "Send preview to yourself"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:772
|
||||
#: snikket_web/admin.py:791
|
||||
msgid "Announcement sent!"
|
||||
msgstr ""
|
||||
|
||||
@@ -265,7 +270,7 @@ msgstr ""
|
||||
msgid "Yesterday"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/infra.py:105
|
||||
#: snikket_web/infra.py:104
|
||||
#, python-format
|
||||
msgid "%(time)s ago"
|
||||
msgstr ""
|
||||
@@ -276,60 +281,60 @@ msgid ""
|
||||
"contact your Snikket operator."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:114
|
||||
#: snikket_web/invite.py:124
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:118 snikket_web/invite.py:186 snikket_web/main.py:43
|
||||
#: snikket_web/invite.py:128 snikket_web/invite.py:200 snikket_web/main.py:43
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:122 snikket_web/invite.py:190
|
||||
#: snikket_web/invite.py:136 snikket_web/invite.py:208
|
||||
msgid "Confirm password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:126 snikket_web/invite.py:194
|
||||
#: snikket_web/invite.py:140 snikket_web/invite.py:212
|
||||
msgid "The passwords must match."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:131
|
||||
#: snikket_web/invite.py:145
|
||||
msgid "Create account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:158
|
||||
#: snikket_web/invite.py:172
|
||||
msgid "That username is already taken."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:162 snikket_web/invite.py:227
|
||||
#: snikket_web/invite.py:176 snikket_web/invite.py:245
|
||||
msgid "Registration was declined for unknown reasons."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:166
|
||||
#: snikket_web/invite.py:180
|
||||
msgid "The username is not valid."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:199 snikket_web/templates/user_home.html:32
|
||||
#: snikket_web/invite.py:217 snikket_web/templates/user_home.html:37
|
||||
#: snikket_web/templates/user_passwd.html:29
|
||||
msgid "Change password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:246
|
||||
#: snikket_web/invite.py:264
|
||||
msgid "Account data file"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:250
|
||||
#: snikket_web/invite.py:268
|
||||
msgid "Import data"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:271
|
||||
#: snikket_web/invite.py:289
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The account data you tried to import is in an unknown format. Please "
|
||||
"upload an XML file in XEP-0227 format (provided format: %(mimetype)s)."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:291 snikket_web/templates/unauth.html:18
|
||||
#: snikket_web/user.py:178
|
||||
#: snikket_web/invite.py:309 snikket_web/templates/unauth.html:18
|
||||
#: snikket_web/user.py:192
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
@@ -357,73 +362,73 @@ msgstr ""
|
||||
msgid "New password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:39
|
||||
#: snikket_web/user.py:42
|
||||
msgid "Confirm new password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:43
|
||||
#: snikket_web/user.py:47
|
||||
msgid "The new passwords must match."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:50
|
||||
#: snikket_web/user.py:56
|
||||
msgid "Sign out"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:55
|
||||
#: snikket_web/user.py:61
|
||||
msgid "Nobody"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:56
|
||||
#: snikket_web/user.py:62
|
||||
msgid "Friends only"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:57
|
||||
#: snikket_web/user.py:63
|
||||
msgid "Everyone"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:67
|
||||
#: snikket_web/user.py:73
|
||||
msgid "Avatar"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:71
|
||||
#: snikket_web/user.py:77
|
||||
msgid "Profile visibility"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:76
|
||||
#: snikket_web/user.py:82
|
||||
msgid "Update profile"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:82
|
||||
#: snikket_web/user.py:88
|
||||
msgid "Account data"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:86
|
||||
#: snikket_web/user.py:92
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:111
|
||||
#: snikket_web/user.py:125
|
||||
msgid "Incorrect password."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:115
|
||||
#: snikket_web/user.py:129
|
||||
msgid "Password changed"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:123
|
||||
#: snikket_web/user.py:138
|
||||
msgid ""
|
||||
"The chosen avatar is too big. To be able to upload larger avatars, please"
|
||||
" use the app."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:170
|
||||
#: snikket_web/user.py:184
|
||||
msgid "Profile updated"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:184
|
||||
#: snikket_web/user.py:198
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:202
|
||||
#: snikket_web/user.py:216
|
||||
msgid "You currently have no account data to export."
|
||||
msgstr ""
|
||||
|
||||
@@ -544,8 +549,8 @@ msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_circles.html:15
|
||||
#: snikket_web/templates/admin_edit_circle.html:45
|
||||
#: snikket_web/templates/admin_edit_circle.html:75
|
||||
#: snikket_web/templates/admin_invites.html:24
|
||||
#: snikket_web/templates/admin_edit_circle.html:74
|
||||
#: snikket_web/templates/admin_invites.html:25
|
||||
#: snikket_web/templates/admin_users.html:10
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
@@ -603,16 +608,42 @@ msgstr ""
|
||||
msgid "Create invitation"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:5
|
||||
#: snikket_web/templates/admin_create_invite_form.html:9
|
||||
#: snikket_web/templates/user_home.html:13
|
||||
msgid "Create new invitation"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:6
|
||||
#: snikket_web/templates/admin_create_invite_form.html:10
|
||||
msgid ""
|
||||
"Create a new invitation link to invite more users to your Snikket service"
|
||||
" by clicking the button below."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:16
|
||||
msgid ""
|
||||
"Choose whether this invitation link will allow more than one person to "
|
||||
"join."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:21
|
||||
#, python-format
|
||||
msgid "<span class=\"invite-type\">%(title)s%(icon)s</span><p>%(description)s</p>"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:34
|
||||
#: snikket_web/templates/admin_edit_user.html:38
|
||||
msgid ""
|
||||
"The access level of a user determines what interactions are allowed for "
|
||||
"them on your Snikket service."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:38
|
||||
#, python-format
|
||||
msgid ""
|
||||
"<span class=\"access-"
|
||||
"level\">%(title)s%(icon)s</span><p>%(description)s</p>"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_debug_user.html:8
|
||||
#, python-format
|
||||
msgid "Debug information for %(user_name)s"
|
||||
@@ -678,7 +709,7 @@ msgid "Delete user %(user_name)s"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_delete_user.html:6
|
||||
#: snikket_web/templates/admin_edit_user.html:74
|
||||
#: snikket_web/templates/admin_edit_user.html:58
|
||||
msgid "Delete user"
|
||||
msgstr ""
|
||||
|
||||
@@ -742,37 +773,37 @@ msgstr ""
|
||||
msgid "All members of the circle will see each other in their contact list."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:85
|
||||
#: snikket_web/templates/admin_edit_circle.html:84
|
||||
msgid "The user has been deleted from the server."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:85
|
||||
#: snikket_web/templates/library.j2:131
|
||||
#: snikket_web/templates/admin_edit_circle.html:84
|
||||
#: snikket_web/templates/library.j2:152
|
||||
msgid "deleted"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:91
|
||||
#: snikket_web/templates/admin_edit_circle.html:89
|
||||
#, python-format
|
||||
msgid "Remove user %(username)s from circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:99
|
||||
#: snikket_web/templates/admin_edit_circle.html:97
|
||||
msgid "This circle currently has no members."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:101
|
||||
#: snikket_web/templates/admin_edit_circle.html:99
|
||||
msgid "Invite more members"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:104
|
||||
#: snikket_web/templates/admin_edit_circle.html:102
|
||||
msgid "Add existing user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:115
|
||||
#: snikket_web/templates/admin_edit_circle.html:113
|
||||
msgid "All users added"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:116
|
||||
#: snikket_web/templates/admin_edit_circle.html:114
|
||||
msgid "All users on this service are already in this circle."
|
||||
msgstr ""
|
||||
|
||||
@@ -790,147 +821,129 @@ msgstr ""
|
||||
msgid "Link"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:22
|
||||
#: snikket_web/templates/admin_edit_invite.html:16
|
||||
msgid "Invitation to Snikket"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:23
|
||||
#: snikket_web/templates/admin_home.html:19
|
||||
msgid "Circles"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:23
|
||||
#: snikket_web/templates/admin_edit_invite.html:24
|
||||
msgid "Users joining via this invitation will be added to the following circles:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:29
|
||||
#: snikket_web/templates/admin_invites.html:23
|
||||
#: snikket_web/templates/admin_edit_invite.html:30
|
||||
#: snikket_web/templates/admin_invites.html:22
|
||||
msgid "Circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:35
|
||||
#: snikket_web/templates/admin_edit_invite.html:36
|
||||
msgid "The user will not be added to any circle and will have no contacts."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:40
|
||||
#: snikket_web/templates/admin_edit_invite.html:41
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:41
|
||||
#: snikket_web/templates/admin_edit_invite.html:42
|
||||
#, python-format
|
||||
msgid "The user will get added as contact of %(peer_jid)s."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:43
|
||||
#: snikket_web/templates/admin_edit_invite.html:44
|
||||
msgid "Created"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:48
|
||||
#: snikket_web/templates/admin_edit_invite.html:49
|
||||
msgid "Return to invitation list"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:5
|
||||
msgid ""
|
||||
"Limited users can interact with users on the same Snikket service and be "
|
||||
"members of circles."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:7
|
||||
msgid ""
|
||||
"Like limited users and can also interact with users on other Snikket "
|
||||
"services."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:9
|
||||
msgid "Like normal users and can access the admin panel in the web portal."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:20
|
||||
#: snikket_web/templates/admin_edit_user.html:4
|
||||
#: snikket_web/templates/admin_users.html:28
|
||||
#, python-format
|
||||
msgid "Edit user %(user_name)s"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:24
|
||||
#: snikket_web/templates/admin_edit_user.html:8
|
||||
msgid "This user account is pending deletion"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:25
|
||||
#: snikket_web/templates/admin_edit_user.html:9
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The owner of the account sent a deletion request on %(date)s using their "
|
||||
"app."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:26
|
||||
#: snikket_web/templates/admin_edit_user.html:10
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The account has been locked, and will be automatically deleted "
|
||||
"permanently in %(time)s."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:28
|
||||
#: snikket_web/templates/admin_edit_user.html:12
|
||||
msgid ""
|
||||
"If this was a mistake, you can cancel the deletion and restore the "
|
||||
"account."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:34
|
||||
#: snikket_web/templates/admin_edit_user.html:18
|
||||
msgid "This user account is locked"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:35
|
||||
#: snikket_web/templates/admin_edit_user.html:19
|
||||
msgid ""
|
||||
"The user will not be able to log in to their account until it is unlocked"
|
||||
" again."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:41
|
||||
#: snikket_web/templates/admin_edit_user.html:25
|
||||
msgid "Edit user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:46
|
||||
#: snikket_web/templates/admin_edit_user.html:30
|
||||
msgid "The login name cannot be changed."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:54
|
||||
msgid ""
|
||||
"The access level of a user determines what interactions are allowed for "
|
||||
"them on your Snikket service."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:61
|
||||
#: snikket_web/templates/admin_edit_user.html:45
|
||||
#, python-format
|
||||
msgid "<strong>%(title)s%(icon)s</strong><p>%(description)s</p>"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:71
|
||||
#: snikket_web/templates/admin_edit_user.html:55
|
||||
msgid "Return to user list"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:79
|
||||
#: snikket_web/templates/admin_edit_user.html:63
|
||||
msgid "Further actions"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:81
|
||||
#: snikket_web/templates/admin_edit_user.html:65
|
||||
msgid "Reset password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:84
|
||||
#: snikket_web/templates/admin_edit_user.html:68
|
||||
msgid ""
|
||||
"If the user has lost their password, you can use the button below to "
|
||||
"create a special link which allows to change the password of the account,"
|
||||
" once."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:89
|
||||
#: snikket_web/templates/admin_edit_user.html:73
|
||||
msgid "Debug information"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:91
|
||||
#: snikket_web/templates/admin_edit_user.html:75
|
||||
msgid ""
|
||||
"In some cases, extended information about the user account and the "
|
||||
"connected devices is necessary to troubleshoot issues. The button below "
|
||||
"reveals this (sensitive) information."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:95
|
||||
#: snikket_web/templates/admin_edit_user.html:79
|
||||
msgid "Show debug information"
|
||||
msgstr ""
|
||||
|
||||
@@ -1003,26 +1016,34 @@ msgid "Pending invitations"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:21
|
||||
msgid "Expires"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:22
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:43
|
||||
msgid "Show invite details"
|
||||
#: snikket_web/templates/admin_invites.html:23
|
||||
msgid "Expires"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:24
|
||||
msgid "Comment"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:46
|
||||
msgid "Copy invite link to clipboard"
|
||||
msgid "Show invite details"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:49
|
||||
msgid "Copy invite link to clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:52
|
||||
msgid "Share invitation link"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:55
|
||||
msgid "Delete invitation"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:57
|
||||
#: snikket_web/templates/admin_invites.html:63
|
||||
msgid "Currently, there are no pending invitations."
|
||||
msgstr ""
|
||||
|
||||
@@ -1060,7 +1081,7 @@ msgstr ""
|
||||
#: snikket_web/templates/admin_system.html:60
|
||||
#: snikket_web/templates/admin_system.html:68
|
||||
#: snikket_web/templates/admin_system.html:76
|
||||
#: snikket_web/templates/admin_system.html:84
|
||||
#: snikket_web/templates/admin_system.html:85
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
|
||||
@@ -1108,14 +1129,30 @@ msgid "Storage used by shared files"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:79
|
||||
msgid "Connected devices"
|
||||
msgid "Active users"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:83
|
||||
msgid "Connected now:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:88
|
||||
msgid "Past 24 hours:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:89
|
||||
msgid "Past 7 days:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:90
|
||||
msgid "Past 30 days:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:97
|
||||
msgid "Broadcast message"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:92
|
||||
#: snikket_web/templates/admin_system.html:99
|
||||
msgid ""
|
||||
"This form allows you to send a message to all users currently online on "
|
||||
"your Snikket server. Use it wisely."
|
||||
@@ -1260,11 +1297,11 @@ msgstr ""
|
||||
msgid "Reset your password | Snikket"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/invite_reset.html:15
|
||||
#: snikket_web/templates/invite_reset.html:14
|
||||
msgid "Reset your password online"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/invite_reset.html:16
|
||||
#: snikket_web/templates/invite_reset.html:15
|
||||
msgid ""
|
||||
"To reset your password online, fill out the fields below and confirm "
|
||||
"using the button."
|
||||
@@ -1358,7 +1395,7 @@ msgid "Your address"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/invite_success.html:15
|
||||
#: snikket_web/templates/user_home.html:21
|
||||
#: snikket_web/templates/user_home.html:26
|
||||
msgid "Copy address"
|
||||
msgstr ""
|
||||
|
||||
@@ -1544,20 +1581,40 @@ msgstr ""
|
||||
msgid " (Restricted)"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:41
|
||||
#: snikket_web/templates/library.j2:42
|
||||
msgid "Copy link"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:104
|
||||
#: snikket_web/templates/library.j2:43
|
||||
msgid "Share"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:125
|
||||
msgid "Invalid input"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:145
|
||||
msgid "Can be used multiple times to create accounts on this Snikket service."
|
||||
#: snikket_web/templates/library.j2:166
|
||||
msgid ""
|
||||
"Limited users can interact with users on the same Snikket service and be "
|
||||
"members of circles."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:147
|
||||
msgid "Can be used once to create an account on this Snikket service."
|
||||
#: snikket_web/templates/library.j2:168
|
||||
msgid ""
|
||||
"Like limited users and can also interact with users on other Snikket "
|
||||
"services."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:170
|
||||
msgid "Like normal users and can access the admin panel in the web portal."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:184
|
||||
msgid "Invite a single person (invitation link can only be used once)."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:186
|
||||
msgid "Invite a group of people (invitation link can be used multiple times)."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/login.html:5
|
||||
@@ -1620,41 +1677,42 @@ msgstr ""
|
||||
msgid "Operation successful"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:9
|
||||
msgid "Welcome!"
|
||||
#: snikket_web/templates/user_home.html:11
|
||||
msgid "Welcome to Snikket!"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:10
|
||||
#, python-format
|
||||
msgid "Welcome home, %(user_name)s."
|
||||
#: snikket_web/templates/user_home.html:12
|
||||
msgid ""
|
||||
"Now your Snikket instance is up and running, the next step is to invite "
|
||||
"people to join it. Family, friends, colleagues... you choose!"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:14
|
||||
#: snikket_web/templates/user_home.html:19
|
||||
msgid "Your account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:20
|
||||
#: snikket_web/templates/user_home.html:25
|
||||
msgid "Your XMPP address"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:31
|
||||
#: snikket_web/templates/user_home.html:36
|
||||
msgid "Edit profile"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:33
|
||||
#: snikket_web/templates/user_home.html:38
|
||||
#: snikket_web/templates/user_manage_data.html:4
|
||||
msgid "Manage your data"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:39
|
||||
#: snikket_web/templates/user_home.html:44
|
||||
msgid "Your Snikket"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:41
|
||||
#: snikket_web/templates/user_home.html:46
|
||||
msgid "Manage users, invitations and circles of your Snikket service."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:43
|
||||
#: snikket_web/templates/user_home.html:48
|
||||
msgid "Admin panel"
|
||||
msgstr ""
|
||||
|
||||
|
||||
BIN
snikket_web/translations/ru/LC_MESSAGES/messages.mo
Normal file
BIN
snikket_web/translations/uk/LC_MESSAGES/messages.mo
Normal file
1961
snikket_web/translations/uk/LC_MESSAGES/messages.po
Normal file
@@ -32,16 +32,22 @@ class ChangePasswordForm(BaseForm):
|
||||
|
||||
new_password = wtforms.PasswordField(
|
||||
_l("New password"),
|
||||
validators=[wtforms.validators.InputRequired()]
|
||||
validators=[
|
||||
wtforms.validators.InputRequired(),
|
||||
wtforms.validators.Length(min=10),
|
||||
]
|
||||
)
|
||||
|
||||
new_password_confirm = wtforms.PasswordField(
|
||||
_l("Confirm new password"),
|
||||
validators=[wtforms.validators.InputRequired(),
|
||||
wtforms.validators.EqualTo(
|
||||
"new_password",
|
||||
_l("The new passwords must match.")
|
||||
)]
|
||||
validators=[
|
||||
wtforms.validators.InputRequired(),
|
||||
wtforms.validators.EqualTo(
|
||||
"new_password",
|
||||
_l("The new passwords must match.")
|
||||
),
|
||||
wtforms.validators.Length(min=10),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -91,7 +97,15 @@ class ImportAccountDataForm(BaseForm):
|
||||
@client.require_session()
|
||||
async def index() -> str:
|
||||
user_info = await client.get_user_info()
|
||||
return await render_template("user_home.html", user_info=user_info)
|
||||
try:
|
||||
metrics = await client.get_system_metrics()
|
||||
except (werkzeug.exceptions.Unauthorized, werkzeug.exceptions.Forbidden):
|
||||
metrics = {}
|
||||
return await render_template(
|
||||
"user_home.html",
|
||||
user_info=user_info,
|
||||
metrics=metrics,
|
||||
)
|
||||
|
||||
|
||||
@bp.route('/passwd', methods=["GET", "POST"])
|
||||
|
||||
@@ -27,6 +27,7 @@ navigation/cancel:cancel
|
||||
navigation/more_vert:more
|
||||
social/groups:groups
|
||||
social/people:people
|
||||
social/person:person
|
||||
social/group_add:create_group
|
||||
social/person_add:add_user
|
||||
social/person_remove:remove_user
|
||||
@@ -35,3 +36,4 @@ image/edit:edit
|
||||
action/admin_panel_settings:admin
|
||||
content/link:link
|
||||
content/insights:insights
|
||||
social/share:share
|
||||
|
||||