mirror of
https://codeberg.org/catask-org/catask.git
synced 2025-04-20 13:53:42 -05:00
374 lines
17 KiB
HTML
374 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
{% if cfg.accessibility.userway.enabled %}
|
|
<script src="https://cdn.userway.org/widget.js" data-account="{{ cfg.accessibility.userway.account }}"></script>
|
|
{% endif %}
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
{% if not (cfg.style.overrideBaseStyles and cfg.style.useCustomCss) %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
|
|
{% endif %}
|
|
{% if not (cfg.style.overrideCatAskStyles and cfg.style.useCustomCss) %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
{% if cfg.style.tintColors %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/tinted.css') }}">
|
|
{% endif %}
|
|
<style>
|
|
{% if cfg.accessibility.font == 'default' %}
|
|
@font-face {
|
|
font-family: "Rubik";
|
|
font-display: swap;
|
|
font-weight: 100 900;
|
|
src: url("/static/fonts/rubik.woff2") format('woff2-variations');
|
|
}
|
|
:root {
|
|
--bs-font-sans-serif: "Rubik", sans-serif;
|
|
}
|
|
{% elif cfg.accessibility.font == 'default' %}
|
|
:root {
|
|
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif;
|
|
}
|
|
{% elif cfg.accessibility.font == 'atkinson' %}
|
|
@font-face {
|
|
font-family: 'Atkinson Hyperlegible';
|
|
src: local('Atkinson Hyperlegible Bold'), local('AtkinsonHyperlegible-Bold'),
|
|
url('/static/fonts/Atkinson-Hyperlegible-Bold.woff2') format('woff2');
|
|
font-weight: bold;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Atkinson Hyperlegible';
|
|
src: local('Atkinson Hyperlegible Bold Italic'), local('AtkinsonHyperlegible-BoldItalic'),
|
|
url('/static/fonts/Atkinson-Hyperlegible-BoldItalic.woff2') format('woff2');
|
|
font-weight: bold;
|
|
font-style: italic;
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Atkinson Hyperlegible';
|
|
src: local('Atkinson Hyperlegible Italic'), local('AtkinsonHyperlegible-Italic'),
|
|
url('/static/fonts/Atkinson-Hyperlegible-Italic.woff2') format('woff2');
|
|
font-weight: normal;
|
|
font-style: italic;
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Atkinson Hyperlegible';
|
|
src: local('Atkinson Hyperlegible Regular'), local('AtkinsonHyperlegible-Regular'),
|
|
url('/static/fonts/Atkinson-Hyperlegible-Regular.woff2') format('woff2');
|
|
font-weight: normal;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
:root {
|
|
--bs-font-sans-serif: "Atkinson Hyperlegible", sans-serif;
|
|
--bs-body-font-size: 1.05rem;
|
|
}
|
|
.dropdown-toggle::after {
|
|
vertical-align: -.125em;
|
|
}
|
|
.btn:not(.btn-sm) {
|
|
--bs-btn-font-size: 1.02rem;
|
|
}
|
|
.btn-group-sm > .btn, .btn-sm {
|
|
--bs-btn-font-size: 0.91rem;
|
|
}
|
|
.nav {
|
|
--bs-nav-link-font-size: 1rem;
|
|
}
|
|
.bi::before, [class*=" bi-"]::before, [class^="bi-"]::before {
|
|
vertical-align: -.2em;
|
|
}
|
|
{% endif %}
|
|
[data-bs-theme=light] {
|
|
--bs-primary: {{ cfg.style.accentLight }} !important;
|
|
}
|
|
[data-bs-theme=dark] {
|
|
--bs-primary: {{ cfg.style.accentDark }} !important;
|
|
}
|
|
</style>
|
|
{% endif %}
|
|
{% if cfg.style.customCss and cfg.style.useCustomCss %}
|
|
<style>
|
|
{{ cfg.style.customCss | safe }}
|
|
</style>
|
|
{% endif %}
|
|
<style>
|
|
/* some essential styles so 3rd-party themes don't break */
|
|
.markdown-content p {
|
|
margin: 0;
|
|
}
|
|
.markdown-content ol {
|
|
margin-bottom: 0;
|
|
}
|
|
.markdown-content blockquote {
|
|
border-left: 3px solid var(--bs-border-color);
|
|
}
|
|
.markdown-content blockquote p {
|
|
margin-left: .5rem;
|
|
}
|
|
.markdown-content p:not(:first-child) {
|
|
margin-top: .5rem;
|
|
}
|
|
.fw-buttons button {
|
|
width: 100%;
|
|
margin-top: .25rem;
|
|
margin-bottom: .25rem;
|
|
}
|
|
.tab {
|
|
display: inline-flex;
|
|
min-width: 130px;
|
|
align-items: center;
|
|
gap: .25em;
|
|
}
|
|
.htmx-indicator {
|
|
display: none;
|
|
}
|
|
.htmx-request .htmx-indicator,
|
|
.htmx-request.htmx-indicator {
|
|
display: inline-block;
|
|
}
|
|
.btn-close {
|
|
--bs-btn-close-bg: none;
|
|
}
|
|
.ts-share {
|
|
max-width: 300px;
|
|
text-overflow: ellipsis;
|
|
align-content: center;
|
|
}
|
|
.no-arrow.dropdown-toggle::after {
|
|
border: none;
|
|
display: none;
|
|
}
|
|
{#- for compatibility #}
|
|
{%- if cfg.style.useCustomCss and cfg.style.overrideCatAskStyles %}
|
|
.modal-header .btn-close i {
|
|
display: none;
|
|
}
|
|
{%- endif %}
|
|
@media screen and (max-width: 1200px) {
|
|
.ts-share {
|
|
max-width: 250px;
|
|
}
|
|
}
|
|
@media screen and (min-width: 620px) and (max-width: 991px) {
|
|
.modal-dialog {
|
|
--bs-modal-width: 95%;
|
|
}
|
|
}
|
|
@media screen and (max-width: 767px) {
|
|
.ts-share {
|
|
max-width: unset;
|
|
width: 100%;
|
|
}
|
|
}
|
|
@media screen and (min-width: 767px) and (max-width: 840px) {
|
|
.ts-share {
|
|
max-width: 190px;
|
|
}
|
|
}
|
|
</style>
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-icons.min.css') }}">
|
|
{%- if cfg.accessibility.font == 'default' -%}
|
|
<link rel="preload" href="{{ url_for('static', filename='fonts/rubik.woff2') }}" as="font" type="font/woff2" crossorigin>
|
|
{%- endif -%}
|
|
|
|
<!-- favicon -->
|
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='icons/favicon/apple-touch-icon.png') }}">
|
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='icons/favicon/favicon-32x32.png') }}">
|
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='icons/favicon/favicon-16x16.png') }}">
|
|
<link rel="icon" type="image/png" sizes="192x192" href="{{ url_for('static', filename='icons/favicon/android-chrome-192x192.png') }}">
|
|
<link rel="icon" type="image/png" sizes="512x512" href="{{ url_for('static', filename='icons/favicon/android-chrome-512x512.png') }}">
|
|
<link rel="shortcut icon" href="{{ url_for('static', filename='icons/favicon/favicon.ico') }}">
|
|
|
|
<!-- metadata -->
|
|
<!-- Primary Meta Tags -->
|
|
<meta name="title" content="{{ metadata.title }}" />
|
|
<meta name="description" content="{{ metadata.description }}" />
|
|
|
|
<!-- Open Graph / Facebook -->
|
|
<meta property="og:type" content="website" />
|
|
<meta property="og:url" content="{{ metadata.url }}" />
|
|
<meta property="og:title" content="{{ metadata.title }}" />
|
|
<meta property="og:description" content="{{ metadata.description }}" />
|
|
<meta property="og:image" content="{{ metadata.image }}" />
|
|
|
|
<!-- Twitter -->
|
|
<meta property="twitter:card" content="summary_large_image" />
|
|
<meta property="twitter:url" content="{{ metadata.url }}" />
|
|
<meta property="twitter:title" content="{{ metadata.title }}" />
|
|
<meta property="twitter:description" content="{{ metadata.description }}" />
|
|
<meta property="twitter:image" content="{{ metadata.image }}" />
|
|
|
|
<!-- pwa manifest -->
|
|
<link rel="manifest" href="{{ url_for('api.pwaManifest') }}" />
|
|
<script src="{{ url_for('static', filename='js/color-modes.js') }}"></script>
|
|
|
|
{% block additionalHeadItems %}{% endblock %}
|
|
<script src="{{ url_for('static', filename='js/htmx.min.js') }}"></script>
|
|
<title>{% block title %}{% endblock %} | {{ cfg.instance.title }}</title>
|
|
</head>
|
|
<body class="">
|
|
<a class="visually-hidden-focusable btn" href="#main-content">Skip to content</a>
|
|
<div class="mb-2{% if not bodyNoXMargin %} px-3{% endif %} col-xxl-11{% if not noContainerFluid %} container-fluid{% endif %}">
|
|
{% block navbar %}
|
|
<div class="d-flex justify-content-between align-items-center mt-3 {% if logged_in %}mb-3{% endif %}">
|
|
<ul class="nav nav-{{ cfg.style.navStyle }} position-relative">
|
|
<li class="nav-item d-flex align-items-center {% if cfg.style.navStyle == 'pills' %}me-1{% endif %}"><a href="{{ url_for('index') }}" aria-label="{{ cfg.instance.title }}'s icon"><img src="{{ url_for('static', filename='icons/favicon/apple-touch-icon.png') }}" loading="lazy" width="32" height="32" alt="{{ cfg.instance.title }}'s icon"></a></li>
|
|
<ul class="d-flex p-0">
|
|
{% include 'snippets/navLinks.html' %}
|
|
</ul>
|
|
</ul>
|
|
<ul class="nav nav-{{ cfg.style.navStyle }} m-0">
|
|
{% if logged_in %}
|
|
<form action="{{ url_for('admin.logout') }}" method="POST" class="d-none" id="logout_form"></form>
|
|
<li>
|
|
<button form="logout_form" type="submit" class="nav-link"{% if cfg.style.navIconsOnly %} title="{{ _('Logout') }}"{% endif %}>
|
|
{% if cfg.style.navIcons %}<i class="bi bi-box-arrow-right fs-mob-5{% if cfg.style.navIconsOnly %} fs-5{% endif %}"></i>{% endif %}
|
|
{% if not cfg.style.navIconsOnly %}<span{% if cfg.style.navIcons %} class="d-none d-lg-inline ms-1"{% endif %}>{{ _('Logout') }}</span>{% endif %}
|
|
</button>
|
|
</li>
|
|
{% else %}
|
|
<li>
|
|
<a class="nav-link {{ loginLink }}" href="{{ url_for('admin.login') }}"{% if cfg.style.navIconsOnly %} title="{{ _('Login') }}"{% endif %}>
|
|
{% if cfg.style.navIcons %}<i class="bi bi-box-arrow-in-right fs-mob-5{% if cfg.style.navIconsOnly %} fs-5{% endif %}"></i>{% endif %}
|
|
{% if not cfg.style.navIconsOnly %}<span{% if cfg.style.navIcons %} class="d-none d-lg-inline ms-1"{% endif %}>{{ _('Login') }}</span>{% endif %}
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
</div>
|
|
{# will do later
|
|
<div class="d-flex border-top bg-body z-3 px-3 py-2 d-md-none fixed-bottom mobile-nav">
|
|
<ul class="nav nav-{{ cfg.style.navStyle }} position-relative d-flex justify-content-between w-100">
|
|
{% with mobileNav = True %}
|
|
{% include 'snippets/navLinks.html' %}
|
|
{% endwith %}
|
|
</ul>
|
|
</div>
|
|
#}
|
|
{% endblock %}
|
|
{% with messages = get_flashed_messages(with_categories=True) %}
|
|
{% if messages %}
|
|
{% for category, message in messages %}
|
|
<div class="alert alert-{{ category }} alert-dismissible col-lg-4 m-auto" role="alert">
|
|
<p class="m-0">{{ message }}</p>
|
|
<button type="button" class="btn-close d-flex align-items-stretch fs-5 p-3" data-bs-dismiss="alert" aria-label="Close"><i class="bi bi-x-lg lh-sm"></i></button>
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endwith %}
|
|
<div id="main-content">
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
{% block footer %}
|
|
<footer class="py-3 my-4 d-flex justify-content-between align-items-center">
|
|
<div class="d-flex gap-2">
|
|
<div class="dropdown bd-mode-toggle">
|
|
<button class="btn btn-outline-secondary py-2 dropdown-toggle"
|
|
id="bd-theme"
|
|
type="button"
|
|
aria-expanded="false"
|
|
data-bs-toggle="dropdown"
|
|
data-bs-auto-close="outside"
|
|
aria-label="Toggle theme (auto)">
|
|
<i class="bi bi-circle-half my-1" id="theme-icon-active"></i>
|
|
<span class="visually-hidden" id="bd-theme-text">{{ _('Toggle theme') }}</span>
|
|
</button>
|
|
<ul class="dropdown-menu" aria-labelledby="bd-theme-text">
|
|
<li>
|
|
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="light" aria-pressed="false">
|
|
<i class="bi me-2 opacity-50 bi-sun-fill"></i> {{ _('Light') }}
|
|
<i class="bi ms-auto d-none bi-check2 theme-check"></i>
|
|
</button>
|
|
</li>
|
|
<li>
|
|
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="dark" aria-pressed="false">
|
|
<i class="bi me-2 opacity-50 bi-moon-stars-fill"></i> {{ _('Dark') }}
|
|
<i class="bi ms-auto d-none bi-check2 theme-check"></i>
|
|
</button>
|
|
</li>
|
|
<li>
|
|
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="auto" aria-pressed="false">
|
|
<i class="bi me-2 opacity-50 bi-circle-half"></i> {{ _('Auto') }}
|
|
<i class="bi ms-auto d-none bi-check2 theme-check"></i>
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
{% if cfg.languages.allowChanging %}
|
|
<div class="dropdown">
|
|
<button class="btn btn-outline-secondary py-2 dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-label="{{ _('Change language') }}">
|
|
<i class="bi bi-translate opacity-50 me-2"></i>
|
|
<span class="visually-hidden">{{ _('Change language') }}</span>
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<form action="{{ url_for('api.changeLanguage') }}" method="POST">
|
|
{% for language in config.available_languages.items() %}
|
|
<li>
|
|
<button type="submit" name="lang" value="{{ language[0] }}" class="dropdown-item d-flex align-items-center{% if language[0] == session.get('language') %} active{% endif %}" aria-pressed="false">
|
|
{{ _(language[1]) }}
|
|
<i class="bi ms-auto{% if language[0] != session.get('language') %} d-none{% endif %} bi-check2"></i>
|
|
</button>
|
|
</li>
|
|
{% endfor %}
|
|
</form>
|
|
</ul>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="text-body-secondary text-end small">
|
|
<p class="text-decoration-none m-0 d-flex align-items-center gap-1">
|
|
<img src="{{ url_for('static', filename='icons/catask.svg') }}" width="20" height="20" alt="{{ const.appName }} logo">
|
|
{{ const.appName }} <span class="fw-medium">{{ version }}{{ version_id }}</span>
|
|
</p>
|
|
<div class="d-flex gap-2 fs-5 justify-content-end">
|
|
<a href="{{ const.homepageUrl }}" class="icon-link text-decoration-none" target="_blank" title="{{ _('Website') }}">
|
|
<i class="bi bi-globe2"></i>
|
|
<span class="visually-hidden">{{ _('Website') }}</span>
|
|
</a>
|
|
<a href="{{ const.docsUrl }}" class="icon-link text-decoration-none" target="_blank" title="{{ _('Documentation') }}">
|
|
<i class="bi bi-book-half"></i>
|
|
<span class="visually-hidden">{{ _('Documentation') }}</span>
|
|
</a>
|
|
<a href="{{ const.social.bskyUrl }}" class="icon-link text-decoration-none" target="_blank" title="{{ _('Bluesky') }}">
|
|
<svg width="20" height="20" viewBox="0 0 568 501" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path fill="currentColor" d="M123.121 33.6637C188.241 82.5526 258.281 181.681 284 234.873C309.719 181.681 379.759 82.5526 444.879 33.6637C491.866 -1.61183 568 -28.9064 568 57.9464C568 75.2916 558.055 203.659 552.222 224.501C531.947 296.954 458.067 315.434 392.347 304.249C507.222 323.8 536.444 388.56 473.333 453.32C353.473 576.312 301.061 422.461 287.631 383.039C285.169 375.812 284.017 372.431 284 375.306C283.983 372.431 282.831 375.812 280.369 383.039C266.939 422.461 214.527 576.312 94.6667 453.32C31.5556 388.56 60.7778 323.8 175.653 304.249C109.933 315.434 36.0535 296.954 15.7778 224.501C9.94525 203.659 0 75.2916 0 57.9464C0 -28.9064 76.1345 -1.61183 123.121 33.6637Z"></path>
|
|
</svg>
|
|
<span class="visually-hidden">{{ _('Bluesky') }}</span>
|
|
</a>
|
|
<a href="{{ const.social.fediUrl }}" class="icon-link text-decoration-none" target="_blank" title="{{ _('Fediverse') }}">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 64 64">
|
|
<path fill="currentColor" d="M12.088 23.868a6.734 6.732 0 0 1-2.88 2.866L25.02 42.602l3.812-1.93Zm20.857 20.93-3.812 1.932 8.012 8.04a6.734 6.732 0 0 1 2.88-2.866z"></path>
|
|
<path fill="currentColor" d="m51.24 30.147-8.952 4.535.66 4.22 10.128-5.131a6.734 6.732 0 0 1-1.837-3.624Zm-14.15 7.168L15.926 48.038a6.734 6.732 0 0 1 1.837 3.624l19.989-10.127z"></path>
|
|
<path fill="currentColor" d="M30.284 10.9 20.071 30.833l3.016 3.027L33.9 12.755a6.734 6.732 0 0 1-3.616-1.854zm-12.87 25.117-5.172 10.095a6.734 6.732 0 0 1 3.615 1.855l4.573-8.925z"></path>
|
|
<path fill="currentColor" d="M9.12 26.778a6.734 6.732 0 0 1-3.364.703 6.734 6.732 0 0 1-.65-.068l3.02 19.316a6.734 6.732 0 0 1 3.365-.703 6.734 6.732 0 0 1 .65.068z"></path>
|
|
<path fill="currentColor" d="M17.779 51.758a6.734 6.732 0 0 1 .07 1.356 6.734 6.732 0 0 1-.71 2.656l19.318 3.099a6.734 6.732 0 0 1-.07-1.356 6.734 6.732 0 0 1 .71-2.656Z"></path>
|
|
<path fill="currentColor" d="m53.144 33.841-8.917 17.402a6.734 6.732 0 0 1 3.617 1.855l8.916-17.402a6.734 6.732 0 0 1-3.616-1.855z"></path>
|
|
<path fill="currentColor" d="M40.983 9.229a6.734 6.732 0 0 1-2.88 2.866L51.91 25.953a6.734 6.732 0 0 1 2.88-2.867z"></path>
|
|
<path fill="currentColor" d="M28.38 7.206 10.922 16.05a6.734 6.732 0 0 1 1.837 3.624l17.456-8.844a6.734 6.732 0 0 1-1.837-3.624Z"></path>
|
|
<path fill="currentColor" d="M38.07 12.111a6.734 6.732 0 0 1-3.42.731 6.734 6.732 0 0 1-.589-.062l1.546 9.898 4.22.677zm-1.564 16.322 3.656 23.402a6.734 6.732 0 0 1 3.315-.678 6.734 6.732 0 0 1 .705.077L40.726 29.11Z"></path>
|
|
<path fill="currentColor" d="M12.772 19.748a6.734 6.732 0 0 1 .075 1.377 6.734 6.732 0 0 1-.7 2.637l9.909 1.59 1.947-3.801zm16.984 2.726-1.948 3.803 23.413 3.759a6.734 6.732 0 0 1-.068-1.341 6.734 6.732 0 0 1 .718-2.67z"></path>
|
|
<circle fill="currentColor" cx="35.017" cy="6.12" r="6.12"></circle>
|
|
<circle fill="currentColor" cx="57.878" cy="29.062" r="6.12"></circle>
|
|
<circle fill="currentColor" cx="43.111" cy="57.88" r="6.12"></circle>
|
|
<circle fill="currentColor" cx="11.124" cy="52.749" r="6.12"></circle>
|
|
<circle fill="currentColor" cx="6.122" cy="20.759" r="6.12"></circle>
|
|
</svg>
|
|
<span class="visually-hidden">{{ _('Fediverse') }}</span>
|
|
</a>
|
|
<a href="{{ const.repoUrl }}" class="icon-link text-decoration-none" target="_blank" title="{{ _('Source code') }}"><i class="bi bi-git"></i> <span class="visually-hidden">{{ _('Source code') }}</span></a>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
{% endblock %}
|
|
</div>
|
|
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
|
|
{% block scripts %}{% endblock %}
|
|
</body>
|
|
</html>
|