@geekity/cms 0.40.0 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/components/blocks.njk +15 -1
- package/admin/pages/appearance/look.njk +135 -0
- package/admin/pages/dashboard/home.njk +9 -3
- package/admin/pages/documents/conflict.njk +35 -10
- package/admin/pages/documents/editor.njk +29 -0
- package/admin/pages/documents/list.njk +44 -1
- package/admin/pages/settings/general.njk +4 -0
- package/admin/pages/settings/reading.njk +14 -0
- package/admin/pages/users/edit.njk +1 -1
- package/admin/pages/users/writing-goals.njk +64 -0
- package/admin/src/admin.css +32 -0
- package/admin/static/admin.css +202 -4
- package/admin/static/dashboard.js +51 -23
- package/admin/static/editor.js +22 -19
- package/dist/access-log.d.ts +3 -0
- package/dist/access-log.d.ts.map +1 -1
- package/dist/access-log.js +13 -9
- package/dist/access-log.js.map +1 -1
- package/dist/admin/autosave-client.d.ts +85 -0
- package/dist/admin/autosave-client.d.ts.map +1 -0
- package/dist/admin/autosave-client.js +218 -0
- package/dist/admin/autosave-client.js.map +1 -0
- package/dist/admin/autosave.d.ts +12 -0
- package/dist/admin/autosave.d.ts.map +1 -0
- package/dist/admin/autosave.js +92 -0
- package/dist/admin/autosave.js.map +1 -0
- package/dist/admin/blocks.d.ts +13 -1
- package/dist/admin/blocks.d.ts.map +1 -1
- package/dist/admin/blocks.js +40 -5
- package/dist/admin/blocks.js.map +1 -1
- package/dist/admin/core-widgets.d.ts.map +1 -1
- package/dist/admin/core-widgets.js +2 -0
- package/dist/admin/core-widgets.js.map +1 -1
- package/dist/admin/dashboard.d.ts +2 -2
- package/dist/admin/dashboard.d.ts.map +1 -1
- package/dist/admin/dashboard.js +23 -15
- package/dist/admin/dashboard.js.map +1 -1
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +223 -16
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/editor-word-counter.d.ts +8 -0
- package/dist/admin/editor-word-counter.d.ts.map +1 -0
- package/dist/admin/editor-word-counter.js +27 -0
- package/dist/admin/editor-word-counter.js.map +1 -0
- package/dist/admin/editor-words.d.ts +7 -0
- package/dist/admin/editor-words.d.ts.map +1 -0
- package/dist/admin/editor-words.js +9 -0
- package/dist/admin/editor-words.js.map +1 -0
- package/dist/admin/flash.d.ts +2 -0
- package/dist/admin/flash.d.ts.map +1 -1
- package/dist/admin/flash.js +12 -0
- package/dist/admin/flash.js.map +1 -1
- package/dist/admin/focus-mode.d.ts +37 -0
- package/dist/admin/focus-mode.d.ts.map +1 -0
- package/dist/admin/focus-mode.js +71 -0
- package/dist/admin/focus-mode.js.map +1 -0
- package/dist/admin/look.d.ts +12 -0
- package/dist/admin/look.d.ts.map +1 -0
- package/dist/admin/look.js +179 -0
- package/dist/admin/look.js.map +1 -0
- package/dist/admin/menu.d.ts.map +1 -1
- package/dist/admin/menu.js +7 -3
- package/dist/admin/menu.js.map +1 -1
- package/dist/admin/preview.d.ts.map +1 -1
- package/dist/admin/preview.js +1 -0
- package/dist/admin/preview.js.map +1 -1
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +8 -4
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/settings-fields.d.ts +1 -1
- package/dist/admin/settings-fields.d.ts.map +1 -1
- package/dist/admin/settings-fields.js +2 -0
- package/dist/admin/settings-fields.js.map +1 -1
- package/dist/admin/settings-general.d.ts.map +1 -1
- package/dist/admin/settings-general.js +1 -0
- package/dist/admin/settings-general.js.map +1 -1
- package/dist/admin/settings-reading.d.ts.map +1 -1
- package/dist/admin/settings-reading.js +7 -1
- package/dist/admin/settings-reading.js.map +1 -1
- package/dist/admin/templates.d.ts +2 -0
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +2 -0
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/users.d.ts.map +1 -1
- package/dist/admin/users.js +4 -0
- package/dist/admin/users.js.map +1 -1
- package/dist/admin/widget-writing.d.ts +3 -0
- package/dist/admin/widget-writing.d.ts.map +1 -0
- package/dist/admin/widget-writing.js +102 -0
- package/dist/admin/widget-writing.js.map +1 -0
- package/dist/admin/widgets.d.ts +4 -1
- package/dist/admin/widgets.d.ts.map +1 -1
- package/dist/admin/widgets.js +19 -8
- package/dist/admin/widgets.js.map +1 -1
- package/dist/admin/writing-goals.d.ts +33 -0
- package/dist/admin/writing-goals.d.ts.map +1 -0
- package/dist/admin/writing-goals.js +149 -0
- package/dist/admin/writing-goals.js.map +1 -0
- package/dist/autosave/index.d.ts +5 -0
- package/dist/autosave/index.d.ts.map +1 -0
- package/dist/autosave/index.js +3 -0
- package/dist/autosave/index.js.map +1 -0
- package/dist/autosave/key.d.ts +13 -0
- package/dist/autosave/key.d.ts.map +1 -0
- package/dist/autosave/key.js +29 -0
- package/dist/autosave/key.js.map +1 -0
- package/dist/autosave/store.d.ts +23 -0
- package/dist/autosave/store.d.ts.map +1 -0
- package/dist/autosave/store.js +114 -0
- package/dist/autosave/store.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +65 -4
- package/dist/cli.js.map +1 -1
- package/dist/cms/app.d.ts.map +1 -1
- package/dist/cms/app.js +1 -0
- package/dist/cms/app.js.map +1 -1
- package/dist/cms/boot.d.ts.map +1 -1
- package/dist/cms/boot.js +2 -0
- package/dist/cms/boot.js.map +1 -1
- package/dist/cms/create.d.ts +11 -2
- package/dist/cms/create.d.ts.map +1 -1
- package/dist/cms/create.js +61 -2
- package/dist/cms/create.js.map +1 -1
- package/dist/cms/server-error.d.ts.map +1 -1
- package/dist/cms/server-error.js +1 -0
- package/dist/cms/server-error.js.map +1 -1
- package/dist/cms/services.d.ts +2 -0
- package/dist/cms/services.d.ts.map +1 -1
- package/dist/cms/services.js +14 -0
- package/dist/cms/services.js.map +1 -1
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -2
- package/dist/config.js.map +1 -1
- package/dist/content/post-type.d.ts +1 -0
- package/dist/content/post-type.d.ts.map +1 -1
- package/dist/content/post-type.js +1 -1
- package/dist/content/post-type.js.map +1 -1
- package/dist/content/words.d.ts +3 -0
- package/dist/content/words.d.ts.map +1 -0
- package/dist/content/words.js +120 -0
- package/dist/content/words.js.map +1 -0
- package/dist/content/write.d.ts +8 -0
- package/dist/content/write.d.ts.map +1 -1
- package/dist/content/write.js +1 -1
- package/dist/content/write.js.map +1 -1
- package/dist/files/data-files.d.ts +5 -0
- package/dist/files/data-files.d.ts.map +1 -1
- package/dist/files/data-files.js +30 -0
- package/dist/files/data-files.js.map +1 -1
- package/dist/fonts/css.d.ts +25 -0
- package/dist/fonts/css.d.ts.map +1 -0
- package/dist/fonts/css.js +88 -0
- package/dist/fonts/css.js.map +1 -0
- package/dist/fonts/family.d.ts +23 -0
- package/dist/fonts/family.d.ts.map +1 -0
- package/dist/fonts/family.js +41 -0
- package/dist/fonts/family.js.map +1 -0
- package/dist/fonts/index.d.ts +10 -0
- package/dist/fonts/index.d.ts.map +1 -0
- package/dist/fonts/index.js +6 -0
- package/dist/fonts/index.js.map +1 -0
- package/dist/fonts/job.d.ts +20 -0
- package/dist/fonts/job.d.ts.map +1 -0
- package/dist/fonts/job.js +49 -0
- package/dist/fonts/job.js.map +1 -0
- package/dist/fonts/roles.d.ts +53 -0
- package/dist/fonts/roles.d.ts.map +1 -0
- package/dist/fonts/roles.js +64 -0
- package/dist/fonts/roles.js.map +1 -0
- package/dist/fonts/store.d.ts +69 -0
- package/dist/fonts/store.d.ts.map +1 -0
- package/dist/fonts/store.js +237 -0
- package/dist/fonts/store.js.map +1 -0
- package/dist/gemini/capsule.d.ts +4 -0
- package/dist/gemini/capsule.d.ts.map +1 -0
- package/dist/gemini/capsule.js +9 -0
- package/dist/gemini/capsule.js.map +1 -0
- package/dist/gemini/certificate.d.ts +34 -0
- package/dist/gemini/certificate.d.ts.map +1 -0
- package/dist/gemini/certificate.js +255 -0
- package/dist/gemini/certificate.js.map +1 -0
- package/dist/gemini/site-certificate.d.ts +8 -0
- package/dist/gemini/site-certificate.d.ts.map +1 -0
- package/dist/gemini/site-certificate.js +17 -0
- package/dist/gemini/site-certificate.js.map +1 -0
- package/dist/micropub/endpoint.d.ts.map +1 -1
- package/dist/micropub/endpoint.js +12 -0
- package/dist/micropub/endpoint.js.map +1 -1
- package/dist/plugin.d.ts +15 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js.map +1 -1
- package/dist/settings/registry.d.ts.map +1 -1
- package/dist/settings/registry.js +5 -1
- package/dist/settings/registry.js.map +1 -1
- package/dist/settings/types.d.ts +1 -1
- package/dist/settings/types.d.ts.map +1 -1
- package/dist/site/dashboard-layout.d.ts +33 -26
- package/dist/site/dashboard-layout.d.ts.map +1 -1
- package/dist/site/dashboard-layout.js +94 -39
- package/dist/site/dashboard-layout.js.map +1 -1
- package/dist/site/namespace.d.ts +6 -0
- package/dist/site/namespace.d.ts.map +1 -1
- package/dist/site/namespace.js +46 -1
- package/dist/site/namespace.js.map +1 -1
- package/dist/site/users.d.ts +7 -0
- package/dist/site/users.d.ts.map +1 -1
- package/dist/site/users.js +7 -0
- package/dist/site/users.js.map +1 -1
- package/dist/site/writing-goals.d.ts +22 -0
- package/dist/site/writing-goals.d.ts.map +1 -0
- package/dist/site/writing-goals.js +42 -0
- package/dist/site/writing-goals.js.map +1 -0
- package/dist/store/schema.d.ts.map +1 -1
- package/dist/store/schema.js +4 -0
- package/dist/store/schema.js.map +1 -1
- package/dist/store/sessions.d.ts +2 -1
- package/dist/store/sessions.d.ts.map +1 -1
- package/dist/store/sessions.js +30 -12
- package/dist/store/sessions.js.map +1 -1
- package/dist/theme/font-family.d.ts +13 -0
- package/dist/theme/font-family.d.ts.map +1 -0
- package/dist/theme/font-family.js +21 -0
- package/dist/theme/font-family.js.map +1 -0
- package/dist/theme/scheme-tokens.d.ts +50 -0
- package/dist/theme/scheme-tokens.d.ts.map +1 -0
- package/dist/theme/scheme-tokens.js +240 -0
- package/dist/theme/scheme-tokens.js.map +1 -0
- package/dist/theme/site-data.d.ts +12 -0
- package/dist/theme/site-data.d.ts.map +1 -1
- package/dist/theme/site-data.js +15 -0
- package/dist/theme/site-data.js.map +1 -1
- package/dist/theme/themes.d.ts +74 -0
- package/dist/theme/themes.d.ts.map +1 -1
- package/dist/theme/themes.js +100 -9
- package/dist/theme/themes.js.map +1 -1
- package/dist/util/public-address.d.ts +1 -0
- package/dist/util/public-address.d.ts.map +1 -1
- package/dist/util/public-address.js +38 -30
- package/dist/util/public-address.js.map +1 -1
- package/dist/web/access-line.d.ts +2 -0
- package/dist/web/access-line.d.ts.map +1 -0
- package/dist/web/access-line.js +6 -0
- package/dist/web/access-line.js.map +1 -0
- package/dist/web/document-page.d.ts.map +1 -1
- package/dist/web/document-page.js +3 -4
- package/dist/web/document-page.js.map +1 -1
- package/dist/web/embed.d.ts.map +1 -1
- package/dist/web/embed.js +2 -1
- package/dist/web/embed.js.map +1 -1
- package/dist/web/env.d.ts +2 -0
- package/dist/web/env.d.ts.map +1 -1
- package/dist/web/feed-routes.d.ts.map +1 -1
- package/dist/web/feed-routes.js +4 -4
- package/dist/web/feed-routes.js.map +1 -1
- package/dist/web/feed-source.d.ts +1 -1
- package/dist/web/feed-source.d.ts.map +1 -1
- package/dist/web/feed-source.js +1 -1
- package/dist/web/feed-source.js.map +1 -1
- package/dist/web/font-routes.d.ts +13 -0
- package/dist/web/font-routes.d.ts.map +1 -0
- package/dist/web/font-routes.js +27 -0
- package/dist/web/font-routes.js.map +1 -0
- package/dist/web/gemini-listener.d.ts +30 -0
- package/dist/web/gemini-listener.d.ts.map +1 -0
- package/dist/web/gemini-listener.js +186 -0
- package/dist/web/gemini-listener.js.map +1 -0
- package/dist/web/gemini-request.d.ts +23 -0
- package/dist/web/gemini-request.d.ts.map +1 -0
- package/dist/web/gemini-request.js +127 -0
- package/dist/web/gemini-request.js.map +1 -0
- package/dist/web/listing-pages.d.ts.map +1 -1
- package/dist/web/listing-pages.js +7 -5
- package/dist/web/listing-pages.js.map +1 -1
- package/dist/web/llms.d.ts +1 -0
- package/dist/web/llms.d.ts.map +1 -1
- package/dist/web/llms.js +3 -0
- package/dist/web/llms.js.map +1 -1
- package/dist/web/maintenance.d.ts.map +1 -1
- package/dist/web/maintenance.js +6 -2
- package/dist/web/maintenance.js.map +1 -1
- package/dist/web/manifest.d.ts +8 -5
- package/dist/web/manifest.d.ts.map +1 -1
- package/dist/web/manifest.js +10 -7
- package/dist/web/manifest.js.map +1 -1
- package/dist/web/markdown-representation.d.ts +11 -20
- package/dist/web/markdown-representation.d.ts.map +1 -1
- package/dist/web/markdown-representation.js +57 -58
- package/dist/web/markdown-representation.js.map +1 -1
- package/dist/web/negotiate.d.ts +4 -16
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +23 -18
- package/dist/web/negotiate.js.map +1 -1
- package/dist/web/oembed.d.ts +17 -3
- package/dist/web/oembed.d.ts.map +1 -1
- package/dist/web/oembed.js +68 -26
- package/dist/web/oembed.js.map +1 -1
- package/dist/web/proxy-protocol.d.ts +13 -0
- package/dist/web/proxy-protocol.d.ts.map +1 -0
- package/dist/web/proxy-protocol.js +79 -0
- package/dist/web/proxy-protocol.js.map +1 -0
- package/dist/web/render.d.ts +52 -22
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +94 -30
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +7 -8
- package/dist/web/routes.js.map +1 -1
- package/dist/web/site-index.d.ts.map +1 -1
- package/dist/web/site-index.js +6 -2
- package/dist/web/site-index.js.map +1 -1
- package/dist/web/status-pages.d.ts +2 -3
- package/dist/web/status-pages.d.ts.map +1 -1
- package/dist/web/status-pages.js +14 -11
- package/dist/web/status-pages.js.map +1 -1
- package/dist/web/throttle.d.ts +9 -0
- package/dist/web/throttle.d.ts.map +1 -1
- package/dist/web/throttle.js +17 -0
- package/dist/web/throttle.js.map +1 -1
- package/dist/webmention/fetch-public.d.ts +6 -0
- package/dist/webmention/fetch-public.d.ts.map +1 -1
- package/dist/webmention/fetch-public.js +6 -1
- package/dist/webmention/fetch-public.js.map +1 -1
- package/dist/writing/ledger.d.ts +15 -0
- package/dist/writing/ledger.d.ts.map +1 -0
- package/dist/writing/ledger.js +70 -0
- package/dist/writing/ledger.js.map +1 -0
- package/dist/writing/progress.d.ts +25 -0
- package/dist/writing/progress.d.ts.map +1 -0
- package/dist/writing/progress.js +83 -0
- package/dist/writing/progress.js.map +1 -0
- package/package.json +2 -1
- package/themes/default/layouts/404.gmi.njk +10 -0
- package/themes/default/layouts/410.gmi.njk +8 -0
- package/themes/default/layouts/500.gmi.njk +9 -0
- package/themes/default/layouts/503.gmi.njk +9 -0
- package/themes/default/layouts/base.njk +31 -16
- package/themes/default/layouts/page.njk +4 -8
- package/themes/default/partials/bio.njk +1 -1
- package/themes/default/partials/contact-form.njk +1 -1
- package/themes/default/partials/markdown-footer.md.njk +9 -1
- package/themes/default/src/style.css +326 -15
- package/themes/default/static/style.css +489 -3
- package/themes/default/theme.json +23 -1
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
<text class="fill-base-content/70" x="24" y="{{ day.y }}" text-anchor="end" font-size="9">{{ day.label }}</text>
|
|
167
167
|
{% endfor %}
|
|
168
168
|
{% for cell in view.cells %}
|
|
169
|
-
<rect class="{% if cell.level == 0 %}fill-base-content/10{% elif cell.level == 1 %}fill-primary/25{% elif cell.level == 2 %}fill-primary/50{% elif cell.level == 3 %}fill-primary/75{% else %}fill-primary{% endif %}" x="{{ cell.x }}" y="{{ cell.y }}" width="{{ view.cell }}" height="{{ view.cell }}" rx="2"><title>{{ cell.title }}</title></rect>
|
|
169
|
+
<rect class="{% if cell.level == 0 %}fill-base-content/10{% elif cell.level == 1 %}fill-primary/25{% elif cell.level == 2 %}fill-primary/50{% elif cell.level == 3 %}fill-primary/75{% else %}fill-primary{% endif %}{% if cell.marked %} stroke-base-content{% endif %}"{% if cell.marked %} stroke-width="1.5"{% endif %} x="{{ cell.x }}" y="{{ cell.y }}" width="{{ view.cell }}" height="{{ view.cell }}" rx="2"><title>{{ cell.title }}</title></rect>
|
|
170
170
|
{% endfor %}
|
|
171
171
|
</svg>
|
|
172
172
|
</div>
|
|
@@ -180,6 +180,12 @@
|
|
|
180
180
|
<rect class="fill-primary" x="56" y="0" width="12" height="12" rx="2" />
|
|
181
181
|
</svg>
|
|
182
182
|
<span>More</span>
|
|
183
|
+
{% if view.mark %}
|
|
184
|
+
<svg class="ml-3 size-3" viewBox="0 0 12 12">
|
|
185
|
+
<rect class="fill-base-content/10 stroke-base-content" stroke-width="1.5" x="0.75" y="0.75" width="10.5" height="10.5" rx="2" />
|
|
186
|
+
</svg>
|
|
187
|
+
<span>{{ view.mark }}</span>
|
|
188
|
+
{% endif %}
|
|
183
189
|
</div>
|
|
184
190
|
{{ numbers(view) }}
|
|
185
191
|
</div>
|
|
@@ -243,6 +249,14 @@
|
|
|
243
249
|
{{ bars(view) }}
|
|
244
250
|
{% elif view.kind == 'calendar' %}
|
|
245
251
|
{{ calendar(view) }}
|
|
252
|
+
{% elif view.kind == 'progress' %}
|
|
253
|
+
<div class="grid gap-1">
|
|
254
|
+
<div class="flex flex-wrap justify-between gap-x-3 text-sm">
|
|
255
|
+
<span>{{ view.label }}</span>
|
|
256
|
+
<span class="tabular-nums">{{ view.value }} of {{ view.max }} · <span class="font-semibold">{{ view.percent }}</span></span>
|
|
257
|
+
</div>
|
|
258
|
+
<progress class="progress progress-primary w-full" value="{{ view.filled }}" max="{{ view.limit }}" aria-label="{{ view.label }}">{{ view.percent }}</progress>
|
|
259
|
+
</div>
|
|
246
260
|
{% else %}
|
|
247
261
|
{% if view.caption %}<p class="text-sm font-semibold">{{ view.caption }}</p>{% endif %}
|
|
248
262
|
<p class="text-sm text-base-content/70">No data to show.</p>
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{% extends "layouts/shell.njk" %}
|
|
2
|
+
{% from "components/alert.njk" import alert %}
|
|
3
|
+
{% from "components/badge.njk" import badge %}
|
|
4
|
+
{% from "components/button.njk" import button %}
|
|
5
|
+
{% from "components/card.njk" import card, cardActions %}
|
|
6
|
+
{% import "components/fields.njk" as field %}
|
|
7
|
+
|
|
8
|
+
{% macro swatch(mode, colours) -%}
|
|
9
|
+
<span class="flex flex-col gap-1" aria-hidden="true">
|
|
10
|
+
<svg data-mode="{{ mode }}" viewBox="0 0 96 56" class="h-auto w-full" focusable="false">
|
|
11
|
+
<rect x="0.5" y="0.5" width="95" height="55" rx="6" fill="{{ colours.page }}" stroke="currentColor" stroke-opacity="0.3" />
|
|
12
|
+
<text x="10" y="35" font-size="20" font-weight="700" fill="{{ colours.text }}">Aa</text>
|
|
13
|
+
<circle cx="58" cy="28" r="9" fill="{{ colours.accent }}" />
|
|
14
|
+
<circle cx="80" cy="28" r="9" fill="{{ colours.secondary }}" />
|
|
15
|
+
</svg>
|
|
16
|
+
<span class="text-xs">{{ 'Light' if mode == 'light' else 'Dark' }}</span>
|
|
17
|
+
</span>
|
|
18
|
+
{%- endmacro %}
|
|
19
|
+
|
|
20
|
+
{% block title %}{{ heading }}{% endblock %}
|
|
21
|
+
|
|
22
|
+
{% block content %}
|
|
23
|
+
<h1 class="mb-6 text-2xl font-bold">{{ heading }}</h1>
|
|
24
|
+
|
|
25
|
+
<div class="flex max-w-5xl flex-col gap-6">
|
|
26
|
+
{% call card(title='Colours') %}
|
|
27
|
+
{% if problems %}
|
|
28
|
+
{% call alert(color='error') %}
|
|
29
|
+
<p>Nothing was changed. {{ problems | join(' ') }}</p>
|
|
30
|
+
{% endcall %}
|
|
31
|
+
{% endif %}
|
|
32
|
+
|
|
33
|
+
<form method="post" action="{{ coloursUrl }}">
|
|
34
|
+
<input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
|
|
35
|
+
|
|
36
|
+
{% if schemes.length %}
|
|
37
|
+
<fieldset class="fieldset">
|
|
38
|
+
<legend class="fieldset-legend">Colour scheme</legend>
|
|
39
|
+
<ul class="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
|
|
40
|
+
{% for scheme in schemes %}
|
|
41
|
+
<li>
|
|
42
|
+
<label data-scheme-card class="card card-border cursor-pointer bg-base-100 has-checked:border-2 has-checked:border-primary">
|
|
43
|
+
<span class="card-body gap-3 p-4">
|
|
44
|
+
<span class="flex flex-wrap items-center gap-2">
|
|
45
|
+
<input type="radio" class="radio radio-sm" name="{{ fields.scheme }}" value="{{ scheme.name }}"{% if scheme.chosen %} checked{% endif %} />
|
|
46
|
+
<span class="font-semibold">{{ scheme.label }}</span>
|
|
47
|
+
{% if scheme.name == savedScheme %}{{ badge('In use', color='primary', style='soft') }}{% endif %}
|
|
48
|
+
</span>
|
|
49
|
+
{% if scheme.light and scheme.dark %}
|
|
50
|
+
<span class="grid grid-cols-2 gap-2">
|
|
51
|
+
{{ swatch('light', scheme.light) }}
|
|
52
|
+
{{ swatch('dark', scheme.dark) }}
|
|
53
|
+
</span>
|
|
54
|
+
{% endif %}
|
|
55
|
+
</span>
|
|
56
|
+
</label>
|
|
57
|
+
</li>
|
|
58
|
+
{% endfor %}
|
|
59
|
+
</ul>
|
|
60
|
+
<p class="label whitespace-normal">Each swatch shows the page, the text, the accent and the secondary colour.</p>
|
|
61
|
+
</fieldset>
|
|
62
|
+
{% else %}
|
|
63
|
+
<p>This theme has one palette, so there is no colour scheme to choose.</p>
|
|
64
|
+
{% endif %}
|
|
65
|
+
|
|
66
|
+
<fieldset class="fieldset">
|
|
67
|
+
<legend class="fieldset-legend">Mode</legend>
|
|
68
|
+
{% for mode in modes %}
|
|
69
|
+
<label class="label cursor-pointer justify-start gap-2">
|
|
70
|
+
<input type="radio" class="radio radio-sm" name="{{ fields.mode }}" value="{{ mode.value }}"{% if mode.chosen %} checked{% endif %} />
|
|
71
|
+
<span class="text-base-content">{{ mode.label }}</span>
|
|
72
|
+
</label>
|
|
73
|
+
{% endfor %}
|
|
74
|
+
<p class="label whitespace-normal">
|
|
75
|
+
{% if schemes.length %}
|
|
76
|
+
Follow the system draws light or dark as each reader's device is set.
|
|
77
|
+
{% else %}
|
|
78
|
+
The theme's stylesheet decides light and dark; the mode applies once the theme declares colour schemes.
|
|
79
|
+
{% endif %}
|
|
80
|
+
</p>
|
|
81
|
+
</fieldset>
|
|
82
|
+
|
|
83
|
+
{% call cardActions() %}
|
|
84
|
+
{{ button('Save colours', type='submit', color='primary') }}
|
|
85
|
+
{% endcall %}
|
|
86
|
+
</form>
|
|
87
|
+
{% endcall %}
|
|
88
|
+
|
|
89
|
+
{% call card(title='Fonts') %}
|
|
90
|
+
{% if fonts.length %}
|
|
91
|
+
{% for font in fonts %}{% if font.sample %}
|
|
92
|
+
<link rel="stylesheet" href="{{ font.sample.href }}" />
|
|
93
|
+
{% endif %}{% endfor %}
|
|
94
|
+
<style nonce="{{ cspNonce }}">
|
|
95
|
+
{% for font in fonts %}
|
|
96
|
+
[data-font-sample="{{ font.role }}"] { font-family: {% if font.sample %}"{{ font.sample.family }}", {% endif %}{{ font.fallback | safe }}; }
|
|
97
|
+
{% endfor %}
|
|
98
|
+
</style>
|
|
99
|
+
|
|
100
|
+
{% if fontProblems %}
|
|
101
|
+
{% call field.summary('The fonts were not saved. Fix the fields marked below.') %}
|
|
102
|
+
{% for font in fonts %}
|
|
103
|
+
{{ field.problem('font-' + font.role + ('-custom' if font.customChosen else ''), font.problem) }}
|
|
104
|
+
{% endfor %}
|
|
105
|
+
{% endcall %}
|
|
106
|
+
{% endif %}
|
|
107
|
+
|
|
108
|
+
<form method="post" action="{{ fontsUrl }}">
|
|
109
|
+
<input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
|
|
110
|
+
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
|
111
|
+
{% for font in fonts %}
|
|
112
|
+
<fieldset class="fieldset" data-font-role="{{ font.role }}">
|
|
113
|
+
<legend class="fieldset-legend">{{ font.label }}</legend>
|
|
114
|
+
<p data-font-sample="{{ font.role }}" class="text-xl">The quick brown fox jumps over the lazy dog.</p>
|
|
115
|
+
{% call field.select('font-' + font.role, font.fields.select, 'Font', error=(font.problem if not font.customChosen else '')) %}
|
|
116
|
+
{% for option in font.options %}
|
|
117
|
+
<option value="{{ option.value }}"{% if option.selected %} selected{% endif %}>{{ option.label }}</option>
|
|
118
|
+
{% endfor %}
|
|
119
|
+
{% endcall %}
|
|
120
|
+
{{ field.text('font-' + font.role + '-custom', font.fields.custom, 'Custom Google Fonts family', value=font.custom, error=(font.problem if font.customChosen else ''), hint='Used when Custom… is chosen. Type the family as Google Fonts names it, such as Bitter.', spellcheck='false', autocomplete='off') }}
|
|
121
|
+
</fieldset>
|
|
122
|
+
{% endfor %}
|
|
123
|
+
</div>
|
|
124
|
+
<p class="label mt-2 block whitespace-normal">Saving downloads each family from Google Fonts to this site, so readers load it from here. Body text needs regular, italic and bold; headings need bold.</p>
|
|
125
|
+
|
|
126
|
+
{% call cardActions() %}
|
|
127
|
+
{{ button('Save fonts', type='submit', color='primary') }}
|
|
128
|
+
{% endcall %}
|
|
129
|
+
</form>
|
|
130
|
+
{% else %}
|
|
131
|
+
<p>This theme declares no fonts to choose.</p>
|
|
132
|
+
{% endif %}
|
|
133
|
+
{% endcall %}
|
|
134
|
+
</div>
|
|
135
|
+
{% endblock %}
|
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
{% for key in widget.shown %}<input type="hidden" name="shown" value="{{ key }}" />{% endfor %}
|
|
37
37
|
{{ button('↑', type='submit', name='action', value='earlier', style='ghost', size='xs', shape='square', ariaLabel='Move ' + widget.title + ' earlier', disabled=widget.first) }}
|
|
38
38
|
{{ button('↓', type='submit', name='action', value='later', style='ghost', size='xs', shape='square', ariaLabel='Move ' + widget.title + ' later', disabled=widget.last) }}
|
|
39
|
+
{{ button('←', type='submit', name='action', value='left', style='ghost', size='xs', shape='square', ariaLabel='Move ' + widget.title + ' to the left column', hidden=widget.side == 'left') }}
|
|
40
|
+
{{ button('→', type='submit', name='action', value='right', style='ghost', size='xs', shape='square', ariaLabel='Move ' + widget.title + ' to the right column', hidden=widget.side == 'right') }}
|
|
39
41
|
{% if widget.collapsed %}
|
|
40
42
|
{{ button('+', type='submit', name='action', value='expand', style='ghost', size='xs', shape='square', ariaLabel='Expand ' + widget.title) }}
|
|
41
43
|
{% else %}
|
|
@@ -107,9 +109,13 @@
|
|
|
107
109
|
</div>
|
|
108
110
|
</div>
|
|
109
111
|
<div class="grid grid-cols-1 gap-6 @3xl:grid-cols-2" data-dashboard-cards data-layout-url="{{ layoutUrl }}">
|
|
110
|
-
{% for
|
|
111
|
-
<div class="min-w-0
|
|
112
|
-
{
|
|
112
|
+
{% for column in columns %}
|
|
113
|
+
<div class="flex min-w-0 flex-col gap-6 @3xl:min-h-24" data-dashboard-column="{{ column.side }}">
|
|
114
|
+
{% for widget in column.cards %}
|
|
115
|
+
<div class="min-w-0" data-dashboard-card="{{ widget.key }}">
|
|
116
|
+
{{ arrangedCard(widget) }}
|
|
117
|
+
</div>
|
|
118
|
+
{% endfor %}
|
|
113
119
|
</div>
|
|
114
120
|
{% endfor %}
|
|
115
121
|
</div>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
saved last. #}
|
|
5
5
|
{% extends "layouts/shell.njk" %}
|
|
6
6
|
|
|
7
|
-
{% block title %}Conflicting edit{% endblock %}
|
|
7
|
+
{% block title %}{% if restoring %}Restore unsaved changes{% else %}Conflicting edit{% endif %}{% endblock %}
|
|
8
8
|
|
|
9
9
|
{% import "components/fields.njk" as field %}
|
|
10
10
|
{% from "components/alert.njk" import alert %}
|
|
@@ -12,16 +12,29 @@
|
|
|
12
12
|
{% from "components/card.njk" import card %}
|
|
13
13
|
|
|
14
14
|
{% block content %}
|
|
15
|
-
|
|
15
|
+
{% if restoring %}
|
|
16
|
+
<h1 class="mb-6 text-2xl font-bold">This {{ kind.singular }} changed since your unsaved changes</h1>
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
<div class="mb-6">
|
|
19
|
+
{% call alert(color='warning', style='soft', polite=true) %}
|
|
20
|
+
<span>
|
|
21
|
+
Nothing has been saved. The file on disk has been written to since your
|
|
22
|
+
unsaved changes were made from it. Read both versions before you choose.
|
|
23
|
+
</span>
|
|
24
|
+
{% endcall %}
|
|
25
|
+
</div>
|
|
26
|
+
{% else %}
|
|
27
|
+
<h1 class="mb-6 text-2xl font-bold">This {{ kind.singular }} changed while you were editing it</h1>
|
|
28
|
+
|
|
29
|
+
<div class="mb-6">
|
|
30
|
+
{% call alert(color='error', style='soft', polite=true) %}
|
|
31
|
+
<span>
|
|
32
|
+
Nothing has been saved. The file on disk is not the one this form was filled in
|
|
33
|
+
from — somebody else, or something else, has written to it.
|
|
34
|
+
</span>
|
|
35
|
+
{% endcall %}
|
|
36
|
+
</div>
|
|
37
|
+
{% endif %}
|
|
25
38
|
|
|
26
39
|
<div class="grid gap-6 lg:grid-cols-2">
|
|
27
40
|
{% call card(title='Your version') %}
|
|
@@ -32,6 +45,17 @@
|
|
|
32
45
|
{% endcall %}
|
|
33
46
|
</div>
|
|
34
47
|
|
|
48
|
+
{% if restoring %}
|
|
49
|
+
<div class="mt-6 flex flex-wrap items-center gap-2">
|
|
50
|
+
<form method="post" action="{{ restoring.discardUrl }}">
|
|
51
|
+
<input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
|
|
52
|
+
<input type="hidden" name="autosave" value="{{ restoring.key }}" />
|
|
53
|
+
<input type="hidden" name="return" value="{{ editUrl }}" />
|
|
54
|
+
{{ button('Discard mine and edit the file on disk', type='submit', style='soft') }}
|
|
55
|
+
</form>
|
|
56
|
+
{{ buttonLink('Edit mine over the file', restoring.rebaseUrl, color='primary') }}
|
|
57
|
+
</div>
|
|
58
|
+
{% else %}
|
|
35
59
|
{# Everything the refused form carried, with the hash the file has now. One
|
|
36
60
|
click is then a deliberate overwrite of a version its author has read. #}
|
|
37
61
|
<form class="mt-6 flex flex-wrap items-center gap-2" method="post" action="{{ saveUrl }}">
|
|
@@ -52,4 +76,5 @@
|
|
|
52
76
|
{{ buttonLink('Discard mine and edit the file on disk', editUrl, style='soft') }}
|
|
53
77
|
{{ button('Keep mine and overwrite the file', type='submit', name='action', value=action, color='error') }}
|
|
54
78
|
</form>
|
|
79
|
+
{% endif %}
|
|
55
80
|
{% endblock %}
|
|
@@ -453,12 +453,33 @@
|
|
|
453
453
|
</div>
|
|
454
454
|
{% endif %}
|
|
455
455
|
|
|
456
|
+
{% if resume %}
|
|
457
|
+
<div class="my-6" id="autosave-resume" data-saved-at="{{ resume.savedAt }}">
|
|
458
|
+
{% call alert(color='warning', direction='responsive', labelledby='autosave-resume-message') %}
|
|
459
|
+
<p id="autosave-resume-message">
|
|
460
|
+
Unsaved changes from <time datetime="{{ resume.savedAt }}">{{ resume.at }}</time>.
|
|
461
|
+
{% if resume.changedSince %}This {{ resume.noun }} has changed since. Restore shows both versions side by side.{% endif %}
|
|
462
|
+
</p>
|
|
463
|
+
<div class="flex flex-wrap gap-2">
|
|
464
|
+
{{ buttonLink('Restore', resume.restoreUrl, color='primary', size='sm') }}
|
|
465
|
+
<form method="post" action="{{ resume.discardUrl }}" id="autosave-resume-discard">
|
|
466
|
+
<input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
|
|
467
|
+
<input type="hidden" name="autosave" value="{{ resume.key }}" />
|
|
468
|
+
<input type="hidden" name="return" value="{{ resume.returnUrl }}" />
|
|
469
|
+
{{ button('Discard', type='submit', style='soft', size='sm') }}
|
|
470
|
+
</form>
|
|
471
|
+
</div>
|
|
472
|
+
{% endcall %}
|
|
473
|
+
</div>
|
|
474
|
+
{% endif %}
|
|
475
|
+
|
|
456
476
|
<form class="group/editor grid items-start gap-6 xl:grid-cols-[minmax(0,1fr)_20rem]" id="editor-form" method="post" action="{{ saveUrl }}">
|
|
457
477
|
<input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
|
|
458
478
|
{# The hash of the file this form was filled in from. A save whose hash no
|
|
459
479
|
longer matches what is on disk is refused rather than overwriting
|
|
460
480
|
somebody else's edit (doc-1). #}
|
|
461
481
|
<input type="hidden" name="hash" value="{{ form.hash }}" />
|
|
482
|
+
<input type="hidden" name="autosave" value="{{ autosaveKey }}" />
|
|
462
483
|
{# Which layout the preview renders through. The save handler ignores it. #}
|
|
463
484
|
<input type="hidden" name="type" value="{{ kind.type }}" />
|
|
464
485
|
{% if editorKind %}
|
|
@@ -481,6 +502,7 @@
|
|
|
481
502
|
{% endif %}
|
|
482
503
|
|
|
483
504
|
{{ field.textarea('editor-body', 'body', (editorKind.body if editorKind else 'Body'), value=form.body, rows=(8 if editorKind and editorKind.sections | length else 20)) }}
|
|
505
|
+
<p id="editor-words" class="text-sm text-base-content/70 tabular-nums"{% if words.today is defined %} data-words-today="{{ words.today }}"{% endif %}>{{ words.label }}</p>
|
|
484
506
|
|
|
485
507
|
{# Everything the editor's own script needs, on the element it hangs
|
|
486
508
|
off. With JavaScript off this is one button that posts the form to
|
|
@@ -494,6 +516,13 @@
|
|
|
494
516
|
data-preview-url="{{ previewUrl }}"
|
|
495
517
|
data-upload-url="{{ uploadsUrl }}"
|
|
496
518
|
data-kind="{{ kind.type }}"
|
|
519
|
+
data-autosave-url="{{ autosaveUrl }}"
|
|
520
|
+
data-autosave-user="{{ autosaveUser }}"
|
|
521
|
+
data-autosave-discard-url="{{ autosaveDiscardUrl }}"
|
|
522
|
+
data-autosave-timezone="{{ autosaveTimezone }}"
|
|
523
|
+
{% if autosaveCopySavedAt %}data-autosave-copy-saved-at="{{ autosaveCopySavedAt }}"{% endif %}
|
|
524
|
+
{% if autosaveFileTime %}data-autosave-file-time="{{ autosaveFileTime }}"{% endif %}
|
|
525
|
+
{% if clearedAutosaves and clearedAutosaves.length %}data-autosave-cleared="{{ clearedAutosaves | dump }}"{% endif %}
|
|
497
526
|
>
|
|
498
527
|
{{ button('Preview', type='submit', id='editor-preview-fallback', style='soft', formaction=previewUrl, formtarget='_blank', formnovalidate=true) }}
|
|
499
528
|
</div>
|
|
@@ -22,7 +22,50 @@
|
|
|
22
22
|
{{ tabs(filters, 'Show ' + (kind.plural | lower)) }}
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
|
-
{% if
|
|
25
|
+
{% if unsaved %}
|
|
26
|
+
{% if unsaved.length %}
|
|
27
|
+
{% call table('Unsaved ' + (kind.plural | lower)) %}
|
|
28
|
+
<thead>
|
|
29
|
+
<tr>
|
|
30
|
+
<th scope="col">Title</th>
|
|
31
|
+
{{ heading('Kind') }}
|
|
32
|
+
{{ heading('Of') }}
|
|
33
|
+
{{ heading('Saved') }}
|
|
34
|
+
</tr>
|
|
35
|
+
</thead>
|
|
36
|
+
<tbody>
|
|
37
|
+
{% for copy in unsaved %}
|
|
38
|
+
{% call row() %}
|
|
39
|
+
<td>
|
|
40
|
+
{% if copy.resumeUrl %}
|
|
41
|
+
<a class="link link-hover font-medium" href="{{ copy.resumeUrl }}">{{ copy.label }}</a>
|
|
42
|
+
{% else %}
|
|
43
|
+
<span class="font-medium">{{ copy.label }}</span>
|
|
44
|
+
{% endif %}
|
|
45
|
+
<div class="-ms-2 mt-1 flex items-center gap-1 whitespace-nowrap">
|
|
46
|
+
{% if copy.resumeUrl %}
|
|
47
|
+
{{ buttonLink('Resume', copy.resumeUrl, style='ghost', size='xs') }}
|
|
48
|
+
{% endif %}
|
|
49
|
+
<form method="post" action="{{ discardUrl }}">
|
|
50
|
+
<input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
|
|
51
|
+
<input type="hidden" name="autosave" value="{{ copy.key }}" />
|
|
52
|
+
<input type="hidden" name="return" value="{{ returnUrl }}" />
|
|
53
|
+
{{ button('Discard', type='submit', style='ghost', size='xs', ariaLabel='Discard the unsaved changes to ' + copy.label) }}
|
|
54
|
+
</form>
|
|
55
|
+
</div>
|
|
56
|
+
{{ rowToggle(copy.label) }}
|
|
57
|
+
</td>
|
|
58
|
+
{% call cell('Kind', nowrap=true) %}{{ copy.kind }}{% endcall %}
|
|
59
|
+
{% call cell('Of') %}{{ copy.of }}{% endcall %}
|
|
60
|
+
{% call cell('Saved', nowrap=true) %}<time datetime="{{ copy.savedAt }}">{{ copy.at }}</time>{% endcall %}
|
|
61
|
+
{% endcall %}
|
|
62
|
+
{% endfor %}
|
|
63
|
+
</tbody>
|
|
64
|
+
{% endcall %}
|
|
65
|
+
{% else %}
|
|
66
|
+
<p>No unsaved changes.</p>
|
|
67
|
+
{% endif %}
|
|
68
|
+
{% elif documents.length %}
|
|
26
69
|
{% call table(kind.plural) %}
|
|
27
70
|
<thead>
|
|
28
71
|
<tr>
|
|
@@ -83,6 +83,10 @@
|
|
|
83
83
|
</p>
|
|
84
84
|
</div>
|
|
85
85
|
|
|
86
|
+
{{ field.checkbox('settings-header-icon', fields.header_icon,
|
|
87
|
+
'Show the icon before the site title in the header', checked=form.header_icon,
|
|
88
|
+
hint='The default theme shows it at the size of the title on every page, once the site has an icon.') }}
|
|
89
|
+
|
|
86
90
|
{% set licenseHint %}What readers may do with your posts. The footer links it, and the structured data and the feeds declare it. A post can name its own with <code>license</code> in its front matter.{% endset %}
|
|
87
91
|
{% call field.select('settings-license', fields.license, 'License', error=problems.license, hintHtml=licenseHint) %}
|
|
88
92
|
<option value=""{% if not form.license %} selected{% endif %}>No license (all rights reserved)</option>
|
|
@@ -161,4 +161,18 @@
|
|
|
161
161
|
{% endset %}
|
|
162
162
|
{{ field.checkbox('settings-index-now', fields.index_now, 'Submit changes to IndexNow',
|
|
163
163
|
checked=form.index_now, hintHtml=indexNowHint) }}
|
|
164
|
+
|
|
165
|
+
{% set geminiHint %}
|
|
166
|
+
Serves the site as a Gemini capsule at <code>gemini://</code> with a self-signed
|
|
167
|
+
certificate the site generates once and keeps. Gemini clients remember the
|
|
168
|
+
certificate on their first visit, so a new one makes every visitor's client warn.
|
|
169
|
+
{% if geminiCertificate and geminiCertificate.ok %}
|
|
170
|
+
<span class="block mt-1">SHA-256 fingerprint:
|
|
171
|
+
<code class="break-all">{{ geminiCertificate.certificate.fingerprint256 }}</code></span>
|
|
172
|
+
{% elif geminiCertificate %}
|
|
173
|
+
<span class="block mt-1 text-error">{{ geminiCertificate.problem }}</span>
|
|
174
|
+
{% endif %}
|
|
175
|
+
{% endset %}
|
|
176
|
+
{{ field.checkbox('settings-gemini', fields.gemini, 'Serve over Gemini',
|
|
177
|
+
checked=form.gemini, hintHtml=geminiHint) }}
|
|
164
178
|
{% endblock %}
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
Every link here is published with <code>rel="me"</code> whether or not
|
|
125
125
|
you type it: it is how Mastodon verifies a profile field that points back
|
|
126
126
|
at this site, and how IndieAuth knows these are yours. Nothing else in
|
|
127
|
-
Geekity needs it.
|
|
127
|
+
Geekity CMS needs it.
|
|
128
128
|
{% endset %}
|
|
129
129
|
{{ field.textarea('profile-links', fields.links, 'Links', account.profile.links, rows='4',
|
|
130
130
|
hintHtml=linksHint, error=profileProblems.links) }}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{% extends "layouts/shell.njk" %}
|
|
2
|
+
{% import "components/fields.njk" as field %}
|
|
3
|
+
{% from "components/button.njk" import button %}
|
|
4
|
+
{% from "components/card.njk" import card %}
|
|
5
|
+
|
|
6
|
+
{% block title %}Writing goals{% endblock %}
|
|
7
|
+
|
|
8
|
+
{% block content %}
|
|
9
|
+
<h1 class="mb-6 text-2xl font-bold">Writing goals</h1>
|
|
10
|
+
|
|
11
|
+
<div class="flex max-w-2xl flex-col gap-6">
|
|
12
|
+
{% if hasProblems %}
|
|
13
|
+
{% call field.summary('Nothing was saved. Fix the fields marked below and save again.') %}
|
|
14
|
+
{{ field.problem('goal-words', problems.words) }}
|
|
15
|
+
{{ field.problem('goal-period', problems.period) }}
|
|
16
|
+
{{ field.problem('streak-daily-words', problems.dailyWords) }}
|
|
17
|
+
{{ field.problem('streak-misses-allowed', problems.missesAllowed) }}
|
|
18
|
+
{% endcall %}
|
|
19
|
+
{% endif %}
|
|
20
|
+
|
|
21
|
+
{% call card() %}
|
|
22
|
+
<form method="post" action="{{ formUrl }}">
|
|
23
|
+
<input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
|
|
24
|
+
|
|
25
|
+
<p class="text-sm">
|
|
26
|
+
The site counts the words you write in the editor whether or not you
|
|
27
|
+
track a goal. Tracking shows your progress and your streak on the
|
|
28
|
+
dashboard. Turning it off keeps your goal for when you turn it on again.
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
{{ field.checkbox('writing-tracking', fields.tracking, 'Track writing goals', checked=form.tracking,
|
|
32
|
+
hint=('Save to set your goal.' if not form.tracking else '')) }}
|
|
33
|
+
|
|
34
|
+
{% if form.tracking or hasProblems %}
|
|
35
|
+
<h2 class="mt-4 font-semibold">Goal</h2>
|
|
36
|
+
{{ field.text('goal-words', fields.words, 'Words', form.words, type='number', min='1', step='1',
|
|
37
|
+
inputmode='numeric', error=problems.words) }}
|
|
38
|
+
{% call field.select('goal-period', fields.period, 'Every', error=problems.period) %}
|
|
39
|
+
{% for period in periods %}
|
|
40
|
+
<option value="{{ period.value }}"{% if period.chosen %} selected{% endif %}>{{ period.label }}</option>
|
|
41
|
+
{% endfor %}
|
|
42
|
+
{% endcall %}
|
|
43
|
+
|
|
44
|
+
<h2 class="mt-4 font-semibold">Streak</h2>
|
|
45
|
+
{% set dailyHint %}
|
|
46
|
+
A day keeps your streak when you write at least this many words. Leave
|
|
47
|
+
it empty to use your goal's daily pace{% if paceWords %} ({{ paceWords }} words){% endif %}.
|
|
48
|
+
{% endset %}
|
|
49
|
+
{{ field.text('streak-daily-words', fields.dailyWords, 'Words a day', form.dailyWords, type='number',
|
|
50
|
+
min='1', step='1', inputmode='numeric', error=problems.dailyWords, hintHtml=dailyHint) }}
|
|
51
|
+
{% set missesHint %}
|
|
52
|
+
How many missed days in a row your streak survives, from 0 to {{ maxMissesAllowed }}.
|
|
53
|
+
With 1, missing a day is fine and missing two in a row ends it.
|
|
54
|
+
{% endset %}
|
|
55
|
+
{{ field.text('streak-misses-allowed', fields.missesAllowed, 'Missed days allowed', form.missesAllowed,
|
|
56
|
+
type='number', min='0', step='1', inputmode='numeric', error=problems.missesAllowed,
|
|
57
|
+
hintHtml=missesHint) }}
|
|
58
|
+
{% endif %}
|
|
59
|
+
|
|
60
|
+
<div class="mt-4">{{ button('Save writing goals', type='submit', color='primary') }}</div>
|
|
61
|
+
</form>
|
|
62
|
+
{% endcall %}
|
|
63
|
+
</div>
|
|
64
|
+
{% endblock %}
|
package/admin/src/admin.css
CHANGED
|
@@ -175,3 +175,35 @@
|
|
|
175
175
|
#editor-surface .cm-md-mark {
|
|
176
176
|
color: color-mix(in oklab, var(--color-base-content) 60%, transparent);
|
|
177
177
|
}
|
|
178
|
+
|
|
179
|
+
html.editor-focus #editor-surface .cm-editor {
|
|
180
|
+
height: auto;
|
|
181
|
+
min-height: 60dvh;
|
|
182
|
+
border-color: transparent;
|
|
183
|
+
background-color: transparent;
|
|
184
|
+
font-size: 1.0625rem;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
html.editor-focus #editor-surface .cm-editor.cm-focused {
|
|
188
|
+
outline: none;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
html.editor-focus #editor-surface .cm-scroller {
|
|
192
|
+
line-height: 1.8;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
html.editor-focus #editor-surface .cm-content {
|
|
196
|
+
padding-block: 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
html.editor-focus #editor-surface .cm-line {
|
|
200
|
+
padding-inline: 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
html.editor-focus #editor-surface .cm-gutters {
|
|
204
|
+
display: none;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
html.editor-focus #editor-surface .cm-activeLine {
|
|
208
|
+
background-color: transparent;
|
|
209
|
+
}
|