Implemented tools as applets, Added Docker CCTV page, Fixed small issues

Update app.py, uuid-generator.yml, and 47 more files...
This commit is contained in:
2025-02-20 17:24:05 +01:00
parent bd96d85699
commit 0e91b5ed96
43 changed files with 889 additions and 337 deletions

View File

@@ -0,0 +1,44 @@
<label for="uuid-generator-option-type" class="mr-xs">{{ l10n("type.label", "uuid-generator", user_lang) }}:</label>
<select name="uuid-generator-option-type" id="uuid-generator-option-type" class="p-xxs border r-s">
<option value="type-uuid4" selected>{{ l10n("type.uuid4", "uuid-generator", user_lang) }}</option>
<!--<option value="type-guid">{{ l10n("type.guid", "uuid-generator", user_lang) }}</option>-->
</select>
<br>
<label for="uuid-generator-option-count" class="mr-xs">{{ l10n("option.count", "uuid-generator", user_lang) }}:</label>
<input id="uuid-generator-option-count" class="p-xxs border r-s" type="number" value="4" min="1" max="1000">
<br>
<label for="uuid-generator-option-hyphens" class="mr-xxs">{{ l10n("option.hyphen", "uuid-generator", user_lang) }}:</label>
<input id="uuid-generator-option-hyphens" class="r-m border" type="checkbox" checked>
<br>
<label for="uuid-generator-option-guid-brackets" class="mr-xxs">{{ l10n("option.guid_brackets", "uuid-generator", user_lang) }}:</label>
<input id="uuid-generator-option-guid-brackets" class="r-m border" type="checkbox">
<hr class="subtle">
<button id="uuid-generator-generate" class="p-xs r-s border b-light success">
<i class="fa-duotone fa-solid fa-gears mr-xs"></i>{{ l10n("generate", "uuid-generator", user_lang) }}
</button>
<button class="p-xs r-s border b-light primary rr-0 br-0">
<i class="fa-duotone fa-solid fa-download"></i>
</button>
<button id="uuid-generator-download-raw" class="p-xs r-s border b-light primary ml-0 r-0 br-0">
{{ l10n("download.raw", "uuid-generator", user_lang) }}
</button>
<button id="uuid-generator-download-json" class="p-xs r-s border b-light primary ml-0 r-0 br-0">
{{ l10n("download.json", "uuid-generator", user_lang) }}
</button>
<button id="uuid-generator-download-yaml" class="p-xs r-s border b-light primary ml-0 rl-0">
{{ l10n("download.yaml", "uuid-generator", user_lang) }}
</button>
<hr class="subtle">
<label for="uuid-generator-preview" class="d-none">{{ l10n("preview.label", "uuid-generator", user_lang) }}:</label>
<textarea name="uuid-generator-preview" id="uuid-generator-preview" rows="16" class="w-full border r-s"></textarea>

View File

@@ -10,7 +10,8 @@
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="alternate icon" href="/favicon.ico">
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.5.1/css/all.min.css">
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/StandardCSS/nibblepoker.min.css">
<!--<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/StandardCSS/nibblepoker.min.css">-->
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/IndevCSS/nibblepoker.min.css">
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/Quantum/Quantum.min.css">
<meta charset="UTF-8">

View File

@@ -19,7 +19,8 @@
{% block extra_preloads %}{% endblock %}
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.5.1/css/all.min.css">
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/StandardCSS/nibblepoker.min.css">
<!--<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/StandardCSS/nibblepoker.min.css">-->
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/IndevCSS/nibblepoker.min.css">
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/Quantum/Quantum.min.css">
{% block extra_stylesheets %}{% endblock %}
@@ -114,4 +115,4 @@
{% block extra_scripts %}{% endblock %}
</body>
</html>
</html>

View File

@@ -0,0 +1,5 @@
<code class="code ox-auto w-full d-inline-block position-relative language-{{ code_language }}">
{% for code_line in code_lines %}
<span class="code-line t-nowrap">{{ code_line }}</span><br>
{% endfor %}
</code>

View File

@@ -0,0 +1,9 @@
<ul class="l-bullets l-bullet-manual">
{% for list_item in list_items %}
{% if list_item.__class__.__name__ == 'list' %}
{{ render_list_ul(list_item) }}
{% else %}
<li>{{ list_item }}</li>
{% endif %}
{% endfor %}
</ul>

View File

@@ -1,3 +1,3 @@
<p class="mt-xs mx-s">
<p class="mt-xs">
{{ paragraph_inner_html }}
</p>

View File

@@ -17,22 +17,20 @@
{{ render_paragraph(l10n("introduction.text.1", "privacy", user_lang)) }}
{{ render_paragraph(l10n("introduction.text.2", "privacy", user_lang) +
'<br><i class="fad fa-globe ml-s t-size-8"></i>
<a href="https://gdpr.eu/privacy-notice/">
https://gdpr.eu/
</a><br>
<a href="https://gdpr.eu/privacy-notice/" class="ml-xs">https://gdpr.eu/</a><br>
<i class="fad fa-globe ml-s t-size-8"></i>
<a href="https://eur-lex.europa.eu/legal-content/ALL/?uri=CELEX%3A32016R0679">
https://eur-lex.europa.eu/
</a>')}}
<a href="https://eur-lex.europa.eu/legal-content/ALL/?uri=CELEX%3A32016R0679" class="ml-xs">https://eur-lex.europa.eu/</a>')}}
{{ render_h1(l10n("v2.data.title", "privacy", user_lang), "fad fa-database") }}
{{ render_paragraph(l10n("v2.data.intro.1", "privacy", user_lang) +
'<br>' + l10n("v2.data.intro.2", "privacy", user_lang)) }}
{{ render_paragraph(l10n('v2.data.private.1', "privacy", user_lang) +
'<ul><li>' + l10n('v2.data.private_list.1', "privacy", user_lang) +
'</li><li>' + l10n('v2.data.private_list.2', "privacy", user_lang) +
'</li></ul>') }}
render_list_ul([
l10n('v2.data.private_list.1', "privacy", user_lang),
l10n('v2.data.private_list.2', "privacy", user_lang),
])
) }}
{{ render_paragraph(l10n('v2.data.non_private.1', "privacy", user_lang) +
'<ul><li>' + l10n('v2.data.non_private_list.1', "privacy", user_lang) +
'</li><li>' + l10n('v2.data.non_private_list.2', "privacy", user_lang) +
@@ -167,17 +165,17 @@
{{ render_h1(l10n("contact.title", "privacy", user_lang), "fad fa-mailbox") }}
{{ render_paragraph(l10n("contact.text.1", "privacy", user_lang) +
'<br><i class="fad fa-at t-size-8 ml-s"></i><a href="mailto:herwin.bozet@gmail.com">herwin.bozet@gmail.com</a>') }}
'<br><i class="fad fa-at t-size-8 ml-s"></i><a class="ml-xs" href="mailto:herwin.bozet@gmail.com">herwin.bozet@gmail.com</a>') }}
{{ render_h1(l10n("complaint.title", "privacy", user_lang), "fad fa-gavel") }}
{{ render_paragraph(l10n("complaint.text.1", "privacy", user_lang)) }}
{{ render_paragraph(l10n('complaint.text.2', "privacy", user_lang) +
'<br><i class="fad fa-globe ml-s t-size-8"></i>' +
'<a href="https://ec.europa.eu/info/law/law-topic/data-protection/reform/rights-citizens/redress/what-should-i-do-if-i-think-my-personal-data-protection-rights-havent-been-respected_en">https://ec.europa.eu/</a>' +
'<a class="ml-xs" href="https://ec.europa.eu/info/law/law-topic/data-protection/reform/rights-citizens/redress/what-should-i-do-if-i-think-my-personal-data-protection-rights-havent-been-respected_en">https://ec.europa.eu/</a>' +
'<span class="ml-s">(' + l10n('english', "langs", user_lang) + ')</span>' +
'<br><i class="fad fa-globe ml-s t-size-8"></i>' +
'<a href="https://gegevensbeschermingsautoriteit.be/citoyen/agir/introduire-une-plainte">https://gegevensbeschermingsautoriteit.be/</a>' +
'<a class="ml-xs" href="https://gegevensbeschermingsautoriteit.be/citoyen/agir/introduire-une-plainte">https://gegevensbeschermingsautoriteit.be/</a>' +
'<span class="ml-s">(' + l10n('french', "langs", user_lang) + ')</span>' ) }}
{% endblock %}

View File

@@ -20,34 +20,35 @@
{{ render_h2(l10n("updates.title", "home", user_lang)) }}
<p><i class="fad fa-calendar-alt mr-xs"></i>{{ l10n("updates.4.date", "home", user_lang) }}</p>
<ul>
<li>{{ l10n("updates.4.text.1", "home", user_lang) }}</li>
<li>{{ l10n("updates.4.text.2", "home", user_lang) }}</li>
<li>{{ l10n("updates.4.text.3", "home", user_lang) }}</li>
<li>{{ l10n("updates.text.privacy", "home", user_lang) }}</li>
</ul>
<p><i class="fad fa-calendar-alt mr-xs mt-s"></i>{{ l10n("updates.4.date", "home", user_lang) }}</p>
{{ render_list_ul([
l10n("updates.4.text.1", "home", user_lang),
l10n("updates.4.text.2", "home", user_lang),
l10n("updates.4.text.3", "home", user_lang),
l10n("updates.text.privacy", "home", user_lang)
]) }}
<p><i class="fad fa-calendar-alt mr-xs"></i>{{ l10n("updates.3.date", "home", user_lang) }}</p>
<ul>
<li>{{ l10n("updates.3.text.1", "home", user_lang) }}</li>
<li>{{ l10n("updates.3.text.2", "home", user_lang) }}</li>
<li>{{ l10n("updates.3.text.3", "home", user_lang) }}</li>
<li>{{ l10n("updates.text.privacy", "home", user_lang) }}</li>
</ul>
<p><i class="fad fa-calendar-alt mr-xs mt-s"></i>{{ l10n("updates.3.date", "home", user_lang) }}</p>
{{ render_list_ul([
l10n("updates.3.text.1", "home", user_lang),
l10n("updates.3.text.2", "home", user_lang),
l10n("updates.3.text.3", "home", user_lang),
l10n("updates.text.privacy", "home", user_lang)
]) }}
<p><i class="fad fa-calendar-alt mr-xs"></i>{{ l10n("updates.2.date", "home", user_lang) }}</p>
<ul>
<li>{{ l10n("updates.2.text.1", "home", user_lang) }}</li>
<li>{{ l10n("updates.2.text.2", "home", user_lang) }}</li>
<li>{{ l10n("updates.2.text.3", "home", user_lang) }}</li>
<li>{{ l10n("updates.2.text.4", "home", user_lang) }}</li>
<li>{{ l10n("updates.text.privacy", "home", user_lang) }}</li>
</ul>
<p><i class="fad fa-calendar-alt mr-xs mt-s"></i>{{ l10n("updates.2.date", "home", user_lang) }}</p>
{{ render_list_ul([
l10n("updates.2.text.1", "home", user_lang),
l10n("updates.2.text.2", "home", user_lang),
l10n("updates.2.text.3", "home", user_lang),
l10n("updates.2.text.4", "home", user_lang),
l10n("updates.text.privacy", "home", user_lang)
]) }}
<p><i class="fad fa-calendar-alt mr-xs mt-s"></i>{{ l10n("updates.1.date", "home", user_lang) }}</p>
{{ render_list_ul([
l10n("updates.1.text.1", "home", user_lang),
l10n("updates.text.privacy", "home", user_lang)
]) }}
<p><i class="fad fa-calendar-alt mr-xs"></i>{{ l10n("updates.1.date", "home", user_lang) }}</p>
<ul>
<li>{{ l10n("updates.1.text.1", "home", user_lang) }}</li>
<li>{{ l10n("updates.text.privacy", "home", user_lang) }}</li>
</ul>
{% endblock %}

View File

@@ -4,9 +4,7 @@
{% block head_description %}{{ l10n(tool_data.metadata.head.description_key, tool_id, user_lang) }}{% endblock %}
{% block extra_stylesheets %}
{% for tool_stylesheet in tool_data.data.stylesheets %}
<link rel="stylesheet" href="{{ url_for("static", filename="/resources/NibblePoker/tools/" + tool_id + "/" + tool_stylesheet) }}">
{% endfor %}
{{ render_applet_head(applet_data) }}
{% endblock %}
{% block header_title %}
@@ -21,16 +19,10 @@
) }}
<div class="px-xxs">
{% block tool_content %}{% endblock %}
{% include 'applets/'+applet_data.id+'.jinja' %}
</div>
{% endblock %}
{% block extra_scripts %}
{% for tool_script in tool_data.data.scripts %}
{% if tool_script.endswith(".mjs") %}
<script src="{{ url_for("static", filename="/resources/NibblePoker/tools/" + tool_id + "/" + tool_script) }}" type="module"></script>
{% else %}
<script src="{{ url_for("static", filename="/resources/NibblePoker/tools/" + tool_id + "/" + tool_script) }}"></script>
{% endif %}
{% endfor %}
{{ render_applet_scripts(applet_data) }}
{% endblock %}

View File

@@ -38,4 +38,5 @@
<script src="https://cdn.nibblepoker.lu/HighlightJS/11.9.0-custom/highlight.min.js"></script>
<script src="{{ url_for("static", filename="/resources/NibblePoker/js/nibblepoker-splide.min.js") }}"></script>
<script src="{{ url_for("static", filename="/resources/NibblePoker/js/nibblepoker-code.min.js") }}"></script>
{% endblock %}

View File

@@ -0,0 +1,131 @@
{% extends "projects/_project.jinja" %}
{% block project_content %}
{{ render_h2(l10n("intro.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("intro.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("intro.2", project_id, user_lang)) }}
{{ render_h2(l10n("preamble.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("preamble.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("preamble.2", project_id, user_lang)) }}
{{ render_h2(l10n("setup.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.2", project_id, user_lang)) }}
{{ render_h3(l10n("setup.camera.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.camera.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.camera.2", project_id, user_lang)) }}
{{ render_h4(l10n("commons.example", project_id, user_lang)) }}
{{
render_code_block([
"nvr_stack:",
" cctv_recorder_cam1:",
" container_name: cctv-recorder-cam1",
" build:",
" context: .",
" dockerfile: Dockerfile_recorder",
" environment:",
" - TZ=Europe/Brussels",
" - \"NP_CCTV_URL=rtsp://user:password@address:554/sub-path\"",
" volumes:",
" - ./recordings/cam1:/data",
" restart: unless-stopped",
], "yaml")
}}
{{ render_paragraph(l10n("setup.camera.3", project_id, user_lang)) }}
{{ render_h3(l10n("setup.cleaner.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.cleaner.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.cleaner.2", project_id, user_lang)) }}
{{ render_h4(l10n("commons.example", project_id, user_lang)) }}
{{
render_code_block([
"nvr_stack:",
" cctv_cleaner:",
" container_name: cctv-cleaner",
" build:",
" context: .",
" dockerfile: Dockerfile_cleaner",
" environment:",
" - TZ=Europe/Brussels",
" - \"NP_MAX_FILE_AGE_HOURS=72\"",
" volumes:",
" - ./recordings:/data",
" - ./cleaner.py:/app/app.py:ro",
" restart: unless-stopped",
], "yaml")
}}
{{ render_h3(l10n("setup.web.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.web.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.web.2", project_id, user_lang)) }}
{{ render_paragraph(l10n("setup.web.3", project_id, user_lang)) }}
{{ render_h4(l10n("commons.web.vars.title", project_id, user_lang)) }}
{{ render_h4(l10n("commons.example", project_id, user_lang)) }}
{{
render_code_block([
"nvr_stack:",
" cctv_web:",
" container_name: cctv-web",
" image: php:apache",
" ports:",
" - 26880:80",
" environment:",
" - TZ=Europe/Brussels",
" - \"NP_CAM_cam1=Camera #1\"",
" - \"NP_CAM_cam2=Camera #2\"",
" - \"NP_TITLE=NibblePoker's Mini CCTV NVR\"",
" - \"NP_FOOTER=Made by <i>BOZET Herwin</i>\"",
" volumes:",
" - ./htdocs:/var/www/html # Cannot be \":ro\" since the recordings are mounted into it.",
" - ./apache2.conf:/etc/apache2/apache2.conf:ro",
" - ./recordings:/var/www/html/data:ro",
" restart: unless-stopped",
], "yaml")
}}
{{ render_h2(l10n("startup.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("startup.1", project_id, user_lang)) }}
{{
render_code_block([
"docker-compose up --build -d",
], "bash")
}}
{{ render_h2(l10n("screenshots.title", project_id, user_lang)) }}
{{ render_splide([
'<img src="' + url_for("static", filename="/resources/NibblePoker/images/content/" + project_id + "/home.png") + '">',
'<img src="' + url_for("static", filename="/resources/NibblePoker/images/content/" + project_id + "/cam.png") + '">',
]) }}
{{ render_h2(l10n("statistics.title", project_id, user_lang)) }}
{{ render_list_ul([
l10n("statistics.1", project_id, user_lang),
[
l10n("statistics.1.1", project_id, user_lang),
],
l10n("statistics.2", project_id, user_lang),
[
l10n("statistics.2.1", project_id, user_lang),
l10n("statistics.2.2", project_id, user_lang),
[
l10n("statistics.2.2.1", project_id, user_lang),
],
],
l10n("statistics.3", project_id, user_lang),
[
l10n("statistics.3.1", project_id, user_lang),
l10n("statistics.3.2", project_id, user_lang),
l10n("statistics.3.3", project_id, user_lang),
],
l10n("statistics.4", project_id, user_lang),
[
l10n("statistics.4.1", project_id, user_lang),
l10n("statistics.4.2", project_id, user_lang),
],
]) }}
{{ render_h2(l10n("license.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("license.1", project_id, user_lang)) }}
{% endblock %}

View File

@@ -1,38 +0,0 @@
{% extends "tools/_tool.jinja" %}
{% block tool_content %}
<div class="px-xs mt-s">
<label for="uuid-generator-option-type" class="mr-xs">{{ l10n("type.label", tool_id, user_lang) }}:</label>
<select name="uuid-generator-option-type" id="uuid-generator-option-type" class="p-xxs border r-s">
<option value="type-uuid4" selected>{{ l10n("type.uuid4", tool_id, user_lang) }}</option>
<option value="type-guid">{{ l10n("type.guid", tool_id, user_lang) }}</option>
</select>
<br>
<label for="uuid-generator-option-count" class="mr-xs">{{ l10n("option.count", tool_id, user_lang) }}:</label>
<input id="uuid-generator-option-count" class="p-xxs border r-s" type="number" value="4" min="1" max="1000">
<br>
<label for="uuid-generator-option-hyphens" class="mr-xxs">{{ l10n("option.hyphen", tool_id, user_lang) }}:</label>
<input id="uuid-generator-option-hyphens" type="checkbox" checked>
<hr class="subtle">
<button id="uuid-generator-generate" class="p-xs r-s border b-light success">
<i class="fa-duotone fa-solid fa-gears mr-xs"></i>{{ l10n("generate", tool_id, user_lang) }}
</button>
<button id="uuid-generator-download" class="p-xs r-s border b-light primary">
<i class="fa-duotone fa-solid fa-download mr-xs"></i>{{ l10n("download", tool_id, user_lang) }}
</button>
<hr class="subtle">
<label for="uuid-generator-preview" class="d-none">{{ l10n("preview.label", tool_id, user_lang) }}:</label>
<textarea name="uuid-generator-preview" id="uuid-generator-preview" rows="16" class="w-full border r-s"></textarea>
</div>
{% endblock %}