diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000000000000000000000000000000000..996cd5aad4d7331e9c74dcaa7eb6483a5116eed9 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,216 @@ +module.exports = { + extends: [ + "eslint:recommended", + "plugin:vue/strongly-recommended", + // "plugin:prettier/recommended", + "plugin:@intlify/vue-i18n/recommended", + ], + rules: { + "no-unused-vars": "warn", + "vue/no-unused-vars": "off", + "vue/multi-word-component-names": "off", + "@intlify/vue-i18n/key-format-style": [ + "error", + "snake_case", + { + splitByDots: false, + }, + ], + // "@intlify/vue-i18n/no-unused-keys": ["warn", {}], + "@intlify/vue-i18n/no-raw-text": [ + "error", + { + ignoreNodes: ["v-icon"], + ignorePattern: "^[-–—·#:()\\[\\]&\\.\\s]+$", + }, + ], + // Fixes for prettier (avoid eslint-config-prettier) + // The following rules can be used in some cases. See the README for more + // information. (These are marked with `0` instead of `"off"` so that a + // script can distinguish them.) + curly: 0, + "lines-around-comment": 0, + "max-len": 0, + "no-confusing-arrow": 0, + "no-mixed-operators": 0, + "no-tabs": 0, + "no-unexpected-multiline": 0, + quotes: 0, + "@typescript-eslint/quotes": 0, + "babel/quotes": 0, + "vue/html-self-closing": 0, + "vue/max-len": 0, + + // The rest are rules that you never need to enable when using Prettier. + "array-bracket-newline": "off", + "array-bracket-spacing": "off", + "array-element-newline": "off", + "arrow-parens": "off", + "arrow-spacing": "off", + "block-spacing": "off", + "brace-style": "off", + "comma-dangle": "off", + "comma-spacing": "off", + "comma-style": "off", + "computed-property-spacing": "off", + "dot-location": "off", + "eol-last": "off", + "func-call-spacing": "off", + "function-call-argument-newline": "off", + "function-paren-newline": "off", + "generator-star": "off", + "generator-star-spacing": "off", + "implicit-arrow-linebreak": "off", + indent: "off", + "jsx-quotes": "off", + "key-spacing": "off", + "keyword-spacing": "off", + "linebreak-style": "off", + "multiline-ternary": "off", + "newline-per-chained-call": "off", + "new-parens": "off", + "no-arrow-condition": "off", + "no-comma-dangle": "off", + "no-extra-parens": "off", + "no-extra-semi": "off", + "no-floating-decimal": "off", + "no-mixed-spaces-and-tabs": "off", + "no-multi-spaces": "off", + "no-multiple-empty-lines": "off", + "no-reserved-keys": "off", + "no-space-before-semi": "off", + "no-trailing-spaces": "off", + "no-whitespace-before-property": "off", + "no-wrap-func": "off", + "nonblock-statement-body-position": "off", + "object-curly-newline": "off", + "object-curly-spacing": "off", + "object-property-newline": "off", + "one-var-declaration-per-line": "off", + "operator-linebreak": "off", + "padded-blocks": "off", + "quote-props": "off", + "rest-spread-spacing": "off", + semi: "off", + "semi-spacing": "off", + "semi-style": "off", + "space-after-function-name": "off", + "space-after-keywords": "off", + "space-before-blocks": "off", + "space-before-function-paren": "off", + "space-before-function-parentheses": "off", + "space-before-keywords": "off", + "space-in-brackets": "off", + "space-in-parens": "off", + "space-infix-ops": "off", + "space-return-throw-case": "off", + "space-unary-ops": "off", + "space-unary-word-ops": "off", + "switch-colon-spacing": "off", + "template-curly-spacing": "off", + "template-tag-spacing": "off", + "unicode-bom": "off", + "wrap-iife": "off", + "wrap-regex": "off", + "yield-star-spacing": "off", + "@babel/object-curly-spacing": "off", + "@babel/semi": "off", + "@typescript-eslint/brace-style": "off", + "@typescript-eslint/comma-dangle": "off", + "@typescript-eslint/comma-spacing": "off", + "@typescript-eslint/func-call-spacing": "off", + "@typescript-eslint/indent": "off", + "@typescript-eslint/keyword-spacing": "off", + "@typescript-eslint/member-delimiter-style": "off", + "@typescript-eslint/no-extra-parens": "off", + "@typescript-eslint/no-extra-semi": "off", + "@typescript-eslint/object-curly-spacing": "off", + "@typescript-eslint/semi": "off", + "@typescript-eslint/space-before-blocks": "off", + "@typescript-eslint/space-before-function-paren": "off", + "@typescript-eslint/space-infix-ops": "off", + "@typescript-eslint/type-annotation-spacing": "off", + "babel/object-curly-spacing": "off", + "babel/semi": "off", + "flowtype/boolean-style": "off", + "flowtype/delimiter-dangle": "off", + "flowtype/generic-spacing": "off", + "flowtype/object-type-curly-spacing": "off", + "flowtype/object-type-delimiter": "off", + "flowtype/quotes": "off", + "flowtype/semi": "off", + "flowtype/space-after-type-colon": "off", + "flowtype/space-before-generic-bracket": "off", + "flowtype/space-before-type-colon": "off", + "flowtype/union-intersection-spacing": "off", + "react/jsx-child-element-spacing": "off", + "react/jsx-closing-bracket-location": "off", + "react/jsx-closing-tag-location": "off", + "react/jsx-curly-newline": "off", + "react/jsx-curly-spacing": "off", + "react/jsx-equals-spacing": "off", + "react/jsx-first-prop-new-line": "off", + "react/jsx-indent": "off", + "react/jsx-indent-props": "off", + "react/jsx-max-props-per-line": "off", + "react/jsx-newline": "off", + "react/jsx-one-expression-per-line": "off", + "react/jsx-props-no-multi-spaces": "off", + "react/jsx-tag-spacing": "off", + "react/jsx-wrap-multilines": "off", + "standard/array-bracket-even-spacing": "off", + "standard/computed-property-even-spacing": "off", + "standard/object-curly-even-spacing": "off", + "unicorn/empty-brace-spaces": "off", + "unicorn/no-nested-ternary": "off", + "unicorn/number-literal-case": "off", + "vue/array-bracket-newline": "off", + "vue/array-bracket-spacing": "off", + "vue/arrow-spacing": "off", + "vue/block-spacing": "off", + "vue/block-tag-newline": "off", + "vue/brace-style": "off", + "vue/comma-dangle": "off", + "vue/comma-spacing": "off", + "vue/comma-style": "off", + "vue/dot-location": "off", + "vue/func-call-spacing": "off", + "vue/html-closing-bracket-newline": "off", + "vue/html-closing-bracket-spacing": "off", + "vue/html-end-tags": "off", + "vue/html-indent": "off", + "vue/html-quotes": "off", + "vue/key-spacing": "off", + "vue/keyword-spacing": "off", + "vue/max-attributes-per-line": "off", + "vue/multiline-html-element-content-newline": "off", + "vue/multiline-ternary": "off", + "vue/mustache-interpolation-spacing": "off", + "vue/no-extra-parens": "off", + "vue/no-multi-spaces": "off", + "vue/no-spaces-around-equal-signs-in-attribute": "off", + "vue/object-curly-newline": "off", + "vue/object-curly-spacing": "off", + "vue/object-property-newline": "off", + "vue/operator-linebreak": "off", + "vue/quote-props": "off", + "vue/script-indent": "off", + "vue/singleline-html-element-content-newline": "off", + "vue/space-in-parens": "off", + "vue/space-infix-ops": "off", + "vue/space-unary-ops": "off", + "vue/template-curly-spacing": "off", + }, + settings: { + "vue-i18n": { + localeDir: "./aleksis/core/frontend/messages/*.{json}", + messageSyntaxVersion: "^8.0.0", + }, + }, + env: { + es2021: true, + }, + parserOptions: { + ecmaVersion: "latest", + }, +}; diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 22daa3005c2ff44f91964a1ecb4627db0a0afe2c..87137173c9f87a1ff436deda92cd180b274d29da 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,17 +1,17 @@ include: - - project: "AlekSIS/official/AlekSIS" - file: /ci/general.yml - - project: "AlekSIS/official/AlekSIS" - file: /ci/prepare/lock.yml - - project: "AlekSIS/official/AlekSIS" - file: /ci/test/lint.yml - - project: "AlekSIS/official/AlekSIS" - file: /ci/test/security.yml - - project: "AlekSIS/official/AlekSIS" - file: /ci/build/dist.yml - - project: "AlekSIS/official/AlekSIS" - file: /ci/build/docs.yml - - project: "AlekSIS/official/AlekSIS" - file: /ci/publish/pypi.yml - - project: "AlekSIS/official/AlekSIS" - file: /ci/deploy/pages.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/general.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/prepare/lock.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/test/lint.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/test/security.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/build/dist.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/build/docs.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/publish/pypi.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/deploy/pages.yml diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000000000000000000000000000000000..38d141b743fd55678f50077c0617924475817095 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,91 @@ +# Byte-compiled / optimized / DLL files +*$py.class +*.py[cod] +__pycache__/ + +# Distribution / packaging +*.egg +*.egg-info/ +.Python +.eggs/ +.installed.cfg +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ + +# Installer logs +pip-delete-this-directory.txt +pip-log.txt + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# pyenv +.python-version + +# Environments +.env +.venv +ENV/ +env/ +venv/ + +# Editors +*~ +DEADJOE +\#*# + +# IntelliJ +.idea +.idea/ + +# Database +db.sqlite3 + +# Sphinx +docs/_build/ + +# TeX +*.aux + +# Generated files +/node_modules/ +/static/ +/whoosh_index/ +poetry.lock + +.coverage +.mypy_cache/ +.tox/ +htmlcov/ +maintenance_mode_state.txt +media/ +package-lock.json +yarn.lock + +# VSCode +.vscode/ +.history/ +*.code-workspace + +/cache + +# Add HTML files to avoid problems with unsupported Django templates +*.html + +# Do not check/reformat generated files +aleksis/core/util/licenses.json +.vite/ diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0ed7fe7ce5203909ec91f09c227deb0bb94390c7..a261e9075dd14243d8069c4a38838a543439f848 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,8 +6,21 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog`_, and this project adheres to `Semantic Versioning`_. -Unreleased ----------- +`3.0b0` - 2023-02-16 +-------------------- + +This version requires AlekSIS-Core 3.0. It is incompatible with any previous +version. + +Removed +~~~~~~~ + +* Legacy menu integration for AlekSIS-Core pre-3.0 + +Added +~~~~~ + +* Add SPA support for AlekSIS-Core 3.0 `2.2`_ - 2022-06-23 ------------------- @@ -68,8 +81,9 @@ Added .. _Keep a Changelog: https://keepachangelog.com/en/1.0.0/ .. _Semantic Versioning: https://semver.org/spec/v2.0.0.html -.. _2.0b0: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.0b0 -.. _2.0b1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.0b1 -.. _2.0: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.0 -.. _2.1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.1 -.. _2.2: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.2 +.. _2.0b0: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/2.0b0 +.. _2.0b1: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/2.0b1 +.. _2.0: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/2.0 +.. _2.1: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/2.1 +.. _2.2: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/2.2 +.. _3.0b0: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/3.0b0 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..2b6e55b7222a392980b7f97473b37f75604a6ad5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,2 @@ +ARG APPS="AlekSIS-App-Resint" +FROM registry.edugit.org/aleksis/official/aleksis-core:master diff --git a/aleksis/apps/resint/frontend/index.js b/aleksis/apps/resint/frontend/index.js new file mode 100644 index 0000000000000000000000000000000000000000..b8b497d77a5bc75236845020ac20d0f2aea50e11 --- /dev/null +++ b/aleksis/apps/resint/frontend/index.js @@ -0,0 +1,150 @@ +import { hasPersonValidator } from "aleksis.core/routeValidators"; + +export default { + meta: { + inMenu: true, + titleKey: "resint.menu_title", + icon: "mdi-open-in-app", + validators: [hasPersonValidator], + }, + children: [ + { + path: "", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.posterIndex", + meta: { + inMenu: true, + titleKey: "resint.manage_posters.menu_title", + icon: "mdi-file-upload-outline", + permission: "resint.view_posters_rule", + }, + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "upload/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.posterUpload", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: ":pk/edit/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.posterEdit", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: ":pk/delete/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.posterDelete", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: ":slug.pdf", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.posterShowCurrent", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "groups/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.posterGroupList", + meta: { + inMenu: true, + titleKey: "resint.poster_groups.menu_title", + icon: "mdi-folder-multiple-outline", + permission: "resint.view_postergroups_rule", + }, + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "groups/create/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.createPosterGroup", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "groups/:pk/edit/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.editPosterGroup", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "groups/:pk/delete/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.deletePosterGroup", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "live/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.liveDocuments", + meta: { + inMenu: true, + titleKey: "resint.live_documents.menu_title", + icon: "mdi-update", + permission: "resint.view_livedocuments_rule", + }, + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "live/:app/:model/create/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.createLiveDocument", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "live/:pk/edit/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.editLiveDocument", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "live_documents/:pk/delete/", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.deleteLiveDocument", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "live_documents/:slug.pdf", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.showLiveDocument", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + { + path: "api/live_documents/:slug.pdf", + component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), + name: "resint.apiShowLiveDocument", + props: { + byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, + }, + }, + ], +}; diff --git a/aleksis/apps/resint/frontend/messages/de.json b/aleksis/apps/resint/frontend/messages/de.json new file mode 100644 index 0000000000000000000000000000000000000000..bb7e90c25aab9103508a9d2d5f8504151ae8b1e6 --- /dev/null +++ b/aleksis/apps/resint/frontend/messages/de.json @@ -0,0 +1,14 @@ +{ + "resint": { + "menu_title": "Dokumente", + "manage_posters": { + "menu_title": "Dokumente verwalten" + }, + "poster_groups": { + "menu_title": "Dokumentengruppen" + }, + "live_documents": { + "menu_title": "Live-Dokumente" + } + } +} diff --git a/aleksis/apps/resint/frontend/messages/en.json b/aleksis/apps/resint/frontend/messages/en.json new file mode 100644 index 0000000000000000000000000000000000000000..376a6a7ea193f002f41a927b604563e5cbdba081 --- /dev/null +++ b/aleksis/apps/resint/frontend/messages/en.json @@ -0,0 +1,14 @@ +{ + "resint": { + "menu_title": "Documents", + "manage_posters": { + "menu_title": "Manage posters" + }, + "poster_groups": { + "menu_title": "Poster groups" + }, + "live_documents": { + "menu_title": "Live documents" + } + } +} diff --git a/aleksis/apps/resint/menus.py b/aleksis/apps/resint/menus.py deleted file mode 100644 index 2967079ee5c00b2955b5ce5c489fe38d7b06f5a0..0000000000000000000000000000000000000000 --- a/aleksis/apps/resint/menus.py +++ /dev/null @@ -1,87 +0,0 @@ -from typing import Any, Dict, List - -from django.apps import apps -from django.urls import reverse -from django.utils.translation import ugettext_lazy as _ - - -def _get_menu_entries() -> List[Dict[str, Any]]: - """Build menu entries for all poster groups. - - This will include only poster groups where ``show_in_menu`` is enabled. - """ - PosterGroup = apps.get_model("resint", "PosterGroup") - return [ - { - "name": group.name, - "url": reverse("poster_show_current", args=[group.slug]), - "icon": "picture_as_pdf", - "validators": [ - ( - "aleksis.apps.resint.rules.permission_validator", - "resint.view_poster_pdf_menu", - group, - ), - ], - "new_tab": True, - } - for group in PosterGroup.objects.all() - ] - - -class MENUS: - def get(menu_name, default=None): - menus = { - "NAV_MENU_CORE": [ - { - "name": _("Documents"), - "url": "#", - "icon": "open_in_browser", - "root": True, - "validators": [ - ( - "aleksis.core.util.predicates.permission_validator", - "resint.view_poster_menu", - ), - ], - "submenu": [ - { - "name": _("Manage posters"), - "url": "poster_index", - "icon": "file_upload", - "validators": [ - ( - "aleksis.core.util.predicates.permission_validator", - "resint.view_posters_rule", - ), - ], - }, - { - "name": _("Poster groups"), - "url": "poster_group_list", - "icon": "topic", - "validators": [ - ( - "aleksis.core.util.predicates.permission_validator", - "resint.view_postergroups_rule", - ), - ], - }, - { - "name": _("Live documents"), - "url": "live_documents", - "icon": "update", - "validators": [ - ( - "aleksis.core.util.predicates.permission_validator", - "resint.view_livedocuments_rule", - ), - ], - }, - ], - } - ] - + _get_menu_entries(), - } - - return menus.get(menu_name, default) diff --git a/aleksis/apps/resint/models.py b/aleksis/apps/resint/models.py index eab9cc406f0dbb80a7b8accf9e7dbd595bc3eef7..aae47aa1693869acd96a5e25b6cd7d7e29a86f98 100644 --- a/aleksis/apps/resint/models.py +++ b/aleksis/apps/resint/models.py @@ -4,6 +4,7 @@ from typing import Any, Optional from django.core.files import File from django.core.validators import FileExtensionValidator, MaxValueValidator, MinValueValidator from django.db import models +from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -15,9 +16,43 @@ from celery.states import SUCCESS from reversion.models import Revision, Version from aleksis.core.mixins import ExtensibleModel, ExtensiblePolymorphicModel +from aleksis.core.models import DynamicRoute from aleksis.core.util.pdf import generate_pdf_from_template +class PosterGroupDynamicRoute(DynamicRoute): + @classmethod + def get_dynamic_routes(cls): + poster_groups = PosterGroup.objects.all() + + dynamic_routes = [] + + for poster_group in poster_groups: + dynamic_routes.append(cls.get_route_data(poster_group)) + + return dynamic_routes + + @classmethod + def get_route_data(cls, instance): + dynamic_route = {} + + dynamic_route["parent_route_name"] = "" + + dynamic_route["route_path"] = reverse("poster_show_current", args=[instance.slug]) + dynamic_route["route_name"] = f"resint.posterGroup.{instance.slug}" + + dynamic_route["display_account_menu"] = False + dynamic_route["display_sidenav_menu"] = instance.show_in_menu + dynamic_route["menu_new_tab"] = True + + dynamic_route["menu_title"] = instance.name + dynamic_route["menu_icon"] = "mdi-file-pdf-box" + + dynamic_route["route_permission"] = "" if instance.public else "resint.view_poster_pdf_menu" + + return dynamic_route + + class PosterGroup(ExtensibleModel): """Group for time-based documents, called posters.""" diff --git a/aleksis/apps/resint/rules.py b/aleksis/apps/resint/rules.py index f1d9f72db0f2e38dfc1b9f20f4c74876a2e10432..a30a6811217ffa0317732bfebd2a93862f44ed14 100644 --- a/aleksis/apps/resint/rules.py +++ b/aleksis/apps/resint/rules.py @@ -102,8 +102,10 @@ view_poster_pdf_predicate = is_public_poster_group | ( ) add_perm("resint.view_poster_pdf", view_poster_pdf_predicate) -# View menu entry for single posters -view_poster_pdf_menu_predicate = show_poster_group_in_menu & view_poster_pdf_predicate +# View poster PDF file in menu +view_poster_pdf_menu_predicate = has_person & ( + has_global_perm("resint.view_postergroup") | has_global_perm("resint.view_poster") +) add_perm("resint.view_poster_pdf_menu", view_poster_pdf_menu_predicate) # Show the poster manage menu diff --git a/docs/conf.py b/docs/conf.py index e09e69554ffa82cf8a1b5edf939ba08914e6baeb..5ab41510c32eec41c4627780b6233e92bc1c1269 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,9 +29,9 @@ copyright = "2018-2022 The AlekSIS team" author = "The AlekSIS Team" # The short X.Y version -version = "2.2" +version = "3.0" # The full version, including alpha/beta/rc tags -release = "2.2.1.dev0" +release = "3.0b0" # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 5a7e4ae64e67a3ba4cc98a32fa2944b3fef7ee1e..fd411643ec458c931758ade53ab5999d0b5b4072 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "AlekSIS-App-Resint" -version = "2.2.1.dev0" +version = "3.0b0" packages = [ { include = "aleksis" } ] @@ -41,7 +41,7 @@ secondary = true [tool.poetry.dependencies] python = "^3.9" -AlekSIS-Core = "^2.1" +AlekSIS-Core = "^3.0b0" [tool.poetry.dev-dependencies] aleksis-builddeps = "*" diff --git a/tox.ini b/tox.ini index 749e0606f4f02fcbd1649627219b15850cbc0a90..6e4b77ab1ded935257117696975c2150772cd85c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,16 +1,15 @@ [tox] skipsdist = True skip_missing_interpreters = true -envlist = py37,py38,py39 +envlist = py39,py310,py311 [testenv] whitelist_externals = poetry - sudo skip_install = true envdir = {toxworkdir}/globalenv commands_pre = poetry install - poetry run aleksis-admin yarn install + poetry run aleksis-admin vite build poetry run aleksis-admin collectstatic --no-input commands = poetry run pytest --cov=. {posargs} aleksis/ @@ -27,6 +26,8 @@ commands = poetry run black --check --diff aleksis/ poetry run isort -c --diff --stdout aleksis/ poetry run flake8 {posargs} aleksis/ + poetry run sh -c "aleksis-admin yarn run prettier --check --ignore-path={toxinidir}/.prettierignore {toxinidir}" + poetry run sh -c "aleksis-admin yarn run eslint {toxinidir}/aleksis/**/*/frontend/**/*.{js,vue} --config={toxinidir}/.eslintrc.js --resolve-plugins-relative-to=." [testenv:security] commands = @@ -46,6 +47,7 @@ commands = poetry run make -C docs/ html {posargs} commands = poetry run isort aleksis/ poetry run black aleksis/ + poetry run sh -c "aleksis-admin yarn run prettier --write --ignore-path={toxinidir}/.prettierignore {toxinidir}" [testenv:makemessages] commands =