picata 0.0.1__tar.gz → 0.0.3__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {picata-0.0.1 → picata-0.0.3}/.gitignore +1 -0
- picata-0.0.3/PKG-INFO +102 -0
- picata-0.0.3/README.md +51 -0
- {picata-0.0.1 → picata-0.0.3}/manage.py +1 -1
- picata-0.0.3/picata/__init__.py +1 -0
- {picata-0.0.1 → picata-0.0.3}/picata/apps.py +6 -6
- {picata-0.0.1 → picata-0.0.3}/picata/blocks.py +3 -2
- {picata-0.0.1 → picata-0.0.3}/picata/helpers/wagtail.py +1 -1
- {picata-0.0.1 → picata-0.0.3}/picata/middleware.py +1 -1
- picata-0.0.3/picata/migrations/0001_initial.py +130 -0
- {picata-0.0.1 → picata-0.0.3}/picata/models.py +6 -5
- {picata-0.0.1 → picata-0.0.3}/picata/settings/base.py +15 -15
- {picata-0.0.1 → picata-0.0.3}/picata/settings/dev.py +4 -2
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/base.html +3 -3
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/previews/theme_gallery.html +1 -1
- {picata-0.0.1 → picata-0.0.3}/picata/templatetags/absolute_static.py +1 -1
- picata-0.0.3/picata/templatetags/menu_tags.py +56 -0
- {picata-0.0.1 → picata-0.0.3}/picata/transformers.py +1 -1
- {picata-0.0.1 → picata-0.0.3}/picata/typing/__init__.py +1 -1
- {picata-0.0.1 → picata-0.0.3}/picata/typing/wagtail.py +1 -1
- {picata-0.0.1 → picata-0.0.3}/picata/urls.py +2 -2
- {picata-0.0.1 → picata-0.0.3}/picata/views.py +3 -2
- {picata-0.0.1 → picata-0.0.3}/picata/wagtail_hooks.py +1 -1
- {picata-0.0.1 → picata-0.0.3}/picata/wsgi.py +2 -2
- {picata-0.0.1 → picata-0.0.3}/pyproject.toml +4 -10
- picata-0.0.1/PKG-INFO +0 -87
- picata-0.0.1/README.md +0 -59
- picata-0.0.1/picata/__init__.py +0 -1
- picata-0.0.1/picata/migrations/0001_initial.py +0 -264
- picata-0.0.1/picata/migrations/0002_alter_article_content_alter_basicpage_content.py +0 -112
- picata-0.0.1/picata/migrations/0003_alter_article_content_alter_basicpage_content.py +0 -104
- picata-0.0.1/picata/migrations/0004_alter_article_content_alter_basicpage_content.py +0 -105
- picata-0.0.1/picata/migrations/0005_socialsettings.py +0 -48
- picata-0.0.1/picata/migrations/0006_alter_article_content.py +0 -71
- picata-0.0.1/picata/migrations/0007_splitviewpage.py +0 -69
- picata-0.0.1/picata/migrations/0008_alter_splitviewpage_content.py +0 -96
- picata-0.0.1/picata/migrations/0009_alter_splitviewpage_content.py +0 -111
- picata-0.0.1/picata/migrations/0010_alter_splitviewpage_content.py +0 -105
- picata-0.0.1/picata/migrations/0011_alter_splitviewpage_options_and_more.py +0 -113
- picata-0.0.1/picata/migrations/0012_alter_splitviewpage_content.py +0 -109
- picata-0.0.1/picata/migrations/0013_alter_article_content.py +0 -43
- picata-0.0.1/picata/migrations/0014_alter_article_content_alter_article_summary.py +0 -24
- picata-0.0.1/picata/migrations/0015_alter_article_options_article_tagline_and_more.py +0 -28
- picata-0.0.1/picata/migrations/0016_alter_article_options_alter_articletag_options_and_more.py +0 -33
- picata-0.0.1/picata/migrations/0017_articletagrelation_alter_article_tags_and_more.py +0 -35
- picata-0.0.1/picata/migrations/0018_rename_articletag_pagetag_and_more.py +0 -21
- picata-0.0.1/picata/migrations/0019_rename_name_plural_articletype__name_plural.py +0 -18
- picata-0.0.1/picata/migrations/0020_rename__name_plural_articletype__pluralised_name.py +0 -18
- picata-0.0.1/picata/migrations/0021_rename_article_type_article_page_type.py +0 -18
- picata-0.0.1/picata/migrations/0022_homepage.py +0 -28
- picata-0.0.1/picata/templatetags/menu_tags.py +0 -42
- {picata-0.0.1 → picata-0.0.3}/LICENSE.md +0 -0
- {picata-0.0.1 → picata-0.0.3}/components/HelloWorld.tsx +0 -0
- {picata-0.0.1 → picata-0.0.3}/entrypoint.tsx +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/helpers/__init__.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/log_utils.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/migrations/__init__.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/settings/__init__.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/settings/mypy.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/settings/prod.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/settings/test.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/ada-profile.jpg +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/ada-social-bear.jpg +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/favicon.ico +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/Bitter-Light.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/Bitter-LightItalic.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/FiraCode-Light.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/FiraCode-SemiBold.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/Sacramento-Regular.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/ZillaSlab-Bold.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/ZillaSlab-BoldItalic.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/ZillaSlab-Light.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/ZillaSlab-LightItalic.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/fonts/ZillaSlabHighlight-Bold.ttf +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/static/picata/icons.svg +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/3_column.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/404.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/500.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/_post_list.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/article.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/basic_page.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/blocks/icon_link_item.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/blocks/icon_link_list.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/blocks/icon_link_list_stream.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/dl_view.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/home_page.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/post_listing.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/previews/3col.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/previews/dl.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/previews/split.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/search_results.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/split_view.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templates/picata/tags/site_menu.html +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templatetags/__init__.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/templatetags/stringify.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/picata/validators.py +0 -0
- {picata-0.0.1 → picata-0.0.3}/pygments.sass +0 -0
- {picata-0.0.1 → picata-0.0.3}/styles.sass +0 -0
picata-0.0.3/PKG-INFO
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: picata
|
3
|
+
Version: 0.0.3
|
4
|
+
Summary: Ada's Wagtail-based CMS & blog
|
5
|
+
Project-URL: Documentation, https://github.com/hipikat/picata#readme
|
6
|
+
Project-URL: Issues, https://github.com/hipikat/picata/issues
|
7
|
+
Project-URL: Source, https://github.com/hipikat/picata
|
8
|
+
Author-email: Ada Wright <ada@hpk.io>
|
9
|
+
License: # The MIT License (MIT)
|
10
|
+
|
11
|
+
Copyright © `2024` `Ada Wright <ada@hpk.io>`
|
12
|
+
|
13
|
+
Permission is hereby granted, free of charge, to any person
|
14
|
+
obtaining a copy of this software and associated documentation
|
15
|
+
files (the “Software”), to deal in the Software without
|
16
|
+
restriction, including without limitation the rights to use,
|
17
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
18
|
+
copies of the Software, and to permit persons to whom the
|
19
|
+
Software is furnished to do so, subject to the following
|
20
|
+
conditions:
|
21
|
+
|
22
|
+
The above copyright notice and this permission notice shall be
|
23
|
+
included in all copies or substantial portions of the Software.
|
24
|
+
|
25
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
26
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
27
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
28
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
29
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
30
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
31
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
32
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
33
|
+
License-File: LICENSE.md
|
34
|
+
Keywords: blog,cms,django,wagtail
|
35
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
36
|
+
Classifier: Framework :: Django CMS
|
37
|
+
Classifier: Framework :: Wagtail :: 6
|
38
|
+
Classifier: Programming Language :: Python
|
39
|
+
Classifier: Programming Language :: Python :: 3.13
|
40
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
41
|
+
Requires-Python: >=3.13
|
42
|
+
Requires-Dist: gunicorn~=23.0.0
|
43
|
+
Requires-Dist: lxml~=5.3.0
|
44
|
+
Requires-Dist: psutil~=6.1.0
|
45
|
+
Requires-Dist: psycopg~=3.2.3
|
46
|
+
Requires-Dist: pygments~=2.18.0
|
47
|
+
Requires-Dist: python-slugify~=8.0.4
|
48
|
+
Requires-Dist: wagtail-modeladmin~=2.1.0
|
49
|
+
Requires-Dist: wagtail~=6.2
|
50
|
+
Description-Content-Type: text/markdown
|
51
|
+
|
52
|
+
# Picata
|
53
|
+
|
54
|
+
**_This project is very much pre-alpha_**
|
55
|
+
|
56
|
+
Picata is a CMS & blog application I forked off from my personal website. At the
|
57
|
+
moment it's effectively a ton of pre-made [Wagtail](https://wagtail.org) "stuff"
|
58
|
+
(models, views, templatetags, middleware, hooks, etc.), made generic enough that
|
59
|
+
you can `pip install` the package, add it to your `INSTALLED_APPS`, and have a
|
60
|
+
CMS/blog up-and-running without having to spend weeks or months tailoring Wagtail
|
61
|
+
to your needs.
|
62
|
+
|
63
|
+
It's still under heavy development, with most documentation and a project
|
64
|
+
template pending but - if you're already working with Wagtail - the source
|
65
|
+
provides many working solutions to common problems. The repo for the aforementioned
|
66
|
+
personal website [lives on GitHub](https://github.com/hipikat/hpk.io), and
|
67
|
+
demonstrates a working implementation of this package (requiring, in fact, only
|
68
|
+
this package as a dependency).
|
69
|
+
|
70
|
+
## What's in the box?
|
71
|
+
|
72
|
+
- [Wagtail](https://wagtail.org) (on [Django](https://www.djangoproject.com)) as the CMS & web frameworks
|
73
|
+
- Runs on [PostgreSQL](https://www.postgresql.org); loaded with scripts for managing the
|
74
|
+
database lifecycle and snapshots
|
75
|
+
- [Tailwind CSS](https://tailwindcss.com) in [Sass](https://sass-lang.com) for front-end styling
|
76
|
+
- [lxml](https://lxml.de) is used for fast HTML processing in a middleware layer
|
77
|
+
|
78
|
+
### Development features & workflows
|
79
|
+
|
80
|
+
Everything's written in very modern Python (circa 2025), with agressive linting and type-checking
|
81
|
+
thanks to [mypy](https://mypy-lang.org),
|
82
|
+
[Pydantic](https://docs.pydantic.dev/latest/)/[Pyright](https://github.com/microsoft/pyright),
|
83
|
+
and [Ruff](https://docs.astral.sh/ruff/). Picata uses [Django Debug Toolbar](https://django-debug-toolbar.readthedocs.io),
|
84
|
+
[runserver_plus](https://django-extensions.readthedocs.io/en/latest/runserver_plus.html), and
|
85
|
+
[iPython](https://www.google.com/search?client=safari&rls=en&q=ipython&ie=UTF-8&oe=UTF-8) for
|
86
|
+
development workflows. The project itself uses [pre-commit](https://pre-commit.com) extensively,
|
87
|
+
with 16 hooks to keep everything neat and tidy.
|
88
|
+
|
89
|
+
All front-end code is written in [TypeScript](https://typescript-eslint.io), with
|
90
|
+
[React](https://react.dev) set up and ready-to-go in the [Webpack](https://webpack.js.org) pipeline,
|
91
|
+
if you're into that kind of thing.
|
92
|
+
|
93
|
+
### Holding things together
|
94
|
+
|
95
|
+
- Uses [UV](https://github.com/astral-sh/uv) and
|
96
|
+
[pyproject.toml](https://packaging.python.org/en/latest/specifications/pyproject-toml/)
|
97
|
+
exclusively for Python project management
|
98
|
+
- [Just](https://just.systems) as a task runner, with over 60 recipes (at last count)
|
99
|
+
- [OpenTofu](https://opentofu.org) (a fork of [Terraform](https://www.terraform.io)) and
|
100
|
+
[cloud-init](https://cloud-init.io) for all DevOps & rapid deployment
|
101
|
+
- [Docker](https://www.docker.com) and [Docker Compose](https://docs.docker.com/compose/) for local
|
102
|
+
development
|
picata-0.0.3/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Picata
|
2
|
+
|
3
|
+
**_This project is very much pre-alpha_**
|
4
|
+
|
5
|
+
Picata is a CMS & blog application I forked off from my personal website. At the
|
6
|
+
moment it's effectively a ton of pre-made [Wagtail](https://wagtail.org) "stuff"
|
7
|
+
(models, views, templatetags, middleware, hooks, etc.), made generic enough that
|
8
|
+
you can `pip install` the package, add it to your `INSTALLED_APPS`, and have a
|
9
|
+
CMS/blog up-and-running without having to spend weeks or months tailoring Wagtail
|
10
|
+
to your needs.
|
11
|
+
|
12
|
+
It's still under heavy development, with most documentation and a project
|
13
|
+
template pending but - if you're already working with Wagtail - the source
|
14
|
+
provides many working solutions to common problems. The repo for the aforementioned
|
15
|
+
personal website [lives on GitHub](https://github.com/hipikat/hpk.io), and
|
16
|
+
demonstrates a working implementation of this package (requiring, in fact, only
|
17
|
+
this package as a dependency).
|
18
|
+
|
19
|
+
## What's in the box?
|
20
|
+
|
21
|
+
- [Wagtail](https://wagtail.org) (on [Django](https://www.djangoproject.com)) as the CMS & web frameworks
|
22
|
+
- Runs on [PostgreSQL](https://www.postgresql.org); loaded with scripts for managing the
|
23
|
+
database lifecycle and snapshots
|
24
|
+
- [Tailwind CSS](https://tailwindcss.com) in [Sass](https://sass-lang.com) for front-end styling
|
25
|
+
- [lxml](https://lxml.de) is used for fast HTML processing in a middleware layer
|
26
|
+
|
27
|
+
### Development features & workflows
|
28
|
+
|
29
|
+
Everything's written in very modern Python (circa 2025), with agressive linting and type-checking
|
30
|
+
thanks to [mypy](https://mypy-lang.org),
|
31
|
+
[Pydantic](https://docs.pydantic.dev/latest/)/[Pyright](https://github.com/microsoft/pyright),
|
32
|
+
and [Ruff](https://docs.astral.sh/ruff/). Picata uses [Django Debug Toolbar](https://django-debug-toolbar.readthedocs.io),
|
33
|
+
[runserver_plus](https://django-extensions.readthedocs.io/en/latest/runserver_plus.html), and
|
34
|
+
[iPython](https://www.google.com/search?client=safari&rls=en&q=ipython&ie=UTF-8&oe=UTF-8) for
|
35
|
+
development workflows. The project itself uses [pre-commit](https://pre-commit.com) extensively,
|
36
|
+
with 16 hooks to keep everything neat and tidy.
|
37
|
+
|
38
|
+
All front-end code is written in [TypeScript](https://typescript-eslint.io), with
|
39
|
+
[React](https://react.dev) set up and ready-to-go in the [Webpack](https://webpack.js.org) pipeline,
|
40
|
+
if you're into that kind of thing.
|
41
|
+
|
42
|
+
### Holding things together
|
43
|
+
|
44
|
+
- Uses [UV](https://github.com/astral-sh/uv) and
|
45
|
+
[pyproject.toml](https://packaging.python.org/en/latest/specifications/pyproject-toml/)
|
46
|
+
exclusively for Python project management
|
47
|
+
- [Just](https://just.systems) as a task runner, with over 60 recipes (at last count)
|
48
|
+
- [OpenTofu](https://opentofu.org) (a fork of [Terraform](https://www.terraform.io)) and
|
49
|
+
[cloud-init](https://cloud-init.io) for all DevOps & rapid deployment
|
50
|
+
- [Docker](https://www.docker.com) and [Docker Compose](https://docs.docker.com/compose/) for local
|
51
|
+
development
|
@@ -5,7 +5,7 @@ from os import environ
|
|
5
5
|
from sys import argv
|
6
6
|
|
7
7
|
if __name__ == "__main__":
|
8
|
-
environ.setdefault("DJANGO_SETTINGS_MODULE", "
|
8
|
+
environ.setdefault("DJANGO_SETTINGS_MODULE", "picata.settings.dev")
|
9
9
|
|
10
10
|
if len(argv) >= 2: # noqa: PLR2004
|
11
11
|
environ.setdefault("DJANGO_MANAGEMENT_COMMAND", argv[1])
|
@@ -0,0 +1 @@
|
|
1
|
+
"""Top-level package for the Picata project."""
|
@@ -1,13 +1,13 @@
|
|
1
|
-
"""Application configuration for the
|
1
|
+
"""Application configuration for the Picata Django app."""
|
2
2
|
|
3
3
|
from django.apps import AppConfig
|
4
4
|
|
5
5
|
|
6
6
|
class Config(AppConfig):
|
7
|
-
"""Configuration class for the
|
7
|
+
"""Configuration class for the Picata Django application."""
|
8
8
|
|
9
9
|
default_auto_field = "django.db.models.BigAutoField"
|
10
|
-
name = "
|
10
|
+
name = "picata"
|
11
11
|
|
12
12
|
def ready(self) -> None:
|
13
13
|
"""Configure Wagtail admin with custom models, and register document transformers."""
|
@@ -15,13 +15,13 @@ class Config(AppConfig):
|
|
15
15
|
# Register the 'custom article type' model with the Wagtail admin
|
16
16
|
from wagtail_modeladmin.options import modeladmin_register
|
17
17
|
|
18
|
-
from
|
18
|
+
from picata.models import ArticleTypeAdmin
|
19
19
|
|
20
20
|
modeladmin_register(ArticleTypeAdmin)
|
21
21
|
|
22
22
|
# Add document transformers to the HTMLProcessingMiddleware
|
23
|
-
from
|
24
|
-
from
|
23
|
+
from picata.middleware import HTMLProcessingMiddleware
|
24
|
+
from picata.transformers import AnchorInserter, add_heading_ids
|
25
25
|
|
26
26
|
## Add ids to all headings missing them within html > body > main
|
27
27
|
HTMLProcessingMiddleware.add_transformer(add_heading_ids)
|
@@ -3,8 +3,6 @@
|
|
3
3
|
import pygments
|
4
4
|
from django.forms import CharField
|
5
5
|
from django.utils.html import format_html
|
6
|
-
from hpk.typing.wagtail import BlockRenderContext, BlockRenderValue
|
7
|
-
from hpk.validators import HREFValidator
|
8
6
|
from pygments import formatters, lexers
|
9
7
|
from pygments.util import ClassNotFound
|
10
8
|
from wagtail.blocks import (
|
@@ -20,6 +18,9 @@ from wagtail.blocks import (
|
|
20
18
|
)
|
21
19
|
from wagtail.images.blocks import ImageChooserBlock
|
22
20
|
|
21
|
+
from picata.typing.wagtail import BlockRenderContext, BlockRenderValue
|
22
|
+
from picata.validators import HREFValidator
|
23
|
+
|
23
24
|
|
24
25
|
class HREFField(CharField):
|
25
26
|
"""Custom field for href attributes (i.e. URLs but also schemes like 'mailto:')."""
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# Generated by Django 5.1.5 on 2025-01-24 00:18
|
2
|
+
|
3
|
+
import django.db.models.deletion
|
4
|
+
import modelcluster.contrib.taggit
|
5
|
+
import modelcluster.fields
|
6
|
+
import wagtail.contrib.routable_page.models
|
7
|
+
import wagtail.fields
|
8
|
+
from django.db import migrations, models
|
9
|
+
|
10
|
+
|
11
|
+
class Migration(migrations.Migration):
|
12
|
+
|
13
|
+
initial = True
|
14
|
+
|
15
|
+
dependencies = [
|
16
|
+
('wagtailcore', '0094_alter_page_locale'),
|
17
|
+
('wagtailimages', '0027_image_description'),
|
18
|
+
]
|
19
|
+
|
20
|
+
operations = [
|
21
|
+
migrations.CreateModel(
|
22
|
+
name='ArticleType',
|
23
|
+
fields=[
|
24
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
25
|
+
('name', models.CharField(help_text='Name of the article type.', max_length=100, unique=True)),
|
26
|
+
('_Pluralised_name', models.CharField(blank=True, help_text="Plural form of the article type name (optional). Defaults to appending 's'.", max_length=100)),
|
27
|
+
('slug', models.SlugField(max_length=100, unique=True)),
|
28
|
+
('description', models.TextField(blank=True, help_text='Optional description of this type.')),
|
29
|
+
],
|
30
|
+
),
|
31
|
+
migrations.CreateModel(
|
32
|
+
name='BasicPage',
|
33
|
+
fields=[
|
34
|
+
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
|
35
|
+
('content', wagtail.fields.StreamField([('rich_text', 0), ('code', 3), ('image', 4)], blank=True, block_lookup={0: ('wagtail.blocks.RichTextBlock', (), {}), 1: ('wagtail.blocks.TextBlock', (), {'help_text': None, 'required': True}), 2: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('python', 'Python'), ('javascript', 'JavaScript'), ('html', 'HTML'), ('css', 'CSS'), ('bash', 'Bash'), ('plaintext', 'Plain Text')], 'required': False}), 3: ('wagtail.blocks.StructBlock', [[('code', 1), ('language', 2)]], {}), 4: ('wagtail.images.blocks.ImageChooserBlock', (), {})}, help_text='Main content for the page.')),
|
36
|
+
],
|
37
|
+
options={
|
38
|
+
'abstract': False,
|
39
|
+
},
|
40
|
+
bases=('wagtailcore.page',),
|
41
|
+
),
|
42
|
+
migrations.CreateModel(
|
43
|
+
name='HomePage',
|
44
|
+
fields=[
|
45
|
+
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
|
46
|
+
('top_content', wagtail.fields.StreamField([('rich_text', 0), ('image', 1), ('icon_link_lists', 11)], blank=True, block_lookup={0: ('wagtail.blocks.RichTextBlock', (), {}), 1: ('picata.blocks.WrappedImageChooserBlock', (), {}), 2: ('wagtail.blocks.CharBlock', (), {'help_text': 'Optional heading for this list (e.g., Social Links).', 'required': False}), 3: ('wagtail.blocks.IntegerBlock', (), {'default': 2, 'help_text': 'Heading level for the list (1-6).', 'max_value': 6, 'min_value': 1, 'required': False}), 4: ('picata.blocks.HREFBlock', (), {'help_text': 'An optional link field', 'max_length': 255, 'required': False}), 5: ('wagtail.blocks.CharBlock', (), {'help_text': 'The title for the list item.', 'max_length': 50, 'required': True}), 6: ('wagtail.blocks.CharBlock', (), {'help_text': 'Id of the icon in the static/icons.svg file.', 'max_length': 255, 'required': False}), 7: ('wagtail.blocks.StructBlock', [[('href', 4), ('label', 5), ('icon', 6)]], {}), 8: ('wagtail.blocks.ListBlock', (7,), {'help_text': 'The list of items.'}), 9: ('wagtail.blocks.StructBlock', [[('heading', 2), ('heading_level', 3), ('items', 8)]], {}), 10: ('wagtail.blocks.StreamBlock', [[('link_list', 9)]], {'help_text': 'Add one or more heading-and-link-list blocks.', 'required': False}), 11: ('wagtail.blocks.StructBlock', [[('lists', 10)]], {})}, help_text="Content stream above 'Recent posts'")),
|
47
|
+
('bottom_content', wagtail.fields.StreamField([('rich_text', 0), ('image', 1), ('icon_link_lists', 11)], blank=True, block_lookup={0: ('wagtail.blocks.RichTextBlock', (), {}), 1: ('picata.blocks.WrappedImageChooserBlock', (), {}), 2: ('wagtail.blocks.CharBlock', (), {'help_text': 'Optional heading for this list (e.g., Social Links).', 'required': False}), 3: ('wagtail.blocks.IntegerBlock', (), {'default': 2, 'help_text': 'Heading level for the list (1-6).', 'max_value': 6, 'min_value': 1, 'required': False}), 4: ('picata.blocks.HREFBlock', (), {'help_text': 'An optional link field', 'max_length': 255, 'required': False}), 5: ('wagtail.blocks.CharBlock', (), {'help_text': 'The title for the list item.', 'max_length': 50, 'required': True}), 6: ('wagtail.blocks.CharBlock', (), {'help_text': 'Id of the icon in the static/icons.svg file.', 'max_length': 255, 'required': False}), 7: ('wagtail.blocks.StructBlock', [[('href', 4), ('label', 5), ('icon', 6)]], {}), 8: ('wagtail.blocks.ListBlock', (7,), {'help_text': 'The list of items.'}), 9: ('wagtail.blocks.StructBlock', [[('heading', 2), ('heading_level', 3), ('items', 8)]], {}), 10: ('wagtail.blocks.StreamBlock', [[('link_list', 9)]], {'help_text': 'Add one or more heading-and-link-list blocks.', 'required': False}), 11: ('wagtail.blocks.StructBlock', [[('lists', 10)]], {})}, help_text="Content stream rendered under 'Recent posts'")),
|
48
|
+
],
|
49
|
+
options={
|
50
|
+
'verbose_name': 'home page',
|
51
|
+
},
|
52
|
+
bases=('wagtailcore.page',),
|
53
|
+
),
|
54
|
+
migrations.CreateModel(
|
55
|
+
name='PageTag',
|
56
|
+
fields=[
|
57
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
58
|
+
('name', models.CharField(max_length=100, unique=True, verbose_name='name')),
|
59
|
+
('slug', models.SlugField(allow_unicode=True, max_length=100, unique=True, verbose_name='slug')),
|
60
|
+
],
|
61
|
+
options={
|
62
|
+
'abstract': False,
|
63
|
+
},
|
64
|
+
),
|
65
|
+
migrations.CreateModel(
|
66
|
+
name='PostGroupPage',
|
67
|
+
fields=[
|
68
|
+
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
|
69
|
+
('intro', wagtail.fields.RichTextField(blank=True, help_text='An optional introduction to this group.')),
|
70
|
+
],
|
71
|
+
options={
|
72
|
+
'verbose_name': 'post listing',
|
73
|
+
'verbose_name_plural': 'post listings',
|
74
|
+
},
|
75
|
+
bases=(wagtail.contrib.routable_page.models.RoutablePageMixin, 'wagtailcore.page'),
|
76
|
+
),
|
77
|
+
migrations.CreateModel(
|
78
|
+
name='SplitViewPage',
|
79
|
+
fields=[
|
80
|
+
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
|
81
|
+
('content', wagtail.fields.StreamField([('rich_text', 0), ('code', 3), ('image', 4), ('icon_link_lists', 14)], blank=True, block_lookup={0: ('wagtail.blocks.RichTextBlock', (), {}), 1: ('wagtail.blocks.TextBlock', (), {'help_text': None, 'required': True}), 2: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('python', 'Python'), ('javascript', 'JavaScript'), ('html', 'HTML'), ('css', 'CSS'), ('bash', 'Bash'), ('plaintext', 'Plain Text')], 'required': False}), 3: ('wagtail.blocks.StructBlock', [[('code', 1), ('language', 2)]], {}), 4: ('picata.blocks.WrappedImageChooserBlock', (), {}), 5: ('wagtail.blocks.CharBlock', (), {'help_text': 'Optional heading for this list (e.g., Social Links).', 'required': False}), 6: ('wagtail.blocks.IntegerBlock', (), {'default': 2, 'help_text': 'Heading level for the list (1-6).', 'max_value': 6, 'min_value': 1, 'required': False}), 7: ('picata.blocks.HREFBlock', (), {'help_text': 'An optional link field', 'max_length': 255, 'required': False}), 8: ('wagtail.blocks.CharBlock', (), {'help_text': 'The title for the list item.', 'max_length': 50, 'required': True}), 9: ('wagtail.blocks.CharBlock', (), {'help_text': 'Id of the icon in the static/icons.svg file.', 'max_length': 255, 'required': False}), 10: ('wagtail.blocks.StructBlock', [[('href', 7), ('label', 8), ('icon', 9)]], {}), 11: ('wagtail.blocks.ListBlock', (10,), {'help_text': 'The list of items.'}), 12: ('wagtail.blocks.StructBlock', [[('heading', 5), ('heading_level', 6), ('items', 11)]], {}), 13: ('wagtail.blocks.StreamBlock', [[('link_list', 12)]], {'help_text': 'Add one or more heading-and-link-list blocks.', 'required': False}), 14: ('wagtail.blocks.StructBlock', [[('lists', 13)]], {})}, help_text='Main content for the split-view page.')),
|
82
|
+
],
|
83
|
+
options={
|
84
|
+
'verbose_name': 'split-view page',
|
85
|
+
'verbose_name_plural': 'split-view pages',
|
86
|
+
},
|
87
|
+
bases=('wagtailcore.page',),
|
88
|
+
),
|
89
|
+
migrations.CreateModel(
|
90
|
+
name='Article',
|
91
|
+
fields=[
|
92
|
+
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
|
93
|
+
('tagline', models.CharField(blank=True, help_text='A short tagline for the article.')),
|
94
|
+
('summary', wagtail.fields.RichTextField(blank=True, help_text='A summary to be displayed in previews.')),
|
95
|
+
('content', wagtail.fields.StreamField([('rich_text', 0), ('code', 3), ('image', 4)], blank=True, block_lookup={0: ('wagtail.blocks.RichTextBlock', (), {}), 1: ('wagtail.blocks.TextBlock', (), {'help_text': None, 'required': True}), 2: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('python', 'Python'), ('javascript', 'JavaScript'), ('html', 'HTML'), ('css', 'CSS'), ('bash', 'Bash'), ('plaintext', 'Plain Text')], 'required': False}), 3: ('wagtail.blocks.StructBlock', [[('code', 1), ('language', 2)]], {}), 4: ('wagtail.images.blocks.ImageChooserBlock', (), {})}, help_text='Main content for the article.')),
|
96
|
+
('page_type', models.ForeignKey(blank=True, help_text='Select the type of article.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='articles', to='picata.articletype')),
|
97
|
+
],
|
98
|
+
options={
|
99
|
+
'abstract': False,
|
100
|
+
},
|
101
|
+
bases=('wagtailcore.page',),
|
102
|
+
),
|
103
|
+
migrations.CreateModel(
|
104
|
+
name='PageTagRelation',
|
105
|
+
fields=[
|
106
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
107
|
+
('content_object', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='picata.article')),
|
108
|
+
('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='picata.pagetag')),
|
109
|
+
],
|
110
|
+
options={
|
111
|
+
'abstract': False,
|
112
|
+
},
|
113
|
+
),
|
114
|
+
migrations.AddField(
|
115
|
+
model_name='article',
|
116
|
+
name='tags',
|
117
|
+
field=modelcluster.contrib.taggit.ClusterTaggableManager(blank=True, help_text='Tags for the article.', through='picata.PageTagRelation', to='picata.PageTag', verbose_name='Tags'),
|
118
|
+
),
|
119
|
+
migrations.CreateModel(
|
120
|
+
name='SocialSettings',
|
121
|
+
fields=[
|
122
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
123
|
+
('default_social_image', models.ForeignKey(blank=True, help_text='Default image for social media previews.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image')),
|
124
|
+
('site', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to='wagtailcore.site')),
|
125
|
+
],
|
126
|
+
options={
|
127
|
+
'abstract': False,
|
128
|
+
},
|
129
|
+
),
|
130
|
+
]
|
@@ -20,8 +20,6 @@ from django.db.models import (
|
|
20
20
|
from django.db.models.functions import Coalesce, ExtractYear
|
21
21
|
from django.http import HttpRequest
|
22
22
|
from django.urls import reverse
|
23
|
-
from hpk.typing import Args, Kwargs
|
24
|
-
from hpk.typing.wagtail import PageContext
|
25
23
|
from modelcluster.contrib.taggit import ClusterTaggableManager
|
26
24
|
from modelcluster.fields import ParentalKey
|
27
25
|
from taggit.models import TagBase, TaggedItemBase
|
@@ -37,6 +35,9 @@ from wagtail.query import PageQuerySet
|
|
37
35
|
from wagtail.search import index
|
38
36
|
from wagtail_modeladmin.options import ModelAdmin
|
39
37
|
|
38
|
+
from picata.typing import Args, Kwargs
|
39
|
+
from picata.typing.wagtail import PageContext
|
40
|
+
|
40
41
|
from .blocks import (
|
41
42
|
CodeBlock,
|
42
43
|
StaticIconLinkListsBlock,
|
@@ -103,7 +104,7 @@ class BasePage(Page):
|
|
103
104
|
|
104
105
|
def get_context(self, request: HttpRequest, *args: Args, **kwargs: Kwargs) -> BasePageContext:
|
105
106
|
"""Gather any publication and preview data available for the page into the context."""
|
106
|
-
from
|
107
|
+
from picata.helpers.wagtail import page_preview_data
|
107
108
|
|
108
109
|
context = super().get_context(request, *args, **kwargs)
|
109
110
|
context.update(page_preview_data(request, self))
|
@@ -356,7 +357,7 @@ class PostGroupPage(RoutablePageMixin, Page):
|
|
356
357
|
"""A top-level page for grouping various types of posts or articles."""
|
357
358
|
|
358
359
|
template = "picata/post_listing.html"
|
359
|
-
subpage_types: ClassVar[list[str]] = ["
|
360
|
+
subpage_types: ClassVar[list[str]] = ["picata.Article"]
|
360
361
|
|
361
362
|
intro = RichTextField(blank=True, help_text="An optional introduction to this group.")
|
362
363
|
|
@@ -465,7 +466,7 @@ class HomePage(BasePage):
|
|
465
466
|
|
466
467
|
def get_context(self, request: HttpRequest, *args: Args, **kwargs: Kwargs) -> HomePageContext:
|
467
468
|
"""Add content streams and a recent posts list to the context."""
|
468
|
-
from
|
469
|
+
from picata.helpers.wagtail import page_preview_data
|
469
470
|
|
470
471
|
recent_posts = Article.objects.live_for_user(request.user).by_date()
|
471
472
|
recent_posts = [page_preview_data(request, post) for post in recent_posts]
|
@@ -13,8 +13,8 @@ import contextlib
|
|
13
13
|
from os import getenv
|
14
14
|
from pathlib import Path
|
15
15
|
|
16
|
-
from
|
17
|
-
from
|
16
|
+
from picata.helpers import get_public_ip
|
17
|
+
from picata.log_utils import FormatterWithEverything
|
18
18
|
|
19
19
|
SRC_DIR = Path(__file__).resolve().parent.parent.parent
|
20
20
|
BASE_DIR = Path(SRC_DIR).parent
|
@@ -35,7 +35,7 @@ SECRET_KEY = getenv("SECRET_KEY")
|
|
35
35
|
|
36
36
|
INSTALLED_APPS = [
|
37
37
|
# Local apps
|
38
|
-
"
|
38
|
+
"picata.apps.Config",
|
39
39
|
# Wagtail
|
40
40
|
"wagtail.contrib.forms",
|
41
41
|
"wagtail.contrib.redirects",
|
@@ -72,10 +72,10 @@ MIDDLEWARE = [
|
|
72
72
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
73
73
|
"django.middleware.security.SecurityMiddleware",
|
74
74
|
"wagtail.contrib.redirects.middleware.RedirectMiddleware",
|
75
|
-
"
|
75
|
+
"picata.middleware.HTMLProcessingMiddleware",
|
76
76
|
]
|
77
77
|
|
78
|
-
ROOT_URLCONF = "
|
78
|
+
ROOT_URLCONF = "picata.urls"
|
79
79
|
|
80
80
|
TEMPLATES = [
|
81
81
|
{
|
@@ -94,7 +94,7 @@ TEMPLATES = [
|
|
94
94
|
},
|
95
95
|
]
|
96
96
|
|
97
|
-
WSGI_APPLICATION = "
|
97
|
+
WSGI_APPLICATION = "picata.wsgi.application"
|
98
98
|
|
99
99
|
|
100
100
|
# Database
|
@@ -103,7 +103,7 @@ WSGI_APPLICATION = "hpk.wsgi.application"
|
|
103
103
|
DATABASES = {
|
104
104
|
"default": {
|
105
105
|
"ENGINE": "django.db.backends.postgresql",
|
106
|
-
"NAME": getenv("
|
106
|
+
"NAME": getenv("PICATA_DB"),
|
107
107
|
"USER": getenv("DB_USER"),
|
108
108
|
"PASSWORD": getenv("DB_PASSWORD"),
|
109
109
|
"HOST": getenv("DB_HOST", "localhost"),
|
@@ -158,14 +158,14 @@ LOGGING = {
|
|
158
158
|
},
|
159
159
|
"django_log": {
|
160
160
|
"level": "INFO",
|
161
|
-
"class": "
|
161
|
+
"class": "picata.log_utils.RotatingDailyFileHandler",
|
162
162
|
"filename": LOG_DIR / "django.log",
|
163
163
|
"formatter": "verbose",
|
164
164
|
},
|
165
|
-
"
|
165
|
+
"picata_log": {
|
166
166
|
"level": "INFO",
|
167
|
-
"class": "
|
168
|
-
"filename": LOG_DIR / "
|
167
|
+
"class": "picata.log_utils.RotatingDailyFileHandler",
|
168
|
+
"filename": LOG_DIR / "picata.log",
|
169
169
|
"formatter": "verbose",
|
170
170
|
},
|
171
171
|
"warnings_log": {
|
@@ -178,8 +178,8 @@ LOGGING = {
|
|
178
178
|
},
|
179
179
|
},
|
180
180
|
"loggers": {
|
181
|
-
"
|
182
|
-
"handlers": ["
|
181
|
+
"picata": {
|
182
|
+
"handlers": ["picata_log"],
|
183
183
|
"level": "INFO",
|
184
184
|
"propagate": True,
|
185
185
|
},
|
@@ -279,7 +279,7 @@ DEFAULT_FROM_EMAIL = getenv("ADMIN_EMAIL")
|
|
279
279
|
# Wagtail
|
280
280
|
# See https://docs.wagtail.org/en/stable/
|
281
281
|
|
282
|
-
WAGTAIL_SITE_NAME = "
|
282
|
+
WAGTAIL_SITE_NAME = "[Example Site Name]"
|
283
283
|
|
284
284
|
# Image serving
|
285
285
|
WAGTAILIMAGES_IMAGE_MODEL = "wagtailimages.Image"
|
@@ -294,7 +294,7 @@ WAGTAILSEARCH_BACKENDS = {
|
|
294
294
|
|
295
295
|
# Base URL to use when referring to full URLs within the Wagtail admin backend -
|
296
296
|
# e.g. in notification emails. Don't include '/admin' or a trailing slash
|
297
|
-
WAGTAILADMIN_BASE_URL = "https://" + getenv("FQDN", "
|
297
|
+
WAGTAILADMIN_BASE_URL = "https://" + getenv("FQDN", "example.com")
|
298
298
|
|
299
299
|
# https://docs.wagtail.org/en/stable/reference/settings.html#general-editing
|
300
300
|
WAGTAILADMIN_RICH_TEXT_EDITORS = {
|
@@ -31,7 +31,9 @@ ALLOWED_HOSTS += CLASS_C_NETWORK_ADDR
|
|
31
31
|
|
32
32
|
if getenv("DJANGO_MANAGEMENT_COMMAND", "").startswith("runserver"):
|
33
33
|
logger.warning(
|
34
|
-
|
34
|
+
"Loading picata.settings.dev…\n"
|
35
|
+
f"INTERNAL_IPS = {INTERNAL_IPS}\n"
|
36
|
+
f"ALLOWED_HOSTS = {ALLOWED_HOSTS}"
|
35
37
|
)
|
36
38
|
|
37
39
|
RUNSERVERPLUS_POLLER_RELOADER_TYPE = "watchdog"
|
@@ -80,7 +82,7 @@ LOGGING["loggers"]["gunicorn"] = {
|
|
80
82
|
"propagate": False,
|
81
83
|
}
|
82
84
|
|
83
|
-
LOGGING["loggers"]["
|
85
|
+
LOGGING["loggers"]["picata"]["level"] = "DEBUG"
|
84
86
|
|
85
87
|
LOGGING["loggers"]["django"]["level"] = "DEBUG"
|
86
88
|
LOGGING["loggers"]["django.db.backends"] = {"level": "INFO"}
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<head>
|
4
4
|
<meta charset="UTF-8" />
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
|
6
|
-
<title>{% block document_title %}{% if title %}{{ title }} · {% endif %}
|
6
|
+
<title>{% block document_title %}{% if title %}{{ title }} · {% endif %}[Example Site]{% endblock %}</title>
|
7
7
|
|
8
8
|
<style>
|
9
9
|
@font-face { font-family: 'Sacramento'; src: url("{% static 'fonts/Sacramento-Regular.ttf' %}") format("truetype"); font-weight: 400; font-style: normal; }
|
@@ -25,7 +25,7 @@
|
|
25
25
|
|
26
26
|
<meta property="og:title" content="{% block og_title %}Hpk.io{% endblock %}">
|
27
27
|
<meta property="og:description" content="{% block og_description %}Ada Wrights's website - Hpk.io{% endblock %}">
|
28
|
-
<meta property="og:image" content="{% block og_image %}{% if settings.
|
28
|
+
<meta property="og:image" content="{% block og_image %}{% if settings.picata.SocialSettings.default_social_image %}{{ request.scheme }}://{{ request.get_host }}/{% image_url settings.hpk.SocialSettings.default_social_image 'fill-1200x630' %}{% else %}{% absolute_static 'ada-social-bear.jpg' %}{% endif %}{% endblock %}">
|
29
29
|
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
30
30
|
<meta property="og:type" content="{% block og_type %}website{% endblock %}">
|
31
31
|
|
@@ -35,7 +35,7 @@
|
|
35
35
|
"@type": "{% block ld_type %}WebPage{% endblock %}",
|
36
36
|
"name": "{{ page.get_social_title }}",
|
37
37
|
"description": "{{ page.get_social_description }}",
|
38
|
-
"image": "{% block ld_image %}{% if settings.
|
38
|
+
"image": "{% block ld_image %}{% if settings.picata.SocialSettings.default_social_image %}{{ request.scheme }}://{{ request.get_host }}/{% image_url settings.picata.SocialSettings.default_social_image 'fill-1200x630' %}{% else %}{% absolute_static 'ada-social-bear.jpg' %}{% endif %}{% endblock %}",
|
39
39
|
"url": "{{ request.build_absolute_uri }}"
|
40
40
|
}
|
41
41
|
</script>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
{% block title %}Theme gallery{% endblock %}
|
6
6
|
|
7
7
|
{% block article %}
|
8
|
-
<img src="{% if settings.
|
8
|
+
<img src="{% if settings.picata.SocialSettings.default_social_image %}{% image_url settings.picata.SocialSettings.default_social_image 'fill-1200x630' %}{% endif %}" width="1200" height="630" />
|
9
9
|
<div class="mx-8 my-8">
|
10
10
|
<div class="grid grid-cols-2 gap-2 md:grid-cols-4">
|
11
11
|
<button class="btn">Default</button>
|