Skip to content
Snippets Groups Projects
Commit 8dc2cdaf authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Merge branch 'release-3.0' into 'master'

Release 3.0

See merge request !56
parents 2cff8501 b362b363
No related branches found
No related tags found
2 merge requests!56Release 3.0b0,!55Resolve "Adapt for SPA operations"
Pipeline #114209 failed
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",
},
};
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
# 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/
......@@ -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
ARG APPS="AlekSIS-App-Resint"
FROM registry.edugit.org/aleksis/official/aleksis-core:master
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,
},
},
],
};
{
"resint": {
"menu_title": "Dokumente",
"manage_posters": {
"menu_title": "Dokumente verwalten"
},
"poster_groups": {
"menu_title": "Dokumentengruppen"
},
"live_documents": {
"menu_title": "Live-Dokumente"
}
}
}
{
"resint": {
"menu_title": "Documents",
"manage_posters": {
"menu_title": "Manage posters"
},
"poster_groups": {
"menu_title": "Poster groups"
},
"live_documents": {
"menu_title": "Live documents"
}
}
}
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)
......@@ -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."""
......
......@@ -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
......
......@@ -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 ---------------------------------------------------
......
[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 = "*"
......
[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 =
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment