Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AlekSIS/official/AlekSIS-App-Resint
  • sunweaver/AlekSIS-App-Resint
2 results
Show changes
Commits on Source (277)
Showing
with 579 additions and 222 deletions
module.exports = {
root: true,
overrides: [
{
files: ["*.js", "*.vue"],
// parser: "vue-eslint-parser",
//processor: "@graphql-eslint/graphql",
extends: [
"eslint:recommended",
"plugin:vue/strongly-recommended",
"plugin:@intlify/vue-i18n/recommended",
],
rules: {
"no-unused-vars": "warn",
"vue/no-unused-vars": "off",
"vue/multi-word-component-names": "off",
"vue/attribute-hyphenation": "error",
"vue/v-slot-style": "error",
"@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]+$",
},
],
"@intlify/vue-i18n/no-deprecated-tc": "off",
// 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",
},
},
{
files: ["*.graphql"],
parser: "@graphql-eslint/eslint-plugin",
plugins: ["@graphql-eslint"],
extends: "plugin:@graphql-eslint/operations-recommended",
parserOptions: {
graphQLConfig: {
schema: "./schema.json",
documents: "../aleksis/**/*/frontend/**/*.graphql",
},
},
rules: {
"@graphql-eslint/no-anonymous-operations": "error",
"@graphql-eslint/no-duplicate-fields": "error",
"@graphql-eslint/naming-convention": [
"error",
{
OperationDefinition: {
style: "camelCase",
forbiddenPrefixes: ["Query", "Mutation", "Subscription", "Get"],
forbiddenSuffixes: ["Query", "Mutation", "Subscription"],
},
},
],
},
},
],
};
{
"name": "aleksis-builddeps",
"version": "1.0.0",
"dependencies": {
"@graphql-eslint/eslint-plugin": "^4.3.0",
"@intlify/eslint-plugin-vue-i18n": "^3.0.0",
"eslint": "^8.26.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-vue": "^9.7.0",
"graphql": "^16.10.0",
"prettier": "^3.4.0",
"stylelint": "^15.0.0",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^34.0.0"
}
}
......@@ -48,11 +48,51 @@ venv/
DEADJOE
\#*#
# IntelliJ
.idea
.idea/
# VSCode
.vscode/
.history/
*.code-workspace
# Database
db.sqlite3
# Sphinx
docs/_build/
# Poetry
# TeX
*.aux
# Generated files
/cache
/node_modules
.dev-js/node_modules
/static/
/whoosh_index/
.vite
.dev-js/.yarn
.dev-js/.pnp.cjs
.dev-js/.pnp.loader.mjs
.dev-js/.yarnrc.yml
.dev-js/schema.json
# Lock files
poetry.lock
package-lock.json
yarn.lock
.dev-js/yarn.lock
# Tests
.coverage
.mypy_cache/
.tox/
htmlcov/
# Data
maintenance_mode_state.txt
media/
aleksis/core/static/style.css
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
# 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/
.pnp.cjs
.pnp.loader.mjs
.git/
Changelog
=========
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
----------
Added
~~~~~
* Menu icon changes when entry is selected.
`3.1`_ – 2023-07-17
-------------------
Added
~~~~~
* Support public live documents
Fixed
~~~~~
* API urls were in the wrong namespace.
`3.0`_ - 2023-05-12
-------------------
Nothing changed.
`3.0b2`_ - 2023-03-20
---------------------
Fixed
~~~~~
* Menu item was shown for all users independent of permissions.
`3.0b1`_ - 2023-03-09
---------------------
Fixed
~~~~~
* Provide PDF documents outside django/ URL namespace again
`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
-------------------
Added
~~~~~
* Add Ukrainian locale (contributed by Sergiy Gorichenko from Fre(i)e Software GmbH).
`2.1`_ - 2022-01-12
-------------------
Added
~~~~~
* Open poster group menu entries in new tab.
* [Dev] LiveDocument.update() now has a default implementaiton, rendering
``self.template`` using ``self.get_context_data()``
* End-user, admin and dev documentation
Fixed
~~~~~
* Live documents table showed two "Actions" columns.
* Menu was not correctly re-generated after creating or editing poster groups
* Button for creation of live documents was there even if there weren't any live document types registered.
`2.0`_ - 2021-12-27
-------------------
Nothing changed.
`2.0b1`_ - 2021-11-07
---------------------
Added
~~~~~
* Provide API view for accessing the current PDF file of a live document (secured with OAuth2).
Changed
~~~~~~~
* German translations were updated.
`2.0b0`_ - 2021-11-03
--------------------
Added
~~~~~
* Provide ``Poster`` model for time-based documents.
* Organise posters in poster groups.
* Return current poster of a poster group as PDF file under a specific endpoint.
* Provide ``LiveDocument`` for periodically updated documents.
.. _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-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
.. _3.0b1: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/3.0b1
.. _3.0b2: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/3.0b2
.. _3.0: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/3.0
.. _3.1: https://edugit.org/AlekSIS/official/AlekSIS-App-Resint/-/tags/3.1
ARG APPS="AlekSIS-App-Resint"
FROM registry.edugit.org/aleksis/official/aleksis-core:master
AlekSIS (School Information System) — App Mēnsa (cantina menu)
==============================================================
AlekSIS (School Information System) — App Resint (Public poster)
================================================================
AlekSIS
-------
This is an application for use with the `AlekSIS`_ platform.
This is an application for use with the `AlekSIS®`_ platform.
Features
--------
The Mēnsa app provides an interface for uploading PDF menus attached by a calendar week in which this menu is valid.
The app provides a public URL `current.pdf` which always returns the current menu PDF and adds an menu item linked to
The Resint app provides an interface for uploading PDF posters attached by a calendar week in which this poster is valid.
The app provides a public URL `current.pdf` which always returns the current poster PDF and adds a poster item linked to
the same URL.
Additionally, it provides data models and update logic for so-called live documents which are periodically updated PDF files.
Licence
-------
::
Copyright © 2018, 2019, 2020, 2021 Jonathan Weth <dev@jonathanweth.de>
Copyright © 2019 Julian Leucker <leuckeju@katharineum.de>
Copyright © 2018, 2019, 2020 Jonathan Weth <wethjo@katharineum.de>
Copyright © 2020, 2021 Frank Poetzsch-Heffter <p-h@katharineum.de>
Copyright © 2022 Dominik George <dominik.george@teckids.org>
Licenced under the EUPL, version 1.2 or later
......@@ -28,5 +32,13 @@ full licence text or on the `European Union Public Licence`_ website
https://joinup.ec.europa.eu/collection/eupl/guidelines-users-and-developers
(including all other official language versions).
.. _AlekSIS: https://edugit.org/AlekSIS/official/AlekSIS
Trademark
---------
AlekSIS® is a registered trademark of the AlekSIS open source project, represented
by Teckids e.V. Please refer to the `trademark policy`_ for hints on using the trademark
AlekSIS®.
.. _AlekSIS®: https://edugit.org/AlekSIS/official/AlekSIS
.. _European Union Public Licence: https://eupl.eu/
.. _trademark policy: https://aleksis.org/pages/about
from django.contrib import admin
from .models import Menu
admin.site.register(Menu)
from aleksis.core.util.apps import AppConfig
class MensaConfig(AppConfig):
name = "aleksis.apps.mensa"
verbose_name = "AlekSIS – Mēnsa (cantina menu)"
File deleted
File deleted
from django import forms
from django.core.validators import FileExtensionValidator
from django.utils import timezone
from material import Layout, Row
from .models import Menu
current_year = timezone.datetime.now().year
options_for_year = [(current_year, current_year), (current_year + 1, current_year + 1)]
calendar_weeks = [(cw, str(cw)) for cw in range(1, 53)]
class MenuUploadForm(forms.ModelForm):
calendar_week = forms.ChoiceField(choices=calendar_weeks, initial=timezone.datetime.now().isocalendar()[1])
year = forms.ChoiceField(
initial=timezone.datetime.now().year, choices=options_for_year
)
pdf = forms.FileField(
validators=[FileExtensionValidator(allowed_extensions=["pdf"])],
)
layout = Layout(
Row("calendar_week", "year"),
Row("pdf")
)
class Meta:
model = Menu
fields = ("calendar_week", "year", "pdf")
from django.utils.translation import ugettext_lazy as _
MENUS = {
"NAV_MENU_CORE": [
{
"name": _("Menu"),
"url": "#",
"icon": "restaurant_menu",
"root": True,
"validators": [
"menu_generator.validators.is_authenticated",
],
"submenu": [
{
"name": _("Current menu"),
"url": "menu_show_current",
"icon": "picture_as_pdf",
"validators": ["menu_generator.validators.is_authenticated"],
},
{
"name": _("Upload menu"),
"url": "menu_index",
"icon": "file_upload",
"validators": ["menu_generator.validators.is_authenticated"],
},
],
}
]
}
# Generated by Django 3.0.2 on 2020-01-18 13:05
from django.db import migrations, models
import aleksis.apps.mensa.models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Menu',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('calendar_week', models.IntegerField(verbose_name='CW')),
('year', models.IntegerField(verbose_name='Year')),
('pdf', models.FileField(upload_to=aleksis.apps.mensa.models.path_and_rename_menu, verbose_name='PDF')),
],
options={
'verbose_name': 'Menu',
'verbose_name_plural': 'Menus',
'unique_together': {('calendar_week', 'year')},
},
),
]
# Generated by Django 3.0.3 on 2020-02-25 15:40
import django.contrib.postgres.fields.jsonb
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('mensa', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='menu',
name='extended_data',
field=django.contrib.postgres.fields.jsonb.JSONField(default=dict, editable=False),
),
]
from django.db import models
from django.utils.translation import gettext_lazy as _
from aleksis.core.mixins import ExtensibleModel
from aleksis.core.util.core_helpers import path_and_rename
def path_and_rename_menu(instance, filename: str) -> str:
return path_and_rename(instance, filename, upload_to="menu")
class Menu(ExtensibleModel):
calendar_week = models.IntegerField(verbose_name=_("CW"))
year = models.IntegerField(verbose_name=_("Year"))
pdf = models.FileField(upload_to=path_and_rename_menu, verbose_name=_("PDF"))
class Meta:
unique_together = ("calendar_week", "year")
verbose_name = _("Menu")
verbose_name_plural = _("Menus")
def __str__(self):
return "{} {}/{}".format(_("CW"), self.calendar_week, self.year)
import os
from datetime import time
from django.utils.translation import gettext_lazy as _
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CONSTANCE_CONFIG = {
"MENSA_NEW_WEEK_DAY": (4, _("Weekday at which the plan of the next week is to be shown"), "weekday_field"),
"MENSA_NEW_WEEK_TIME": (time(14, 00), _("Time at which the plan of the next week is to be shown"), time)
}
CONSTANCE_CONFIG_FIELDSETS = {
"Mensa settings": ("MENSA_NEW_WEEK_DAY", "MENSA_NEW_WEEK_TIME"),
}
{% extends "core/base.html" %}
{% load msg_box static i18n %}
{% block content %}
<a class="waves-effect waves-light btn green" href="{% url "menu_upload" %}"><i class="material-icons left">add</i>
{% trans "Upload new menu" %}
</a>
<a class="waves-effect waves-light btn orange" href="{% url "menu_show_current" %}"><i class="material-icons left">picture_as_pdf</i>
{% trans "Show current menu" %}
</a>
<h5>{% trans "All uploaded menus" %}</h5>
<ul class="collection">
{% for menu in menus %}
<li class="collection-item ">
<span class="title">{{ menu }}</span>
<p>
<a class="btn-flat waves-effect waves-green" href="{% get_media_prefix %}{{ menu.pdf }}" target="_blank">
<i class="material-icons left">picture_as_pdf</i> {% trans "Show" %}
</a>
<a class="btn-flat delete-menu waves-effect waves-red" href="{% url "menu_delete" menu.id %}">
<i class="material-icons left">delete</i> {% trans "Delete" %}
</a>
</p>
</li>
{% endfor %}
</ul>
<script type="text/javascript">
$(".delete-menu").click(function (e) {
if (!confirm("Wirklich löschen?")) {
e.preventDefault();
}
})
</script>
{% endblock %}
{% extends "core/base.html" %}
{% load msg_box i18n material_form %}
{% block page_title %}{% trans "Upload menu" %}{% endblock %}
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{% form form=form %}{% endform %}
<button class="waves-effect waves-light btn green" type="submit">
<i class="material-icons left">cloud_upload</i>
{% trans "Upload and publish menu" %}
</button>
</form>
<p>
<a href="{% url 'menu_index' %}" class="waves-effect waves-teal btn-flat">{% trans "Back to overview" %}</a>
</p>
{% endblock %}