diff --git a/docker/Dockerfile b/docker/Dockerfile index b35d82f7..73979ad6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -31,7 +31,7 @@ CMD ["yarn", "start"] # BASE # --------------------------------------------------------------------- # Base backend -FROM python:3.10-alpine as base +FROM python:3.12-alpine as base ENV PYCURL_SSL_LIBRARY openssl RUN apk update && apk add postgresql-libs postgresql-client libevent libjpeg openjpeg zlib @@ -85,7 +85,7 @@ COPY docker/init-dev.sh /app/docker/ ADD https://raw.githubusercontent.com/mrako/wait-for/d9699cb9fe8a4622f05c4ee32adf2fd93239d005/wait-for /usr/local/bin/ USER root -RUN apk add --no-cache bash +RUN apk add --no-cache bash postgresql-dev RUN pip3 install -r requirements/dev.txt RUN chmod +rx /usr/local/bin/wait-for USER www diff --git a/ietf/bibliography/models.py b/ietf/bibliography/models.py index c456fe1f..96305861 100644 --- a/ietf/bibliography/models.py +++ b/ietf/bibliography/models.py @@ -143,7 +143,8 @@ def save(self, *args, **kwargs): recreate_bibliography_items = False if recreate_bibliography_items: - self.bibliography_items.all().delete() + if self.pk is not None: + self.bibliography_items.all().delete() all_content = "".join( [ diff --git a/ietf/bibliography/wagtail_hooks.py b/ietf/bibliography/wagtail_hooks.py index 4007ce38..40d3093a 100644 --- a/ietf/bibliography/wagtail_hooks.py +++ b/ietf/bibliography/wagtail_hooks.py @@ -8,6 +8,6 @@ def register_references_menu_item(): return MenuItem( "References", reverse("referenced_types"), - classnames="icon icon-folder-inverse", + classname="icon icon-folder-inverse", order=10000, ) diff --git a/ietf/home/wagtail_hooks.py b/ietf/home/wagtail_hooks.py index 76cabb98..3eccd0a9 100644 --- a/ietf/home/wagtail_hooks.py +++ b/ietf/home/wagtail_hooks.py @@ -8,6 +8,6 @@ def register_resource_menu_item(): return MenuItem( "Documentation", reverse("django-admindocs-docroot"), - classnames="icon icon-folder-inverse", + classname="icon icon-folder-inverse", order=10000, ) diff --git a/ietf/images/migrations/0003_wagtail_42_wagtailimagefield.py b/ietf/images/migrations/0003_wagtail_42_wagtailimagefield.py new file mode 100644 index 00000000..5844449f --- /dev/null +++ b/ietf/images/migrations/0003_wagtail_42_wagtailimagefield.py @@ -0,0 +1,24 @@ +# Generated by Django 4.0.10 on 2023-11-29 10:19 + +from django.db import migrations +import wagtail.images.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('images', '0002_alter_ietfimage_file_hash'), + ] + + operations = [ + migrations.AlterField( + model_name='ietfimage', + name='file', + field=wagtail.images.models.WagtailImageField(height_field='height', upload_to=wagtail.images.models.get_upload_to, verbose_name='file', width_field='width'), + ), + migrations.AlterField( + model_name='ietfrendition', + name='file', + field=wagtail.images.models.WagtailImageField(height_field='height', upload_to=wagtail.images.models.get_rendition_upload_to, width_field='width'), + ), + ] diff --git a/ietf/images/migrations/0004_django_42_rendition_storage.py b/ietf/images/migrations/0004_django_42_rendition_storage.py new file mode 100644 index 00000000..e5348115 --- /dev/null +++ b/ietf/images/migrations/0004_django_42_rendition_storage.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.7 on 2023-11-29 12:17 + +from django.db import migrations +import wagtail.images.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('images', '0003_wagtail_42_wagtailimagefield'), + ] + + operations = [ + migrations.AlterField( + model_name='ietfrendition', + name='file', + field=wagtail.images.models.WagtailImageField(height_field='height', storage=wagtail.images.models.get_rendition_storage, upload_to=wagtail.images.models.get_rendition_upload_to, width_field='width'), + ), + ] diff --git a/ietf/search/templates/search/search.html b/ietf/search/templates/search/search.html index 24099177..a61e30b4 100644 --- a/ietf/search/templates/search/search.html +++ b/ietf/search/templates/search/search.html @@ -1,5 +1,5 @@ {% extends settings.utils.LayoutSettings.base_template %} -{% load static wagtailcore_tags %} +{% load static wagtailcore_tags wagtailsearchpromotions_tags %} {% block title %}Search{% endblock %} @@ -38,6 +38,7 @@
blog body
"}]', + ) + blogindex.add_child(instance=blog) + + home.button_text = "blog button text" + home.button_link = blog + home.save() + + resp = self.client.get(f"{reverse('search')}?query=introduction") + + self.assertEqual(resp.context["search_query"], "introduction") + self.assertEqual( + list(resp.context["search_results"]), + [Page.objects.get(pk=blog.pk)], + ) diff --git a/ietf/search/views.py b/ietf/search/views.py index 4dd0b0bb..448951fd 100644 --- a/ietf/search/views.py +++ b/ietf/search/views.py @@ -1,8 +1,7 @@ from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.shortcuts import render -from wagtail.contrib.search_promotions.models import SearchPromotion from wagtail.models import Page -from wagtail.search.models import Query +from wagtail.contrib.search_promotions.models import Query def search(request): @@ -12,16 +11,10 @@ def search(request): # Search if search_query and "\x00" not in search_query: search_results = Page.objects.live().search(search_query) - query = Query.get(search_query) + Query.get(search_query).add_hit() - # Record hit - query.add_hit() - - # Get search picks - search_picks = query.editors_picks.all() else: search_results = Page.objects.none() - search_picks = SearchPromotion.objects.none() # Pagination paginator = Paginator(search_results, 10) @@ -38,6 +31,5 @@ def search(request): { "search_query": search_query, "search_results": search_results, - "search_picks": search_picks, }, ) diff --git a/ietf/settings/base.py b/ietf/settings/base.py index 382c58d9..36dc0474 100644 --- a/ietf/settings/base.py +++ b/ietf/settings/base.py @@ -52,10 +52,9 @@ "wagtail.contrib.settings", "wagtail.contrib.table_block", "wagtail.contrib.routable_page", - "wagtail.contrib.modeladmin", + "wagtail_modeladmin", "wagtail.contrib.typed_table_block", "modelcluster", - "compressor", "taggit", "django.contrib.admin", "django.contrib.auth", @@ -129,8 +128,6 @@ USE_I18N = True -USE_L10N = True - USE_TZ = True @@ -140,12 +137,18 @@ STATICFILES_FINDERS = ( "django.contrib.staticfiles.finders.FileSystemFinder", "django.contrib.staticfiles.finders.AppDirectoriesFinder", - "compressor.finders.CompressorFinder", ) STATICFILES_DIRS = (os.path.join(PROJECT_DIR, "static"),) -STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage" +STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage", + }, +} STATIC_ROOT = os.path.join(BASE_DIR, "static") STATIC_URL = "/static/" @@ -157,11 +160,6 @@ # https://docs.djangoproject.com/en/3.2/ref/settings/#file-upload-permissions FILE_UPLOAD_PERMISSIONS = 0o664 -# Django compressor settings -# http://django-compressor.readthedocs.org/en/latest/settings/ - -COMPRESS_PRECOMPILERS = (("text/x-scss", "django_libsass.SassCompiler"),) - CACHES = { "default": { diff --git a/ietf/settings/production.py b/ietf/settings/production.py index df4827a7..e65e8f4d 100644 --- a/ietf/settings/production.py +++ b/ietf/settings/production.py @@ -10,16 +10,6 @@ DEBUG = False -# Compress static files offline and minify CSS -# http://django-compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_OFFLINE -COMPRESS_OFFLINE = True -COMPRESS_CSS_FILTERS = [ - 'compressor.filters.css_default.CssAbsoluteFilter', - 'compressor.filters.cssmin.CSSMinFilter', -] -COMPRESS_CSS_HASHING_METHOD = 'content' - - # Configuration from environment variables # Alternatively, you can set these in a local.py file on the server diff --git a/ietf/snippets/models.py b/ietf/snippets/models.py index 358983c0..e1a1095c 100644 --- a/ietf/snippets/models.py +++ b/ietf/snippets/models.py @@ -1,7 +1,8 @@ from django.conf import settings from django.db import models from django.template.loader import get_template -from wagtail.admin.panels import FieldPanel +from wagtail.admin.panels import FieldPanel, TitleFieldPanel +from wagtail.admin.widgets.slug import SlugInput from wagtail.fields import RichTextField from wagtail.search import index from wagtail.search.index import Indexed @@ -31,8 +32,10 @@ class Charter(models.Model, index.Indexed): ) search_fields = [ - index.SearchField("title", partial_match=True, boost=10), + index.SearchField("title", boost=10), + index.AutocompleteField("title", boost=10), index.SearchField("abstract"), + index.AutocompleteField("abstract"), ] def __str__(self): @@ -61,9 +64,12 @@ class WorkingGroup(models.Model, index.Indexed): # There is no field currently to capture area/parent search_fields = [ - index.SearchField("name", partial_match=True, boost=10), + index.SearchField("name", boost=10), + index.AutocompleteField("name", boost=10), index.SearchField("acronym"), + index.AutocompleteField("acronym"), index.SearchField("description"), + index.AutocompleteField("description"), ] @property @@ -102,10 +108,14 @@ class RFC(models.Model, index.Indexed): ) search_fields = [ - index.SearchField("title", partial_match=True, boost=10), + index.SearchField("title", boost=10), + index.AutocompleteField("title", boost=10), index.SearchField("rfc", boost=10), + index.AutocompleteField("rfc", boost=10), index.SearchField("authors"), + index.AutocompleteField("authors"), index.SearchField("abstract"), + index.AutocompleteField("abstract"), ] def __str__(self): @@ -129,7 +139,10 @@ class Person(models.Model, Indexed): name = models.CharField(max_length=511) link = models.URLField() - search_fields = [index.SearchField("name")] + search_fields = [ + index.SearchField("name"), + index.AutocompleteField("name"), + ] panels = [FieldPanel("name")] def __str__(self): @@ -143,7 +156,10 @@ class Meta: class Role(models.Model, Indexed): name = models.CharField(max_length=255, help_text="A role within the IETF.") - search_fields = [index.SearchField("name")] + search_fields = [ + index.SearchField("name"), + index.AutocompleteField("name"), + ] panels = [FieldPanel("name")] @@ -186,8 +202,11 @@ class Group(models.Model, Indexed, RenderableSnippetMixin): search_fields = [ index.SearchField("name"), + index.AutocompleteField("name"), index.SearchField("summary"), + index.AutocompleteField("summary"), index.SearchField("email"), + index.AutocompleteField("email"), ] panels = [ @@ -223,8 +242,11 @@ class CallToAction(Indexed, RelatedLink, RenderableSnippetMixin): search_fields = [ index.SearchField("title"), + index.AutocompleteField("title"), index.SearchField("blurb"), + index.AutocompleteField("blurb"), index.SearchField("button_text"), + index.AutocompleteField("button_text"), ] panels = RelatedLink.panels + [ @@ -278,9 +300,13 @@ class MailingListSignup(models.Model, Indexed, RenderableSnippetMixin): search_fields = [ index.SearchField("title"), + index.AutocompleteField("title"), index.SearchField("blurb"), + index.AutocompleteField("blurb"), index.SearchField("button_text"), + index.AutocompleteField("button_text"), index.SearchField("sign_up"), + index.AutocompleteField("sign_up"), ] panels = [ @@ -323,12 +349,14 @@ class Topic(models.Model, Indexed): search_fields = [ index.SearchField("title"), + index.AutocompleteField("title"), index.SearchField("slug"), + index.AutocompleteField("slug"), ] panels = [ - FieldPanel("title"), - FieldPanel("slug"), + TitleFieldPanel("title"), + FieldPanel("slug", widget=SlugInput), ] def __str__(self): @@ -355,6 +383,7 @@ class Sponsor(models.Model, Indexed): search_fields = [ index.SearchField("title"), + index.AutocompleteField("title"), ] panels = [FieldPanel("title"), FieldPanel("logo"), FieldPanel("link")] @@ -379,7 +408,9 @@ class GlossaryItem(models.Model, Indexed): search_fields = [ index.SearchField("title"), + index.AutocompleteField("title"), index.SearchField("body"), + index.AutocompleteField("body"), ] panels = [ diff --git a/ietf/templates/iab_base.html b/ietf/templates/iab_base.html index e082a9fe..0e9167e8 100644 --- a/ietf/templates/iab_base.html +++ b/ietf/templates/iab_base.html @@ -1,4 +1,4 @@ -{% load compress static wagtailuserbar wagtailcore_tags wagtailimages_tags ietf_tags analytical %} +{% load static wagtailuserbar wagtailcore_tags wagtailimages_tags ietf_tags analytical %} diff --git a/ietf/templates_src/base.html b/ietf/templates_src/base.html index 74f58f6b..bf73ab41 100644 --- a/ietf/templates_src/base.html +++ b/ietf/templates_src/base.html @@ -1,4 +1,4 @@ -{% load compress static wagtailuserbar wagtailcore_tags wagtailimages_tags ietf_tags analytical %} +{% load static wagtailuserbar wagtailcore_tags wagtailimages_tags ietf_tags analytical %} diff --git a/ietf/utils/wagtail_hooks.py b/ietf/utils/wagtail_hooks.py index fe81ea0d..70c3ad99 100644 --- a/ietf/utils/wagtail_hooks.py +++ b/ietf/utils/wagtail_hooks.py @@ -1,13 +1,13 @@ from django.conf import settings from django.utils.html import format_html from wagtail import hooks -from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register +from wagtail_modeladmin.options import ModelAdmin, modeladmin_register from wagtailorderable.modeladmin.mixins import OrderableMixin from ietf.utils.models import MenuItem -@hooks.register("insert_editor_css") +@hooks.register("insert_global_admin_css") def editor_css(): return format_html( '=0.5.0,<0.6 -django-libsass>=0.8 -django>=3.0,<3.3 -django_analytical>=2.5 -django_compressor>=2.2 -libsass>=0.8.3 -psycopg2-binary>=2.7.5 +dj-database-url +django>=4.2,<4.3 +django_analytical +psycopg2 pymemcache -tqdm>=3.7.0 +tqdm typed-environment-configuration>=0.1.3,<0.2 wagtail-markdown +wagtail-modeladmin wagtail-orderable -wagtail>=4.1,<4.2 +wagtail>=5.2,<5.3 diff --git a/requirements/base.txt b/requirements/base.txt index dc3b57af..e8487015 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.10 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile base.in @@ -20,12 +20,12 @@ charset-normalizer==3.3.2 # via requests defusedxml==0.7.1 # via willow -dj-database-url==0.5.0 +dj-database-url==2.1.0 # via -r base.in -django==3.2.23 +django==4.2.7 # via # -r base.in - # django-appconf + # dj-database-url # django-filter # django-modelcluster # django-permissionedforms @@ -35,21 +35,13 @@ django==3.2.23 # wagtail django-analytical==3.1.0 # via -r base.in -django-appconf==1.0.6 - # via django-compressor -django-compressor==4.4 - # via - # -r base.in - # django-libsass -django-filter==22.1 +django-filter==23.4 # via wagtail -django-libsass==0.9 - # via -r base.in django-modelcluster==6.1 # via wagtail django-permissionedforms==0.1 # via wagtail -django-taggit==3.1.0 +django-taggit==4.0.0 # via wagtail django-treebeard==4.7 # via wagtail @@ -67,10 +59,6 @@ idna==3.6 # via requests l18n==2021.3 # via wagtail -libsass==0.22.0 - # via - # -r base.in - # django-libsass markdown==3.5.1 # via wagtail-markdown mbstrdecoder==1.1.3 @@ -80,23 +68,22 @@ openpyxl==3.1.2 packaging==23.2 # via bleach pillow==10.1.0 - # via wagtail -psycopg2-binary==2.9.9 + # via + # pillow-heif + # wagtail +pillow-heif==0.13.1 + # via willow +psycopg2==2.9.9 # via -r base.in pymemcache==4.0.0 # via -r base.in pytz==2023.3.post1 # via - # django # django-modelcluster # djangorestframework # l18n -rcssmin==1.1.1 - # via django-compressor requests==2.31.0 # via wagtail -rjsmin==1.2.1 - # via django-compressor six==1.16.0 # via # bleach @@ -115,21 +102,24 @@ typed-environment-configuration==0.1.5 typepy==1.3.0 # via typed-environment-configuration typing-extensions==4.8.0 - # via asgiref + # via dj-database-url urllib3==2.1.0 # via requests -wagtail==4.1.9 +wagtail==5.2.1 # via # -r base.in # wagtail-markdown + # wagtail-modeladmin # wagtail-orderable wagtail-markdown==0.11.1 # via -r base.in +wagtail-modeladmin==1.0.0 + # via -r base.in wagtail-orderable==1.2.0 # via -r base.in webencodings==0.5.1 # via # bleach # html5lib -willow==1.6.3 +willow[heif]==1.6.3 # via wagtail diff --git a/requirements/dev.txt b/requirements/dev.txt index 5366e4de..ef30d09b 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.10 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile dev.in @@ -9,11 +9,7 @@ build==1.0.3 click==8.1.7 # via pip-tools coverage[toml]==7.3.2 - # via - # coverage - # pytest-cov -exceptiongroup==1.2.0 - # via pytest + # via pytest-cov iniconfig==2.0.0 # via pytest packaging==23.2 @@ -35,13 +31,6 @@ pytest-cov==4.1.0 # via -r dev.in pytest-django==4.7.0 # via -r dev.in -tomli==2.0.1 - # via - # build - # coverage - # pip-tools - # pyproject-hooks - # pytest wheel==0.42.0 # via pip-tools diff --git a/requirements/docker.txt b/requirements/docker.txt index 3a8ab334..e4e3a571 100644 --- a/requirements/docker.txt +++ b/requirements/docker.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.10 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile docker.in diff --git a/webpack.config.js b/webpack.config.js index ae3c2d86..b8980519 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -11,7 +11,7 @@ module.exports = (env, options) => { return { mode: options.mode, devtool: - options.mode !== 'production' ? 'inline-source-map' : undefined, + options.mode !== 'production' ? 'eval-source-map' : undefined, entry: './ietf/static_src/index.js', output: { filename: '[name].js',