Skip to content
Commits on Source (22)
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/deploy/trigger_dist.yml"
- project: "AlekSIS/official/AlekSIS"
file: "/ci/docker/image.yml"
- project: "AlekSIS/official/AlekSIS"
file: /ci/publish/pypi.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/deploy/trigger_dist.yml"
- project: "AlekSIS/official/AlekSIS"
file: "/ci/docker/image.yml"
- project: "AlekSIS/official/AlekSIS"
file: /ci/publish/pypi.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,6 +6,32 @@ 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`_.
`2.0`_ - 2023-05-15
-------------------
Nothing changed.
`2.0b0`_ - 2023-03-01
---------------------
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
Fixed
~~~~~
* When no page to redirect to was passed to some of the seating plan views, an error occured.
`1.0.2`_ - 2022-11-04
---------------------
......@@ -37,6 +63,8 @@ Added
.. _Semantic Versioning: https://semver.org/spec/v2.0.0.html
.. _1.0: https://edugit.org/AlekSIS/official//AlekSIS-App-Stoelindeling/-/tags/1.0
.. _1.0.1: https://edugit.org/AlekSIS/official//AlekSIS-App-Stoelindeling/-/tags/1.0.1
.. _1.0.2: https://edugit.org/AlekSIS/official//AlekSIS-App-Stoelindeling/-/tags/1.0.2
.. _1.0: https://edugit.org/AlekSIS/official/AlekSIS-App-Stoelindeling/-/tags/1.0
.. _1.0.1: https://edugit.org/AlekSIS/official/AlekSIS-App-Stoelindeling/-/tags/1.0.1
.. _1.0.2: https://edugit.org/AlekSIS/official/AlekSIS-App-Stoelindeling/-/tags/1.0.2
.. _2.0b0: https://edugit.org/AlekSIS/official/AlekSIS-App-Stoelindeling/-/tags/2.0b0
.. _2.0: https://edugit.org/AlekSIS/official/AlekSIS-App-Stoelindeling/-/tags/2.0
export default {
meta: {
inMenu: true,
titleKey: "stoelindeling.menu_title",
icon: "mdi-view-list-outline",
permission: "stoelindeling.view_seatingplans_rule",
},
props: {
byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
},
children: [
{
path: "seating_plans/",
component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
name: "stoelindeling.seatingPlans",
meta: {
inMenu: true,
titleKey: "stoelindeling.menu_title",
icon: "mdi-view-list-outline",
permission: "stoelindeling.view_seatingplans_rule",
},
props: {
byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
},
},
{
path: "seating_plans/create/",
component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
name: "stoelindeling.createSeatingPlan",
props: {
byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
},
},
{
path: "seating_plans/:pk/",
component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
name: "stoelindeling.seatingPlan",
props: {
byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
},
},
{
path: "seating_plans/:pk/edit/",
component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
name: "stoelindeling.editSeatingPlan",
props: {
byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
},
},
{
path: "seating_plans/:pk/copy/",
component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
name: "stoelindeling.copySeatingPlan",
props: {
byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
},
},
{
path: "seating_plans/:pk/delete/",
component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
name: "stoelindeling.deleteSeatingPlan",
props: {
byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
},
},
],
};
{
"stoelindeling": {
"menu_title": "Sitzpläne"
}
}
{
"stoelindeling": {
"menu_title": "Seating plans"
}
}
{
"stoelindeling": {
"menu_title": "Планы рассадки"
}
}
{
"stoelindeling": {
"menu_title": "Плани розсаджень"
}
}
from django.utils.translation import gettext_lazy as _
MENUS = {
"NAV_MENU_CORE": [
{
"name": _("Seating plans"),
"url": "seating_plans",
"svg_icon": "mdi:view-list-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"stoelindeling.view_seatingplans_rule",
),
],
},
]
}
......@@ -15,6 +15,10 @@ class Migration(migrations.Migration):
('chronos', '0010_remove_subject_unique_name_per_site'),
]
run_before = [
('core', '0047_add_room_model'),
]
operations = [
migrations.CreateModel(
name='SeatingPlan',
......
# Generated by Django 4.1.5 on 2023-02-26 15:44
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("core", "0047_add_room_model"),
("stoelindeling", "0004_alter_seatingplan_subject"),
]
run_before = [
("chronos", "0013_move_room_to_core"),
]
operations = [
migrations.AlterField(
model_name="seatingplan",
name="room",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="core.room",
verbose_name="Room",
),
),
]
......@@ -2,9 +2,9 @@ from typing import Union
from django.apps import apps
from aleksis.apps.chronos.models import Room, Subject
from aleksis.apps.chronos.models import Subject
from aleksis.apps.stoelindeling.models import SeatingPlan
from aleksis.core.models import Group
from aleksis.core.models import Group, Room
@Group.method
......
from django.db import models
from django.utils.translation import gettext_lazy as _
from aleksis.apps.chronos.models import Room, Subject
from aleksis.apps.chronos.models import Subject
from aleksis.apps.stoelindeling.managers import SeatManager, SeatQuerySet
from aleksis.core.mixins import ExtensibleModel
from aleksis.core.models import Group, Person
from aleksis.core.models import Group, Person, Room
class SeatingPlan(ExtensibleModel):
......
.seat {
width: 80px;
height: 80px;
margin: 2px;
padding: 2px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
align-items: center;
font-size: 0.8em;
word-break: break-word;
position: relative;
width: 80px;
height: 80px;
margin: 2px;
padding: 2px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
align-items: center;
font-size: 0.8em;
word-break: break-word;
position: relative;
}
.drag-area .seat {
cursor: grab;
cursor: grab;
}
#seats {
overflow: auto;
width: auto;
overflow: auto;
width: auto;
}
.seat-grid {
display: flex;
overflow-x: scroll;
display: flex;
overflow-x: scroll;
}
.seat-grid-col {
margin: 0;
margin: 0;
}
.seat-grid-cell {
width: 86px;
height: 86px;
border: 1px dashed darkgrey;
width: 86px;
height: 86px;
border: 1px dashed darkgrey;
}
#not-used-seats {
display: flex;
flex-direction: row;
flex-wrap: wrap;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.seat-grid-add-col {
padding: 0 5px;
padding: 0 5px;
}
.seat-grid-add-col button {
height: 100%;
padding: 0 5px;
height: 100%;
padding: 0 5px;
}
.seat-grid-add-row {
padding: 5px 5px;
width: 100%;
padding: 5px 5px;
width: 100%;
}
.seat-grid-add-row button {
width: 100%;
width: 100%;
}
.seat .clip-circle {
width: auto;
height: 60%;
position: absolute;
left: 16px;
right: 16px;
top: 5px;
width: auto;
height: 60%;
position: absolute;
left: 16px;
right: 16px;
top: 5px;
}
.seat-name {
position: absolute;
bottom: 2px;
left: 2px;
right: 2px;
position: absolute;
bottom: 2px;
left: 2px;
right: 2px;
}
function setPosition(event) {
const parent = $(event.to);
const xPos = parent.data("x");
const yPos = parent.data("y");
const parent = $(event.to);
const xPos = parent.data("x");
const yPos = parent.data("y");
let pk = $(event.item).attr("data-pk");
let sel = $("#seating-plan-form input[value=" + pk + "].pk-input");
let x = sel.nextAll("input.x-input").first();
let y = sel.nextAll("input.y-input").first();
let seated = sel.nextAll("input.seated-input").first();
let pk = $(event.item).attr("data-pk");
let sel = $("#seating-plan-form input[value=" + pk + "].pk-input");
let x = sel.nextAll("input.x-input").first();
let y = sel.nextAll("input.y-input").first();
let seated = sel.nextAll("input.seated-input").first();
if (parent.hasClass("seat-grid-cell")) {
x.val(xPos);
y.val(yPos);
seated.val("True");
} else {
x.val("0");
y.val("0");
seated.val("False");
}
if (parent.hasClass("seat-grid-cell")) {
x.val(xPos);
y.val(yPos);
seated.val("True");
} else {
x.val("0");
y.val("0");
seated.val("False");
}
}
function enableSeatGridCells() {
$('.seat-grid-cell').sortable({
group: 'seats',
animation: 150,
onEnd: setPosition
});
$(".seat-grid-cell").sortable({
group: "seats",
animation: 150,
onEnd: setPosition,
});
}
function getStartY() {
return Number.parseInt($(".seat-grid .seat-grid-col .seat-grid-cell").first().data("y"))
return Number.parseInt(
$(".seat-grid .seat-grid-col .seat-grid-cell").first().data("y")
);
}
function getEndY() {
return Number.parseInt($(".seat-grid .seat-grid-col .seat-grid-cell").last().data("y"))
return Number.parseInt(
$(".seat-grid .seat-grid-col .seat-grid-cell").last().data("y")
);
}
function getStartX() {
return Number.parseInt($(".seat-grid .seat-grid-col .seat-grid-cell").first().data("x"))
return Number.parseInt(
$(".seat-grid .seat-grid-col .seat-grid-cell").first().data("x")
);
}
function getEndX() {
return Number.parseInt($(".seat-grid .seat-grid-col .seat-grid-cell").last().data("x"))
return Number.parseInt(
$(".seat-grid .seat-grid-col .seat-grid-cell").last().data("x")
);
}
function buildRow(x) {
const el = $("<div class='seat-grid-col'></div>");
for (let y = getStartY(); y <= getEndY(); y++) {
el.append("<div class='seat-grid-cell' data-x='" + x + "' data-y='" + y + "'></div>");
}
return el;
const el = $("<div class='seat-grid-col'></div>");
for (let y = getStartY(); y <= getEndY(); y++) {
el.append(
"<div class='seat-grid-cell' data-x='" + x + "' data-y='" + y + "'></div>"
);
}
return el;
}
$(document).ready(function () {
$('#not-used-seats').sortable({
group: 'seats',
animation: 150,
onEnd: setPosition
});
enableSeatGridCells();
$("#not-used-seats").sortable({
group: "seats",
animation: 150,
onEnd: setPosition,
});
enableSeatGridCells();
$("#seat-row-add-top").click(function () {
const y = getStartY() - 1;
$(".seat-grid .seat-grid-col").each(function (idx, el) {
const x = Number.parseInt($(el).children(".seat-grid-cell").first().data("x"));
$(el).prepend("<div class='seat-grid-cell' data-x='" + x + "' data-y='" + y + "'></div>");
});
enableSeatGridCells();
});
$("#seat-row-add-bottom").click(function () {
const y = getEndY() + 1;
$(".seat-grid .seat-grid-col").each(function (idx, el) {
const x = Number.parseInt($(el).children(".seat-grid-cell").first().data("x"));
$(el).prepend("<div class='seat-grid-cell' data-x='" + x + "' data-y='" + y + "'></div>");
});
enableSeatGridCells();
$("#seat-row-add-top").click(function () {
const y = getStartY() - 1;
$(".seat-grid .seat-grid-col").each(function (idx, el) {
const x = Number.parseInt(
$(el).children(".seat-grid-cell").first().data("x")
);
$(el).prepend(
"<div class='seat-grid-cell' data-x='" +
x +
"' data-y='" +
y +
"'></div>"
);
});
$("#seat-col-add-left").click(function () {
const el = buildRow(getStartX() - 1);
el.insertBefore(".seat-grid-col:first");
enableSeatGridCells();
});
$("#seat-col-add-right").click(function () {
const el = buildRow(getEndX() + 1);
el.insertAfter(".seat-grid-col:last");
enableSeatGridCells();
enableSeatGridCells();
});
$("#seat-row-add-bottom").click(function () {
const y = getEndY() + 1;
$(".seat-grid .seat-grid-col").each(function (idx, el) {
const x = Number.parseInt(
$(el).children(".seat-grid-cell").first().data("x")
);
$(el).prepend(
"<div class='seat-grid-cell' data-x='" +
x +
"' data-y='" +
y +
"'></div>"
);
});
enableSeatGridCells();
});
$("#seat-col-add-left").click(function () {
const el = buildRow(getStartX() - 1);
el.insertBefore(".seat-grid-col:first");
enableSeatGridCells();
});
$("#seat-col-add-right").click(function () {
const el = buildRow(getEndX() + 1);
el.insertAfter(".seat-grid-col:last");
enableSeatGridCells();
});
});
from django.contrib import messages
from django.shortcuts import redirect
from django.urls import reverse, reverse_lazy
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.translation import gettext as _
from django.views.decorators.cache import never_cache
......@@ -10,6 +10,7 @@ from django_tables2 import SingleTableView
from reversion.views import RevisionMixin
from rules.contrib.views import PermissionRequiredMixin
from aleksis.core.decorators import pwa_cache
from aleksis.core.mixins import (
AdvancedCreateView,
AdvancedDeleteView,
......@@ -24,6 +25,7 @@ from .tables import SeatingPlanTable
from .util.perms import get_allowed_seating_plans
@method_decorator(pwa_cache, name="dispatch")
class SeatingPlanListView(PermissionRequiredMixin, SingleTableView):
"""Table of all seating plans."""
......@@ -36,6 +38,7 @@ class SeatingPlanListView(PermissionRequiredMixin, SingleTableView):
return get_allowed_seating_plans(self.request.user)
@method_decorator(pwa_cache, name="dispatch")
class SeatingPlanDetailView(PermissionRequiredMixin, DetailView):
"""Detail view for seating plans."""
......@@ -52,7 +55,7 @@ class SeatingPlanCreateView(PermissionRequiredMixin, SuccessNextMixin, AdvancedC
form_class = SeatingPlanCreateForm
permission_required = "stoelindeling.create_seatingplan_rule"
template_name = "stoelindeling/seating_plan/create.html"
success_url = reverse_lazy("seating_plans")
next_page = "seating_plans"
success_message = _("The seating plan has been created.")
def get_form_kwargs(self):
......@@ -180,5 +183,5 @@ class SeatingPlanDeleteView(
model = SeatingPlan
permission_required = "stoelindeling.delete_seatingplan_rule"
template_name = "core/pages/delete.html"
success_url = reverse_lazy("seating_plans")
next_page = "seating_plans"
success_message = _("The seating plan has been deleted.")
......@@ -29,9 +29,9 @@ copyright = "2018-2022 The AlekSIS team"
author = "The AlekSIS Team"
# The short X.Y version
version = "1.0"
version = "2.0"
# The full version, including alpha/beta/rc tags
release = "1.0.2"
release = "2.0"
# -- General configuration ---------------------------------------------------
......
[tool.poetry]
name = "AlekSIS-App-Stoelindeling"
version = "1.0.2"
version = "2.0"
packages = [
{ include = "aleksis" }
]
......@@ -15,7 +15,7 @@ description = "AlekSIS (School Information System) — App Stoelindeling (Cr
authors = ["Jonathan Weth <dev@jonathanweth.de>"]
license = "EUPL-1.2-or-later"
homepage = "https://aleksis.org"
repository = "https://edugit.org/AlekSIS/official//AlekSIS-App-Stoelindeling"
repository = "https://edugit.org/AlekSIS/official/AlekSIS-App-Stoelindeling"
documentation = "https://aleksis.org/official/AlekSIS/docs/html/"
classifiers = [
"Environment :: Web Environment",
......@@ -30,8 +30,8 @@ secondary = true
[tool.poetry.dependencies]
python = "^3.9"
aleksis-core = "^2.8"
aleksis-app-chronos = "^2.0"
aleksis-core = "^3.0"
aleksis-app-chronos = "^3.0"
[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 =
......