diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d58e466b99296765d1b74fb19eb350e5e67b15ea..6e535409dd609de46245d7f9210ec440be8bc59c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,28 @@ 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`_. +`4.0.0.dev3`_ - 2024-07-10 +-------------------------- + +Added +~~~~~ + +* Support for entering personal notes for students in the new coursebook interface. +* Support for entering tardiness for students in the new coursebook interface. + +`4.0.0.dev2`_ - 2024-07-13 +-------------------------- + +Fixed version of 4.0.0.dev1 + +`4.0.0.dev1`_ - 2024-06-13 +-------------------------- + +Added +~~~~~ + +* Support for entering absences for students in the new coursebook interface. + `4.0.0.dev0`_ - 2024-04-23 -------------------------- @@ -33,6 +55,14 @@ Fixed * Migrating failed due to an incorrect field reference. +`3.0.1`_ - 2023-09-02 +------------------- + +Fixed +~~~~~ + +* Migrations failed on empty database + `3.0`_ - 2023-05-15 ------------------- @@ -343,4 +373,8 @@ Fixed .. _2.1.1: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/2.1.1 .. _3.0b0: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/3.0b0 .. _3.0: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/3.0 +.. _3.0.1: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/3.0.1 .. _4.0.0.dev0: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/4.0.0.dev0 +.. _4.0.0.dev1: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/4.0.0.dev1 +.. _4.0.0.dev2: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/4.0.0.dev2 +.. _4.0.0.dev3: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/4.0.0.dev3 diff --git a/README.rst b/README.rst index 61e80f73c24aa9077218aa86a2427463f75f1f0f..53fbc493f0f1acfd35a0f893c816cfb117a27572 100644 --- a/README.rst +++ b/README.rst @@ -34,10 +34,11 @@ Licence Copyright © 2019, 2021 Dominik George <dominik.george@teckids.org> Copyright © 2019, 2020 Tom Teichler <tom.teichler@teckids.org> Copyright © 2019 mirabilos <thorsten.glaser@teckids.org> - Copyright © 2020, 2021, 2022 Jonathan Weth <dev@jonathanweth.de> - Copyright © 2020, 2021 Julian Leucker <leuckeju@katharineum.de> - Copyright © 2020, 2022 Hangzhi Yu <yuha@katharineum.de> + Copyright © 2020, 2021, 2022, 2024 Jonathan Weth <dev@jonathanweth.de> + Copyright © 2020, 2021, 2024 Julian Leucker <leuckeju@katharineum.de> + Copyright © 2020, 2022, 2023, 2024 Hangzhi Yu <yuha@katharineum.de> Copyright © 2021 Lloyd Meins <meinsll@katharineum.de> + Copyright © 2024 Michael Bauer <michael-bauer@posteo.de> Licenced under the EUPL, version 1.2 or later, by Teckids e.V. (Bonn, Germany). diff --git a/aleksis/apps/alsijil/apps.py b/aleksis/apps/alsijil/apps.py index b523b38afa08c965628afbfbe61327e8b03f7067..c52e13fde3532817e6b427355978080e3b856ea1 100644 --- a/aleksis/apps/alsijil/apps.py +++ b/aleksis/apps/alsijil/apps.py @@ -13,8 +13,22 @@ class AlsijilConfig(AppConfig): ([2019, 2021], "Dominik George", "dominik.george@teckids.org"), ([2019, 2020], "Tom Teichler", "tom.teichler@teckids.org"), ([2019], "mirabilos", "thorsten.glaser@teckids.org"), - ([2020, 2021, 2022], "Jonathan Weth", "dev@jonathanweth.de"), - ([2020, 2021], "Julian Leucker", "leuckeju@katharineum.de"), - ([2020, 2022], "Hangzhi Yu", "yuha@katharineum.de"), + ([2020, 2021, 2022, 2024], "Jonathan Weth", "dev@jonathanweth.de"), + ([2020, 2021, 2024], "Julian Leucker", "leuckeju@katharineum.de"), + ([2020, 2022, 2023, 2024], "Hangzhi Yu", "yuha@katharineum.de"), ([2021], "Lloyd Meins", "meinsll@katharineum.de"), + ([2024], "Michael Bauer", "michael-bauer@posteo.de"), ) + + def post_migrate( + self, + app_config: AppConfig, + verbosity: int, + interactive: bool, + using: str, + **kwargs, + ) -> None: + super().post_migrate(app_config, verbosity, interactive, using, **kwargs) + from .util.alsijil_helpers import get_absence_reason_tag + + get_absence_reason_tag() diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/Coursebook.vue b/aleksis/apps/alsijil/frontend/components/coursebook/Coursebook.vue index 4e673db88090f473f2bc036bd128881327d21fc3..21b903a2fd2894249dcd2398518c4e6f9bab96e8 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/Coursebook.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/Coursebook.vue @@ -1,89 +1,108 @@ <template> - <c-r-u-d-iterator - i18n-key="alsijil.coursebook" - :gql-query="gqlQuery" - :gql-additional-query-args="gqlQueryArgs" - :enable-create="false" - :enable-edit="false" - :elevated="false" - @lastQuery="lastQuery = $event" - ref="iterator" - fixed-header - disable-pagination - hide-default-footer - use-deep-search - > - <template #additionalActions="{ attrs, on }"> - <coursebook-filters v-model="filters" /> - </template> - <template #default="{ items }"> - <coursebook-loader /> - <coursebook-day - v-for="{ date, docs, first, last } in groupDocsByDay(items)" - v-intersect="{ - handler: intersectHandler(date, first, last), - options: { - rootMargin: '-' + topMargin + 'px 0px 0px 0px', - threshold: [0, 1], - }, - }" - :date="date" - :docs="docs" - :lastQuery="lastQuery" - :focus-on-mount="initDate && initDate.toMillis() === date.toMillis()" - @init="transition" - :key="'day-' + date" - ref="days" - /> - <coursebook-loader /> + <div> + <infinite-scrolling-date-sorted-c-r-u-d-iterator + i18n-key="alsijil.coursebook" + :gql-query="gqlQuery" + :gql-additional-query-args="gqlQueryArgs" + :enable-create="false" + :enable-edit="false" + :elevated="false" + @lastQuery="lastQuery = $event" + ref="iterator" + fixed-header + disable-pagination + hide-default-footer + use-deep-search + > + <template #additionalActions="{ attrs, on }"> + <coursebook-filters :page-type="pageType" v-model="filters" /> + <v-expand-transition> + <v-card + outlined + class="full-width" + v-show=" + pageType === 'absences' && combinedSelectedParticipations.length + " + > + <v-card-text> + <v-row align="center"> + <v-col cols="6"> + {{ + $tc( + "alsijil.coursebook.absences.action_for_selected", + combinedSelectedParticipations.length, + ) + }} + </v-col> + <v-col cols="6"> + <absence-reason-buttons + allow-empty + empty-value="present" + :custom-absence-reasons="absenceReasons" + @input="handleMultipleAction" + /> + </v-col> + </v-row> + </v-card-text> + </v-card> + </v-expand-transition> + </template> - <date-select-footer - :value="currentDate" - @input="gotoDate" - @prev="gotoPrev" - @next="gotoNext" - /> - </template> - <template #loading> - <coursebook-loader :number-of-days="10" :number-of-docs="5" /> - </template> + <template #item="{ item, lastQuery }"> + <component + :is="itemComponent" + :extra-marks="extraMarks" + :absence-reasons="absenceReasons" + :subjects="subjects" + :documentation="item" + :affected-query="lastQuery" + :value="(selectedParticipations[item.id] ??= [])" + @input="selectParticipation(item.id, $event)" + /> + </template> - <template #no-data> - <CoursebookEmptyMessage icon="mdi-book-off-outline"> - {{ $t("alsijil.coursebook.no_data") }} - </CoursebookEmptyMessage> - </template> + <template #loading> + <coursebook-loader :number-of-days="10" :number-of-docs="5" /> + </template> - <template #no-results> - <CoursebookEmptyMessage icon="mdi-book-alert-outline"> - {{ - $t("alsijil.coursebook.no_results", { search: $refs.iterator.search }) - }} - </CoursebookEmptyMessage> - </template> - </c-r-u-d-iterator> + <template #itemLoader> + <DocumentationLoader /> + </template> + </infinite-scrolling-date-sorted-c-r-u-d-iterator> + <v-scale-transition> + <absence-creation-dialog v-if="pageType === 'absences'" /> + </v-scale-transition> + </div> </template> <script> -import CRUDIterator from "aleksis.core/components/generic/CRUDIterator.vue"; -import DateSelectFooter from "aleksis.core/components/generic/DateSelectFooter.vue"; -import CoursebookDay from "./CoursebookDay.vue"; -import { DateTime, Interval } from "luxon"; +import InfiniteScrollingDateSortedCRUDIterator from "aleksis.core/components/generic/InfiniteScrollingDateSortedCRUDIterator.vue"; import { documentationsForCoursebook } from "./coursebook.graphql"; +import AbsenceReasonButtons from "aleksis.apps.kolego/components/AbsenceReasonButtons.vue"; import CoursebookFilters from "./CoursebookFilters.vue"; import CoursebookLoader from "./CoursebookLoader.vue"; -import CoursebookEmptyMessage from "./CoursebookEmptyMessage.vue"; +import DocumentationModal from "./documentation/DocumentationModal.vue"; +import DocumentationAbsencesModal from "./absences/DocumentationAbsencesModal.vue"; +import AbsenceCreationDialog from "./absences/AbsenceCreationDialog.vue"; +import { extraMarks } from "../extra_marks/extra_marks.graphql"; +import DocumentationLoader from "./documentation/DocumentationLoader.vue"; +import sendToServerMixin from "./absences/sendToServerMixin"; +import { absenceReasons } from "./absences/absenceReasons.graphql"; +import { subjects } from "aleksis.apps.cursus/components/subject.graphql"; export default { name: "Coursebook", components: { - CoursebookEmptyMessage, + DocumentationLoader, + AbsenceReasonButtons, CoursebookFilters, CoursebookLoader, - CRUDIterator, - DateSelectFooter, - CoursebookDay, + DocumentationModal, + DocumentationAbsencesModal, + InfiniteScrollingDateSortedCRUDIterator, + AbsenceCreationDialog, }, + mixins: [sendToServerMixin], props: { filterType: { type: String, @@ -99,6 +118,11 @@ export default { required: false, default: null, }, + pageType: { + type: String, + required: false, + default: "documentations", + }, /** * Number of consecutive to load at once * This number of days is initially loaded and loaded @@ -128,12 +152,31 @@ export default { groups: [], courses: [], incomplete: false, + absencesExist: true, ready: false, initDate: false, currentDate: "", hashUpdater: false, + extraMarks: [], + absenceReasons: [], + subjects: [], + selectedParticipations: {}, }; }, + apollo: { + extraMarks: { + query: extraMarks, + update: (data) => data.items, + }, + absenceReasons: { + query: absenceReasons, + update: (data) => data.items, + }, + subjects: { + query: subjects, + update: (data) => data.items, + }, + }, computed: { // Assertion: Should only fire on page load or selection change. // Resets date range. @@ -145,6 +188,7 @@ export default { dateStart: this.dateStart, dateEnd: this.dateEnd, incomplete: !!this.incomplete, + absencesExist: !!this.absencesExist && this.pageType === "absences", }; }, filters: { @@ -154,15 +198,20 @@ export default { objId: this.objId, filterType: this.filterType, incomplete: this.incomplete, + pageType: this.pageType, + absencesExist: this.absencesExist, }; }, set(selectedFilters) { if (Object.hasOwn(selectedFilters, "incomplete")) { this.incomplete = selectedFilters.incomplete; + } else if (Object.hasOwn(selectedFilters, "absencesExist")) { + this.absencesExist = selectedFilters.absencesExist; } else if ( Object.hasOwn(selectedFilters, "filterType") || Object.hasOwn(selectedFilters, "objId") || - Object.hasOwn(selectedFilters, "objType") + Object.hasOwn(selectedFilters, "objType") || + Object.hasOwn(selectedFilters, "pageType") ) { this.$router.push({ name: "alsijil.coursebook", @@ -172,194 +221,65 @@ export default { : this.filterType, objType: selectedFilters.objType, objId: selectedFilters.objId, + pageType: selectedFilters.pageType + ? selectedFilters.pageType + : this.pageType, }, hash: this.$route.hash, }); // computed should not have side effects // but this was actually done before filters was refactored into // its own component - this.resetDate(); + this.$refs.iterator.resetDate(); // might skip query until both set = atomic - } - }, - }, - }, - methods: { - resetDate(toDate) { - // Assure current date - console.log("Resetting date range", this.$route.hash); - this.currentDate = toDate || this.$route.hash?.substring(1); - if (!this.currentDate) { - console.log("Set default date"); - this.setDate(DateTime.now().toISODate()); - } - - const date = DateTime.fromISO(this.currentDate); - this.initDate = date; - this.dateStart = date.minus({ days: this.dayIncrement }).toISODate(); - this.dateEnd = date.plus({ days: this.dayIncrement }).toISODate(); - }, - transition() { - this.initDate = false; - this.ready = true; - }, - groupDocsByDay(docs) { - // => {dt: {date: dt, docs: doc ...} ...} - const docsByDay = docs.reduce((byDay, doc) => { - // This works with dummy. Does actual doc have dateStart instead? - const day = DateTime.fromISO(doc.datetimeStart).startOf("day"); - byDay[day] ??= { date: day, docs: [] }; - byDay[day].docs.push(doc); - return byDay; - }, {}); - // => [{date: dt, docs: doc ..., idx: idx, lastIdx: last-idx} ...] - // sorting is necessary since backend can send docs unordered - return Object.keys(docsByDay) - .sort() - .map((key, idx, { length }) => { - const day = docsByDay[key]; - day.first = idx === 0; - const lastIdx = length - 1; - day.last = idx === lastIdx; - return day; - }); - }, - // docsByDay: {dt: [dt doc ...] ...} - fetchMore(from, to, then) { - console.log("fetching", from, to); - this.lastQuery.fetchMore({ - variables: { - dateStart: from, - dateEnd: to, - }, - // Transform the previous result with new data - updateQuery: (previousResult, { fetchMoreResult }) => { - console.log("Received more"); - then(); - return { items: previousResult.items.concat(fetchMoreResult.items) }; - }, - }); - }, - setDate(date) { - this.currentDate = date; - if (!this.hashUpdater) { - this.hashUpdater = window.requestIdleCallback(() => { - if (!(this.$route.hash.substring(1) === this.currentDate)) { - this.$router.replace({ hash: this.currentDate }); - } - this.hashUpdater = false; - }); - } - }, - fixScrollPos(height, top) { - this.$nextTick(() => { - if (height < document.documentElement.scrollHeight) { - document.documentElement.scrollTop = - document.documentElement.scrollHeight - height + top; - this.ready = true; - } else { - // Update top, could have changed in the meantime. - this.fixScrollPos(height, document.documentElement.scrollTop); - } - }); - }, - intersectHandler(date, first, last) { - let once = true; - return (entries) => { - const entry = entries[0]; - if (entry.isIntersecting) { - if (entry.boundingClientRect.top <= this.topMargin || first) { - console.log("@ ", date.toISODate()); - this.setDate(date.toISODate()); - } - - if (once && this.ready && first) { - console.log("load up", date.toISODate()); - this.ready = false; - this.fetchMore( - date.minus({ days: this.dayIncrement }).toISODate(), - date.minus({ days: 1 }).toISODate(), - () => { - this.fixScrollPos( - document.documentElement.scrollHeight, - document.documentElement.scrollTop, - ); - }, + if (Object.hasOwn(selectedFilters, "pageType")) { + this.absencesExist = true; + this.$setToolBarTitle( + this.$t(`alsijil.coursebook.title_${selectedFilters.pageType}`), + null, ); - once = false; - } else if (once && this.ready && last) { - console.log("load down", date.toISODate()); - this.ready = false; - this.fetchMore( - date.plus({ days: 1 }).toISODate(), - date.plus({ days: this.dayIncrement }).toISODate(), - () => { - this.ready = true; - }, - ); - once = false; } } - }; + }, }, - // Improve me? - // The navigation logic could be a bit simpler if the current days - // where known as a sorted array (= result of groupDocsByDay) But - // then the list would need its own component and this gets rather - // complicated. Then the calendar could also show the present days - // / gray out the missing. - // - // Next two: arg date is ts object - findPrev(date) { - return this.$refs.days - .map((day) => day.date) - .sort() - .reverse() - .find((date2) => date2 < date); + itemComponent() { + if (this.pageType === "documentations") { + return "DocumentationModal"; + } else { + return "DocumentationAbsencesModal"; + } }, - findNext(date) { - return this.$refs.days - .map((day) => day.date) - .sort() - .find((date2) => date2 > date); + combinedSelectedParticipations() { + return Object.values(this.selectedParticipations).flat(); }, - gotoDate(date) { - const present = this.$refs.days.find( - (day) => day.date.toISODate() === date, + }, + methods: { + selectParticipation(id, value) { + this.selectedParticipations = Object.assign( + {}, + this.selectedParticipations, + { [id]: value }, ); - - if (present) { - // React immediatly -> smoother navigation - // Also intersect handler does not always react to scrollIntoView - this.setDate(date); - present.focus("smooth"); - } else { - const prev = this.findPrev(DateTime.fromISO(date)); - const next = this.findNext(DateTime.fromISO(date)); - if (prev && next) { - // In between two present days -> goto prev - this.gotoDate(prev.toISODate()); - } else { - // Outsite present day range - this.resetDate(date); - } - } }, - gotoPrev() { - const prev = this.findPrev(DateTime.fromISO(this.currentDate)); - if (prev) { - this.gotoDate(prev.toISODate()); - } + handleMultipleAction(absenceReasonId) { + this.loadSelectedParticiptions = true; + this.sendToServer( + this.combinedSelectedParticipations, + "absenceReason", + absenceReasonId, + ); + this.$once("save", this.resetMultipleAction); }, - gotoNext() { - const next = this.findNext(DateTime.fromISO(this.currentDate)); - if (next) { - this.gotoDate(next.toISODate()); - } + resetMultipleAction() { + this.loadSelectedParticiptions = false; + this.selectedParticipations = {}; }, }, - created() { - this.resetDate(); + mounted() { + this.$setToolBarTitle( + this.$t(`alsijil.coursebook.title_${this.pageType}`), + null, + ); }, }; </script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookDay.vue b/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookDay.vue deleted file mode 100644 index 2f15c3fd031c62ff9fc96cf5c35042f2274d3321..0000000000000000000000000000000000000000 --- a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookDay.vue +++ /dev/null @@ -1,67 +0,0 @@ -<template> - <v-list-item :style="{ scrollMarginTop: '145px' }" two-line class="px-0"> - <v-list-item-content> - <v-subheader class="text-h6 px-1">{{ - $d(date, "dateWithWeekday") - }}</v-subheader> - <v-list max-width="100%" class="pt-0 mt-n1"> - <v-list-item - v-for="doc in docs" - :key="'documentation-' + (doc.oldId || doc.id)" - class="px-1" - > - <documentation-modal - :documentation="doc" - :affected-query="lastQuery" - /> - </v-list-item> - </v-list> - </v-list-item-content> - </v-list-item> -</template> - -<script> -import DocumentationModal from "./documentation/DocumentationModal.vue"; -export default { - name: "CoursebookDay", - components: { - DocumentationModal, - }, - props: { - date: { - type: Object, - required: true, - }, - docs: { - type: Array, - required: true, - }, - lastQuery: { - type: Object, - required: true, - }, - focusOnMount: { - type: Boolean, - required: false, - default: false, - }, - }, - emits: ["init"], - methods: { - focus(how) { - this.$el.scrollIntoView({ - behavior: how, - block: "start", - inline: "nearest", - }); - console.log("focused @", this.date.toISODate()); - }, - }, - mounted() { - if (this.focusOnMount) { - this.$nextTick(this.focus("instant")); - this.$emit("init"); - } - }, -}; -</script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookEmptyMessage.vue b/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookEmptyMessage.vue deleted file mode 100644 index 346ecc63c272ab5c57a1da9f5e5f78b825739a79..0000000000000000000000000000000000000000 --- a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookEmptyMessage.vue +++ /dev/null @@ -1,25 +0,0 @@ -<template> - <v-list-item> - <v-list-item-content - class="d-flex justify-center align-center flex-column full-width" - > - <div class="mb-4"> - <v-icon large color="primary">{{ icon }}</v-icon> - </div> - <v-list-item-title> - <slot></slot> - </v-list-item-title> - </v-list-item-content> - </v-list-item> -</template> -<script> -export default { - name: "CoursebookEmptyMessage", - props: { - icon: { - type: String, - default: "mdi-book-alert-outline", - }, - }, -}; -</script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookFilters.vue b/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookFilters.vue index b47ebbfbb1d1cd8219686f05085eb0eeb8f453d3..6b9dcc92fb433ff320f0c76790656c7b76c0472f 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookFilters.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookFilters.vue @@ -1,8 +1,11 @@ <template> - <div class="d-flex flex-grow-1 justify-end"> + <div + class="d-flex flex-column flex-sm-row flex-nowrap flex-grow-1 justify-end gap align-stretch" + > <v-autocomplete :items="selectable" item-text="name" + :item-value="(item) => `${item.__typename}-${item.id}`" clearable return-object filled @@ -15,7 +18,7 @@ @click:clear="selectObject" class="max-width" /> - <div class="ml-6"> + <div class="mx-6"> <v-switch :loading="selectLoading" :label="$t('alsijil.coursebook.filter.own')" @@ -38,7 +41,29 @@ inset hide-details /> + <v-switch + v-if="pageType === 'absences'" + :loading="selectLoading" + :label="$t('alsijil.coursebook.filter.absences_exist')" + :input-value="value.absencesExist" + @change=" + $emit('input', { + absencesExist: $event, + }) + " + dense + inset + hide-details + /> </div> + <v-btn + outlined + color="primary" + :loading="selectLoading" + @click="togglePageType()" + > + {{ pageTypeButtonText }} + </v-btn> </div> </template> @@ -63,6 +88,11 @@ export default { type: Object, required: true, }, + pageType: { + type: String, + required: false, + default: "documentations", + }, }, emits: ["input"], apollo: { @@ -95,6 +125,13 @@ export default { o.id === this.value.objId, ); }, + pageTypeButtonText() { + if (this.value.pageType === "documentations") { + return this.$t("alsijil.coursebook.filter.page_type.absences"); + } else { + return this.$t("alsijil.coursebook.filter.page_type.documentations"); + } + }, }, methods: { selectObject(selection) { @@ -110,6 +147,16 @@ export default { objId: this.value.objId, }); }, + togglePageType() { + this.$emit("input", { + pageType: + this.value.pageType === "documentations" + ? "absences" + : "documentations", + objType: this.value.objType, + objId: this.value.objId, + }); + }, }, }; </script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationDialog.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationDialog.vue index 51ac72d2873661f5247dfbb197f547dc5f73f5ff..3263225dc890242ed038f8b5f58153278e5aea64 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationDialog.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationDialog.vue @@ -1,30 +1,79 @@ <template> - <mobile-fullscreen-dialog v-model="popup"> + <mobile-fullscreen-dialog v-model="popup" persistent :close-button="false"> <template #activator="activator"> - <!-- button +? --> - <!-- -> popup = true --> + <fab-button + color="secondary" + @click="popup = true" + :disabled="popup" + :class="{ + 'd-none': !checkPermission('alsijil.view_register_absence_rule'), + }" + icon-text="$plus" + i18n-key="alsijil.coursebook.absences.button" + > + <v-icon>$plus</v-icon> + </fab-button> </template> <template #title> - <!-- Abwesenheit/Entschuldigung erfassen --> - <!-- Abwesenheit/Entschuldigung Zusammenfassung --> + <div> + {{ $t("alsijil.coursebook.absences.title") }} + </div> + <span v-if="!form" class="px-2">·</span> + <div v-if="!form"> + {{ $t("alsijil.coursebook.absences.summary") }} + </div> </template> <template #content> - <absence-form v-if="form" /> - <absence-summary v-else /> + <absence-creation-form + :persons="persons" + :start-date="startDate" + :end-date="endDate" + :comment="comment" + :absence-reason="absenceReason" + @valid="formValid = $event" + @persons="persons = $event" + @start-date="startDate = $event" + @end-date="endDate = $event" + @comment="comment = $event" + @absence-reason="absenceReason = $event" + :class="{ + 'd-none': !form, + }" + /> + <absence-creation-summary + v-if="!form" + :persons="persons" + :start-date="startDate" + :end-date="endDate" + @loading="handleLoading" + /> + </template> + <template #actionsLeft> + <cancel-button @click="cancel" /> </template> <template #actions> <!-- secondary --> - <!-- TODO: Return to form on cancel? form=true --> - <cancel-button @click="popup = false" disabled="loading" /> + <secondary-action-button + @click="form = true" + v-if="!form" + :disabled="loading" + i18n-key="actions.back" + > + <v-icon left>$prev</v-icon> + {{ $t("actions.back") }} + </secondary-action-button> <!-- primary --> <save-button v-if="form" - i18n-key="actions.continue" @click="form = false" :loading="loading" - /> + :disabled="!formValid" + > + {{ $t("actions.continue") }} + <v-icon right>$next</v-icon> + </save-button> <save-button - v-if="form" + v-else i18n-key="actions.confirm" @click="confirm" :loading="loading" @@ -35,31 +84,96 @@ <script> import MobileFullscreenDialog from "aleksis.core/components/generic/dialogs/MobileFullscreenDialog.vue"; -import AbsenceForm from "./AbsenceForm.vue"; -import AbsenceSummary from "./AbsenceSummary.vue"; +import AbsenceCreationForm from "./AbsenceCreationForm.vue"; +import AbsenceCreationSummary from "./AbsenceCreationSummary.vue"; +import FabButton from "aleksis.core/components/generic/buttons/FabButton.vue"; import CancelButton from "aleksis.core/components/generic/buttons/CancelButton.vue"; import SaveButton from "aleksis.core/components/generic/buttons/SaveButton.vue"; +import SecondaryActionButton from "aleksis.core/components/generic/buttons/SecondaryActionButton.vue"; +import loadingMixin from "aleksis.core/mixins/loadingMixin.js"; +import permissionsMixin from "aleksis.core/mixins/permissions.js"; +import mutateMixin from "aleksis.core/mixins/mutateMixin.js"; +import { DateTime } from "luxon"; + +import { createAbsencesForPersons } from "./absenceCreation.graphql"; export default { - name: "AbsenceDialog", + name: "AbsenceCreationDialog", components: { MobileFullscreenDialog, - AbsenceForm, - AbsenceSummary, + AbsenceCreationForm, + AbsenceCreationSummary, CancelButton, SaveButton, + SecondaryActionButton, + FabButton, }, + mixins: [loadingMixin, mutateMixin, permissionsMixin], data() { return { popup: false, form: true, - loading: false, + formValid: false, + persons: [], + startDate: "", + endDate: "", + comment: "", + absenceReason: "", }; }, + mounted() { + this.addPermissions(["alsijil.view_register_absence_rule"]); + this.clearForm(); + }, methods: { + cancel() { + this.popup = false; + this.form = true; + this.clearForm(); + }, + clearForm() { + this.persons = []; + this.startDate = DateTime.now() + .startOf("day") + .toISO({ suppressSeconds: true }); + this.endDate = DateTime.now() + .endOf("day") + .toISO({ suppressSeconds: true }); + this.comment = ""; + this.absenceReason = ""; + }, confirm() { - // TODO: Send mutation (shown in absence-summary) - popup = false, + this.handleLoading(true); + this.mutate( + createAbsencesForPersons, + { + persons: this.persons.map((p) => p.id), + start: this.$toUTCISO(this.$parseISODate(this.startDate)), + end: this.$toUTCISO(this.$parseISODate(this.endDate)), + comment: this.comment, + reason: this.absenceReason, + }, + (storedDocumentations, incomingStatuses) => { + const documentation = storedDocumentations.find( + (doc) => doc.id === this.documentation.id, + ); + + incomingStatuses.forEach((newStatus) => { + const participationStatus = documentation.participations.find( + (part) => part.id === newStatus.id, + ); + participationStatus.absenceReason = newStatus.absenceReason; + participationStatus.isOptimistic = newStatus.isOptimistic; + }); + + return storedDocumentations; + }, + ); + this.$once("save", this.handleSave); + }, + handleSave() { + this.cancel(); + this.$toastSuccess(this.$t("alsijil.coursebook.absences.success")); }, }, }; diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue index 09cf3ea5adbb59e39ed3b782bc5a114a22a123da..239c83d6bbd48700773c024967636a82f3d3c4a8 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue @@ -1,44 +1,140 @@ <template> - <v-container> - <v-row> - <!-- persons --> - <!-- v-autocomplete --> - </v-row> - <v-row> - <!-- Start --> - <v-col cols="12" :sm="6"> - <date-field - :value="value" - @input="$emit('input', $event)" - :label="$t('date_select.label')" - :disabled="loading" + <v-form @input="$emit('valid', $event)"> + <v-container> + <v-row> + <div aria-required="true" class="full-width"> + <!-- FIXME Vue 3: clear-on-select --> + <v-autocomplete + :label="$t('forms.labels.persons')" + :items="allPersons" + item-text="fullName" + return-object + multiple + chips + deletable-chips + :rules=" + $rules().build([ + (value) => value.length > 0 || $t('forms.errors.required'), + ]) + " + :value="persons" + :loading="$apollo.queries.allPersons.loading" + @input="$emit('persons', $event)" + /> + </div> + </v-row> + <v-row> + <v-col cols="12" :sm="6" class="pl-0"> + <div aria-required="true"> + <date-time-field + :label="$t('forms.labels.start')" + :max-date="endDate" + :max-time="maxStartTime" + :rules="$rules().required.build()" + :value="startDate" + @input="$emit('start-date', $event)" + /> + </div> + </v-col> + <v-col cols="12" :sm="6" class="pr-0"> + <div aria-required="true"> + <date-time-field + :label="$t('forms.labels.end')" + :min-date="startDate" + :min-time="minEndTime" + :rules="$rules().required.build()" + :value="endDate" + @input="$emit('end-date', $event)" + /> + </div> + </v-col> + </v-row> + <v-row> + <v-text-field + :label="$t('forms.labels.comment')" + :value="comment" + @input="$emit('comment', $event)" /> - </v-col> - <!-- End --> - <v-col cols="12" :sm="6"> - <date-field - :value="value" - @input="$emit('input', $event)" - :label="$t('date_select.label')" - :disabled="loading" - /> - </v-col> - </v-row> - <v-row> - <!-- comment --> - </v-row> - <v-row> - <!-- TODO: Component from Julian --> - </v-row> - </v-container> + </v-row> + <v-row> + <div aria-required="true"> + <absence-reason-group-select + :rules="$rules().required.build()" + :value="absenceReason" + @input="$emit('absence-reason', $event)" + /> + </div> + </v-row> + </v-container> + </v-form> </template> <script> -import DateField from "aleksis.core/components/generic/forms/DateField.vue"; +import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue"; +import DateTimeField from "aleksis.core/components/generic/forms/DateTimeField.vue"; +import { persons } from "./absenceCreation.graphql"; +import formRulesMixin from "aleksis.core/mixins/formRulesMixin.js"; +import { DateTime } from "luxon"; + export default { - name: "AbsenceForm", + name: "AbsenceCreationForm", components: { - DateField, + AbsenceReasonGroupSelect, + DateTimeField, + }, + mixins: [formRulesMixin], + emits: [ + "valid", + "persons", + "start-date", + "end-date", + "comment", + "absence-reason", + ], + apollo: { + allPersons: persons, + }, + props: { + persons: { + type: Array, + required: true, + }, + startDate: { + type: String, + required: true, + }, + endDate: { + type: String, + required: true, + }, + comment: { + type: String, + required: true, + }, + absenceReason: { + type: String, + required: true, + }, + }, + computed: { + maxStartTime() { + // Only if on the same day + const start = DateTime.fromISO(this.startDate); + const end = DateTime.fromISO(this.endDate); + + if (start.day !== end.day) return; + + return end.minus({ minutes: 5 }).toFormat("HH:mm"); + }, + minEndTime() { + // Only if on the same day + const start = DateTime.fromISO(this.startDate); + const end = DateTime.fromISO(this.endDate); + + if (start.day !== end.day) return; + + return start.plus({ minutes: 5 }).toFormat("HH:mm"); + }, }, }; </script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationSummary.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationSummary.vue index 569bc64903ecb8740ba166f457956cc64ca09496..17a7795e697caeed9346c3aa13fe6b10e2f54c28 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationSummary.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationSummary.vue @@ -1,25 +1,123 @@ <template> - <!-- TODO: Hide header --> - <c-r-u-d-iterator - :gql-query="" - :gql-additional-query-args="FROM FORM" - :enable-create="false" - :enable-edit="false" - :elevated="false" - > - <template #default="{ items }"> - <!-- expandable card per person --> - </template> - </c-r-u-d-iterator> + <div> + <message-box dense type="warning" class="mt-5"> + {{ $t("alsijil.coursebook.absences.warning") }} + </message-box> + <!-- MAYBE introduce a minimal variant of CRUDIterator --> + <!-- with most features disabled for this list usecase --> + <c-r-u-d-iterator + i18n-key="" + :gql-query="gqlQuery" + :gql-additional-query-args="gqlArgs" + :enable-search="false" + :enable-create="false" + :enable-edit="false" + :elevated="false" + disable-pagination + hide-default-footer + @loading="handleLoading" + > + <template #default="{ items }"> + <v-expansion-panels> + <v-expansion-panel v-for="person in items" :key="person.id"> + <v-expansion-panel-header> + <div> + {{ persons.find((p) => p.id === person.id).fullName }} + </div> + <v-spacer /> + <div> + {{ + $tc( + "alsijil.coursebook.absences.lessons", + person.lessons.length, + { count: person.lessons.length }, + ) + }} + </div> + </v-expansion-panel-header> + <v-expansion-panel-content> + <v-list-item + v-for="lesson in person.lessons" + class="px-0" + :key="lesson.id" + > + <v-row> + <!-- TODO: We should extract this display & share it --> + <v-col cols="3"> + <time :datetime="lesson.datetimeStart" class="text-no-wrap"> + {{ + $d( + $parseISODate(lesson.datetimeStart), + "shortWithWeekday", + ) + }} + </time> + </v-col> + <v-col cols="3"> + <time :datetime="lesson.datetimeStart" class="text-no-wrap"> + {{ $d($parseISODate(lesson.datetimeStart), "shortTime") }} + </time> + <span> - </span> + <time :datetime="lesson.datetimeEnd" class="text-no-wrap"> + {{ $d($parseISODate(lesson.datetimeEnd), "shortTime") }} + </time> + </v-col> + <v-col cols="3"> + {{ lesson.course?.name }} + </v-col> + <v-col cols="3"> + <subject-chip :subject="lesson.subject" /> + </v-col> + </v-row> + </v-list-item> + </v-expansion-panel-content> + </v-expansion-panel> + </v-expansion-panels> + </template> + </c-r-u-d-iterator> + </div> </template> <script> import CRUDIterator from "aleksis.core/components/generic/CRUDIterator.vue"; +import SubjectChip from "aleksis.apps.cursus/components/SubjectChip.vue"; +import { lessonsForPersons } from "./absenceCreation.graphql"; +import loadingMixin from "aleksis.core/mixins/loadingMixin.js"; export default { - name: "AbsenceSummary", + name: "AbsenceCreationSummary", components: { CRUDIterator, + SubjectChip, + }, + mixins: [loadingMixin], + props: { + persons: { + type: Array, + required: true, + }, + startDate: { + type: String, + required: true, + }, + endDate: { + type: String, + required: true, + }, + }, + data() { + return { + gqlQuery: lessonsForPersons, + }; + }, + computed: { + gqlArgs() { + return { + persons: this.persons.map((person) => person.id), + start: this.startDate, + end: this.endDate, + }; + }, }, }; </script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsences.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsences.vue new file mode 100644 index 0000000000000000000000000000000000000000..8dbe68847629ba81e0bca1da804c516de4562bf4 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsences.vue @@ -0,0 +1,111 @@ +<template> + <v-card :class="{ 'my-1 full-width': true, 'd-flex flex-column': !compact }"> + <v-card-title v-if="!compact"> + <lesson-information v-bind="documentationPartProps" /> + </v-card-title> + + <v-card-text + class="full-width main-body" + :class="{ + vertical: !compact || $vuetify.breakpoint.mobile, + 'pa-2': compact, + }" + > + <lesson-information v-if="compact" v-bind="documentationPartProps" /> + + <lesson-notes class="span-2" v-bind="documentationPartProps" /> + <participation-list + v-if="documentation.canEditParticipationStatus" + :include-present="false" + class="participation-list" + v-bind="documentationPartProps" + :value="value" + @input="$emit('input', $event)" + /> + </v-card-text> + <v-spacer /> + <v-divider /> + <v-card-actions v-if="!compact"> + <v-spacer /> + <cancel-button + v-if="documentation.canEdit" + @click="$emit('close')" + :disabled="loading" + /> + <save-button + v-if="documentation.canEdit" + @click="save" + :loading="loading" + /> + <cancel-button + v-if="!documentation.canEdit" + i18n-key="actions.close" + @click="$emit('close')" + /> + </v-card-actions> + </v-card> +</template> + +<script> +import ParticipationList from "./ParticipationList.vue"; +import LessonInformation from "../documentation/LessonInformation.vue"; +import LessonNotes from "../documentation/LessonNotes.vue"; + +import SaveButton from "aleksis.core/components/generic/buttons/SaveButton.vue"; +import CancelButton from "aleksis.core/components/generic/buttons/CancelButton.vue"; + +import { createOrUpdateDocumentations } from "../coursebook.graphql"; + +import documentationPartMixin from "../documentation/documentationPartMixin"; + +export default { + name: "DocumentationAbsences", + components: { + ParticipationList, + LessonInformation, + LessonNotes, + SaveButton, + CancelButton, + }, + emits: ["open", "close"], + mixins: [documentationPartMixin], + data() { + return { + loading: false, + documentationsMutation: createOrUpdateDocumentations, + selectedParticipations: [], + }; + }, + props: { + value: { + type: Array, + required: true, + }, + }, + methods: { + save() { + this.$refs.summary.save(); + this.$emit("close"); + }, + }, +}; +</script> + +<style scoped> +.main-body { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: min-content min-content; + column-gap: 1em; +} +.participation-list { + grid-column-start: 1; + grid-column-end: span 3; +} +.span-2 { + grid-column-end: span 2; +} +.vertical > * { + grid-column-end: span 3; +} +</style> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsencesModal.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsencesModal.vue new file mode 100644 index 0000000000000000000000000000000000000000..f639e731da82cd400c1d2b5cbba8dbc90da8d70e --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsencesModal.vue @@ -0,0 +1,60 @@ +<!-- Wrapper around DocumentationAbsences.vue --> +<!-- That uses it either as list item or as editable modal dialog. --> +<template> + <mobile-fullscreen-dialog v-model="popup" max-width="500px"> + <template #activator="activator"> + <!-- list view -> activate dialog --> + <documentation-absences + compact + v-bind="$attrs" + :extra-marks="extraMarks" + :absence-reasons="absenceReasons" + :dialog-activator="activator" + :value="value" + @input="$emit('input', $event)" + /> + </template> + <!-- dialog view -> deactivate dialog --> + <!-- cancel | save (through lesson-summary) --> + <documentation + v-bind="$attrs" + :extra-marks="extraMarks" + :absence-reasons="absenceReasons" + @close="popup = false" + /> + </mobile-fullscreen-dialog> +</template> + +<script> +import MobileFullscreenDialog from "aleksis.core/components/generic/dialogs/MobileFullscreenDialog.vue"; +import DocumentationAbsences from "./DocumentationAbsences.vue"; +import Documentation from "../documentation/Documentation.vue"; + +export default { + name: "DocumentationAbsencesModal", + components: { + MobileFullscreenDialog, + Documentation, + DocumentationAbsences, + }, + data() { + return { + popup: false, + }; + }, + props: { + value: { + type: Array, + required: true, + }, + extraMarks: { + type: Array, + required: true, + }, + absenceReasons: { + type: Array, + required: true, + }, + }, +}; +</script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue index 3af1db58846f37b5e7e7837dba08a4468294269e..3248becfa4ddeaaaf998794f5398d5845f38d21f 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue @@ -2,27 +2,46 @@ import AbsenceReasonButtons from "aleksis.apps.kolego/components/AbsenceReasonButtons.vue"; import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue"; import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue"; -import CancelButton from "aleksis.core/components/generic/buttons/CancelButton.vue"; +import DialogCloseButton from "aleksis.core/components/generic/buttons/DialogCloseButton.vue"; +import SecondaryActionButton from "aleksis.core/components/generic/buttons/SecondaryActionButton.vue"; import MobileFullscreenDialog from "aleksis.core/components/generic/dialogs/MobileFullscreenDialog.vue"; -import mutateMixin from "aleksis.core/mixins/mutateMixin.js"; -import documentationPartMixin from "../documentation/documentationPartMixin"; +import updateParticipationMixin from "./updateParticipationMixin.js"; +import deepSearchMixin from "aleksis.core/mixins/deepSearchMixin.js"; import LessonInformation from "../documentation/LessonInformation.vue"; -import { updateParticipationStatuses } from "./participationStatus.graphql"; +import { + extendParticipationStatuses, + updateParticipationStatuses, +} from "./participationStatus.graphql"; import SlideIterator from "aleksis.core/components/generic/SlideIterator.vue"; +import PersonalNotes from "../personal_notes/PersonalNotes.vue"; +import PersonalNoteChip from "../personal_notes/PersonalNoteChip.vue"; +import ExtraMarkChip from "../../extra_marks/ExtraMarkChip.vue"; +import TardinessChip from "./TardinessChip.vue"; +import TardinessField from "./TardinessField.vue"; +import ExtraMarkButtons from "../../extra_marks/ExtraMarkButtons.vue"; +import MessageBox from "aleksis.core/components/generic/MessageBox.vue"; export default { name: "ManageStudentsDialog", extends: MobileFullscreenDialog, components: { + ExtraMarkButtons, + TardinessChip, + ExtraMarkChip, AbsenceReasonChip, AbsenceReasonGroupSelect, AbsenceReasonButtons, - CancelButton, + PersonalNotes, + PersonalNoteChip, LessonInformation, + MessageBox, MobileFullscreenDialog, + SecondaryActionButton, SlideIterator, + TardinessField, + DialogCloseButton, }, - mixins: [documentationPartMixin, mutateMixin], + mixins: [updateParticipationMixin, deepSearchMixin], data() { return { dialog: false, @@ -30,6 +49,14 @@ export default { loadSelected: false, selected: [], isExpanded: false, + markAsAbsentDay: { + showAlert: false, + num: 0, + reason: "no reason", + name: "nobody", + participationIDs: [], + loading: false, + }, }; }, props: { @@ -38,6 +65,11 @@ export default { default: false, required: false, }, + useDeepSearch: { + type: Boolean, + default: true, + required: false, + }, }, computed: { items() { @@ -45,16 +77,56 @@ export default { }, }, methods: { - sendToServer(participations, field, value) { - if (field !== "absenceReason") return; + handleMultipleAction(field, id) { + this.loadSelected = true; + this.sendToServer(this.selected, field, id); + this.$once("save", this.resetMultipleAction); + }, + resetMultipleAction() { + this.loadSelected = false; + this.$set(this.selected, []); + this.$refs.iterator.selected = []; + }, + activateFullDayDialog(items) { + const itemIds = items.map((item) => item.id); + const participations = this.documentation.participations.filter((part) => + itemIds.includes(part.id), + ); + + if (this.markAsAbsentDay.num === 1) { + this.markAsAbsentDay.name = participations[0].person.firstName; + } + + this.$set(this.markAsAbsentDay, "participationIDs", itemIds); + + this.markAsAbsentDay.loading = false; + this.markAsAbsentDay.showAlert = true; + }, + beforeSendToServer() { + this.markAsAbsentDay.showAlert = false; + this.markAsAbsentDay.participationIDs = []; + }, + duringUpdateSendToServer( + _participations, + _field, + _value, + incomingStatuses, + ) { + this.markAsAbsentDay.reason = incomingStatuses[0].absenceReason?.name; + this.markAsAbsentDay.num = incomingStatuses.length; + }, + afterSendToServer(_participations, field, value) { + if (field === "absenceReason" && value !== "present") { + this.$once("save", this.activateFullDayDialog); + } + }, + markAsAbsentDayClick() { + this.markAsAbsentDay.loading = true; this.mutate( - updateParticipationStatuses, + extendParticipationStatuses, { - input: participations.map((participation) => ({ - id: participation.id, - absenceReason: value === "present" ? null : value, - })), + input: this.markAsAbsentDay.participationIDs, }, (storedDocumentations, incomingStatuses) => { const documentation = storedDocumentations.find( @@ -65,24 +137,21 @@ export default { const participationStatus = documentation.participations.find( (part) => part.id === newStatus.id, ); - participationStatus.absenceReason = newStatus.absenceReason; + participationStatus.baseAbsence = newStatus.baseAbsence; participationStatus.isOptimistic = newStatus.isOptimistic; }); + this.markAsAbsentDay.reason = "no reason"; + this.markAsAbsentDay.num = 0; + this.markAsAbsentDay.participationIDs = []; + this.markAsAbsentDay.loading = false; + + this.markAsAbsentDay.showAlert = false; + return storedDocumentations; }, ); }, - handleMultipleAction(absenceReasonId) { - this.loadSelected = true; - this.sendToServer(this.selected, "absenceReason", absenceReasonId); - this.$once("save", this.resetMultipleAction); - }, - resetMultipleAction() { - this.loadSelected = false; - this.$set(this.selected, []); - this.$refs.iterator.selected = []; - }, }, }; </script> @@ -93,13 +162,17 @@ export default { v-bind="$attrs" v-on="$listeners" v-model="dialog" + :close-button="false" > <template #activator="activator"> <slot name="activator" v-bind="activator" /> </template> <template #title> - <lesson-information v-bind="documentationPartProps" :compact="false" /> + <div class="d-flex full-width"> + <lesson-information v-bind="documentationPartProps" :compact="false" /> + <dialog-close-button @click="dialog = false" class="ml-4" /> + </div> <v-scroll-x-transition leave-absolute> <v-text-field v-show="!isExpanded" @@ -116,15 +189,40 @@ export default { class="pt-4 full-width" /> </v-scroll-x-transition> - <v-scroll-x-transition> - <div v-show="selected.length > 0" class="full-width mt-4"> - <absence-reason-buttons - allow-empty - empty-value="present" - @input="handleMultipleAction" - /> + <message-box + v-model="markAsAbsentDay.showAlert" + color="success" + icon="$success" + transition="slide-y-transition" + dismissible + class="mt-4 mb-0 full-width" + > + <div class="text-subtitle-2"> + {{ + $tc( + "alsijil.coursebook.mark_as_absent_day.title", + markAsAbsentDay.num, + markAsAbsentDay, + ) + }} </div> - </v-scroll-x-transition> + <p class="text-body-2 pa-0 ma-0" style="word-break: break-word"> + {{ + $t( + "alsijil.coursebook.mark_as_absent_day.description", + markAsAbsentDay, + ) + }} + </p> + + <secondary-action-button + color="success" + i18n-key="alsijil.coursebook.mark_as_absent_day.action_button" + class="mt-2" + :loading="markAsAbsentDay.loading" + @click="markAsAbsentDayClick" + /> + </message-box> </template> <template #content> <slide-iterator @@ -139,13 +237,43 @@ export default { :loading="loadingIndicator || loadSelected" :load-only-selected="loadSelected" :disabled="loading" + :custom-filter="deepSearch" > <template #listItemContent="{ item }"> <v-list-item-title> {{ item.person.fullName }} </v-list-item-title> - <v-list-item-subtitle v-if="item.absenceReason"> - <absence-reason-chip small :absence-reason="item.absenceReason" /> + <v-list-item-subtitle + v-if=" + item.absenceReason || + item.notesWithNote?.length > 0 || + item.notesWithExtraMark?.length > 0 || + item.tardiness + " + class="d-flex flex-wrap gap" + > + <absence-reason-chip + v-if="item.absenceReason" + small + :absence-reason="item.absenceReason" + /> + <personal-note-chip + v-for="note in item.notesWithNote" + :key="'text-note-note-overview-' + note.id" + :note="note" + small + /> + <extra-mark-chip + v-for="note in item.notesWithExtraMark" + :key="'extra-mark-note-overview-' + note.id" + :extra-mark="extraMarks.find((e) => e.id === note.extraMark.id)" + small + /> + <tardiness-chip + v-if="item.tardiness" + :tardiness="item.tardiness" + small + /> </v-list-item-subtitle> </template> @@ -164,22 +292,59 @@ export default { <v-card-text> <absence-reason-group-select allow-empty - empty-value="present" - :loadSelectedChip="loading" + :load-selected-chip="loading" :value="item.absenceReason?.id || 'present'" + :custom-absence-reasons="absenceReasons" @input="sendToServer([item], 'absenceReason', $event)" /> + <tardiness-field + v-bind="documentationPartProps" + :loading="loading" + :disabled="loading" + :participation="item" + :value="item.tardiness" + @input="sendToServer([item], 'tardiness', $event)" + /> + </v-card-text> + <v-divider /> + <v-card-text> + <personal-notes + v-bind="documentationPartProps" + :participation=" + documentation.participations.find((p) => p.id === item.id) + " + /> </v-card-text> </template> </slide-iterator> </template> <template #actions> - <cancel-button - @click="dialog = false" - i18n-key="actions.close" - v-show="$vuetify.breakpoint.mobile" - /> + <v-scroll-y-reverse-transition> + <div v-show="selected.length > 0" class="full-width"> + <h4>{{ $t("alsijil.coursebook.participation_status") }}</h4> + <absence-reason-buttons + class="mb-1" + allow-empty + empty-value="present" + :custom-absence-reasons="absenceReasons" + @input="handleMultipleAction('absenceReason', $event)" + /> + <h4>{{ $t("alsijil.extra_marks.title_plural") }}</h4> + <extra-mark-buttons + @input="handleMultipleAction('extraMark', $event)" + /> + <h4>{{ $t("alsijil.personal_notes.tardiness") }}</h4> + <tardiness-field + v-bind="documentationPartProps" + :loading="loading" + :disabled="loading" + :value="0" + :participations="selected" + @input="handleMultipleAction('tardiness', $event)" + /> + </div> + </v-scroll-y-reverse-transition> </template> </mobile-fullscreen-dialog> </template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsTrigger.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsTrigger.vue index 572036c67955b3365bb46eb69f6ab41ee86cf074..963367cbddb77174251a3b2deb21f65102e3c960 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsTrigger.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsTrigger.vue @@ -15,6 +15,13 @@ export default { timeout: null, }; }, + props: { + labelKey: { + type: String, + required: false, + default: undefined, + }, + }, mounted() { const lessonStart = DateTime.fromISO(this.documentation.datetimeStart); const now = DateTime.now(); @@ -50,6 +57,17 @@ export default { ); }, }, + computed: { + showLabel() { + return !!this.labelKey || !this.canOpenParticipation; + }, + innerLabelKey() { + if (this.documentation.futureNoticeParticipationStatus) { + return "alsijil.coursebook.notes.future"; + } + return this.labelKey; + }, + }, }; </script> @@ -58,6 +76,7 @@ export default { v-bind="documentationPartProps" @update="() => null" :loading-indicator="loading" + v-if="!documentation.amends?.cancelled" > <template #activator="{ attrs, on }"> <v-chip @@ -69,7 +88,10 @@ export default { v-on="on" @click="touchDocumentation" > - <v-icon>$edit</v-icon> + <v-icon :left="showLabel">mdi-account-edit-outline</v-icon> + <template v-if="showLabel"> + {{ $t(innerLabelKey) }} + </template> </v-chip> </template> </manage-students-dialog> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ParticipationList.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ParticipationList.vue new file mode 100644 index 0000000000000000000000000000000000000000..dd84e644a78059284cdc338b6cd899f96a36066c --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ParticipationList.vue @@ -0,0 +1,96 @@ +<script setup> +import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue"; +</script> + +<template> + <v-list v-if="filteredParticipations.length"> + <v-divider /> + + <v-list-item-group :value="value" multiple @change="changeSelect"> + <template v-for="(participation, index) in filteredParticipations"> + <v-list-item + :key="`documentation-${documentation.id}-participation-${participation.id}`" + :value="participation.id" + v-bind="$attrs" + two-line + > + <template #default="{ active }"> + <v-list-item-action> + <v-checkbox :input-value="active" /> + </v-list-item-action> + <v-list-item-content> + <v-list-item-title> + {{ participation.person.fullName }} + </v-list-item-title> + <absence-reason-group-select + v-if="participation.absenceReason && !compact" + class="full-width" + allow-empty + :load-selected-chip="loading" + :custom-absence-reasons="absenceReasons" + :value="participation.absenceReason?.id || 'present'" + @input="sendToServer([participation], 'absenceReason', $event)" + /> + </v-list-item-content> + <v-list-item-action v-if="participation.absenceReason && compact"> + <absence-reason-group-select + allow-empty + :load-selected-chip="loading" + :custom-absence-reasons="absenceReasons" + :value="participation.absenceReason?.id || 'present'" + @input="sendToServer([participation], 'absenceReason', $event)" + /> + </v-list-item-action> + </template> + </v-list-item> + <v-divider + v-if="index < filteredParticipations.length - 1" + :key="index" + ></v-divider> + </template> + </v-list-item-group> + </v-list> +</template> + +<script> +import updateParticipationMixin from "./updateParticipationMixin"; + +export default { + name: "ParticipationList", + mixins: [updateParticipationMixin], + data() { + return { + loading: false, + participationDialogs: false, + isExpanded: false, + }; + }, + props: { + includePresent: { + type: Boolean, + required: false, + default: true, + }, + value: { + type: Array, + required: true, + }, + }, + computed: { + filteredParticipations() { + if (!this.includePresent) { + return this.documentation.participations.filter( + (p) => !!p.absenceReason, + ); + } else { + return this.documentation.participations; + } + }, + }, + methods: { + changeSelect(value) { + this.$emit("input", value); + }, + }, +}; +</script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessChip.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessChip.vue new file mode 100644 index 0000000000000000000000000000000000000000..6be1fea3942fed64d37d2a68dde699344e55c35b --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessChip.vue @@ -0,0 +1,34 @@ +<script> +export default { + name: "TardinessChip", + props: { + tardiness: { + type: Number, + required: false, + default: 0, + }, + loading: { + type: Boolean, + required: false, + default: false, + }, + }, + extends: "v-chip", +}; +</script> + +<template> + <v-chip dense outlined v-bind="$attrs" v-on="$listeners"> + <v-avatar left> + <v-icon small>mdi-clock-alert-outline</v-icon> + </v-avatar> + <slot name="prepend" /> + <slot> + {{ $tc("alsijil.personal_notes.minutes_late", tardiness) }} + </slot> + <slot name="append" /> + <v-avatar right v-if="loading"> + <v-progress-circular indeterminate :size="16" :width="2" /> + </v-avatar> + </v-chip> +</template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue new file mode 100644 index 0000000000000000000000000000000000000000..774decab0a88867af0fdb510ac8813edefec9a14 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue @@ -0,0 +1,175 @@ +<script> +import { DateTime } from "luxon"; +import documentationPartMixin from "../documentation/documentationPartMixin"; +import ConfirmDialog from "aleksis.core/components/generic/dialogs/ConfirmDialog.vue"; +import formRulesMixin from "aleksis.core/mixins/formRulesMixin.js"; + +export default { + name: "TardinessField", + components: { ConfirmDialog }, + mixins: [documentationPartMixin, formRulesMixin], + props: { + value: { + type: Number, + default: null, + required: false, + }, + participations: { + type: Array, + required: true, + }, + }, + computed: { + lessonLength() { + const lessonStart = DateTime.fromISO(this.documentation.datetimeStart); + const lessonEnd = DateTime.fromISO(this.documentation.datetimeEnd); + + let diff = lessonEnd.diff(lessonStart, "minutes"); + return diff.toObject().minutes; + }, + defaultTimes() { + const lessonStart = DateTime.fromISO(this.documentation.datetimeStart); + const lessonEnd = DateTime.fromISO(this.documentation.datetimeEnd); + const now = DateTime.now(); + + let current = []; + + if (now >= lessonStart && now <= lessonEnd) { + const diff = parseInt( + now.diff(lessonStart, "minutes").toObject().minutes, + ); + + current.push({ + text: diff, + value: diff, + current: true, + }); + } + + return current.concat([ + { + text: 5, + value: 5, + }, + { + text: 10, + value: 10, + }, + { + text: 15, + value: 15, + }, + ]); + }, + }, + methods: { + lessonLengthRule(time) { + return ( + time == null || + time <= this.lessonLength || + this.$t("alsijil.personal_notes.lesson_length_exceeded") + ); + }, + saveValue(value) { + this.$emit("input", value); + this.previousValue = value; + }, + confirm() { + this.saveValue(0); + }, + cancel() { + this.saveValue(this.previousValue); + }, + processValueObjectOptional(value) { + if (Object.hasOwn(value, "value")) { + return value.value; + } + + return value; + }, + set(newValue) { + newValue = this.processValueObjectOptional(newValue); + + if (!newValue || parseInt(newValue) === 0) { + // this is a DELETE action, show the dialog, ... + this.showDeleteConfirm = true; + return; + } + + this.saveValue(parseInt(newValue)); + }, + }, + data() { + return { + showDeleteConfirm: false, + previousValue: 0, + }; + }, + mounted() { + this.previousValue = this.value; + }, +}; +</script> + +<template> + <v-combobox + outlined + class="mt-1" + prepend-inner-icon="mdi-clock-alert-outline" + :suffix="$t('time.minutes')" + :label="$t('alsijil.personal_notes.tardiness')" + :rules=" + $rules() + .isANumber.isAWholeNumber.isGreaterThan(0) + .build([lessonLengthRule]) + .map((f) => (v) => f(this.processValueObjectOptional(v))) + " + :items="defaultTimes" + :value="value" + @change="set($event)" + v-bind="$attrs" + > + <template #item="{ item }"> + <v-list-item-icon v-if="item.current"> + <v-icon>mdi-shimmer</v-icon> + </v-list-item-icon> + <v-list-item-content> + <v-list-item-title> + {{ + $tc( + item.current + ? "alsijil.personal_notes.minutes_late_current" + : "time.minutes_n", + item.value, + ) + }} + </v-list-item-title> + </v-list-item-content> + </template> + <template #append> + <confirm-dialog + v-model="showDeleteConfirm" + @confirm="confirm" + @cancel="cancel" + > + <template #title> + {{ $t("alsijil.personal_notes.confirm_delete") }} + </template> + <template #text> + {{ + $t("alsijil.personal_notes.confirm_delete_tardiness", { + tardiness: previousValue, + name: participations.map((p) => p.person.firstName).join(", "), + }) + }} + </template> + </confirm-dialog> + </template> + </v-combobox> +</template> + +<style scoped> +.mt-n1-5 { + margin-top: -6px; +} +</style> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceCreation.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceCreation.graphql index 5bc9ee2d62125800ccb43fa0ec677956b9343e32..5a520453f35062d49edd5eb82aca291384e2f739 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceCreation.graphql +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceCreation.graphql @@ -1,13 +1,12 @@ # Uses core persons query query persons { - persons: persons { + allPersons: absenceCreationPersons { id - firstName - lastName + fullName } } -query lessonsForPersons($persons: [ID!]!, $start: Date!, $end: Date!) { +query lessonsForPersons($persons: [ID]!, $start: DateTime!, $end: DateTime!) { items: lessonsForPersons(persons: $persons, start: $start, end: $end) { id lessons { @@ -30,22 +29,33 @@ query lessonsForPersons($persons: [ID!]!, $start: Date!, $end: Date!) { } # Use absencesInputType? -mutation createAbsences( - $persons: [ID!]! - $start: Date! - $end: Date! +mutation createAbsencesForPersons( + $persons: [ID]! + $start: DateTime! + $end: DateTime! $comment: String $reason: ID! ) { - createAbsences( - person: $persons + createAbsencesForPersons( + persons: $persons start: $start end: $end comment: $comment reason: $reason ) { - items: absences { - ok + ok + items: participationStatuses { + id + isOptimistic + relatedDocumentation { + id + } + absenceReason { + id + name + shortName + colour + } } } } diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceReasons.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceReasons.graphql new file mode 100644 index 0000000000000000000000000000000000000000..a86f608ec78d1bbc50bf558b5e0650cba5b5e8a7 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceReasons.graphql @@ -0,0 +1,11 @@ +query absenceReasons($orderBy: [String], $filters: JSONString) { + items: coursebookAbsenceReasons(orderBy: $orderBy, filters: $filters) { + id + shortName + name + colour + default + canEdit + canDelete + } +} diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/participationStatus.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/absences/participationStatus.graphql index 81a3a5fb1eb3a99bef25eb9938cd254b9068981b..39eb59528c4f876eb2c75c20f187e5ded6fae2bc 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/participationStatus.graphql +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/participationStatus.graphql @@ -4,7 +4,6 @@ mutation updateParticipationStatuses( updateParticipationStatuses(input: $input) { items: participationStatuses { id - isOptimistic relatedDocumentation { id } @@ -14,6 +13,19 @@ mutation updateParticipationStatuses( shortName colour } + notesWithExtraMark { + id + extraMark { + id + showInCoursebook + } + } + notesWithNote { + id + note + } + tardiness + isOptimistic } } } @@ -35,8 +47,31 @@ mutation touchDocumentation($documentationId: ID!) { shortName colour } + notesWithExtraMark { + id + extraMark { + id + showInCoursebook + } + } + notesWithNote { + id + note + } + tardiness isOptimistic } } } } + +mutation extendParticipationStatuses($input: [ID]!) { + extendParticipationStatuses(input: $input) { + items: participations { + id + } + absences { + id + } + } +} diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/selectParticipationMixin.js b/aleksis/apps/alsijil/frontend/components/coursebook/absences/selectParticipationMixin.js new file mode 100644 index 0000000000000000000000000000000000000000..2d6d522692690c6def6aaa53e2dc0e7835019681 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/selectParticipationMixin.js @@ -0,0 +1,27 @@ +/** + * Mixin to provide passing through functionality for the events emitted when (de)selecting participations on the absence overview page + */ +export default { + emits: ["select", "deselect"], + methods: { + handleSelect(participation) { + this.$emit("select", participation); + }, + handleDeselect(participation) { + this.$emit("deselect", participation); + }, + }, + + computed: { + /** + * All necessary listeners bundled together to easily pass to child components + * @returns {{select: Function, deselect: Function}} + */ + selectListeners() { + return { + select: this.handleSelect, + deselect: this.handleDeselect, + }; + }, + }, +}; diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/sendToServerMixin.js b/aleksis/apps/alsijil/frontend/components/coursebook/absences/sendToServerMixin.js new file mode 100644 index 0000000000000000000000000000000000000000..e269bddee80dbe9056e399d63581212ebfdd36c4 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/sendToServerMixin.js @@ -0,0 +1,115 @@ +/** + * Mixin to provide shared functionality needed to send updated participation data to the server + */ +import { createPersonalNotes } from "../personal_notes/personal_notes.graphql"; +import { updateParticipationStatuses } from "./participationStatus.graphql"; +import mutateMixin from "aleksis.core/mixins/mutateMixin.js"; + +export default { + mixins: [mutateMixin], + methods: { + sendToServer(participations, field, value) { + let fieldValue; + + if (field === "absenceReason") { + fieldValue = { + absenceReason: value === "present" ? null : value, + }; + } else if (field === "tardiness") { + fieldValue = { + tardiness: value, + }; + } else if (field === "extraMark") { + // Too much different logic → own method + this.addExtraMarks(participations, value); + return; + } else { + console.error(`Wrong field '${field}' for sendToServer`); + return; + } + + this.beforeSendToServer(participations, field, value); + + this.mutate( + updateParticipationStatuses, + { + input: participations.map((participation) => ({ + id: participation?.id || participation, + ...fieldValue, + })), + }, + (storedDocumentations, incomingStatuses) => { + // TODO: what should happen here in places where there is more than one documentation? + const documentation = storedDocumentations.find( + (doc) => doc.id === this.documentation.id, + ); + + incomingStatuses.forEach((newStatus) => { + const participationStatus = documentation.participations.find( + (part) => part.id === newStatus.id, + ); + participationStatus.absenceReason = newStatus.absenceReason; + participationStatus.tardiness = newStatus.tardiness; + participationStatus.isOptimistic = newStatus.isOptimistic; + }); + + this.duringUpdateSendToServer( + participations, + field, + value, + incomingStatuses, + ); + + return storedDocumentations; + }, + ); + + this.afterSendToServer(participations, field, value); + }, + addExtraMarks(participations, extraMarkId) { + // Get all participation statuses without this extra mark and get the respective person ids + const participants = participations + .filter( + (participation) => + !participation.notesWithExtraMark.some( + (note) => note.extraMark.id === extraMarkId, + ), + ) + .map((participation) => participation.person.id); + + // CREATE new personal note + this.mutate( + createPersonalNotes, + { + input: participants.map((person) => ({ + documentation: this.documentation.id, + person: person, + extraMark: extraMarkId, + })), + }, + (storedDocumentations, incomingPersonalNotes) => { + const documentation = storedDocumentations.find( + (doc) => doc.id === this.documentation.id, + ); + incomingPersonalNotes.forEach((note, index) => { + const participationStatus = documentation.participations.find( + (part) => part.person.id === participants[index], + ); + participationStatus.notesWithExtraMark.push(note); + }); + + return storedDocumentations; + }, + ); + }, + beforeSendToServer(_participations, _field, _value) { + // Noop hook + }, + duringUpdateSendToServer(_participations, _field, _value, _incoming) { + // Noop hook + }, + afterSendToServer(_participations, _field, _value) { + // Noop hook + }, + }, +}; diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/updateParticipationMixin.js b/aleksis/apps/alsijil/frontend/components/coursebook/absences/updateParticipationMixin.js new file mode 100644 index 0000000000000000000000000000000000000000..2ed2c537d8bda9d11b2757468f72ad19cb89b7c6 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/updateParticipationMixin.js @@ -0,0 +1,9 @@ +/** + * Mixin to provide shared functionality needed to update participations + */ +import documentationPartMixin from "../documentation/documentationPartMixin"; +import sendToServerMixin from "./sendToServerMixin"; + +export default { + mixins: [documentationPartMixin, sendToServerMixin], +}; diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/coursebook.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/coursebook.graphql index 6348a24f189033fc60e97325c0c69cde5d11fbc9..a49b73f149129fa86e131b804e027908c84f65db 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/coursebook.graphql +++ b/aleksis/apps/alsijil/frontend/components/coursebook/coursebook.graphql @@ -19,6 +19,7 @@ query documentationsForCoursebook( $dateStart: Date! $dateEnd: Date! $incomplete: Boolean + $absencesExist: Boolean ) { items: documentationsForCoursebook( own: $own @@ -27,6 +28,7 @@ query documentationsForCoursebook( dateStart: $dateStart dateEnd: $dateEnd incomplete: $incomplete + absencesExist: $absencesExist ) { id course { @@ -35,8 +37,14 @@ query documentationsForCoursebook( } amends { id + title + slotNumberStart + slotNumberEnd amends { id + title + slotNumberStart + slotNumberEnd teachers { id shortName @@ -79,6 +87,18 @@ query documentationsForCoursebook( shortName colour } + notesWithExtraMark { + id + extraMark { + id + showInCoursebook + } + } + notesWithNote { + id + note + } + tardiness isOptimistic } topic @@ -92,6 +112,9 @@ query documentationsForCoursebook( canEdit futureNotice canDelete + futureNoticeParticipationStatus + canEditParticipationStatus + canViewParticipationStatus } } @@ -116,8 +139,27 @@ mutation createOrUpdateDocumentations($input: [DocumentationInputType]!) { shortName colour } + notesWithExtraMark { + id + extraMark { + id + showInCoursebook + } + } + notesWithNote { + id + note + } + tardiness isOptimistic } + subject { + id + name + shortName + colourFg + colourBg + } } } } diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue index 5bbc21c0de53b613986c30360e853ee6720526b5..1a70d655e00a3bc6c85f002d417497282387af7a 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue @@ -1,7 +1,11 @@ <template> <v-card :class="{ 'my-1 full-width': true, 'd-flex flex-column': !compact }"> <v-card-title v-if="!compact"> - <lesson-information v-bind="documentationPartProps" /> + <lesson-information + v-bind="{ ...$attrs, ...documentationPartProps }" + :is-create="false" + :gql-patch-mutation="documentationsMutation" + /> </v-card-title> <v-card-text @@ -11,7 +15,12 @@ 'pa-2': compact, }" > - <lesson-information v-if="compact" v-bind="documentationPartProps" /> + <lesson-information + v-if="compact" + v-bind="documentationPartProps" + :is-create="false" + :gql-patch-mutation="documentationsMutation" + /> <lesson-summary ref="summary" v-bind="{ ...$attrs, ...documentationPartProps }" @@ -91,6 +100,6 @@ export default { gap: 1em; } .vertical { - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); } </style> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationCompactDetails.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationCompactDetails.vue index 09ae0e5d09903387dd314bc25b8885c9eff1b370..6bfa946e18004dcb7e300f142c482bdae6414acd 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationCompactDetails.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationCompactDetails.vue @@ -1,19 +1,25 @@ <template> <v-card outlined dense rounded="lg" v-bind="$attrs" v-on="$listeners"> - <div class="font-weight-medium mr-2"> - {{ $t("alsijil.coursebook.summary.topic.label") }}: - </div> - <div class="text-truncate">{{ documentation.topic || "–" }}</div> + <template v-if="documentation.topic"> + <div class="font-weight-medium mr-2"> + {{ $t("alsijil.coursebook.summary.topic.label") }}: + </div> + <div class="text-truncate">{{ documentation.topic }}</div> + </template> - <div class="font-weight-medium mr-2"> - {{ $t("alsijil.coursebook.summary.homework.label") }}: - </div> - <div class="text-truncate">{{ documentation.homework || "–" }}</div> + <template v-if="documentation.homework"> + <div class="font-weight-medium mr-2"> + {{ $t("alsijil.coursebook.summary.homework.label") }}: + </div> + <div class="text-truncate">{{ documentation.homework }}</div> + </template> - <div class="font-weight-medium mr-2"> - {{ $t("alsijil.coursebook.summary.group_note.label") }}: - </div> - <div class="text-truncate">{{ documentation.groupNote || "–" }}</div> + <template v-if="documentation.groupNote"> + <div class="font-weight-medium mr-2"> + {{ $t("alsijil.coursebook.summary.group_note.label") }}: + </div> + <div class="text-truncate">{{ documentation.groupNote }}</div> + </template> </v-card> </template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationFullDetails.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationFullDetails.vue index 58ef4285647a5b80e7c8dd94aae54955aa95c81d..e9bd354bafe68b8785c8996988b5893989a21a8c 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationFullDetails.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationFullDetails.vue @@ -10,13 +10,23 @@ <v-card-title class="text-subtitle-2 pb-1 font-weight-medium"> {{ $t("alsijil.coursebook.summary.homework.label") }} </v-card-title> - <v-card-text>{{ documentation.homework || "–" }}</v-card-text> + <v-card-text> + {{ + documentation.homework || + $t("alsijil.coursebook.summary.homework.empty_yet") + }} + </v-card-text> </v-card> <v-card outlined dense rounded="lg"> <v-card-title class="text-subtitle-2 pb-1 font-weight-medium"> {{ $t("alsijil.coursebook.summary.group_note.label") }} </v-card-title> - <v-card-text>{{ documentation.groupNote || "–" }}</v-card-text> + <v-card-text> + {{ + documentation.groupNote || + $t("alsijil.coursebook.summary.group_note.empty") + }} + </v-card-text> </v-card> </div> </template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationModal.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationModal.vue index 460f39f97fc15b61d0476dd99ed33d29cf43029c..5b5dd101b76288cd1b09ba5418a452d70a9425fa 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationModal.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationModal.vue @@ -4,11 +4,24 @@ <mobile-fullscreen-dialog v-model="popup" max-width="500px"> <template #activator="activator"> <!-- list view -> activate dialog --> - <documentation compact v-bind="$attrs" :dialog-activator="activator" /> + <documentation + compact + v-bind="$attrs" + :dialog-activator="activator" + :extra-marks="extraMarks" + :absence-reasons="absenceReasons" + :subjects="subjects" + /> </template> <!-- dialog view -> deactivate dialog --> <!-- cancel | save (through lesson-summary) --> - <documentation v-bind="$attrs" @close="popup = false" /> + <documentation + v-bind="$attrs" + :extra-marks="extraMarks" + :absence-reasons="absenceReasons" + :subjects="subjects" + @close="popup = false" + /> </mobile-fullscreen-dialog> </template> @@ -27,5 +40,19 @@ export default { popup: false, }; }, + props: { + extraMarks: { + type: Array, + required: true, + }, + absenceReasons: { + type: Array, + required: true, + }, + subjects: { + type: Array, + required: true, + }, + }, }; </script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonInformation.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonInformation.vue index 652609dccaf430d3a4ab138f80ee2f810b84b4af..a104d84425d8317091d649ce7b0b88919fdf9c52 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonInformation.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonInformation.vue @@ -1,12 +1,35 @@ <script setup> import DocumentationStatus from "./DocumentationStatus.vue"; import PersonChip from "aleksis.core/components/person/PersonChip.vue"; +import SubjectChip from "aleksis.apps.cursus/components/SubjectChip.vue"; +import SubjectChipSelectField from "aleksis.apps.cursus/components/SubjectChipSelectField.vue"; </script> <template> <div :class="{ 'full-width grid': true, 'large-grid': largeGrid }"> <div class="d-flex"> <documentation-status v-if="compact" v-bind="documentationPartProps" /> + <div + v-if="documentation.amends?.slotNumberStart" + :class="{ + 'text-h5 mr-3 d-flex flex-column justify-center slot-number': true, + 'ml-2 slot-number-mobile': !largeGrid, + }" + > + <span + v-if=" + documentation.amends?.slotNumberStart == + documentation.amends?.slotNumberEnd + " + > + {{ documentation.amends?.slotNumberStart }}. + </span> + <span v-else> + {{ documentation.amends?.slotNumberStart }}.–{{ + documentation.amends?.slotNumberEnd + }}. + </span> + </div> <div :class="{ 'text-right d-flex flex-column fit-content': largeGrid }"> <time :datetime="documentation.datetimeStart" class="text-no-wrap"> {{ $d(toDateTime(documentation.datetimeStart), "shortTime") }} @@ -24,7 +47,11 @@ import PersonChip from "aleksis.core/components/person/PersonChip.vue"; 'font-weight-medium': largeGrid, }" > - {{ documentation.course?.name }} + {{ + documentation.course?.name || + documentation.amends.title || + documentation.amends.amends.title + }} </span> <div :class="{ @@ -33,12 +60,21 @@ import PersonChip from "aleksis.core/components/person/PersonChip.vue"; 'justify-start': !largeGrid, }" > - <subject-chip - v-if="documentation.subject" - :subject="documentation.subject" - v-bind="compact ? dialogActivator.attrs : {}" - v-on="compact ? dialogActivator.on : {}" - /> + <template v-if="documentation.subject"> + <subject-chip-select-field + v-if="documentation.canEdit" + :items="subjects" + :value="documentation.subject" + :disabled="loading" + :loading="loading" + @input="editSubject" + /> + <subject-chip + v-else + :subject="documentation.subject" + :disabled="loading" + /> + </template> <subject-chip v-if=" documentation?.amends?.amends?.subject && @@ -80,20 +116,32 @@ import PersonChip from "aleksis.core/components/person/PersonChip.vue"; </template> <script> -import SubjectChip from "aleksis.apps.cursus/components/SubjectChip.vue"; import { DateTime } from "luxon"; + +import createOrPatchMixin from "aleksis.core/mixins/createOrPatchMixin.js"; + import documentationPartMixin from "./documentationPartMixin"; +import documentationCacheUpdateMixin from "./documentationCacheUpdateMixin"; export default { name: "LessonInformation", - mixins: [documentationPartMixin], - components: { - SubjectChip, - }, + mixins: [ + createOrPatchMixin, + documentationCacheUpdateMixin, + documentationPartMixin, + ], methods: { toDateTime(dateString) { return DateTime.fromISO(dateString); }, + editSubject(subject) { + this.createOrPatch([ + { + id: this.documentation.id, + subject: subject.id, + }, + ]); + }, }, computed: { largeGrid() { @@ -140,4 +188,15 @@ export default { .gap { gap: 0.25em; } + +.slot-number { + font-size: 1.6rem !important; + font-weight: 300; + line-height: 1.6rem; +} + +.slot-number-mobile { + font-size: 1.4rem !important; + line-height: 1.4rem; +} </style> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonNotes.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonNotes.vue index bc0da4a742917e0639a0c1983186fad29764babb..a412d39deed9232c8668e60716a3825096394347 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonNotes.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonNotes.vue @@ -1,41 +1,238 @@ <script setup> import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue"; +import ExtraMarkChip from "../../extra_marks/ExtraMarkChip.vue"; +import ExtraMarksNote from "../personal_notes/ExtraMarksNote.vue"; +import TardinessChip from "../absences/TardinessChip.vue"; +import PersonalNoteChip from "../personal_notes/PersonalNoteChip.vue"; +import TextNoteCard from "../personal_notes/TextNoteCard.vue"; </script> <template> - <div - class="d-flex align-center justify-space-between justify-md-end flex-wrap gap" - > - <v-chip dense color="success" outlined v-if="total > 0"> - {{ $t("alsijil.coursebook.present_number", { present, total }) }} - </v-chip> - <absence-reason-chip - v-for="[reasonId, participations] in Object.entries(absences)" - :key="'reason-' + reasonId" - :absence-reason="participations[0].absenceReason" - dense + <div> + <div + class="d-flex align-center justify-space-between justify-md-end flex-wrap gap" + v-if="compact || documentation.canViewParticipationStatus" > - <template #append> - <span - >: - <span> - {{ - participations - .slice(0, 5) - .map((participation) => participation.person.firstName) - .join(", ") - }} - </span> - <span v-if="participations.length > 5"> - <!-- eslint-disable @intlify/vue-i18n/no-raw-text --> - +{{ participations.length - 5 }} - <!-- eslint-enable @intlify/vue-i18n/no-raw-text --> - </span> - </span> + <v-chip + dense + color="success" + outlined + v-if="total > 0 && documentation.canViewParticipationStatus" + > + {{ + $t("alsijil.coursebook.participations.present_number", { + present, + total, + }) + }} + </v-chip> + <v-chip + dense + color="success" + outlined + @click="$emit('open')" + v-bind="dialogActivator.attrs" + v-on="dialogActivator.on" + v-else-if=" + total == 1 && + present == 1 && + !documentation.canViewParticipationStatus + " + > + {{ $t("alsijil.coursebook.participations.present") }} + </v-chip> + + <template v-if="documentation.canViewParticipationStatus"> + <absence-reason-chip + v-for="[reasonId, participations] in Object.entries(absences)" + :key="'reason-' + reasonId" + :absence-reason="participations[0].absenceReason" + dense + > + <template #append> + <span + >: + <span> + {{ + participations + .slice(0, 5) + .map((participation) => participation.person.firstName) + .join(", ") + }} + </span> + <span v-if="participations.length > 5"> + <!-- eslint-disable @intlify/vue-i18n/no-raw-text --> + +{{ participations.length - 5 }} + <!-- eslint-enable @intlify/vue-i18n/no-raw-text --> + </span> + </span> + </template> + </absence-reason-chip> + </template> + <template v-else> + <absence-reason-chip + v-for="[reasonId, participations] in Object.entries(absences)" + :key="'reason-' + reasonId" + :absence-reason="participations[0].absenceReason" + dense + @click="$emit('open')" + v-bind="dialogActivator.attrs" + v-on="dialogActivator.on" + /> + </template> + + <template v-if="documentation.canViewParticipationStatus"> + <extra-mark-chip + v-for="[markId, [mark, ...participations]] in Object.entries( + extraMarkChips, + )" + :key="'extra-mark-' + markId" + :extra-mark="mark" + dense + > + <template #append> + <span + >: + <span> + {{ + participations + .slice(0, 5) + .map((participation) => participation.person.firstName) + .join(", ") + }} + </span> + <span v-if="participations.length > 5"> + <!-- eslint-disable @intlify/vue-i18n/no-raw-text --> + +{{ participations.length - 5 }} + <!-- eslint-enable @intlify/vue-i18n/no-raw-text --> + </span> + </span> + </template> + </extra-mark-chip> + </template> + <template v-else> + <extra-mark-chip + v-for="[markId, [mark, ...participations]] in Object.entries( + extraMarkChips, + )" + :key="'extra-mark-' + markId" + :extra-mark="mark" + dense + @click="$emit('open')" + v-bind="dialogActivator.attrs" + v-on="dialogActivator.on" + /> + </template> + + <template v-if="documentation.canViewParticipationStatus"> + <tardiness-chip v-if="tardyParticipations.length > 0"> + <template #default> + {{ $t("alsijil.personal_notes.late") }} + </template> + + <template #append> + <span + >: + {{ + tardyParticipations + .slice(0, 5) + .map((participation) => participation.person.firstName) + .join(", ") + }} + + <span v-if="tardyParticipations.length > 5"> + <!-- eslint-disable @intlify/vue-i18n/no-raw-text --> + +{{ tardyParticipations.length - 5 }} + <!-- eslint-enable @intlify/vue-i18n/no-raw-text --> + </span> + </span> + </template> + </tardiness-chip> + </template> + <template v-else> + <tardiness-chip + v-if="tardyParticipations.length > 0" + :tardiness=" + tardyParticipations.length == 1 + ? tardyParticipations[0].tardiness + : undefined + " + @click="$emit('open')" + v-bind="dialogActivator.attrs" + v-on="dialogActivator.on" + /> + </template> + + <template v-if="!documentation.canViewParticipationStatus && total == 1"> + <personal-note-chip + v-for="note in documentation?.participations[0]?.notesWithNote" + :key="'text-note-note-' + note.id" + :note="note" + @click="$emit('open')" + v-bind="dialogActivator.attrs" + v-on="dialogActivator.on" + /> </template> - </absence-reason-chip> - <manage-students-trigger v-bind="documentationPartProps" /> + <manage-students-trigger + v-if="documentation.canEditParticipationStatus" + :label-key="manageStudentsLabelKey" + v-bind="documentationPartProps" + /> + </div> + + <!-- not compact --> + <div class="main-body" v-else> + <template + v-if=" + tardyParticipations.length > 0 || Object.entries(absences).length > 0 + " + > + <v-divider /> + <div + class="d-flex align-center justify-space-between justify-md-end flex-wrap gap" + > + <tardiness-chip + v-if="tardyParticipations.length > 0" + :tardiness=" + tardyParticipations.length == 1 + ? tardyParticipations[0].tardiness + : undefined + " + /> + <absence-reason-chip + v-for="[reasonId, participations] in Object.entries(absences)" + :key="'reason-' + reasonId" + :absence-reason="participations[0].absenceReason" + dense + /> + </div> + </template> + <template v-if="total == 1"> + <v-divider /> + <extra-marks-note + v-bind="documentationPartProps" + :participation="documentation?.participations[0]" + :value="documentation?.participations[0].notesWithExtraMark" + :disabled="true" + /> + </template> + <template + v-if=" + total == 1 && + documentation?.participations[0]?.notesWithNote.length > 0 + " + > + <v-divider /> + <div> + <text-note-card + v-for="note in documentation?.participations[0]?.notesWithNote" + :key="'text-note-note-' + note.id" + :note="note" + /> + </div> + </template> + </div> </div> </template> @@ -51,13 +248,18 @@ export default { total() { return this.documentation.participations.length; }, + /** + * Return the number of present people. + */ present() { return this.documentation.participations.filter( (p) => p.absenceReason === null, ).length; }, + /** + * Get all course attendants who have an absence reason, grouped by that reason. + */ absences() { - // Get all course attendants who have an absence reason return Object.groupBy( this.documentation.participations.filter( (p) => p.absenceReason !== null, @@ -65,6 +267,48 @@ export default { ({ absenceReason }) => absenceReason.id, ); }, + /** + * Parse and combine all extraMark notes. + * + * Notes with extraMarks are grouped by ExtraMark. ExtraMarks with the showInCoursebook property set to false are ignored. + * @return An object where the keys are extraMark IDs and the values have the structure [extraMark, note1, note2, ..., noteN] + */ + extraMarkChips() { + // Apply the inner function to each participation, with value being the resulting object + return this.documentation.participations.reduce((value, p) => { + // Go through every extra mark of this participation + for (const { extraMark } of p.notesWithExtraMark) { + // Only proceed if the extraMark should be displayed here + if (!extraMark.showInCoursebook) { + continue; + } + + // value[extraMark.id] is an Array with the structure [extraMark, note1, note2, ..., noteN] + if (value[extraMark.id]) { + value[extraMark.id].push(p); + } else { + value[extraMark.id] = [ + this.extraMarks.find((e) => e.id === extraMark.id), + p, + ]; + } + } + + return value; + }, {}); + }, + /** + * Return a list Participations with a set tardiness + */ + tardyParticipations() { + return this.documentation.participations.filter((p) => p.tardiness); + }, + manageStudentsLabelKey() { + if (this.total == 0) { + return "alsijil.coursebook.notes.show_list"; + } + return ""; + }, }, }; </script> @@ -73,4 +317,9 @@ export default { .gap { gap: 0.25em; } +.main-body { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 1em; +} </style> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonSummary.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonSummary.vue index f4ef410e2f12f17d7e284178e7a2b6acc8022e66..3710a45f83c7d267ba281f95d2cbbaaae95f46f3 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonSummary.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonSummary.vue @@ -146,10 +146,15 @@ import DocumentationFullDetails from "./DocumentationFullDetails.vue"; <script> import createOrPatchMixin from "aleksis.core/mixins/createOrPatchMixin.js"; import documentationPartMixin from "./documentationPartMixin"; +import documentationCacheUpdateMixin from "./documentationCacheUpdateMixin"; export default { name: "LessonSummary", - mixins: [createOrPatchMixin, documentationPartMixin], + mixins: [ + createOrPatchMixin, + documentationCacheUpdateMixin, + documentationPartMixin, + ], emits: ["open"], data() { return { @@ -161,28 +166,6 @@ export default { }; }, methods: { - handleUpdateAfterCreateOrPatch(itemId) { - return (cached, incoming) => { - for (const object of incoming) { - console.log("summary: handleUpdateAfterCreateOrPatch", object); - // Replace the current documentation - const index = cached.findIndex( - (o) => o[itemId] === this.documentation.id, - ); - // merged with the incoming partial documentation - // if creation of proper documentation from dummy one, set ID of documentation currently being edited as oldID so that key in coursebook doesn't change - cached[index] = { - ...this.documentation, - ...object, - oldId: - this.documentation.id !== object.id - ? this.documentation.id - : this.documentation.oldId, - }; - } - return cached; - }; - }, handleAppendIconSuccess() { this.topicError = null; this.appendIcon = "$success"; diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/documentationCacheUpdateMixin.js b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/documentationCacheUpdateMixin.js new file mode 100644 index 0000000000000000000000000000000000000000..0e00a61a6cbcd5fbadbe5638a9138730acbf1369 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/documentationCacheUpdateMixin.js @@ -0,0 +1,29 @@ +/** + * Mixin to provide the cache update functionality used after creating or patching documentations + */ +export default { + methods: { + handleUpdateAfterCreateOrPatch(itemId) { + return (cached, incoming) => { + for (const object of incoming) { + console.log("summary: handleUpdateAfterCreateOrPatch", object); + // Replace the current documentation + const index = cached.findIndex( + (o) => o[itemId] === this.documentation.id, + ); + // merged with the incoming partial documentation + // if creation of proper documentation from dummy one, set ID of documentation currently being edited as oldID so that key in coursebook doesn't change + cached[index] = { + ...this.documentation, + ...object, + oldId: + this.documentation.id !== object.id + ? this.documentation.id + : this.documentation.oldId, + }; + } + return cached; + }; + }, + }, +}; diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/documentationPartMixin.js b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/documentationPartMixin.js index 88a8e852f8cc6e333303034fb5f590d174708886..2b30e38d57a9f803b56a4e0ea1c8f7c5c27dc49f 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/documentationPartMixin.js +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/documentationPartMixin.js @@ -33,6 +33,27 @@ export default { required: false, default: () => ({ attrs: {}, on: {} }), }, + /** + * Once loaded list of all extra marks to avoid excessive network and database queries + */ + extraMarks: { + type: Array, + required: true, + }, + /** + * Once loaded list of absence reasons to avoid excessive network and database queries + */ + absenceReasons: { + type: Array, + required: true, + }, + /** + * Once loaded list of subjects to avoid excessive network and database queries + */ + subjects: { + type: Array, + required: true, + }, }, computed: { @@ -46,6 +67,9 @@ export default { compact: this.compact, dialogActivator: this.dialogActivator, affectedQuery: this.affectedQuery, + extraMarks: this.extraMarks, + absenceReasons: this.absenceReasons, + subjects: this.subjects, }; }, }, diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarkNoteCheckbox.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarkNoteCheckbox.vue new file mode 100644 index 0000000000000000000000000000000000000000..e6985a1f854b9915d6effb282674b0ca9bd478f0 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarkNoteCheckbox.vue @@ -0,0 +1,104 @@ +<script> +import { + createPersonalNotes, + deletePersonalNotes, +} from "./personal_notes.graphql"; +import personalNoteRelatedMixin from "./personalNoteRelatedMixin"; +import mutateMixin from "aleksis.core/mixins/mutateMixin.js"; + +export default { + name: "ExtraMarkNoteCheckbox", + mixins: [mutateMixin, personalNoteRelatedMixin], + props: { + personalNote: { + type: Object, + default: null, + }, + /** + * Extra Mark + */ + value: { + type: Object, + required: true, + }, + }, + computed: { + model: { + get() { + return !!this.personalNote?.id; + }, + set(newValue) { + if (newValue && !this.personalNote) { + // CREATE new personal note + this.mutate( + createPersonalNotes, + { + input: [ + { + documentation: this.documentation.id, + person: this.participation.person.id, + extraMark: this.value.id, + }, + ], + }, + (storedDocumentations, incomingPersonalNotes) => { + const note = incomingPersonalNotes[0]; + const documentation = storedDocumentations.find( + (doc) => doc.id === this.documentation.id, + ); + const participationStatus = documentation.participations.find( + (part) => part.id === this.participation.id, + ); + participationStatus.notesWithExtraMark.push(note); + + return storedDocumentations; + }, + ); + } else { + // DELETE personal note + this.mutate( + deletePersonalNotes, + { + ids: [this.personalNote.id], + }, + (storedDocumentations) => { + const documentation = storedDocumentations.find( + (doc) => doc.id === this.documentation.id, + ); + const participationStatus = documentation.participations.find( + (part) => part.id === this.participation.id, + ); + const index = participationStatus.notesWithExtraMark.findIndex( + (n) => n.id === this.personalNote.id, + ); + participationStatus.notesWithExtraMark.splice(index, 1); + + return storedDocumentations; + }, + ); + } + }, + }, + }, +}; +</script> + +<template> + <v-checkbox + :label="value.name" + :value="value.id" + v-model="model" + :disabled="$attrs?.disabled || loading" + :true-value="true" + :false-value="false" + > + <template #append> + <v-progress-circular + v-if="loading" + indeterminate + :size="16" + :width="2" + ></v-progress-circular> + </template> + </v-checkbox> +</template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarksNote.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarksNote.vue new file mode 100644 index 0000000000000000000000000000000000000000..f6bed5bb8f03e7442aebad04ec01346eee801fbd --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarksNote.vue @@ -0,0 +1,28 @@ +<script> +import ExtraMarkNoteCheckbox from "./ExtraMarkNoteCheckbox.vue"; +import personalNoteRelatedMixin from "./personalNoteRelatedMixin"; + +export default { + name: "ExtraMarksNote", + components: { ExtraMarkNoteCheckbox }, + mixins: [personalNoteRelatedMixin], + props: { + value: { + type: Array, + required: true, + }, + }, +}; +</script> + +<template> + <div> + <extra-mark-note-checkbox + v-for="extraMark in extraMarks" + :key="'checkbox-extramark-' + extraMark.id" + v-bind="{ ...personalNoteRelatedProps, ...$attrs }" + :value="extraMark" + :personal-note="value.find((pn) => pn.extraMark.id === extraMark.id)" + /> + </div> +</template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNoteChip.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNoteChip.vue new file mode 100644 index 0000000000000000000000000000000000000000..5d7326894ecbd367b83ac08b385732d17e2a5310 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNoteChip.vue @@ -0,0 +1,45 @@ +<script> +export default { + name: "PersonalNoteChip", + props: { + note: { + type: Object, + required: true, + }, + loading: { + type: Boolean, + required: false, + default: false, + }, + }, + extends: "v-chip", +}; +</script> + +<template> + <v-tooltip bottom> + <template #activator="{ on, attrs }"> + <v-chip + dense + outlined + v-bind="{ ...$attrs, ...attrs }" + v-on="{ ...$listeners, ...on }" + > + <v-avatar left> + <v-icon small>mdi-note-outline</v-icon> + </v-avatar> + <slot name="prepend" /> + <slot> + <span class="text-truncate" style="max-width: 30ch"> + {{ note.note }} + </span> + </slot> + <slot name="append" /> + <v-avatar right v-if="loading"> + <v-progress-circular indeterminate :size="16" :width="2" /> + </v-avatar> + </v-chip> + </template> + <span v-text="note.note" /> + </v-tooltip> +</template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNotes.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNotes.vue new file mode 100644 index 0000000000000000000000000000000000000000..2a3d953f03484ef2af2f1ac7a8f876bcb658f8bf --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNotes.vue @@ -0,0 +1,28 @@ +<script setup> +import ExtraMarksNote from "./ExtraMarksNote.vue"; +import TextNotes from "./TextNotes.vue"; +</script> +<script> +import personalNoteRelatedMixin from "./personalNoteRelatedMixin"; + +export default { + name: "PersonalNotes", + mixins: [personalNoteRelatedMixin], +}; +</script> + +<template> + <div> + <text-notes + v-bind="personalNoteRelatedProps" + :value="participation.notesWithNote" + /> + + <extra-marks-note + v-bind="personalNoteRelatedProps" + :value="participation.notesWithExtraMark" + /> + </div> +</template> + +<style scoped></style> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue new file mode 100644 index 0000000000000000000000000000000000000000..43175c7402100c5ef9e4b84c153a8e79a9bb7f76 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue @@ -0,0 +1,164 @@ +<script> +import { + createPersonalNotes, + deletePersonalNotes, + updatePersonalNotes, +} from "./personal_notes.graphql"; +import personalNoteRelatedMixin from "./personalNoteRelatedMixin"; +import mutateMixin from "aleksis.core/mixins/mutateMixin.js"; +import DeleteDialog from "aleksis.core/components/generic/dialogs/DeleteDialog.vue"; + +export default { + name: "TextNote", + components: { DeleteDialog }, + mixins: [mutateMixin, personalNoteRelatedMixin], + props: { + value: { + type: Object, + required: true, + }, + }, + computed: { + model: { + get() { + return this.value.note; + }, + set(newValue) { + if (!newValue) { + // this is a DELETE action, show the dialog, ... + this.showDeleteConfirm = true; + return; + } + const create = !this.value.id; + + this.mutate( + create ? createPersonalNotes : updatePersonalNotes, + this.getInput( + newValue, + create + ? { + documentation: this.documentation.id, + person: this.participation.person.id, + extraMark: null, + } + : { + id: this.value.id, + }, + ), + this.getUpdater(create ? "create" : "update"), + ); + }, + }, + }, + methods: { + getInput(newValue, extras) { + return { + input: [ + { + note: newValue, + ...extras, + }, + ], + }; + }, + getUpdater(mode) { + return (storedDocumentations, incomingPersonalNotes) => { + const note = incomingPersonalNotes?.[0] || undefined; + const documentation = storedDocumentations.find( + (doc) => doc.id === this.documentation.id, + ); + const participationStatus = documentation.participations.find( + (part) => part.id === this.participation.id, + ); + switch (mode.toLowerCase()) { + case "update": + case "delete": { + const updateIndex = participationStatus.notesWithNote.findIndex( + (n) => n.id === this.value.id, + ); + if (mode === "update") { + participationStatus.notesWithNote.splice(updateIndex, 1, note); + } else { + participationStatus.notesWithNote.splice(updateIndex, 1); + } + + break; + } + + case "create": + participationStatus.notesWithNote.push(note); + + this.$emit("create"); + break; + + default: + console.error("Invalid mode in getUpdater():", mode); + break; + } + + return storedDocumentations; + }; + }, + }, + data() { + return { + showDeleteConfirm: false, + deletePersonalNotes, + }; + }, +}; +</script> + +<template> + <v-textarea + auto-grow + :rows="3" + outlined + hide-details + class="mb-4" + :label="$t('alsijil.personal_notes.note')" + :value="model" + @change="model = $event" + :loading="loading" + > + <template #append> + <v-slide-x-reverse-transition> + <v-btn + v-if="!!model" + icon + @click="showDeleteConfirm = true" + class="mt-n1-5" + > + <v-icon> $deleteContent </v-icon> + </v-btn> + </v-slide-x-reverse-transition> + + <delete-dialog + v-model="showDeleteConfirm" + :gql-delete-mutation="deletePersonalNotes" + :affected-query="affectedQuery" + item-attribute="fullName" + :items="[value]" + :custom-update="getUpdater('delete')" + > + <template #title> + {{ $t("alsijil.personal_notes.confirm_delete") }} + </template> + <template #body> + {{ + $t("alsijil.personal_notes.confirm_delete_explanation", { + note: value.note, + name: participation.person.fullName, + }) + }} + </template> + </delete-dialog> + </template> + </v-textarea> +</template> + +<style scoped> +.mt-n1-5 { + margin-top: -6px; +} +</style> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNoteCard.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNoteCard.vue new file mode 100644 index 0000000000000000000000000000000000000000..f180603b7563f36f5ecd59bcce134d586bae0bda --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNoteCard.vue @@ -0,0 +1,27 @@ +<template> + <v-card + outlined + dense + rounded="lg" + class="mb-2" + v-bind="$attrs" + v-on="$listeners" + > + <v-card-title class="text-subtitle-2 pb-1 font-weight-medium"> + {{ $t("alsijil.personal_notes.card.title") }} + </v-card-title> + <v-card-text>{{ note.note || "–" }}</v-card-text> + </v-card> +</template> + +<script> +export default { + name: "TextNoteCard", + props: { + note: { + type: Object, + required: true, + }, + }, +}; +</script> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNotes.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNotes.vue new file mode 100644 index 0000000000000000000000000000000000000000..dd32164db251b16acdc8b61daa29559b9a776fde --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNotes.vue @@ -0,0 +1,48 @@ +<script setup> +import SecondaryActionButton from "aleksis.core/components/generic/buttons/SecondaryActionButton.vue"; +import TextNote from "./TextNote.vue"; +</script> +<script> +import personalNoteRelatedMixin from "./personalNoteRelatedMixin"; + +export default { + name: "TextNotes", + mixins: [personalNoteRelatedMixin], + props: { + value: { + type: Array, + required: true, + }, + }, + data() { + return { + showNewNote: true, + }; + }, + computed: { + notes() { + return this.showNewNote ? [...this.value, { note: "" }] : this.value; + }, + }, +}; +</script> + +<template> + <div> + <text-note + v-for="note in notes" + :key="note.id || -1" + v-bind="personalNoteRelatedProps" + :value="note" + @create="showNewNote = false" + /> + + <secondary-action-button + i18n-key="alsijil.personal_notes.create_personal_note" + icon-text="$plus" + class="full-width" + @click="showNewNote = true" + :disabled="showNewNote" + /> + </div> +</template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/personalNoteRelatedMixin.js b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/personalNoteRelatedMixin.js new file mode 100644 index 0000000000000000000000000000000000000000..0eda6c4ca625afb16742d9ea8e585254d041e970 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/personalNoteRelatedMixin.js @@ -0,0 +1,19 @@ +import documentationPartMixin from "../documentation/documentationPartMixin"; + +export default { + mixins: [documentationPartMixin], + props: { + participation: { + type: Object, + required: true, + }, + }, + computed: { + personalNoteRelatedProps() { + return { + ...this.documentationPartProps, + participation: this.participation, + }; + }, + }, +}; diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/personal_notes.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/personal_notes.graphql new file mode 100644 index 0000000000000000000000000000000000000000..014178c1326960f02dee24cf92f8eb5c679298f5 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/personal_notes.graphql @@ -0,0 +1,45 @@ +query personalNotes($orderBy: [String], $filters: JSONString) { + items: personalNotes(orderBy: $orderBy, filters: $filters) { + id + note + extraMark { + id + } + canEdit + canDelete + } +} + +mutation createPersonalNotes($input: [BatchCreatePersonalNoteInput]!) { + createPersonalNotes(input: $input) { + items: personalNotes { + id + note + extraMark { + id + } + canEdit + canDelete + } + } +} + +mutation deletePersonalNotes($ids: [ID]!) { + deletePersonalNotes(ids: $ids) { + deletionCount + } +} + +mutation updatePersonalNotes($input: [BatchPatchPersonalNoteInput]!) { + updatePersonalNotes(input: $input) { + items: personalNotes { + id + note + extraMark { + id + } + canEdit + canDelete + } + } +} diff --git a/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkButtons.vue b/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkButtons.vue new file mode 100644 index 0000000000000000000000000000000000000000..919749ac85ed97f937d5b862a6aa37d199529b30 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkButtons.vue @@ -0,0 +1,73 @@ +<script> +import { extraMarks } from "./extra_marks.graphql"; + +export default { + name: "ExtraMarkButtons", + data() { + return { + extraMarks: [], + }; + }, + apollo: { + extraMarks: { + query: extraMarks, + update: (data) => data.items, + skip() { + return this.customExtraMarks > 0; + }, + }, + }, + props: { + customExtraMarks: { + type: Array, + required: false, + default: () => [], + }, + }, + computed: { + innerExtraMarks() { + if (this.customExtraMarks.length > 0) { + return this.customExtraMarks; + } else { + return this.extraMarks; + } + }, + }, + methods: { + emit(value) { + this.$emit("input", value); + this.$emit("click", value); + }, + }, +}; +</script> + +<template> + <div class="d-flex flex-wrap" style="gap: 0.5em"> + <v-skeleton-loader + class="full-width d-flex flex-wrap child-flex-grow-1" + style="gap: 0.5em" + v-if="$apollo.queries.extraMarks.loading" + type="button@4" + /> + <template v-else> + <v-btn + v-for="extraMark in innerExtraMarks" + :key="'extra-mark-' + extraMark.id" + :color="extraMark.colourBg" + :style="{ color: extraMark.colourFg }" + class="flex-grow-1" + depressed + @click="emit(extraMark.id)" + > + {{ extraMark.name }} + </v-btn> + </template> + </div> +</template> + +<style> +.child-flex-grow-1 > * { + flex-grow: 1; +} +</style> diff --git a/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkChip.vue b/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkChip.vue new file mode 100644 index 0000000000000000000000000000000000000000..da5cd4182d6f25965374934a31d64691dbdf852f --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkChip.vue @@ -0,0 +1,49 @@ +<script> +import CounterChip from "aleksis.core/components/generic/chips/CounterChip.vue"; + +export default { + name: "ExtraMarkChip", + components: { CounterChip }, + props: { + extraMark: { + type: Object, + required: true, + }, + short: { + type: Boolean, + required: false, + default: false, + }, + loading: { + type: Boolean, + required: false, + default: false, + }, + }, + extends: CounterChip, + computed: { + text() { + return this.short ? this.extraMark.shortName : this.extraMark.name; + }, + }, +}; +</script> + +<template> + <counter-chip + :color="extraMark.colourBg" + :text-color="extraMark.colourFg" + :value="extraMark.id" + :count="count" + :outlined="false" + v-bind="$attrs" + v-on="$listeners" + > + <slot name="prepend" /> + {{ text }} + <slot name="append" /> + <v-avatar right v-if="loading"> + <v-progress-circular indeterminate :size="16" :width="2" /> + </v-avatar> + </counter-chip> +</template> diff --git a/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarks.vue b/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarks.vue new file mode 100644 index 0000000000000000000000000000000000000000..9468ac1dba5d291abd251659586d24aa95fe0278 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarks.vue @@ -0,0 +1,138 @@ +<script setup> +import ColorField from "aleksis.core/components/generic/forms/ColorField.vue"; +import InlineCRUDList from "aleksis.core/components/generic/InlineCRUDList.vue"; +</script> + +<template> + <v-container> + <inline-c-r-u-d-list + :headers="headers" + :i18n-key="i18nKey" + create-item-i18n-key="alsijil.extra_marks.create" + :gql-query="gqlQuery" + :gql-create-mutation="gqlCreateMutation" + :gql-patch-mutation="gqlPatchMutation" + :gql-delete-mutation="gqlDeleteMutation" + :default-item="defaultItem" + > + <!-- eslint-disable-next-line vue/valid-v-slot --> + <template #name.field="{ attrs, on }"> + <div aria-required="true"> + <v-text-field + v-bind="attrs" + v-on="on" + :rules="$rules().required.build()" + /> + </div> + </template> + + <!-- eslint-disable-next-line vue/valid-v-slot --> + <template #shortName.field="{ attrs, on }"> + <div aria-required="true"> + <v-text-field + v-bind="attrs" + v-on="on" + :rules="$rules().required.build()" + /> + </div> + </template> + + <template #colourFg="{ item }"> + <v-chip :color="item.colourFg" outlined v-if="item.colourFg"> + {{ item.colourFg }} + </v-chip> + <span v-else>–</span> + </template> + <!-- eslint-disable-next-line vue/valid-v-slot --> + <template #colourFg.field="{ attrs, on }"> + <color-field v-bind="attrs" v-on="on" /> + </template> + + <template #colourBg="{ item }"> + <v-chip :color="item.colourBg" outlined v-if="item.colourBg"> + {{ item.colourBg }} + </v-chip> + <span v-else>–</span> + </template> + <!-- eslint-disable-next-line vue/valid-v-slot --> + <template #colourBg.field="{ attrs, on }"> + <color-field v-bind="attrs" v-on="on" /> + </template> + + <template #showInCoursebook="{ item }"> + <v-switch + :input-value="item.showInCoursebook" + disabled + inset + :false-value="false" + :true-value="true" + /> + </template> + <!-- eslint-disable-next-line vue/valid-v-slot --> + <template #showInCoursebook.field="{ attrs, on }"> + <v-switch + v-bind="attrs" + v-on="on" + inset + :false-value="false" + :true-value="true" + :hint="$t('alsijil.extra_marks.show_in_coursebook_helptext')" + persistent-hint + /> + </template> + </inline-c-r-u-d-list> + </v-container> +</template> + +<script> +import formRulesMixin from "aleksis.core/mixins/formRulesMixin.js"; +import { + extraMarks, + createExtraMarks, + deleteExtraMarks, + updateExtraMarks, +} from "./extra_marks.graphql"; + +export default { + name: "ExtraMarks", + mixins: [formRulesMixin], + data() { + return { + headers: [ + { + text: this.$t("alsijil.extra_marks.short_name"), + value: "shortName", + }, + { + text: this.$t("alsijil.extra_marks.name"), + value: "name", + }, + { + text: this.$t("alsijil.extra_marks.colour_fg"), + value: "colourFg", + }, + { + text: this.$t("alsijil.extra_marks.colour_bg"), + value: "colourBg", + }, + { + text: this.$t("alsijil.extra_marks.show_in_coursebook"), + value: "showInCoursebook", + }, + ], + i18nKey: "alsijil.extra_marks", + gqlQuery: extraMarks, + gqlCreateMutation: createExtraMarks, + gqlPatchMutation: updateExtraMarks, + gqlDeleteMutation: deleteExtraMarks, + defaultItem: { + shortName: "", + name: "", + colourFg: "", + colourBg: "", + showInCoursebook: true, + }, + }; + }, +}; +</script> diff --git a/aleksis/apps/alsijil/frontend/components/extra_marks/extra_marks.graphql b/aleksis/apps/alsijil/frontend/components/extra_marks/extra_marks.graphql new file mode 100644 index 0000000000000000000000000000000000000000..73e8ba4121c215dc4c3968b3ed2021b71b5ecfc1 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/extra_marks/extra_marks.graphql @@ -0,0 +1,48 @@ +query extraMarks($orderBy: [String], $filters: JSONString) { + items: extraMarks(orderBy: $orderBy, filters: $filters) { + id + shortName + name + colourFg + colourBg + showInCoursebook + canEdit + canDelete + } +} + +mutation createExtraMarks($input: [BatchCreateExtraMarkInput]!) { + createExtraMarks(input: $input) { + items: extraMarks { + id + shortName + name + colourFg + colourBg + showInCoursebook + canEdit + canDelete + } + } +} + +mutation deleteExtraMarks($ids: [ID]!) { + deleteExtraMarks(ids: $ids) { + deletionCount + } +} + +mutation updateExtraMarks($input: [BatchPatchExtraMarkInput]!) { + updateExtraMarks(input: $input) { + items: extraMarks { + id + shortName + name + colourFg + colourBg + showInCoursebook + canEdit + canDelete + } + } +} diff --git a/aleksis/apps/alsijil/frontend/index.js b/aleksis/apps/alsijil/frontend/index.js index c7cc473f95e134565a701d11e95afbed1dc6a7ba..e63cfc25222367f53265f4041e95879f5f4dece2 100644 --- a/aleksis/apps/alsijil/frontend/index.js +++ b/aleksis/apps/alsijil/frontend/index.js @@ -1,7 +1,4 @@ -import { - notLoggedInValidator, - hasPersonValidator, -} from "aleksis.core/routeValidators"; +import { hasPersonValidator } from "aleksis.core/routeValidators"; import { DateTime } from "luxon"; export const collectionItems = { @@ -30,45 +27,6 @@ export default { byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, }, children: [ - { - path: "extra_marks/", - component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), - name: "alsijil.extraMarks", - meta: { - inMenu: true, - titleKey: "alsijil.extra_marks.menu_title", - icon: "mdi-label-variant-outline", - iconActive: "mdi-label-variant", - permission: "alsijil.view_extramarks_rule", - }, - props: { - byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, - }, - }, - { - path: "extra_marks/create/", - component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), - name: "alsijil.createExtraMark", - props: { - byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, - }, - }, - { - path: "extra_marks/:pk(\\d+)/edit/", - component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), - name: "alsijil.editExtraMark", - props: { - byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, - }, - }, - { - path: "extra_marks/:pk(\\d+)/delete/", - component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"), - name: "alsijil.deleteExtraMark", - props: { - byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true, - }, - }, { path: "coursebook/", component: () => import("./components/coursebook/Coursebook.vue"), @@ -77,6 +35,7 @@ export default { name: "alsijil.coursebook", params: { filterType: "my", + pageType: "documentations", }, hash: "#" + DateTime.now().toISODate(), }; @@ -93,7 +52,7 @@ export default { }, children: [ { - path: ":filterType(my|all)/:objType(group|course|teacher)?/:objId(\\d+)?/", + path: ":pageType(documentations|absences)/:filterType(my|all)/:objType(group|course|teacher)?/:objId(\\d+)?/", component: () => import("./components/coursebook/Coursebook.vue"), name: "alsijil.coursebook", meta: { @@ -105,6 +64,18 @@ export default { }, ], }, + { + path: "extra_marks/", + component: () => import("./components/extra_marks/ExtraMarks.vue"), + name: "alsijil.extraMarks", + meta: { + inMenu: true, + titleKey: "alsijil.extra_marks.menu_title", + icon: "mdi-label-variant-outline", + iconActive: "mdi-label-variant", + permission: "alsijil.view_extramarks_rule", + }, + }, { path: "stats/", component: () => diff --git a/aleksis/apps/alsijil/frontend/messages/de.json b/aleksis/apps/alsijil/frontend/messages/de.json index 034f1482cb55c852f8cfbc0456cdc992a33e0b67..8966f6e068e342b876f790aae1f2dc2e00f7c2fc 100644 --- a/aleksis/apps/alsijil/frontend/messages/de.json +++ b/aleksis/apps/alsijil/frontend/messages/de.json @@ -1,4 +1,7 @@ { + "actions": { + "back_to_overview": "Zurück zur Übersicht" + }, "alsijil": { "absence": { "menu_title": "Abwesenheit eintragen" @@ -7,21 +10,55 @@ "menu_title": "Alle Stunden" }, "coursebook": { + "absences": { + "action_for_selected": "Ausgewählten Teilnehmer markieren als: | {count} ausgewählte Teilnehmer markieren als", + "button": "Abwesenheiten erfassen", + "lessons": "Keine Stunden | 1 Stunde | {count} Stunden", + "success": "Die Abwesenheiten wurden erfolgreich erfasst.", + "summary": "Zusammenfassung", + "title": "Abwesenheiten erfassen", + "warning": "Die folgenden Stunden liegen im ausgewählten Zeitraum. Bitte überprüfen Sie vor dem Bestätigen, ob Sie die Abwesenheiten für diese Stunden erfassen möchten." + }, "filter": { + "absences_exist": "Nur Stunden mit abwesenden Teilnehmenden anzeigen", "courses": "Kurse", "filter_for_obj": "Nach Gruppe und Kurs filtern", "groups": "Gruppen", "missing": "Nur unvollständige Stunden anzeigen", - "own": "Nur eigene Stunden anzeigen" + "own": "Nur eigene Stunden anzeigen", + "page_type": { + "absences": "Abwesenheiten anzeigen", + "documentations": "Dokumentationen anzeigen" + } + }, + "information": { + "subject": { + "field": "Fach bearbeiten" + } + }, + "mark_as_absent_day": { + "action_button": "Abwesenheit ausweiten", + "description": "Wollen Sie die Person(en) für den Rest des Tages als {reason} markieren?", + "title": "Fehler: keine Person | {name} erfolgreich als {reason} markiert | {n} Personen erfolgreich als {reason} markiert" }, "menu_title": "Kursbuch", "no_data": "Keine Stunden der ausgewählten Gruppen und Kurse im aktuellen Zeitraum", "no_results": "Keine Suchergebnisse für {search}", + "notes": { + "future": "Stunde ist in der Zukunft", + "show_list": "Liste der Teilnehmer*innen" + }, "notices": { "future": "Diese Stunde darf nicht bearbeitet werden, da sie in der Zukunft liegt.", "no_entry": "Für diese Stunde gibt es noch keinen Eintrag." }, "page_title": "Kursbuch für {name}", + "participation_status": "Teilnahmestatus", + "participations": { + "present": "Anwesend", + "present_number": "{present}/{total} anwesend" + }, + "present_number": "{present}/{total} anwesend", "status": { "available": "Kursbucheintrag vorhanden", "cancelled": "Stunde fällt aus", @@ -38,6 +75,7 @@ }, "homework": { "empty": "Keine Hausaufgaben", + "empty_yet": "Noch keine Hausaufgaben festgelegt.", "label": "Hausaufgaben", "value": "HA: {homework}" }, @@ -49,8 +87,9 @@ } } }, + "title_absences": "Kursbuch · Abwesenheiten", + "title_documentations": "Kursbuch", "title_plural": "Kursbuch", - "present_number": "{present}/{total} anwesend", "statistics": { "person_compact": { "title": "Kursbuch · Statistiken" @@ -64,20 +103,16 @@ "menu_title": "Entschuldigungsarten" }, "extra_marks": { - "menu_title": "Zusätzliche Markierungen", + "colour_bg": "Hintergrundfarbe", + "colour_fg": "Schriftfarbe", "create": "Markierung erstellen", + "menu_title": "Zusätzliche Markierungen", "name": "Markierung", "short_name": "Abkürzung", - "colour_fg": "Schriftfarbe", - "colour_bg": "Hintergrundfarbe", "show_in_coursebook": "In Kursbuch-Übersicht zeigen", - "show_in_coursebook_helptext": "Wenn aktiviert tauchen diese Markierungen in den Zeilen im Kursbuch auf." - }, - "personal_notes": { - "note": "Notiz", - "create_personal_note": "Weitere Notiz", - "confirm_delete": "Notiz wirklich löschen?", - "confirm_delete_explanation": "Die Notiz \"{note}\" für {name} wird entfernt." + "show_in_coursebook_helptext": "Wenn aktiviert tauchen diese Markierungen in den Zeilen im Kursbuch auf.", + "title": "Zusätzliche Markierung", + "title_plural": "Zusätzliche Markierungen" }, "group_roles": { "menu_title_assign": "Gruppenrollen zuweisen", @@ -93,6 +128,21 @@ "my_overview": { "menu_title": "Meine Übersicht" }, + "personal_notes": { + "card": { + "title": "Persönliche Notiz" + }, + "confirm_delete": "Anmerkung wirklich löschen?", + "confirm_delete_explanation": "Die Notiz \"{note}\" für {name} wird entfernt.", + "confirm_delete_tardiness": "Die Verspätung von {name} in Höhe von {tardiness} Minuten wird entfernt.", + "create_personal_note": "Weitere Notiz", + "late": "Verspätet", + "lesson_length_exceeded": "Die Verspätung überschreitet die Stundenlänge.", + "minutes_late": "pünktlich | eine Minute verspätet | {n} Minuten zu spät", + "minutes_late_current": "pünktlich (basierend auf der aktuellen Uhrzeit) | eine Minute zu spät (basierend auf der aktuellen Uhrzeit) | {n} Minuten zu spät (basierend auf der aktuellen Uhrzeit)", + "note": "Notiz", + "tardiness": "Verspätung" + }, "persons": { "menu_title": "Meine Schüler*innen" }, @@ -103,7 +153,8 @@ "plural": "Verspätungen" } }, - "actions": { - "back_to_overview": "Zurück zur Übersicht" + "time": { + "minutes": "Minuten", + "minutes_n": "keine Minuten | eine Minute | {n} Minuten" } } diff --git a/aleksis/apps/alsijil/frontend/messages/en.json b/aleksis/apps/alsijil/frontend/messages/en.json index c9e36553c1c34208c231cb008a2632967ed2283b..0f3a1bb0f7e29eaf4f44e96471187baeeb25e124 100644 --- a/aleksis/apps/alsijil/frontend/messages/en.json +++ b/aleksis/apps/alsijil/frontend/messages/en.json @@ -19,7 +19,16 @@ "menu_title": "My overview" }, "extra_marks": { - "menu_title": "Extra marks" + "menu_title": "Extra marks", + "title": "Extra mark", + "title_plural": "Extra marks", + "create": "Create Extra mark", + "name": "Mark", + "short_name": "Abbreviation", + "colour_fg": "Foreground Colour", + "colour_bg": "Background Colour", + "show_in_coursebook": "Show in Coursebook Overview", + "show_in_coursebook_helptext": "When checked, this extra mark will be displayed in the lesson summary in the coursebook" }, "excuse_types": { "menu_title": "Excuse types" @@ -39,6 +48,8 @@ "menu_title": "Coursebook", "page_title": "Coursebook for {name}", "title_plural": "Coursebook", + "title_documentations": "Coursebook", + "title_absences": "Coursebook · Absences", "status": { "available": "Documentation available", "missing": "Documentation missing", @@ -47,6 +58,7 @@ "cancelled": "Lesson cancelled", "pending": "Lesson pending" }, + "participation_status": "Participation Status", "summary": { "topic": { "label": "Topic", @@ -58,7 +70,8 @@ "homework": { "label": "Homework", "value": "HW: {homework}", - "empty": "No homework" + "empty": "No homework", + "empty_yet": "No homework defined yet." }, "group_note": { "label": "Group note", @@ -66,6 +79,10 @@ "empty": "No group note" } }, + "notes": { + "show_list": "List of participants", + "future": "Lesson is in the future" + }, "notices": { "future": "Editing this lesson isn't allowed as this lesson is in the future.", "no_entry": "There is no entry for this lesson yet." @@ -75,11 +92,54 @@ "missing": "Only show incomplete lessons", "groups": "Groups", "courses": "Courses", - "filter_for_obj": "Filter for group and course" + "filter_for_obj": "Filter for group and course", + "page_type": { + "documentations": "Show documentations", + "absences": "Show absences" + }, + "absences_exist": "Only show lessons with absent participants" + }, + "information": { + "subject": { + "field": "Edit subject" + } }, - "present_number": "{present}/{total} present", "no_data": "No lessons for the selected groups and courses in this period", "no_results": "No search results for {search}", + "participations": { + "present_number": "{present}/{total} present", + "present": "Present" + }, + "absences": { + "action_for_selected": "Mark selected participant as: | Mark {count} selected participants as", + "title": "Register absences", + "button": "Register absences", + "summary": "Summary", + "lessons": "No lessons | 1 lesson | {count} lessons", + "success": "The absences were registered successfully.", + "warning": "The following lessons are in the selected time period. Please check that you want to register the absences for these lessons before confirming." + }, + "mark_as_absent_day": { + "title": "Error: no person | Successfully marked {name} as {reason} | Successfully marked {n} people as {reason}", + "description": "Do you want to mark them as {reason} for the rest of their day?", + "action_button": "Extend absence" + } + }, + "personal_notes": { + "card": { + "title": "Personal note" + }, + "note": "Note", + "create_personal_note": "Add another note", + "tardiness": "Tardiness", + "late": "Late", + "minutes_late": "on time | one minute late | {n} minutes late", + "minutes_late_current": "on time (based on current time) | one minute late (based on current time) | {n} minutes late (based on current time)", + "lesson_length_exceeded": "The tardiness exceeds the length of the lesson", + "confirm_delete": "Delete note?", + "confirm_delete_explanation": "The note \"{note}\" for {name} will be removed.", + "confirm_delete_tardiness": "The tardiness of {tardiness} minutes will be removed for {name}.", + "no_results": "No search results for {search}", "statistics": { "person_compact": { "title": "Coursebook · Statistics" @@ -93,6 +153,10 @@ "actions": { "back_to_overview": "Back to overview" }, + "time": { + "minutes": "minutes", + "minutes_n": "no minutes | one minute | {n} minutes" + }, "group": { "tabs": { "statistics": "Coursebook Statistics", diff --git a/aleksis/apps/alsijil/frontend/messages/ru.json b/aleksis/apps/alsijil/frontend/messages/ru.json index 80cd02ad8e25ac807b4c294140f076529dafd77e..3f20ae686429082b97521d0f36ba0bdca9e6367a 100644 --- a/aleksis/apps/alsijil/frontend/messages/ru.json +++ b/aleksis/apps/alsijil/frontend/messages/ru.json @@ -1,4 +1,7 @@ { + "actions": { + "back_to_overview": "Ðазад к обзору" + }, "alsijil": { "absence": { "menu_title": "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ÑутÑтвиÑ" diff --git a/aleksis/apps/alsijil/frontend/messages/uk.json b/aleksis/apps/alsijil/frontend/messages/uk.json index 1c516bb201cf66daecc93129aa34de51f2860638..f567697a8af4deb02905af7eeaf0dd61e10c62f9 100644 --- a/aleksis/apps/alsijil/frontend/messages/uk.json +++ b/aleksis/apps/alsijil/frontend/messages/uk.json @@ -1,4 +1,7 @@ { + "actions": { + "back_to_overview": "Ðазад до оглÑду" + }, "alsijil": { "absence": { "menu_title": "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð²Ñ–Ð´ÑутноÑті" @@ -7,8 +10,17 @@ "menu_title": "УÑÑ– уроки" }, "coursebook": { + "absences": { + "action_for_selected": "Відмітити обраного відвідувача Ñк: | Відмітити {count} відвідувачів Ñк", + "button": "ЗареєÑтрувати відÑутноÑті", + "title": "ЗареєÑтрувати відÑутноÑті" + }, "filter": { + "courses": "КурÑи", "groups": "Групи" + }, + "participations": { + "present": "ПриÑутній" } }, "excuse_types": { @@ -31,6 +43,9 @@ "my_overview": { "menu_title": "Мій оглÑд" }, + "personal_notes": { + "tardiness": "ЗапізненнÑ" + }, "persons": { "menu_title": "Мої Ñтуденти" }, diff --git a/aleksis/apps/alsijil/locale/ar/LC_MESSAGES/django.po b/aleksis/apps/alsijil/locale/ar/LC_MESSAGES/django.po index 461e0f3cec97715fef05f37eae2d09b466b6e984..dcf1d42ca73b6368729531ed4b7798b1ace1f3e4 100644 --- a/aleksis/apps/alsijil/locale/ar/LC_MESSAGES/django.po +++ b/aleksis/apps/alsijil/locale/ar/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-23 21:13+0200\n" +"POT-Creation-Date: 2024-08-18 16:34+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -31,8 +31,8 @@ msgstr "" msgid "Mark as {excuse_type.name}" msgstr "" -#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:29 -#: aleksis/apps/alsijil/tables.py:53 aleksis/apps/alsijil/tables.py:78 +#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:33 +#: aleksis/apps/alsijil/tables.py:58 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:29 msgid "Delete" msgstr "" @@ -111,7 +111,7 @@ msgid "Before" msgstr "" #: aleksis/apps/alsijil/filters.py:14 aleksis/apps/alsijil/forms.py:371 -#: aleksis/apps/alsijil/models.py:471 aleksis/apps/alsijil/tables.py:116 +#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:96 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:126 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:223 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:189 @@ -152,20 +152,20 @@ msgid "You can't select a group and a teacher both." msgstr "" #: aleksis/apps/alsijil/forms.py:193 aleksis/apps/alsijil/forms.py:291 -#: aleksis/apps/alsijil/models.py:609 aleksis/apps/alsijil/models.py:658 +#: aleksis/apps/alsijil/models.py:788 aleksis/apps/alsijil/models.py:879 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:63 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:27 msgid "Person" msgstr "" #: aleksis/apps/alsijil/forms.py:194 aleksis/apps/alsijil/forms.py:372 -#: aleksis/apps/alsijil/models.py:730 +#: aleksis/apps/alsijil/models.py:960 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:64 msgid "Start date" msgstr "" #: aleksis/apps/alsijil/forms.py:195 aleksis/apps/alsijil/forms.py:373 -#: aleksis/apps/alsijil/models.py:734 +#: aleksis/apps/alsijil/models.py:964 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:65 msgid "End date" msgstr "" @@ -178,8 +178,8 @@ msgstr "" msgid "End period" msgstr "" -#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/models.py:623 -#: aleksis/apps/alsijil/tables.py:117 aleksis/apps/alsijil/tables.py:138 +#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/tables.py:97 +#: aleksis/apps/alsijil/tables.py:118 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:50 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:392 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:28 @@ -188,7 +188,7 @@ msgstr "" msgid "Absent" msgstr "" -#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:146 +#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:126 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:54 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:135 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:30 @@ -198,8 +198,8 @@ msgstr "" msgid "Excused" msgstr "" -#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:79 -#: aleksis/apps/alsijil/models.py:255 +#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:85 +#: aleksis/apps/alsijil/models.py:261 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:31 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:72 msgid "Excuse type" @@ -220,7 +220,7 @@ msgstr "" msgid "Has lesson documentation" msgstr "" -#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:130 +#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:110 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:172 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:236 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:311 @@ -228,7 +228,7 @@ msgstr "" #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:21 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:375 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:455 -#: aleksis/apps/alsijil/util/alsijil_helpers.py:330 +#: aleksis/apps/alsijil/util/alsijil_helpers.py:331 msgid "Event" msgstr "" @@ -272,41 +272,39 @@ msgstr "" msgid "Can register an absence for a person" msgstr "" -#: aleksis/apps/alsijil/models.py:58 aleksis/apps/alsijil/models.py:432 +#: aleksis/apps/alsijil/models.py:64 aleksis/apps/alsijil/models.py:438 msgid "Short name" msgstr "" -#: aleksis/apps/alsijil/models.py:59 aleksis/apps/alsijil/models.py:433 -#: aleksis/apps/alsijil/models.py:694 +#: aleksis/apps/alsijil/models.py:65 aleksis/apps/alsijil/models.py:439 +#: aleksis/apps/alsijil/models.py:924 #: aleksis/apps/alsijil/templates/alsijil/class_register/groups.html:20 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:12 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:25 msgid "Name" msgstr "" -#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/tables.py:41 +#: aleksis/apps/alsijil/models.py:69 aleksis/apps/alsijil/tables.py:21 msgid "Count as absent" msgstr "" -#: aleksis/apps/alsijil/models.py:65 +#: aleksis/apps/alsijil/models.py:71 msgid "If checked, this excuse type will be counted as a missed lesson. If not checked,it won't show up in the absence report." msgstr "" -#: aleksis/apps/alsijil/models.py:80 +#: aleksis/apps/alsijil/models.py:86 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:9 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:30 msgid "Excuse types" msgstr "" -#: aleksis/apps/alsijil/models.py:235 aleksis/apps/alsijil/models.py:334 +#: aleksis/apps/alsijil/models.py:241 aleksis/apps/alsijil/models.py:340 msgid "Year" msgstr "" -#: aleksis/apps/alsijil/models.py:260 aleksis/apps/alsijil/models.py:450 -#: aleksis/apps/alsijil/tables.py:120 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:8 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:9 +#: aleksis/apps/alsijil/models.py:266 aleksis/apps/alsijil/models.py:456 +#: aleksis/apps/alsijil/tables.py:100 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:57 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:32 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:19 @@ -314,18 +312,18 @@ msgstr "" msgid "Extra marks" msgstr "" -#: aleksis/apps/alsijil/models.py:294 +#: aleksis/apps/alsijil/models.py:300 msgid "Personal note" msgstr "" -#: aleksis/apps/alsijil/models.py:295 +#: aleksis/apps/alsijil/models.py:301 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:47 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:370 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:21 msgid "Personal notes" msgstr "" -#: aleksis/apps/alsijil/models.py:346 +#: aleksis/apps/alsijil/models.py:352 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:128 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:259 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:337 @@ -334,7 +332,7 @@ msgstr "" msgid "Lesson topic" msgstr "" -#: aleksis/apps/alsijil/models.py:347 aleksis/apps/alsijil/models.py:483 +#: aleksis/apps/alsijil/models.py:353 aleksis/apps/alsijil/models.py:491 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:129 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:265 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:342 @@ -343,7 +341,7 @@ msgstr "" msgid "Homework" msgstr "" -#: aleksis/apps/alsijil/models.py:348 +#: aleksis/apps/alsijil/models.py:354 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:130 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:271 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:346 @@ -351,293 +349,316 @@ msgstr "" msgid "Group note" msgstr "" -#: aleksis/apps/alsijil/models.py:398 +#: aleksis/apps/alsijil/models.py:404 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:16 msgid "Lesson documentation" msgstr "" -#: aleksis/apps/alsijil/models.py:399 +#: aleksis/apps/alsijil/models.py:405 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:43 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:77 msgid "Lesson documentations" msgstr "" -#: aleksis/apps/alsijil/models.py:435 +#: aleksis/apps/alsijil/models.py:441 msgid "Foreground colour" msgstr "" -#: aleksis/apps/alsijil/models.py:436 +#: aleksis/apps/alsijil/models.py:442 msgid "Background colour" msgstr "" -#: aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:444 msgid "Show in coursebook" msgstr "" -#: aleksis/apps/alsijil/models.py:449 +#: aleksis/apps/alsijil/models.py:455 msgid "Extra mark" msgstr "" -#: aleksis/apps/alsijil/models.py:467 +#: aleksis/apps/alsijil/models.py:475 msgid "Course" msgstr "" -#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:111 +#: aleksis/apps/alsijil/models.py:487 aleksis/apps/alsijil/tables.py:91 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:127 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:253 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:331 msgid "Teachers" msgstr "" -#: aleksis/apps/alsijil/models.py:482 +#: aleksis/apps/alsijil/models.py:490 msgid "Lesson Topic" msgstr "" -#: aleksis/apps/alsijil/models.py:484 +#: aleksis/apps/alsijil/models.py:492 msgid "Group Note" msgstr "" -#: aleksis/apps/alsijil/models.py:512 aleksis/apps/alsijil/models.py:619 -#: aleksis/apps/alsijil/models.py:665 +#: aleksis/apps/alsijil/models.py:496 +msgid "Participation touched at" +msgstr "" + +#: aleksis/apps/alsijil/models.py:525 aleksis/apps/alsijil/models.py:798 +#: aleksis/apps/alsijil/models.py:886 msgid "Documentation" msgstr "" -#: aleksis/apps/alsijil/models.py:513 +#: aleksis/apps/alsijil/models.py:526 msgid "Documentations" msgstr "" -#: aleksis/apps/alsijil/models.py:612 +#: aleksis/apps/alsijil/models.py:791 msgid "Groups of Person" msgstr "" -#: aleksis/apps/alsijil/models.py:625 +#: aleksis/apps/alsijil/models.py:804 msgid "Absence Reason" msgstr "" -#: aleksis/apps/alsijil/models.py:634 +#: aleksis/apps/alsijil/models.py:816 msgid "Base Absence" msgstr "" -#: aleksis/apps/alsijil/models.py:641 aleksis/apps/alsijil/models.py:642 +#: aleksis/apps/alsijil/models.py:819 aleksis/apps/alsijil/tables.py:98 +#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 +#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 +#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 +msgid "Tardiness" +msgstr "" + +#: aleksis/apps/alsijil/models.py:862 aleksis/apps/alsijil/models.py:863 msgid "Participation Status" msgstr "" -#: aleksis/apps/alsijil/models.py:670 +#: aleksis/apps/alsijil/models.py:891 msgid "Note" msgstr "" -#: aleksis/apps/alsijil/models.py:672 +#: aleksis/apps/alsijil/models.py:893 msgid "Extra Mark" msgstr "" -#: aleksis/apps/alsijil/models.py:679 +#: aleksis/apps/alsijil/models.py:900 msgid "Personal Note" msgstr "" -#: aleksis/apps/alsijil/models.py:680 +#: aleksis/apps/alsijil/models.py:901 msgid "Personal Notes" msgstr "" -#: aleksis/apps/alsijil/models.py:695 +#: aleksis/apps/alsijil/models.py:912 +msgid "A person got assigned the same extra mark multiple times per documentation." +msgstr "" + +#: aleksis/apps/alsijil/models.py:925 msgid "Icon" msgstr "" -#: aleksis/apps/alsijil/models.py:696 +#: aleksis/apps/alsijil/models.py:926 msgid "Colour" msgstr "" -#: aleksis/apps/alsijil/models.py:702 aleksis/apps/alsijil/models.py:717 +#: aleksis/apps/alsijil/models.py:932 aleksis/apps/alsijil/models.py:947 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:62 msgid "Group role" msgstr "" -#: aleksis/apps/alsijil/models.py:703 +#: aleksis/apps/alsijil/models.py:933 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:90 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:9 msgid "Group roles" msgstr "" -#: aleksis/apps/alsijil/models.py:704 +#: aleksis/apps/alsijil/models.py:934 msgid "Can assign group role" msgstr "" -#: aleksis/apps/alsijil/models.py:723 +#: aleksis/apps/alsijil/models.py:953 msgid "Assigned person" msgstr "" -#: aleksis/apps/alsijil/models.py:728 aleksis/apps/alsijil/tables.py:105 +#: aleksis/apps/alsijil/models.py:958 aleksis/apps/alsijil/tables.py:85 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:124 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:242 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:321 msgid "Groups" msgstr "" -#: aleksis/apps/alsijil/models.py:735 +#: aleksis/apps/alsijil/models.py:965 msgid "Can be left empty if end date is not clear yet" msgstr "" -#: aleksis/apps/alsijil/models.py:750 +#: aleksis/apps/alsijil/models.py:980 msgid "Group role assignment" msgstr "" -#: aleksis/apps/alsijil/models.py:751 +#: aleksis/apps/alsijil/models.py:981 msgid "Group role assignments" msgstr "" -#: aleksis/apps/alsijil/models.py:758 +#: aleksis/apps/alsijil/models.py:988 msgid "Can view lesson overview" msgstr "" -#: aleksis/apps/alsijil/models.py:759 +#: aleksis/apps/alsijil/models.py:989 msgid "Can view week overview" msgstr "" -#: aleksis/apps/alsijil/models.py:760 +#: aleksis/apps/alsijil/models.py:990 msgid "Can view full register" msgstr "" -#: aleksis/apps/alsijil/models.py:761 +#: aleksis/apps/alsijil/models.py:991 msgid "Can register absence" msgstr "" -#: aleksis/apps/alsijil/models.py:762 +#: aleksis/apps/alsijil/models.py:992 msgid "Can list all personal note filters" msgstr "" -#: aleksis/apps/alsijil/preferences.py:9 +#: aleksis/apps/alsijil/preferences.py:16 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:16 msgid "Class register" msgstr "" -#: aleksis/apps/alsijil/preferences.py:17 +#: aleksis/apps/alsijil/preferences.py:24 msgid "Block adding personal notes for cancelled lessons" msgstr "" -#: aleksis/apps/alsijil/preferences.py:25 +#: aleksis/apps/alsijil/preferences.py:32 msgid "Allow users to view their own personal notes" msgstr "" -#: aleksis/apps/alsijil/preferences.py:34 +#: aleksis/apps/alsijil/preferences.py:41 msgid "Allow primary group owners to register future absences for students in their groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:44 +#: aleksis/apps/alsijil/preferences.py:51 msgid "Grant the owner of a parent group the same privileges as the owners of the respective child groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:54 +#: aleksis/apps/alsijil/preferences.py:61 msgid "Allow original teachers to edit their lessons although they are substituted" msgstr "" -#: aleksis/apps/alsijil/preferences.py:63 +#: aleksis/apps/alsijil/preferences.py:70 msgid "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods" msgstr "" -#: aleksis/apps/alsijil/preferences.py:66 +#: aleksis/apps/alsijil/preferences.py:73 msgid "This will carry over data only if the data in the following periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:75 +#: aleksis/apps/alsijil/preferences.py:82 msgid "Allow carrying over data from any lesson period to all other lesson periods with the same lesson and in the same week" msgstr "" -#: aleksis/apps/alsijil/preferences.py:79 +#: aleksis/apps/alsijil/preferences.py:86 msgid "This will carry over data only if the data in the aforementioned periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:88 +#: aleksis/apps/alsijil/preferences.py:95 msgid "Carry over personal notes to all following lesson periods on the same day." msgstr "" -#: aleksis/apps/alsijil/preferences.py:97 +#: aleksis/apps/alsijil/preferences.py:104 msgid "Allow teachers to open lesson periods on the same day and not just at the beginning of the period" msgstr "" -#: aleksis/apps/alsijil/preferences.py:101 +#: aleksis/apps/alsijil/preferences.py:108 msgid "Lessons in the past are not affected by this setting, you can open them whenever you want." msgstr "" -#: aleksis/apps/alsijil/preferences.py:110 +#: aleksis/apps/alsijil/preferences.py:117 msgid "Allow teachers to add data for lessons in holidays" msgstr "" -#: aleksis/apps/alsijil/preferences.py:119 +#: aleksis/apps/alsijil/preferences.py:126 msgid "Allow group owners to assign group roles to the parents of the group's members" msgstr "" -#: aleksis/apps/alsijil/preferences.py:128 +#: aleksis/apps/alsijil/preferences.py:135 msgid "Show assigned group roles in week view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:129 +#: aleksis/apps/alsijil/preferences.py:136 msgid "Only week view of groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:137 +#: aleksis/apps/alsijil/preferences.py:144 msgid "Show assigned group roles in lesson view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:147 +#: aleksis/apps/alsijil/preferences.py:154 msgid "Items per page in lessons table" msgstr "" -#: aleksis/apps/alsijil/preferences.py:151 +#: aleksis/apps/alsijil/preferences.py:158 msgid "Each page must show at least one item." msgstr "" -#: aleksis/apps/alsijil/preferences.py:159 +#: aleksis/apps/alsijil/preferences.py:166 msgid "Filter lessons by existence of their lesson documentation on default" msgstr "" -#: aleksis/apps/alsijil/preferences.py:170 +#: aleksis/apps/alsijil/preferences.py:177 msgid "Allow editing of all future documentations" msgstr "" -#: aleksis/apps/alsijil/preferences.py:173 +#: aleksis/apps/alsijil/preferences.py:180 msgid "Allow editing of all documentations up to and including those on the current day" msgstr "" -#: aleksis/apps/alsijil/preferences.py:178 +#: aleksis/apps/alsijil/preferences.py:185 msgid "Allow editing of all documentations up to and including those on the current date and time" msgstr "" -#: aleksis/apps/alsijil/preferences.py:183 +#: aleksis/apps/alsijil/preferences.py:190 msgid "Set time range for which documentations may be edited" msgstr "" -#: aleksis/apps/alsijil/tables.py:23 aleksis/apps/alsijil/tables.py:47 -#: aleksis/apps/alsijil/tables.py:72 +#: aleksis/apps/alsijil/preferences.py:201 +msgid "User is allowed to register absences for members of groups the user is an owner of with these group types" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:205 +msgid "If you leave it empty, all member of groups the user is an owner of will be shown." +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:217 +msgid "Group type of groups to be shown first in the group select field on the coursebook overview page" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:220 +msgid "If you leave it empty, no group type will be used." +msgstr "" + +#: aleksis/apps/alsijil/tables.py:27 aleksis/apps/alsijil/tables.py:52 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:13 msgid "Edit" msgstr "" -#: aleksis/apps/alsijil/tables.py:96 +#: aleksis/apps/alsijil/tables.py:76 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:348 msgid "Date" msgstr "" -#: aleksis/apps/alsijil/tables.py:99 +#: aleksis/apps/alsijil/tables.py:79 #: aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html:30 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:122 msgid "Period" msgstr "" -#: aleksis/apps/alsijil/tables.py:118 -#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 -#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 -#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 -msgid "Tardiness" -msgstr "" - -#: aleksis/apps/alsijil/tables.py:119 +#: aleksis/apps/alsijil/tables.py:99 msgid "Excuse" msgstr "" -#: aleksis/apps/alsijil/tables.py:156 +#: aleksis/apps/alsijil/tables.py:136 #, python-brace-format msgid "{value}' tardiness" msgstr "" @@ -964,17 +985,6 @@ msgid "" " " msgstr "" -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:7 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:14 -msgid "Create extra mark" -msgstr "" - -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:7 -msgid "Edit extra mark" -msgstr "" - #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:9 #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:16 #, python-format @@ -1468,98 +1478,86 @@ msgstr "" msgid "Notes" msgstr "" -#: aleksis/apps/alsijil/views.py:114 +#: aleksis/apps/alsijil/views.py:112 msgid "You either selected an invalid lesson or there is currently no lesson in progress." msgstr "" -#: aleksis/apps/alsijil/views.py:147 +#: aleksis/apps/alsijil/views.py:145 msgid "You are not allowed to create a lesson documentation for a lesson in the future." msgstr "" -#: aleksis/apps/alsijil/views.py:264 +#: aleksis/apps/alsijil/views.py:262 msgid "The lesson documentation has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:298 +#: aleksis/apps/alsijil/views.py:296 msgid "The personal notes have been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:658 +#: aleksis/apps/alsijil/views.py:656 msgid "Generate full register printout for {}" msgstr "" -#: aleksis/apps/alsijil/views.py:659 +#: aleksis/apps/alsijil/views.py:657 msgid "Generate full register printout …" msgstr "" -#: aleksis/apps/alsijil/views.py:660 +#: aleksis/apps/alsijil/views.py:658 msgid "The printout has been generated successfully." msgstr "" -#: aleksis/apps/alsijil/views.py:661 +#: aleksis/apps/alsijil/views.py:659 msgid "There was a problem while generating the printout." msgstr "" -#: aleksis/apps/alsijil/views.py:664 +#: aleksis/apps/alsijil/views.py:662 msgid "Download PDF" msgstr "" -#: aleksis/apps/alsijil/views.py:1030 +#: aleksis/apps/alsijil/views.py:1028 msgid "The absence has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1051 +#: aleksis/apps/alsijil/views.py:1049 msgid "The personal note has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1074 -msgid "The extra mark has been created." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1086 -msgid "The extra mark has been saved." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1097 -msgid "The extra mark has been deleted." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1119 +#: aleksis/apps/alsijil/views.py:1072 msgid "The excuse type has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1131 +#: aleksis/apps/alsijil/views.py:1084 msgid "The excuse type has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1142 +#: aleksis/apps/alsijil/views.py:1095 msgid "The excuse type has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1164 +#: aleksis/apps/alsijil/views.py:1117 msgid "The group role has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1176 +#: aleksis/apps/alsijil/views.py:1129 msgid "The group role has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1187 +#: aleksis/apps/alsijil/views.py:1140 msgid "The group role has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1221 aleksis/apps/alsijil/views.py:1253 +#: aleksis/apps/alsijil/views.py:1174 aleksis/apps/alsijil/views.py:1206 msgid "The group role has been assigned." msgstr "" -#: aleksis/apps/alsijil/views.py:1272 +#: aleksis/apps/alsijil/views.py:1225 msgid "The group role assignment has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1293 +#: aleksis/apps/alsijil/views.py:1246 msgid "The group role assignment has been stopped." msgstr "" -#: aleksis/apps/alsijil/views.py:1306 +#: aleksis/apps/alsijil/views.py:1259 msgid "The group role assignment has been deleted." msgstr "" diff --git a/aleksis/apps/alsijil/locale/de_DE/LC_MESSAGES/django.po b/aleksis/apps/alsijil/locale/de_DE/LC_MESSAGES/django.po index 8f5aa6cf99694bfd5f1220819de95475f837bfca..32ea0b2793090ad547ce81871145a6d11216904e 100644 --- a/aleksis/apps/alsijil/locale/de_DE/LC_MESSAGES/django.po +++ b/aleksis/apps/alsijil/locale/de_DE/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-23 21:13+0200\n" -"PO-Revision-Date: 2024-04-23 19:39+0000\n" +"POT-Creation-Date: 2024-08-18 16:34+0200\n" +"PO-Revision-Date: 2024-08-19 09:46+0000\n" "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" "Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis-app-alsijil/de/>\n" "Language: de_DE\n" @@ -31,8 +31,8 @@ msgstr "Als unentschuldigt markieren" msgid "Mark as {excuse_type.name}" msgstr "Als {excuse_type.name} markieren" -#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:29 -#: aleksis/apps/alsijil/tables.py:53 aleksis/apps/alsijil/tables.py:78 +#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:33 +#: aleksis/apps/alsijil/tables.py:58 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:29 msgid "Delete" msgstr "Löschen" @@ -43,8 +43,12 @@ msgstr "{} bittet Sie, einige Klassenbucheinträge zu überprüfen." #: aleksis/apps/alsijil/actions.py:86 #, python-brace-format -msgid "We have successfully sent notifications to {count_teachers} persons for {count_items} lessons." -msgstr "Wir haben erfolgreich Benachrichtigungen an {count_teachers} Personen für {count_items} Stunden gesendet." +msgid "" +"We have successfully sent notifications to {count_teachers} persons for " +"{count_items} lessons." +msgstr "" +"Wir haben erfolgreich Benachrichtigungen an {count_teachers} Personen für " +"{count_items} Stunden gesendet." #: aleksis/apps/alsijil/actions.py:92 msgid "Ask teacher to check data" @@ -64,7 +68,9 @@ msgstr "Persönliche Notiz zurücksetzen" #: aleksis/apps/alsijil/data_checks.py:49 msgid "Ensure that there are no personal notes in cancelled lessons" -msgstr "Sicherstellen, dass es keine persönlichen Notizen in ausgefallenen Stunden gibt" +msgstr "" +"Sicherstellen, dass es keine persönlichen Notizen in ausgefallenen Stunden " +"gibt" #: aleksis/apps/alsijil/data_checks.py:50 msgid "The personal note is related to a cancelled lesson." @@ -72,7 +78,9 @@ msgstr "Die persönliche Notiz ist einer ausgefallenen Stunde zugeordnet." #: aleksis/apps/alsijil/data_checks.py:77 msgid "Ensure that 'groups_of_person' is set for every personal note" -msgstr "Sicherstellen, dass \"groups_of_person\" für alle persönlichen Notizen gesetzt ist" +msgstr "" +"Sicherstellen, dass \"groups_of_person\" für alle persönlichen Notizen " +"gesetzt ist" #: aleksis/apps/alsijil/data_checks.py:78 msgid "The personal note has no group in 'groups_of_person'." @@ -80,7 +88,9 @@ msgstr "Die persönliche Notiz hat keine Gruppe in \"groups_of_person\"." #: aleksis/apps/alsijil/data_checks.py:103 msgid "Ensure that there are no filled out lesson documentations on holidays" -msgstr "Sicherstellen, dass es keine ausgefüllten Stundendokumentationen in den Ferien gibt" +msgstr "" +"Sicherstellen, dass es keine ausgefüllten Stundendokumentationen in den " +"Ferien gibt" #: aleksis/apps/alsijil/data_checks.py:104 msgid "The lesson documentation is on holidays." @@ -88,7 +98,9 @@ msgstr "Die Stundendokumentation ist in den Ferien." #: aleksis/apps/alsijil/data_checks.py:137 msgid "Ensure that there are no filled out personal notes on holidays" -msgstr "Sicherstellen, dass es keine ausgefüllten persönlichen Notizen in den Ferien gibt" +msgstr "" +"Sicherstellen, dass es keine ausgefüllten persönlichen Notizen in den Ferien " +"gibt" #: aleksis/apps/alsijil/data_checks.py:138 msgid "The personal note is on holidays." @@ -96,11 +108,14 @@ msgstr "Die persönliche Notiz ist in den Ferien." #: aleksis/apps/alsijil/data_checks.py:166 msgid "Ensure that there are no excused personal notes without an absence" -msgstr "Sicherstellen, dass es keine entschuldigten persönlichen Notizen ohne eine Absenz gibt" +msgstr "" +"Sicherstellen, dass es keine entschuldigten persönlichen Notizen ohne eine " +"Absenz gibt" #: aleksis/apps/alsijil/data_checks.py:167 msgid "The personal note is marked as excused, but not as absent." -msgstr "Die persönliche Notiz ist als entschuldigt, aber nicht als abwesend markiert." +msgstr "" +"Die persönliche Notiz ist als entschuldigt, aber nicht als abwesend markiert." #: aleksis/apps/alsijil/filters.py:12 msgid "After" @@ -111,11 +126,12 @@ msgid "Before" msgstr "Bevor" #: aleksis/apps/alsijil/filters.py:14 aleksis/apps/alsijil/forms.py:371 -#: aleksis/apps/alsijil/models.py:471 aleksis/apps/alsijil/tables.py:116 +#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:96 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:126 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:223 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:189 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:220 +#: aleksis/apps/alsijil/models.py:478 msgid "Subject" msgstr "Fach" @@ -133,7 +149,9 @@ msgstr "Hausaufgabe zur nächsten Stunde" #: aleksis/apps/alsijil/forms.py:53 msgid "Carry over data to all other lessons with the same subject in this week" -msgstr "Daten zu allen weiteren Stunden mit dem gleichen Fach in dieser Woche übernehmen" +msgstr "" +"Daten zu allen weiteren Stunden mit dem gleichen Fach in dieser Woche " +"übernehmen" #: aleksis/apps/alsijil/forms.py:98 aleksis/apps/alsijil/forms.py:278 #: aleksis/apps/alsijil/forms.py:370 @@ -149,24 +167,28 @@ msgstr "Lehrkraft" #: aleksis/apps/alsijil/forms.py:121 msgid "You can't select a group and a teacher both." -msgstr "Es kann nur entweder eine Gruppe oder eine Lehrkraft ausgewählt werden." +msgstr "" +"Es kann nur entweder eine Gruppe oder eine Lehrkraft ausgewählt werden." #: aleksis/apps/alsijil/forms.py:193 aleksis/apps/alsijil/forms.py:291 -#: aleksis/apps/alsijil/models.py:609 aleksis/apps/alsijil/models.py:658 +#: aleksis/apps/alsijil/models.py:788 aleksis/apps/alsijil/models.py:879 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:63 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:27 +#: aleksis/apps/alsijil/models.py:763 aleksis/apps/alsijil/models.py:822 msgid "Person" msgstr "Person" #: aleksis/apps/alsijil/forms.py:194 aleksis/apps/alsijil/forms.py:372 -#: aleksis/apps/alsijil/models.py:730 +#: aleksis/apps/alsijil/models.py:960 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:64 +#: aleksis/apps/alsijil/models.py:903 msgid "Start date" msgstr "Startdatum" #: aleksis/apps/alsijil/forms.py:195 aleksis/apps/alsijil/forms.py:373 -#: aleksis/apps/alsijil/models.py:734 +#: aleksis/apps/alsijil/models.py:964 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:65 +#: aleksis/apps/alsijil/models.py:907 msgid "End date" msgstr "Enddatum" @@ -178,8 +200,8 @@ msgstr "Startstunde" msgid "End period" msgstr "Endstunde" -#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/models.py:623 -#: aleksis/apps/alsijil/tables.py:117 aleksis/apps/alsijil/tables.py:138 +#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/tables.py:97 +#: aleksis/apps/alsijil/tables.py:118 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:50 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:392 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:28 @@ -188,7 +210,7 @@ msgstr "Endstunde" msgid "Absent" msgstr "Abwesend" -#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:146 +#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:126 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:54 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:135 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:30 @@ -198,10 +220,11 @@ msgstr "Abwesend" msgid "Excused" msgstr "Entschuldigt" -#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:79 -#: aleksis/apps/alsijil/models.py:255 +#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:85 +#: aleksis/apps/alsijil/models.py:261 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:31 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:72 +#: aleksis/apps/alsijil/models.py:84 aleksis/apps/alsijil/models.py:260 msgid "Excuse type" msgstr "Entschuldigungsart" @@ -220,7 +243,7 @@ msgstr "Schuljahr" msgid "Has lesson documentation" msgstr "Hat eine Stunden-Dokumentation" -#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:130 +#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:110 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:172 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:236 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:311 @@ -228,6 +251,7 @@ msgstr "Hat eine Stunden-Dokumentation" #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:21 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:375 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:455 +#: aleksis/apps/alsijil/util/alsijil_helpers.py:331 #: aleksis/apps/alsijil/util/alsijil_helpers.py:330 msgid "Event" msgstr "Veranstaltung" @@ -272,372 +296,499 @@ msgstr "Kann eine Gruppenrolle für diese Gruppe zuweisen" msgid "Can register an absence for a person" msgstr "Kann eine Absenz für eine Person registrieren" -#: aleksis/apps/alsijil/models.py:58 aleksis/apps/alsijil/models.py:432 +#: aleksis/apps/alsijil/models.py:64 aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/models.py:437 msgid "Short name" msgstr "Kurzname" -#: aleksis/apps/alsijil/models.py:59 aleksis/apps/alsijil/models.py:433 -#: aleksis/apps/alsijil/models.py:694 +#: aleksis/apps/alsijil/models.py:65 aleksis/apps/alsijil/models.py:439 +#: aleksis/apps/alsijil/models.py:924 #: aleksis/apps/alsijil/templates/alsijil/class_register/groups.html:20 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:12 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:25 msgid "Name" msgstr "Name" -#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/tables.py:41 +#: aleksis/apps/alsijil/models.py:69 aleksis/apps/alsijil/tables.py:21 +#: aleksis/apps/alsijil/models.py:68 msgid "Count as absent" msgstr "Als abwesend zählen" -#: aleksis/apps/alsijil/models.py:65 -msgid "If checked, this excuse type will be counted as a missed lesson. If not checked,it won't show up in the absence report." -msgstr "Wenn ausgewählt wird diese Entschuldigungsart als eine verpasste Stunde gezählt. Wenn nicht ausgewählt wird es nicht im Abwesenheitsbericht auftauchen." +#: aleksis/apps/alsijil/models.py:71 aleksis/apps/alsijil/models.py:70 +msgid "" +"If checked, this excuse type will be counted as a missed lesson. If not " +"checked,it won't show up in the absence report." +msgstr "" +"Wenn ausgewählt wird diese Entschuldigungsart als eine verpasste Stunde " +"gezählt. Wenn nicht ausgewählt wird es nicht im Abwesenheitsbericht " +"auftauchen." -#: aleksis/apps/alsijil/models.py:80 +#: aleksis/apps/alsijil/models.py:86 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:9 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:30 +#: aleksis/apps/alsijil/models.py:85 msgid "Excuse types" msgstr "Entschuldigungsarten" -#: aleksis/apps/alsijil/models.py:235 aleksis/apps/alsijil/models.py:334 +#: aleksis/apps/alsijil/models.py:241 aleksis/apps/alsijil/models.py:340 +#: aleksis/apps/alsijil/models.py:240 aleksis/apps/alsijil/models.py:339 msgid "Year" msgstr "Jahr" -#: aleksis/apps/alsijil/models.py:260 aleksis/apps/alsijil/models.py:450 -#: aleksis/apps/alsijil/tables.py:120 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:8 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:9 +#: aleksis/apps/alsijil/models.py:266 aleksis/apps/alsijil/models.py:456 +#: aleksis/apps/alsijil/tables.py:100 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:57 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:32 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:19 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:331 +#: aleksis/apps/alsijil/models.py:265 aleksis/apps/alsijil/models.py:455 msgid "Extra marks" msgstr "Zusätzliche Markierungen" -#: aleksis/apps/alsijil/models.py:294 +#: aleksis/apps/alsijil/models.py:300 aleksis/apps/alsijil/models.py:299 msgid "Personal note" msgstr "Persönliche Notiz" -#: aleksis/apps/alsijil/models.py:295 +#: aleksis/apps/alsijil/models.py:301 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:47 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:370 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:21 +#: aleksis/apps/alsijil/models.py:300 msgid "Personal notes" msgstr "Persönliche Notizen" -#: aleksis/apps/alsijil/models.py:346 +#: aleksis/apps/alsijil/models.py:352 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:128 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:259 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:337 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:25 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:421 +#: aleksis/apps/alsijil/models.py:351 msgid "Lesson topic" msgstr "Stundenthema" -#: aleksis/apps/alsijil/models.py:347 aleksis/apps/alsijil/models.py:483 +#: aleksis/apps/alsijil/models.py:353 aleksis/apps/alsijil/models.py:491 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:129 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:265 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:342 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:33 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:422 +#: aleksis/apps/alsijil/models.py:352 aleksis/apps/alsijil/models.py:490 msgid "Homework" msgstr "Hausaufgaben" -#: aleksis/apps/alsijil/models.py:348 +#: aleksis/apps/alsijil/models.py:354 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:130 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:271 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:346 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:41 +#: aleksis/apps/alsijil/models.py:353 msgid "Group note" msgstr "Gruppennotiz" -#: aleksis/apps/alsijil/models.py:398 +#: aleksis/apps/alsijil/models.py:404 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:16 +#: aleksis/apps/alsijil/models.py:403 msgid "Lesson documentation" msgstr "Stunden-Dokumentation" -#: aleksis/apps/alsijil/models.py:399 +#: aleksis/apps/alsijil/models.py:405 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:43 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:77 +#: aleksis/apps/alsijil/models.py:404 msgid "Lesson documentations" msgstr "Stunden-Dokumentationen" -#: aleksis/apps/alsijil/models.py:435 +#: aleksis/apps/alsijil/models.py:441 aleksis/apps/alsijil/models.py:440 msgid "Foreground colour" msgstr "Vordergrundfarbe" -#: aleksis/apps/alsijil/models.py:436 +#: aleksis/apps/alsijil/models.py:442 aleksis/apps/alsijil/models.py:441 msgid "Background colour" msgstr "Hintergrundfarbe" -#: aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:444 aleksis/apps/alsijil/models.py:443 msgid "Show in coursebook" msgstr "In Kursbuch anzeigen" -#: aleksis/apps/alsijil/models.py:449 +#: aleksis/apps/alsijil/models.py:455 aleksis/apps/alsijil/models.py:454 msgid "Extra mark" msgstr "Zusätzliche Markierung" -#: aleksis/apps/alsijil/models.py:467 +#: aleksis/apps/alsijil/models.py:475 aleksis/apps/alsijil/models.py:474 msgid "Course" msgstr "Kurs" -#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:111 +#: aleksis/apps/alsijil/models.py:487 aleksis/apps/alsijil/tables.py:91 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:127 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:253 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:331 +#: aleksis/apps/alsijil/models.py:486 msgid "Teachers" msgstr "Lehrkräfte" -#: aleksis/apps/alsijil/models.py:482 +#: aleksis/apps/alsijil/models.py:490 aleksis/apps/alsijil/models.py:489 msgid "Lesson Topic" msgstr "Stundenthema" -#: aleksis/apps/alsijil/models.py:484 +#: aleksis/apps/alsijil/models.py:492 aleksis/apps/alsijil/models.py:491 msgid "Group Note" msgstr "Gruppennotiz" -#: aleksis/apps/alsijil/models.py:512 aleksis/apps/alsijil/models.py:619 -#: aleksis/apps/alsijil/models.py:665 +#: aleksis/apps/alsijil/models.py:496 aleksis/apps/alsijil/models.py:495 +msgid "Participation touched at" +msgstr "Teilnahmestatus angelegt am" + +#: aleksis/apps/alsijil/models.py:525 aleksis/apps/alsijil/models.py:798 +#: aleksis/apps/alsijil/models.py:886 aleksis/apps/alsijil/models.py:524 +#: aleksis/apps/alsijil/models.py:773 aleksis/apps/alsijil/models.py:829 msgid "Documentation" msgstr "Dokumentation" -#: aleksis/apps/alsijil/models.py:513 +#: aleksis/apps/alsijil/models.py:526 aleksis/apps/alsijil/models.py:525 msgid "Documentations" msgstr "Dokumentationen" -#: aleksis/apps/alsijil/models.py:612 +#: aleksis/apps/alsijil/models.py:791 aleksis/apps/alsijil/models.py:766 msgid "Groups of Person" msgstr "Gruppen der Person" -#: aleksis/apps/alsijil/models.py:625 +#: aleksis/apps/alsijil/models.py:804 aleksis/apps/alsijil/models.py:779 msgid "Absence Reason" msgstr "Abwesenheitsgrund" -#: aleksis/apps/alsijil/models.py:634 +#: aleksis/apps/alsijil/models.py:816 aleksis/apps/alsijil/models.py:791 msgid "Base Absence" msgstr "Basis-Abwesenheit" -#: aleksis/apps/alsijil/models.py:641 aleksis/apps/alsijil/models.py:642 +#: aleksis/apps/alsijil/models.py:819 aleksis/apps/alsijil/tables.py:98 +#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 +#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 +#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 +#: aleksis/apps/alsijil/models.py:794 +msgid "Tardiness" +msgstr "Verspätung" + +#: aleksis/apps/alsijil/models.py:862 aleksis/apps/alsijil/models.py:863 +#: aleksis/apps/alsijil/models.py:805 aleksis/apps/alsijil/models.py:806 msgid "Participation Status" msgstr "Teilnahmestatus" -#: aleksis/apps/alsijil/models.py:670 +#: aleksis/apps/alsijil/models.py:891 aleksis/apps/alsijil/models.py:834 msgid "Note" msgstr "Notiz" -#: aleksis/apps/alsijil/models.py:672 +#: aleksis/apps/alsijil/models.py:893 aleksis/apps/alsijil/models.py:836 msgid "Extra Mark" msgstr "Zusätzliche Markierung" -#: aleksis/apps/alsijil/models.py:679 +#: aleksis/apps/alsijil/models.py:900 aleksis/apps/alsijil/models.py:843 msgid "Personal Note" msgstr "Persönliche Notiz" -#: aleksis/apps/alsijil/models.py:680 +#: aleksis/apps/alsijil/models.py:901 aleksis/apps/alsijil/models.py:844 msgid "Personal Notes" msgstr "Persönliche Notizen" -#: aleksis/apps/alsijil/models.py:695 +#: aleksis/apps/alsijil/models.py:912 aleksis/apps/alsijil/models.py:855 +msgid "" +"A person got assigned the same extra mark multiple times per documentation." +msgstr "" +"Eine Person hat die gleiche zusätzliche Markierung für eine Dokumentation " +"mehrfach zugeordnet bekommen." + +#: aleksis/apps/alsijil/models.py:925 aleksis/apps/alsijil/models.py:868 msgid "Icon" msgstr "Symbol" -#: aleksis/apps/alsijil/models.py:696 +#: aleksis/apps/alsijil/models.py:926 aleksis/apps/alsijil/models.py:869 msgid "Colour" msgstr "Farbe" -#: aleksis/apps/alsijil/models.py:702 aleksis/apps/alsijil/models.py:717 +#: aleksis/apps/alsijil/models.py:932 aleksis/apps/alsijil/models.py:947 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:62 +#: aleksis/apps/alsijil/models.py:875 aleksis/apps/alsijil/models.py:890 msgid "Group role" msgstr "Gruppenrolle" -#: aleksis/apps/alsijil/models.py:703 +#: aleksis/apps/alsijil/models.py:933 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:90 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:9 +#: aleksis/apps/alsijil/models.py:876 msgid "Group roles" msgstr "Gruppenrollen" -#: aleksis/apps/alsijil/models.py:704 +#: aleksis/apps/alsijil/models.py:934 aleksis/apps/alsijil/models.py:877 msgid "Can assign group role" msgstr "Kann Gruppenrolle zuweisen" -#: aleksis/apps/alsijil/models.py:723 +#: aleksis/apps/alsijil/models.py:953 aleksis/apps/alsijil/models.py:896 msgid "Assigned person" msgstr "Zugewiesene Person" -#: aleksis/apps/alsijil/models.py:728 aleksis/apps/alsijil/tables.py:105 +#: aleksis/apps/alsijil/models.py:958 aleksis/apps/alsijil/tables.py:85 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:124 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:242 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:321 +#: aleksis/apps/alsijil/models.py:901 msgid "Groups" msgstr "Gruppen" -#: aleksis/apps/alsijil/models.py:735 +#: aleksis/apps/alsijil/models.py:965 aleksis/apps/alsijil/models.py:908 msgid "Can be left empty if end date is not clear yet" msgstr "Kann frei gelassen werden, wenn das Enddatum noch nicht feststeht" -#: aleksis/apps/alsijil/models.py:750 +#: aleksis/apps/alsijil/models.py:980 aleksis/apps/alsijil/models.py:923 msgid "Group role assignment" msgstr "Zuweisung von Gruppenrollen" -#: aleksis/apps/alsijil/models.py:751 +#: aleksis/apps/alsijil/models.py:981 aleksis/apps/alsijil/models.py:924 msgid "Group role assignments" msgstr "Zuweisungen von Gruppenrollen" -#: aleksis/apps/alsijil/models.py:758 +#: aleksis/apps/alsijil/models.py:988 aleksis/apps/alsijil/models.py:931 msgid "Can view lesson overview" msgstr "Kann die Stundenübersicht sehen" -#: aleksis/apps/alsijil/models.py:759 +#: aleksis/apps/alsijil/models.py:989 aleksis/apps/alsijil/models.py:932 msgid "Can view week overview" msgstr "Kann die Wochenübersicht sehen" -#: aleksis/apps/alsijil/models.py:760 +#: aleksis/apps/alsijil/models.py:990 aleksis/apps/alsijil/models.py:933 msgid "Can view full register" msgstr "Kann komplettes Klassenbuch sehen" -#: aleksis/apps/alsijil/models.py:761 +#: aleksis/apps/alsijil/models.py:991 aleksis/apps/alsijil/models.py:934 msgid "Can register absence" msgstr "Kann eine Absenz registrieren" -#: aleksis/apps/alsijil/models.py:762 +#: aleksis/apps/alsijil/models.py:992 aleksis/apps/alsijil/models.py:935 msgid "Can list all personal note filters" msgstr "Kann alle Filter für persönliche Notizen anzeigen" -#: aleksis/apps/alsijil/preferences.py:9 +#: aleksis/apps/alsijil/preferences.py:16 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:16 +#: aleksis/apps/alsijil/preferences.py:9 msgid "Class register" msgstr "Klassenbuch" +#: aleksis/apps/alsijil/preferences.py:24 #: aleksis/apps/alsijil/preferences.py:17 msgid "Block adding personal notes for cancelled lessons" -msgstr "Blockiere das Hinzufügen von persönlichen Notizen für ausgefallene Stunden" +msgstr "" +"Blockiere das Hinzufügen von persönlichen Notizen für ausgefallene Stunden" +#: aleksis/apps/alsijil/preferences.py:32 #: aleksis/apps/alsijil/preferences.py:25 msgid "Allow users to view their own personal notes" msgstr "Erlaube Benutzern, ihre eigenen persönlichen Notizen zu sehen" +#: aleksis/apps/alsijil/preferences.py:41 #: aleksis/apps/alsijil/preferences.py:34 -msgid "Allow primary group owners to register future absences for students in their groups" -msgstr "Erlaube Primärgruppeninhabern Absenzen in der Zukunft für Mitglieder ihrer Gruppen zu registrieren" +msgid "" +"Allow primary group owners to register future absences for students in their " +"groups" +msgstr "" +"Erlaube Primärgruppeninhabern Absenzen in der Zukunft für Mitglieder ihrer " +"Gruppen zu registrieren" +#: aleksis/apps/alsijil/preferences.py:51 #: aleksis/apps/alsijil/preferences.py:44 -msgid "Grant the owner of a parent group the same privileges as the owners of the respective child groups" -msgstr "Gebe dem Besitzer einer Elterngruppe die gleichen Rechte wie den Besitzern der entsprechenden Kindgruppen" +msgid "" +"Grant the owner of a parent group the same privileges as the owners of the " +"respective child groups" +msgstr "" +"Gebe dem Besitzer einer Elterngruppe die gleichen Rechte wie den Besitzern " +"der entsprechenden Kindgruppen" +#: aleksis/apps/alsijil/preferences.py:61 #: aleksis/apps/alsijil/preferences.py:54 -msgid "Allow original teachers to edit their lessons although they are substituted" -msgstr "Erlaube den Ursprungslehrkräften, ihre Stunden zu bearbeiten, obwohl sie vertreten worden sind" +msgid "" +"Allow original teachers to edit their lessons although they are substituted" +msgstr "" +"Erlaube den Ursprungslehrkräften, ihre Stunden zu bearbeiten, obwohl sie " +"vertreten worden sind" +#: aleksis/apps/alsijil/preferences.py:70 #: aleksis/apps/alsijil/preferences.py:63 -msgid "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods" +msgid "" +"Carry over data from first lesson period to the following lesson periods in " +"lessons over multiple periods" msgstr "Daten von der ersten Stunde zu weiteren folgenden Stunden übernehmen" +#: aleksis/apps/alsijil/preferences.py:73 #: aleksis/apps/alsijil/preferences.py:66 -msgid "This will carry over data only if the data in the following periods are empty." -msgstr "Dies wird die Daten nur übernehmen, wenn die Daten in den Folgestunden leer sind." +msgid "" +"This will carry over data only if the data in the following periods are " +"empty." +msgstr "" +"Dies wird die Daten nur übernehmen, wenn die Daten in den Folgestunden leer " +"sind." +#: aleksis/apps/alsijil/preferences.py:82 #: aleksis/apps/alsijil/preferences.py:75 -msgid "Allow carrying over data from any lesson period to all other lesson periods with the same lesson and in the same week" -msgstr "Erlaube das Übernehmen von Daten von einer Stunde zu allen weiteren Stunden mit dem gleichen Unterricht in der gleichen Woche" +msgid "" +"Allow carrying over data from any lesson period to all other " +"lesson periods with the same lesson and in the same week" +msgstr "" +"Erlaube das Übernehmen von Daten von einer Stunde zu allen weiteren Stunden " +"mit dem gleichen Unterricht in der gleichen Woche" +#: aleksis/apps/alsijil/preferences.py:86 #: aleksis/apps/alsijil/preferences.py:79 -msgid "This will carry over data only if the data in the aforementioned periods are empty." -msgstr "Dies wird die Daten nur übernehmen, wenn die Daten in den eben genannten Stunden leer sind." +msgid "" +"This will carry over data only if the data in the aforementioned periods are " +"empty." +msgstr "" +"Dies wird die Daten nur übernehmen, wenn die Daten in den eben genannten " +"Stunden leer sind." +#: aleksis/apps/alsijil/preferences.py:95 #: aleksis/apps/alsijil/preferences.py:88 -msgid "Carry over personal notes to all following lesson periods on the same day." -msgstr "Persönliche Notizen in alle folgenden Unterrichtsstunden am gleichen Tag übernehmen." +msgid "" +"Carry over personal notes to all following lesson periods on the same day." +msgstr "" +"Persönliche Notizen in alle folgenden Unterrichtsstunden am gleichen Tag " +"übernehmen." +#: aleksis/apps/alsijil/preferences.py:104 #: aleksis/apps/alsijil/preferences.py:97 -msgid "Allow teachers to open lesson periods on the same day and not just at the beginning of the period" -msgstr "Erlaube Lehrkräften, Unterrichtsstunden bereits am gleichen Tag und nicht erst zu Beginn der Stunde zu öffnen" +msgid "" +"Allow teachers to open lesson periods on the same day and not just at the " +"beginning of the period" +msgstr "" +"Erlaube Lehrkräften, Unterrichtsstunden bereits am gleichen Tag und nicht " +"erst zu Beginn der Stunde zu öffnen" +#: aleksis/apps/alsijil/preferences.py:108 #: aleksis/apps/alsijil/preferences.py:101 -msgid "Lessons in the past are not affected by this setting, you can open them whenever you want." -msgstr "Unterrichtsstunden in der Vergangenheit werden nicht durch diese Einstellung beeinflusst, sie können immer geöffnet werden." +msgid "" +"Lessons in the past are not affected by this setting, you can open them " +"whenever you want." +msgstr "" +"Unterrichtsstunden in der Vergangenheit werden nicht durch diese Einstellung " +"beeinflusst, sie können immer geöffnet werden." +#: aleksis/apps/alsijil/preferences.py:117 #: aleksis/apps/alsijil/preferences.py:110 msgid "Allow teachers to add data for lessons in holidays" msgstr "Lehrkräften erlauben, Daten für Stunden in den Ferien hinzuzufügen" +#: aleksis/apps/alsijil/preferences.py:126 #: aleksis/apps/alsijil/preferences.py:119 -msgid "Allow group owners to assign group roles to the parents of the group's members" -msgstr "Erlaube Gruppenbesitzern, Gruppenrollen für Eltern von Gruppenmitgliedern zuzuweisen" +msgid "" +"Allow group owners to assign group roles to the parents of the group's " +"members" +msgstr "" +"Erlaube Gruppenbesitzern, Gruppenrollen für Eltern von Gruppenmitgliedern " +"zuzuweisen" +#: aleksis/apps/alsijil/preferences.py:135 #: aleksis/apps/alsijil/preferences.py:128 msgid "Show assigned group roles in week view" msgstr "Zugewiesene Gruppenrollen in der Wochenansicht zeigen" +#: aleksis/apps/alsijil/preferences.py:136 #: aleksis/apps/alsijil/preferences.py:129 msgid "Only week view of groups" msgstr "Nur Wochenansicht von Gruppen" +#: aleksis/apps/alsijil/preferences.py:144 #: aleksis/apps/alsijil/preferences.py:137 msgid "Show assigned group roles in lesson view" msgstr "Zugewiesene Gruppenrollen in der Stundenansicht anzeigen" +#: aleksis/apps/alsijil/preferences.py:154 #: aleksis/apps/alsijil/preferences.py:147 msgid "Items per page in lessons table" msgstr "Einträge pro Seite in der Stundentabelle" +#: aleksis/apps/alsijil/preferences.py:158 #: aleksis/apps/alsijil/preferences.py:151 msgid "Each page must show at least one item." msgstr "Jede Seite muss mindestens einen Eintrag anzeigen." +#: aleksis/apps/alsijil/preferences.py:166 #: aleksis/apps/alsijil/preferences.py:159 msgid "Filter lessons by existence of their lesson documentation on default" -msgstr "Stunden standardmäßig anhand der Existenz ihrer Stundendokumentation filtern" +msgstr "" +"Stunden standardmäßig anhand der Existenz ihrer Stundendokumentation filtern" +#: aleksis/apps/alsijil/preferences.py:177 #: aleksis/apps/alsijil/preferences.py:170 msgid "Allow editing of all future documentations" msgstr "Bearbeiten von allen zukünftigen Dokumentationen erlauben" +#: aleksis/apps/alsijil/preferences.py:180 #: aleksis/apps/alsijil/preferences.py:173 -msgid "Allow editing of all documentations up to and including those on the current day" -msgstr "Bearbeiten von allen Dokumentationen bis inklusive zum aktuellen Tag erlauben" +msgid "" +"Allow editing of all documentations up to and including those on the current " +"day" +msgstr "" +"Bearbeiten von allen Dokumentationen bis inklusive zum aktuellen Tag erlauben" +#: aleksis/apps/alsijil/preferences.py:185 #: aleksis/apps/alsijil/preferences.py:178 -msgid "Allow editing of all documentations up to and including those on the current date and time" -msgstr "Bearbeiten von allen Dokumentationen bis inklusive zum aktuellen Tag und zur aktuellen Uhrzeit erlauben" +msgid "" +"Allow editing of all documentations up to and including those on the current " +"date and time" +msgstr "" +"Bearbeiten von allen Dokumentationen bis inklusive zum aktuellen Tag und zur " +"aktuellen Uhrzeit erlauben" +#: aleksis/apps/alsijil/preferences.py:190 #: aleksis/apps/alsijil/preferences.py:183 msgid "Set time range for which documentations may be edited" msgstr "Zeitraum setzen, in dem Dokumentationen bearbeitet werden dürfen" -#: aleksis/apps/alsijil/tables.py:23 aleksis/apps/alsijil/tables.py:47 -#: aleksis/apps/alsijil/tables.py:72 +#: aleksis/apps/alsijil/preferences.py:201 +msgid "" +"User is allowed to register absences for members of groups the user is an " +"owner of with these group types" +msgstr "Benutzer*innen dürfen Abwesenheiten für Mitglieder von Gruppen mit diesen Gruppentypen, in denen sie Besitzer*innen sind, registrieren" + +#: aleksis/apps/alsijil/preferences.py:205 +msgid "" +"If you leave it empty, all member of groups the user is an owner of will be " +"shown." +msgstr "Wenn Sie es leer lassen, werden alle Mitglieder von Gruppen angezeigt, in denen Benutzer*innen Besitzer*innen sind." + +#: aleksis/apps/alsijil/preferences.py:217 +msgid "" +"Group type of groups to be shown first in the group select field on the " +"coursebook overview page" +msgstr "Gruppentyp von Gruppen, die zuerst im Gruppenauswahlfeld auf der Kursbuchübersichtsseite angezeigt werden" + +#: aleksis/apps/alsijil/preferences.py:220 +msgid "If you leave it empty, no group type will be used." +msgstr "Wenn Sie es leer lassen, wird kein Gruppentyp benutzt." + +#: aleksis/apps/alsijil/tables.py:27 aleksis/apps/alsijil/tables.py:52 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:13 msgid "Edit" msgstr "Bearbeiten" -#: aleksis/apps/alsijil/tables.py:96 +#: aleksis/apps/alsijil/tables.py:76 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:348 msgid "Date" msgstr "Datum" -#: aleksis/apps/alsijil/tables.py:99 +#: aleksis/apps/alsijil/tables.py:79 #: aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html:30 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:122 msgid "Period" msgstr "Stunde" -#: aleksis/apps/alsijil/tables.py:118 -#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 -#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 -#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 -msgid "Tardiness" -msgstr "Verspätung" - -#: aleksis/apps/alsijil/tables.py:119 +#: aleksis/apps/alsijil/tables.py:99 msgid "Excuse" msgstr "Entschuldigen" -#: aleksis/apps/alsijil/tables.py:156 +#: aleksis/apps/alsijil/tables.py:136 #, python-brace-format msgid "{value}' tardiness" msgstr "{value}' Verspätung" @@ -717,11 +868,13 @@ msgstr " %(count)s betroffene Stunden " #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:40 msgid "" "\n" -" There are no affected lessons. Registering this absence won't have any effect.\n" +" There are no affected lessons. Registering this absence " +"won't have any effect.\n" " " msgstr "" "\n" -" Es gibt keine betroffenen Stunden. Das Eintragen dieser Abwesenheit wird keinen Effekt haben.\n" +" Es gibt keine betroffenen Stunden. Das Eintragen dieser " +"Abwesenheit wird keinen Effekt haben.\n" " " #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:57 @@ -819,7 +972,8 @@ msgid "" " " msgstr "" "\n" -" Diese Stunde ist in den Ferien und kann somit nicht bearbeitet werden.\n" +" Diese Stunde ist in den Ferien und kann somit nicht " +"bearbeitet werden.\n" " " #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:10 @@ -882,7 +1036,7 @@ msgstr "Statistiken zu Fehlzeiten, Verspätungen und Bemerkungen" #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:82 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:291 msgid "Absences" -msgstr "Fehlstunden" +msgstr "Abwesenheiten" #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:133 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:139 @@ -958,11 +1112,13 @@ msgstr "Keine Stunden verfügbar" #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:434 msgid "" "\n" -" There are no lessons for the selected group or teacher in this week.\n" +" There are no lessons for the selected group or teacher in this " +"week.\n" " " msgstr "" "\n" -" Es gibt keine Stunden für die ausgewählte Gruppe oder Lehrkraft in dieser Woche.\n" +" Es gibt keine Stunden für die ausgewählte Gruppe oder Lehrkraft " +"in dieser Woche.\n" " " #: aleksis/apps/alsijil/templates/alsijil/excuse_type/create.html:6 @@ -980,26 +1136,20 @@ msgstr "Entschuldigungsart bearbeiten" #: aleksis/apps/alsijil/templates/alsijil/group_role/warning.html:4 msgid "" "\n" -" This function should only be used to define alternatives to the default excuse which also will be counted extra.\n" -" Don't use this to create a default excuse or if you don't divide between different types of excuse.\n" +" This function should only be used to define alternatives to the default " +"excuse which also will be counted extra.\n" +" Don't use this to create a default excuse or if you don't divide between " +"different types of excuse.\n" " " msgstr "" "\n" -" Diese Funktion sollte nur benutzt werden, um Alternativen zur normalen Entschuldigung, welche von sich aus extra gezählt wird, zu definieren.\n" -"Benutzen Sie diese Funktion nicht, um eine Entschuldigungsart für normale Entschuldigungen zu erstellen oder wenn Sie nicht zwischen verschiedenen Entschuldigungsarten unterscheiden möchten.\n" +" Diese Funktion sollte nur benutzt werden, um Alternativen zur normalen " +"Entschuldigung, welche von sich aus extra gezählt wird, zu definieren.\n" +"Benutzen Sie diese Funktion nicht, um eine Entschuldigungsart für normale " +"Entschuldigungen zu erstellen oder wenn Sie nicht zwischen verschiedenen " +"Entschuldigungsarten unterscheiden möchten.\n" " " -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:7 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:14 -msgid "Create extra mark" -msgstr "Zusätzliche Markierung erstellen" - -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:7 -msgid "Edit extra mark" -msgstr "Zusätzliche Markierung bearbeiten" - #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:9 #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:16 #, python-format @@ -1065,12 +1215,14 @@ msgstr "Niemand zugewiesen." #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assigned_roles.html:41 msgid "" "\n" -" You can get some additional actions for each group role assignment if you click on the name of the\n" +" You can get some additional actions for each group role assignment if " +"you click on the name of the\n" " corresponding person.\n" " " msgstr "" "\n" -" Sie können zusätzliche Aktionen für jede Gruppenrollenzuweisung aufrufen, \n" +" Sie können zusätzliche Aktionen für jede Gruppenrollenzuweisung " +"aufrufen, \n" "wenn Sie auf den Namen der entsprechenden Person klicken.\n" " " @@ -1079,8 +1231,12 @@ msgid "Stop" msgstr "Beenden" #: aleksis/apps/alsijil/templates/alsijil/notifications/check.html:1 -msgid "Please check if the following class register entries are complete and correct:" -msgstr "Bitte prüfen Sie, ob die folgenden Klassenbucheinträge komplett und richtig sind:" +msgid "" +"Please check if the following class register entries are complete and " +"correct:" +msgstr "" +"Bitte prüfen Sie, ob die folgenden Klassenbucheinträge komplett und richtig " +"sind:" #: aleksis/apps/alsijil/templates/alsijil/partials/absences.html:6 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:22 @@ -1240,13 +1396,17 @@ msgstr "" #, python-format msgid "" "\n" -" This seating plan is taken from the parent group of %(child_group)s.\n" -" If you want, you can take it over for your group and then customize it.\n" +" This seating plan is taken from the parent group of " +"%(child_group)s.\n" +" If you want, you can take it over for your group and then " +"customize it.\n" " " msgstr "" "\n" -" Dieser Sitzplan wurde von der Elterngruppe von %(child_group)s übernommen.\n" -"Wenn Sie wollen, können Sie ihn für Ihre Gruppe übernehmen und dann anpassen.\n" +" Dieser Sitzplan wurde von der Elterngruppe von %(child_group)s " +"übernommen.\n" +"Wenn Sie wollen, können Sie ihn für Ihre Gruppe übernehmen und dann " +"anpassen.\n" " " #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/seating_plan.html:30 @@ -1265,11 +1425,13 @@ msgstr "Es gibt keinen Sitzplan für diese Stunde." #, python-format msgid "" "\n" -" Create a new seating plan for %(group)s (%(subject)s) in %(room)s\n" +" Create a new seating plan for %(group)s (%(subject)s) in " +"%(room)s\n" " " msgstr "" "\n" -" Einen neuen Sitzplan für %(group)s (%(subject)s) in %(room)s erstellen\n" +" Einen neuen Sitzplan für %(group)s (%(subject)s) in " +"%(room)s erstellen\n" " " #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/seating_plan.html:78 @@ -1280,7 +1442,8 @@ msgid "" " " msgstr "" "\n" -" Einen neuen Sitzplan für %(group)s in %(room)s erstellen\n" +" Einen neuen Sitzplan für %(group)s in %(room)s " +"erstellen\n" " " #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:6 @@ -1387,8 +1550,10 @@ msgid "" " " msgstr "" "\n" -" Kopien des Klassenbuches, sowohl digital als auch als Ausdruck, dürfen\n" -" ausschließlich in der Schule und/oder auf von der Schule autorisierten Geräten\n" +" Kopien des Klassenbuches, sowohl digital als auch als Ausdruck, " +"dürfen\n" +" ausschließlich in der Schule und/oder auf von der Schule " +"autorisierten Geräten\n" " gespeichert werden.\n" " " @@ -1400,7 +1565,8 @@ msgid "" " " msgstr "" "\n" -" Die Leitung der Gruppe sowie die Schulleitung bestätigen die obigen Hinweise sowie\n" +" Die Leitung der Gruppe sowie die Schulleitung bestätigen die obigen " +"Hinweise sowie\n" " die Richtigkeit des Ausdrucks.\n" " " @@ -1532,104 +1698,113 @@ msgstr "KW" msgid "Notes" msgstr "Notizen" -#: aleksis/apps/alsijil/views.py:114 -msgid "You either selected an invalid lesson or there is currently no lesson in progress." +#: aleksis/apps/alsijil/views.py:112 +msgid "" +"You either selected an invalid lesson or there is currently no lesson in " +"progress." msgstr "" "Sie haben eine ungültige Stunde ausgewählt oder es\n" " läuft momentan keine Stunde." -#: aleksis/apps/alsijil/views.py:147 -msgid "You are not allowed to create a lesson documentation for a lesson in the future." -msgstr "Ihnen ist es nicht erlaubt, eine Eintragung für eine Unterrichtsstunde in der Zukunft vorzunehmen." +#: aleksis/apps/alsijil/views.py:145 +msgid "" +"You are not allowed to create a lesson documentation for a lesson in the " +"future." +msgstr "" +"Ihnen ist es nicht erlaubt, eine Eintragung für eine Unterrichtsstunde in " +"der Zukunft vorzunehmen." -#: aleksis/apps/alsijil/views.py:264 +#: aleksis/apps/alsijil/views.py:262 msgid "The lesson documentation has been saved." msgstr "Die Stunden-Dokumentation wurde gespeichert." -#: aleksis/apps/alsijil/views.py:298 +#: aleksis/apps/alsijil/views.py:296 msgid "The personal notes have been saved." msgstr "Die persönlichen Notizen wurden gespeichert." -#: aleksis/apps/alsijil/views.py:658 +#: aleksis/apps/alsijil/views.py:656 msgid "Generate full register printout for {}" msgstr "Vollständigen Klassenbuchausdruck für {} generieren" -#: aleksis/apps/alsijil/views.py:659 +#: aleksis/apps/alsijil/views.py:657 msgid "Generate full register printout …" msgstr "Vollständigen Klassenbuchausdruck generieren …" -#: aleksis/apps/alsijil/views.py:660 +#: aleksis/apps/alsijil/views.py:658 msgid "The printout has been generated successfully." msgstr "Der Ausdruck wurde erfolgreich generiert." -#: aleksis/apps/alsijil/views.py:661 +#: aleksis/apps/alsijil/views.py:659 msgid "There was a problem while generating the printout." msgstr "Es ist ein Fehler beim Generieren des Ausdrucks aufgetreten." -#: aleksis/apps/alsijil/views.py:664 +#: aleksis/apps/alsijil/views.py:662 msgid "Download PDF" msgstr "PDF herunterladen" -#: aleksis/apps/alsijil/views.py:1030 +#: aleksis/apps/alsijil/views.py:1028 msgid "The absence has been saved." msgstr "Die Abwesenheit wurde gespeichert." -#: aleksis/apps/alsijil/views.py:1051 +#: aleksis/apps/alsijil/views.py:1049 msgid "The personal note has been deleted." msgstr "Die persönliche Notiz wurde gelöscht." -#: aleksis/apps/alsijil/views.py:1074 -msgid "The extra mark has been created." -msgstr "Die zusätzliche Markierung wurde erstellt." - -#: aleksis/apps/alsijil/views.py:1086 -msgid "The extra mark has been saved." -msgstr "Die zusätzliche Markierung wurde gespeichert." - -#: aleksis/apps/alsijil/views.py:1097 -msgid "The extra mark has been deleted." -msgstr "Die zusätzliche Markierung wurde gelöscht." - -#: aleksis/apps/alsijil/views.py:1119 +#: aleksis/apps/alsijil/views.py:1072 msgid "The excuse type has been created." msgstr "Die Entschuldigungsart wurde erstellt." -#: aleksis/apps/alsijil/views.py:1131 +#: aleksis/apps/alsijil/views.py:1084 msgid "The excuse type has been saved." msgstr "Die Entschuldigunsart wurde gespeichert." -#: aleksis/apps/alsijil/views.py:1142 +#: aleksis/apps/alsijil/views.py:1095 msgid "The excuse type has been deleted." msgstr "Die Entschuldigungsart wurde gelöscht." -#: aleksis/apps/alsijil/views.py:1164 +#: aleksis/apps/alsijil/views.py:1117 msgid "The group role has been created." msgstr "Die Gruppenrolle wurde erstellt." -#: aleksis/apps/alsijil/views.py:1176 +#: aleksis/apps/alsijil/views.py:1129 msgid "The group role has been saved." msgstr "Die Gruppenrolle wurde gespeichert." -#: aleksis/apps/alsijil/views.py:1187 +#: aleksis/apps/alsijil/views.py:1140 msgid "The group role has been deleted." msgstr "Die Gruppenrolle wurde gelöscht." -#: aleksis/apps/alsijil/views.py:1221 aleksis/apps/alsijil/views.py:1253 +#: aleksis/apps/alsijil/views.py:1174 aleksis/apps/alsijil/views.py:1206 msgid "The group role has been assigned." msgstr "Die Gruppenrolle wurde zugewiesen." -#: aleksis/apps/alsijil/views.py:1272 +#: aleksis/apps/alsijil/views.py:1225 msgid "The group role assignment has been saved." msgstr "Die Gruppenrollenzuweisung wurde gespeichert." -#: aleksis/apps/alsijil/views.py:1293 +#: aleksis/apps/alsijil/views.py:1246 msgid "The group role assignment has been stopped." msgstr "Die Gruppenrollenzuweisung wurde beendet." -#: aleksis/apps/alsijil/views.py:1306 +#: aleksis/apps/alsijil/views.py:1259 msgid "The group role assignment has been deleted." msgstr "Die Gruppenrollenzuweisung wurde gelöscht." +#~ msgid "Create extra mark" +#~ msgstr "Zusätzliche Markierung erstellen" + +#~ msgid "Edit extra mark" +#~ msgstr "Zusätzliche Markierung bearbeiten" + +#~ msgid "The extra mark has been created." +#~ msgstr "Die zusätzliche Markierung wurde erstellt." + +#~ msgid "The extra mark has been saved." +#~ msgstr "Die zusätzliche Markierung wurde gespeichert." + +#~ msgid "The extra mark has been deleted." +#~ msgstr "Die zusätzliche Markierung wurde gelöscht." + #~ msgid "Current lesson" #~ msgstr "Aktuelle Unterrichtsstunde" diff --git a/aleksis/apps/alsijil/locale/fr/LC_MESSAGES/django.po b/aleksis/apps/alsijil/locale/fr/LC_MESSAGES/django.po index e283f3797931d09214dbc06954730515b45eda92..37bfd8669e34b3235d3f1de6bbd93d5402b9aacf 100644 --- a/aleksis/apps/alsijil/locale/fr/LC_MESSAGES/django.po +++ b/aleksis/apps/alsijil/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-23 21:13+0200\n" +"POT-Creation-Date: 2024-08-18 16:34+0200\n" "PO-Revision-Date: 2021-06-16 11:59+0000\n" "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" "Language-Team: French <https://translate.edugit.org/projects/aleksis/aleksis-app-alsijil/fr/>\n" @@ -33,8 +33,8 @@ msgstr "Injustifié(e)" msgid "Mark as {excuse_type.name}" msgstr "" -#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:29 -#: aleksis/apps/alsijil/tables.py:53 aleksis/apps/alsijil/tables.py:78 +#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:33 +#: aleksis/apps/alsijil/tables.py:58 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:29 msgid "Delete" msgstr "" @@ -123,7 +123,7 @@ msgid "Before" msgstr "" #: aleksis/apps/alsijil/filters.py:14 aleksis/apps/alsijil/forms.py:371 -#: aleksis/apps/alsijil/models.py:471 aleksis/apps/alsijil/tables.py:116 +#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:96 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:126 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:223 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:189 @@ -168,20 +168,20 @@ msgid "You can't select a group and a teacher both." msgstr "" #: aleksis/apps/alsijil/forms.py:193 aleksis/apps/alsijil/forms.py:291 -#: aleksis/apps/alsijil/models.py:609 aleksis/apps/alsijil/models.py:658 +#: aleksis/apps/alsijil/models.py:788 aleksis/apps/alsijil/models.py:879 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:63 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:27 msgid "Person" msgstr "Personne" #: aleksis/apps/alsijil/forms.py:194 aleksis/apps/alsijil/forms.py:372 -#: aleksis/apps/alsijil/models.py:730 +#: aleksis/apps/alsijil/models.py:960 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:64 msgid "Start date" msgstr "Date de début" #: aleksis/apps/alsijil/forms.py:195 aleksis/apps/alsijil/forms.py:373 -#: aleksis/apps/alsijil/models.py:734 +#: aleksis/apps/alsijil/models.py:964 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:65 msgid "End date" msgstr "Date de fin" @@ -198,8 +198,8 @@ msgstr "De la période" msgid "End period" msgstr "De la période" -#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/models.py:623 -#: aleksis/apps/alsijil/tables.py:117 aleksis/apps/alsijil/tables.py:138 +#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/tables.py:97 +#: aleksis/apps/alsijil/tables.py:118 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:50 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:392 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:28 @@ -208,7 +208,7 @@ msgstr "De la période" msgid "Absent" msgstr "Absent(e)" -#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:146 +#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:126 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:54 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:135 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:30 @@ -218,8 +218,8 @@ msgstr "Absent(e)" msgid "Excused" msgstr "Excusé" -#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:79 -#: aleksis/apps/alsijil/models.py:255 +#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:85 +#: aleksis/apps/alsijil/models.py:261 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:31 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:72 #, fuzzy @@ -244,7 +244,7 @@ msgstr "" msgid "Has lesson documentation" msgstr "Documentation de cours" -#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:130 +#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:110 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:172 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:236 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:311 @@ -252,7 +252,7 @@ msgstr "Documentation de cours" #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:21 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:375 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:455 -#: aleksis/apps/alsijil/util/alsijil_helpers.py:330 +#: aleksis/apps/alsijil/util/alsijil_helpers.py:331 msgid "Event" msgstr "" @@ -306,29 +306,29 @@ msgstr "" msgid "Can register an absence for a person" msgstr "Registre de la classe" -#: aleksis/apps/alsijil/models.py:58 aleksis/apps/alsijil/models.py:432 +#: aleksis/apps/alsijil/models.py:64 aleksis/apps/alsijil/models.py:438 #, fuzzy #| msgid "First name" msgid "Short name" msgstr "Prénom" -#: aleksis/apps/alsijil/models.py:59 aleksis/apps/alsijil/models.py:433 -#: aleksis/apps/alsijil/models.py:694 +#: aleksis/apps/alsijil/models.py:65 aleksis/apps/alsijil/models.py:439 +#: aleksis/apps/alsijil/models.py:924 #: aleksis/apps/alsijil/templates/alsijil/class_register/groups.html:20 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:12 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:25 msgid "Name" msgstr "" -#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/tables.py:41 +#: aleksis/apps/alsijil/models.py:69 aleksis/apps/alsijil/tables.py:21 msgid "Count as absent" msgstr "" -#: aleksis/apps/alsijil/models.py:65 +#: aleksis/apps/alsijil/models.py:71 msgid "If checked, this excuse type will be counted as a missed lesson. If not checked,it won't show up in the absence report." msgstr "" -#: aleksis/apps/alsijil/models.py:80 +#: aleksis/apps/alsijil/models.py:86 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:9 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:30 @@ -337,14 +337,12 @@ msgstr "" msgid "Excuse types" msgstr "Excusé" -#: aleksis/apps/alsijil/models.py:235 aleksis/apps/alsijil/models.py:334 +#: aleksis/apps/alsijil/models.py:241 aleksis/apps/alsijil/models.py:340 msgid "Year" msgstr "" -#: aleksis/apps/alsijil/models.py:260 aleksis/apps/alsijil/models.py:450 -#: aleksis/apps/alsijil/tables.py:120 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:8 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:9 +#: aleksis/apps/alsijil/models.py:266 aleksis/apps/alsijil/models.py:456 +#: aleksis/apps/alsijil/tables.py:100 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:57 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:32 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:19 @@ -352,20 +350,20 @@ msgstr "" msgid "Extra marks" msgstr "" -#: aleksis/apps/alsijil/models.py:294 +#: aleksis/apps/alsijil/models.py:300 #, fuzzy #| msgid "Personal notes" msgid "Personal note" msgstr "Notes personnelles" -#: aleksis/apps/alsijil/models.py:295 +#: aleksis/apps/alsijil/models.py:301 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:47 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:370 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:21 msgid "Personal notes" msgstr "Notes personnelles" -#: aleksis/apps/alsijil/models.py:346 +#: aleksis/apps/alsijil/models.py:352 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:128 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:259 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:337 @@ -374,7 +372,7 @@ msgstr "Notes personnelles" msgid "Lesson topic" msgstr "Sujet de cours" -#: aleksis/apps/alsijil/models.py:347 aleksis/apps/alsijil/models.py:483 +#: aleksis/apps/alsijil/models.py:353 aleksis/apps/alsijil/models.py:491 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:129 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:265 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:342 @@ -383,7 +381,7 @@ msgstr "Sujet de cours" msgid "Homework" msgstr "Devoirs" -#: aleksis/apps/alsijil/models.py:348 +#: aleksis/apps/alsijil/models.py:354 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:130 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:271 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:346 @@ -393,12 +391,12 @@ msgstr "Devoirs" msgid "Group note" msgstr "Groupe" -#: aleksis/apps/alsijil/models.py:398 +#: aleksis/apps/alsijil/models.py:404 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:16 msgid "Lesson documentation" msgstr "Documentation de cours" -#: aleksis/apps/alsijil/models.py:399 +#: aleksis/apps/alsijil/models.py:405 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:43 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:77 #, fuzzy @@ -406,118 +404,136 @@ msgstr "Documentation de cours" msgid "Lesson documentations" msgstr "Documentation de cours" -#: aleksis/apps/alsijil/models.py:435 +#: aleksis/apps/alsijil/models.py:441 msgid "Foreground colour" msgstr "" -#: aleksis/apps/alsijil/models.py:436 +#: aleksis/apps/alsijil/models.py:442 msgid "Background colour" msgstr "" -#: aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:444 msgid "Show in coursebook" msgstr "" -#: aleksis/apps/alsijil/models.py:449 +#: aleksis/apps/alsijil/models.py:455 msgid "Extra mark" msgstr "" -#: aleksis/apps/alsijil/models.py:467 +#: aleksis/apps/alsijil/models.py:475 msgid "Course" msgstr "" -#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:111 +#: aleksis/apps/alsijil/models.py:487 aleksis/apps/alsijil/tables.py:91 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:127 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:253 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:331 msgid "Teachers" msgstr "Profs" -#: aleksis/apps/alsijil/models.py:482 +#: aleksis/apps/alsijil/models.py:490 #, fuzzy #| msgid "Lesson topic" msgid "Lesson Topic" msgstr "Sujet de cours" -#: aleksis/apps/alsijil/models.py:484 +#: aleksis/apps/alsijil/models.py:492 #, fuzzy #| msgid "Group" msgid "Group Note" msgstr "Groupe" -#: aleksis/apps/alsijil/models.py:512 aleksis/apps/alsijil/models.py:619 -#: aleksis/apps/alsijil/models.py:665 +#: aleksis/apps/alsijil/models.py:496 +msgid "Participation touched at" +msgstr "" + +#: aleksis/apps/alsijil/models.py:525 aleksis/apps/alsijil/models.py:798 +#: aleksis/apps/alsijil/models.py:886 #, fuzzy #| msgid "Lesson documentation" msgid "Documentation" msgstr "Documentation de cours" -#: aleksis/apps/alsijil/models.py:513 +#: aleksis/apps/alsijil/models.py:526 #, fuzzy #| msgid "Lesson documentation" msgid "Documentations" msgstr "Documentation de cours" -#: aleksis/apps/alsijil/models.py:612 +#: aleksis/apps/alsijil/models.py:791 #, fuzzy #| msgid "Group" msgid "Groups of Person" msgstr "Groupe" -#: aleksis/apps/alsijil/models.py:625 +#: aleksis/apps/alsijil/models.py:804 #, fuzzy #| msgid "Absences" msgid "Absence Reason" msgstr "Absences" -#: aleksis/apps/alsijil/models.py:634 +#: aleksis/apps/alsijil/models.py:816 #, fuzzy #| msgid "Absences" msgid "Base Absence" msgstr "Absences" -#: aleksis/apps/alsijil/models.py:641 aleksis/apps/alsijil/models.py:642 +#: aleksis/apps/alsijil/models.py:819 aleksis/apps/alsijil/tables.py:98 +#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 +#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 +#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 +msgid "Tardiness" +msgstr "Retard" + +#: aleksis/apps/alsijil/models.py:862 aleksis/apps/alsijil/models.py:863 msgid "Participation Status" msgstr "" -#: aleksis/apps/alsijil/models.py:670 +#: aleksis/apps/alsijil/models.py:891 #, fuzzy #| msgid "Notes" msgid "Note" msgstr "Notes" -#: aleksis/apps/alsijil/models.py:672 +#: aleksis/apps/alsijil/models.py:893 msgid "Extra Mark" msgstr "" -#: aleksis/apps/alsijil/models.py:679 +#: aleksis/apps/alsijil/models.py:900 #, fuzzy #| msgid "Personal notes" msgid "Personal Note" msgstr "Notes personnelles" -#: aleksis/apps/alsijil/models.py:680 +#: aleksis/apps/alsijil/models.py:901 #, fuzzy #| msgid "Personal notes" msgid "Personal Notes" msgstr "Notes personnelles" -#: aleksis/apps/alsijil/models.py:695 +#: aleksis/apps/alsijil/models.py:912 +msgid "A person got assigned the same extra mark multiple times per documentation." +msgstr "" + +#: aleksis/apps/alsijil/models.py:925 msgid "Icon" msgstr "" -#: aleksis/apps/alsijil/models.py:696 +#: aleksis/apps/alsijil/models.py:926 msgid "Colour" msgstr "" -#: aleksis/apps/alsijil/models.py:702 aleksis/apps/alsijil/models.py:717 +#: aleksis/apps/alsijil/models.py:932 aleksis/apps/alsijil/models.py:947 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:62 #, fuzzy #| msgid "Group" msgid "Group role" msgstr "Groupe" -#: aleksis/apps/alsijil/models.py:703 +#: aleksis/apps/alsijil/models.py:933 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:90 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:9 @@ -526,19 +542,19 @@ msgstr "Groupe" msgid "Group roles" msgstr "Groupe" -#: aleksis/apps/alsijil/models.py:704 +#: aleksis/apps/alsijil/models.py:934 #, fuzzy #| msgid "Persons in group" msgid "Can assign group role" msgstr "Personnes en groupe" -#: aleksis/apps/alsijil/models.py:723 +#: aleksis/apps/alsijil/models.py:953 #, fuzzy #| msgid "Absences" msgid "Assigned person" msgstr "Absences" -#: aleksis/apps/alsijil/models.py:728 aleksis/apps/alsijil/tables.py:105 +#: aleksis/apps/alsijil/models.py:958 aleksis/apps/alsijil/tables.py:85 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:124 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:242 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:321 @@ -547,183 +563,188 @@ msgstr "Absences" msgid "Groups" msgstr "Groupe" -#: aleksis/apps/alsijil/models.py:735 +#: aleksis/apps/alsijil/models.py:965 msgid "Can be left empty if end date is not clear yet" msgstr "" -#: aleksis/apps/alsijil/models.py:750 +#: aleksis/apps/alsijil/models.py:980 msgid "Group role assignment" msgstr "" -#: aleksis/apps/alsijil/models.py:751 +#: aleksis/apps/alsijil/models.py:981 msgid "Group role assignments" msgstr "" -#: aleksis/apps/alsijil/models.py:758 +#: aleksis/apps/alsijil/models.py:988 #, fuzzy #| msgid "Personal overview" msgid "Can view lesson overview" msgstr "Vue d'ensemble personnelle" -#: aleksis/apps/alsijil/models.py:759 +#: aleksis/apps/alsijil/models.py:989 msgid "Can view week overview" msgstr "" -#: aleksis/apps/alsijil/models.py:760 +#: aleksis/apps/alsijil/models.py:990 #, fuzzy #| msgid "Class register" msgid "Can view full register" msgstr "Registre de la classe" -#: aleksis/apps/alsijil/models.py:761 +#: aleksis/apps/alsijil/models.py:991 #, fuzzy #| msgid "Register absence" msgid "Can register absence" msgstr "Registre de Absence" -#: aleksis/apps/alsijil/models.py:762 +#: aleksis/apps/alsijil/models.py:992 #, fuzzy #| msgid "List of all personal note filters" msgid "Can list all personal note filters" msgstr "Liste de filtres de notes personnelles" -#: aleksis/apps/alsijil/preferences.py:9 +#: aleksis/apps/alsijil/preferences.py:16 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:16 msgid "Class register" msgstr "Registre de la classe" -#: aleksis/apps/alsijil/preferences.py:17 +#: aleksis/apps/alsijil/preferences.py:24 msgid "Block adding personal notes for cancelled lessons" msgstr "" -#: aleksis/apps/alsijil/preferences.py:25 +#: aleksis/apps/alsijil/preferences.py:32 msgid "Allow users to view their own personal notes" msgstr "" -#: aleksis/apps/alsijil/preferences.py:34 +#: aleksis/apps/alsijil/preferences.py:41 msgid "Allow primary group owners to register future absences for students in their groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:44 +#: aleksis/apps/alsijil/preferences.py:51 msgid "Grant the owner of a parent group the same privileges as the owners of the respective child groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:54 +#: aleksis/apps/alsijil/preferences.py:61 msgid "Allow original teachers to edit their lessons although they are substituted" msgstr "" -#: aleksis/apps/alsijil/preferences.py:63 +#: aleksis/apps/alsijil/preferences.py:70 msgid "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods" msgstr "" -#: aleksis/apps/alsijil/preferences.py:66 +#: aleksis/apps/alsijil/preferences.py:73 msgid "This will carry over data only if the data in the following periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:75 +#: aleksis/apps/alsijil/preferences.py:82 msgid "Allow carrying over data from any lesson period to all other lesson periods with the same lesson and in the same week" msgstr "" -#: aleksis/apps/alsijil/preferences.py:79 +#: aleksis/apps/alsijil/preferences.py:86 msgid "This will carry over data only if the data in the aforementioned periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:88 +#: aleksis/apps/alsijil/preferences.py:95 msgid "Carry over personal notes to all following lesson periods on the same day." msgstr "" -#: aleksis/apps/alsijil/preferences.py:97 +#: aleksis/apps/alsijil/preferences.py:104 msgid "Allow teachers to open lesson periods on the same day and not just at the beginning of the period" msgstr "" -#: aleksis/apps/alsijil/preferences.py:101 +#: aleksis/apps/alsijil/preferences.py:108 msgid "Lessons in the past are not affected by this setting, you can open them whenever you want." msgstr "" -#: aleksis/apps/alsijil/preferences.py:110 +#: aleksis/apps/alsijil/preferences.py:117 #, fuzzy #| msgid "Teachers and lessons in group" msgid "Allow teachers to add data for lessons in holidays" msgstr "Profs et cours en groupe" -#: aleksis/apps/alsijil/preferences.py:119 +#: aleksis/apps/alsijil/preferences.py:126 msgid "Allow group owners to assign group roles to the parents of the group's members" msgstr "" -#: aleksis/apps/alsijil/preferences.py:128 +#: aleksis/apps/alsijil/preferences.py:135 msgid "Show assigned group roles in week view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:129 +#: aleksis/apps/alsijil/preferences.py:136 msgid "Only week view of groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:137 +#: aleksis/apps/alsijil/preferences.py:144 msgid "Show assigned group roles in lesson view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:147 +#: aleksis/apps/alsijil/preferences.py:154 msgid "Items per page in lessons table" msgstr "" -#: aleksis/apps/alsijil/preferences.py:151 +#: aleksis/apps/alsijil/preferences.py:158 msgid "Each page must show at least one item." msgstr "" -#: aleksis/apps/alsijil/preferences.py:159 +#: aleksis/apps/alsijil/preferences.py:166 msgid "Filter lessons by existence of their lesson documentation on default" msgstr "" -#: aleksis/apps/alsijil/preferences.py:170 +#: aleksis/apps/alsijil/preferences.py:177 msgid "Allow editing of all future documentations" msgstr "" -#: aleksis/apps/alsijil/preferences.py:173 +#: aleksis/apps/alsijil/preferences.py:180 msgid "Allow editing of all documentations up to and including those on the current day" msgstr "" -#: aleksis/apps/alsijil/preferences.py:178 +#: aleksis/apps/alsijil/preferences.py:185 msgid "Allow editing of all documentations up to and including those on the current date and time" msgstr "" -#: aleksis/apps/alsijil/preferences.py:183 +#: aleksis/apps/alsijil/preferences.py:190 msgid "Set time range for which documentations may be edited" msgstr "" -#: aleksis/apps/alsijil/tables.py:23 aleksis/apps/alsijil/tables.py:47 -#: aleksis/apps/alsijil/tables.py:72 +#: aleksis/apps/alsijil/preferences.py:201 +msgid "User is allowed to register absences for members of groups the user is an owner of with these group types" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:205 +msgid "If you leave it empty, all member of groups the user is an owner of will be shown." +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:217 +msgid "Group type of groups to be shown first in the group select field on the coursebook overview page" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:220 +msgid "If you leave it empty, no group type will be used." +msgstr "" + +#: aleksis/apps/alsijil/tables.py:27 aleksis/apps/alsijil/tables.py:52 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:13 msgid "Edit" msgstr "" -#: aleksis/apps/alsijil/tables.py:96 +#: aleksis/apps/alsijil/tables.py:76 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:348 msgid "Date" msgstr "Date" -#: aleksis/apps/alsijil/tables.py:99 +#: aleksis/apps/alsijil/tables.py:79 #: aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html:30 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:122 msgid "Period" msgstr "Période" -#: aleksis/apps/alsijil/tables.py:118 -#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 -#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 -#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 -msgid "Tardiness" -msgstr "Retard" - -#: aleksis/apps/alsijil/tables.py:119 +#: aleksis/apps/alsijil/tables.py:99 #, fuzzy #| msgid "Excused" msgid "Excuse" msgstr "Excusé" -#: aleksis/apps/alsijil/tables.py:156 +#: aleksis/apps/alsijil/tables.py:136 #, fuzzy, python-brace-format #| msgid "Summed up tardiness" msgid "{value}' tardiness" @@ -1101,17 +1122,6 @@ msgid "" " " msgstr "" -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:7 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:14 -msgid "Create extra mark" -msgstr "" - -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:7 -msgid "Edit extra mark" -msgstr "" - #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:9 #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:16 #, python-format @@ -1646,126 +1656,120 @@ msgstr "Vue de semaine" msgid "Notes" msgstr "Notes" -#: aleksis/apps/alsijil/views.py:114 +#: aleksis/apps/alsijil/views.py:112 msgid "You either selected an invalid lesson or there is currently no lesson in progress." msgstr "" -#: aleksis/apps/alsijil/views.py:147 +#: aleksis/apps/alsijil/views.py:145 msgid "You are not allowed to create a lesson documentation for a lesson in the future." msgstr "" -#: aleksis/apps/alsijil/views.py:264 +#: aleksis/apps/alsijil/views.py:262 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The lesson documentation has been saved." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:298 +#: aleksis/apps/alsijil/views.py:296 msgid "The personal notes have been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:658 +#: aleksis/apps/alsijil/views.py:656 msgid "Generate full register printout for {}" msgstr "" -#: aleksis/apps/alsijil/views.py:659 +#: aleksis/apps/alsijil/views.py:657 msgid "Generate full register printout …" msgstr "" -#: aleksis/apps/alsijil/views.py:660 +#: aleksis/apps/alsijil/views.py:658 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The printout has been generated successfully." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:661 +#: aleksis/apps/alsijil/views.py:659 msgid "There was a problem while generating the printout." msgstr "" -#: aleksis/apps/alsijil/views.py:664 +#: aleksis/apps/alsijil/views.py:662 msgid "Download PDF" msgstr "" -#: aleksis/apps/alsijil/views.py:1030 +#: aleksis/apps/alsijil/views.py:1028 msgid "The absence has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1051 +#: aleksis/apps/alsijil/views.py:1049 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The personal note has been deleted." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:1074 -#, fuzzy -#| msgid "Lesson documentation for calendar week" -msgid "The extra mark has been created." -msgstr "Documentation de cours pour la semaine calendrier" - -#: aleksis/apps/alsijil/views.py:1086 -#, fuzzy -#| msgid "Lesson documentation for calendar week" -msgid "The extra mark has been saved." -msgstr "Documentation de cours pour la semaine calendrier" - -#: aleksis/apps/alsijil/views.py:1097 -msgid "The extra mark has been deleted." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1119 +#: aleksis/apps/alsijil/views.py:1072 msgid "The excuse type has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1131 +#: aleksis/apps/alsijil/views.py:1084 msgid "The excuse type has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1142 +#: aleksis/apps/alsijil/views.py:1095 msgid "The excuse type has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1164 +#: aleksis/apps/alsijil/views.py:1117 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The group role has been created." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:1176 +#: aleksis/apps/alsijil/views.py:1129 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The group role has been saved." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:1187 +#: aleksis/apps/alsijil/views.py:1140 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The group role has been deleted." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:1221 aleksis/apps/alsijil/views.py:1253 +#: aleksis/apps/alsijil/views.py:1174 aleksis/apps/alsijil/views.py:1206 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The group role has been assigned." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:1272 +#: aleksis/apps/alsijil/views.py:1225 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The group role assignment has been saved." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:1293 +#: aleksis/apps/alsijil/views.py:1246 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The group role assignment has been stopped." msgstr "Documentation de cours pour la semaine calendrier" -#: aleksis/apps/alsijil/views.py:1306 +#: aleksis/apps/alsijil/views.py:1259 #, fuzzy #| msgid "Lesson documentation for calendar week" msgid "The group role assignment has been deleted." msgstr "Documentation de cours pour la semaine calendrier" +#, fuzzy +#~| msgid "Lesson documentation for calendar week" +#~ msgid "The extra mark has been created." +#~ msgstr "Documentation de cours pour la semaine calendrier" + +#, fuzzy +#~| msgid "Lesson documentation for calendar week" +#~ msgid "The extra mark has been saved." +#~ msgstr "Documentation de cours pour la semaine calendrier" + #~ msgid "Current lesson" #~ msgstr "Lecon actuelle" diff --git a/aleksis/apps/alsijil/locale/la/LC_MESSAGES/django.po b/aleksis/apps/alsijil/locale/la/LC_MESSAGES/django.po index a3ca7ecd62424293afd0f457fe4b67c95cbeb5af..ffbc44cdc05e07e5e46c4578ae0e7db6a6fd31fa 100644 --- a/aleksis/apps/alsijil/locale/la/LC_MESSAGES/django.po +++ b/aleksis/apps/alsijil/locale/la/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-23 21:13+0200\n" +"POT-Creation-Date: 2024-08-18 16:34+0200\n" "PO-Revision-Date: 2020-07-26 14:08+0000\n" "Last-Translator: Julian <leuckerj@gmail.com>\n" "Language-Team: Latin <https://translate.edugit.org/projects/aleksis/aleksis-app-alsijil/la/>\n" @@ -31,8 +31,8 @@ msgstr "" msgid "Mark as {excuse_type.name}" msgstr "" -#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:29 -#: aleksis/apps/alsijil/tables.py:53 aleksis/apps/alsijil/tables.py:78 +#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:33 +#: aleksis/apps/alsijil/tables.py:58 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:29 msgid "Delete" msgstr "" @@ -111,7 +111,7 @@ msgid "Before" msgstr "" #: aleksis/apps/alsijil/filters.py:14 aleksis/apps/alsijil/forms.py:371 -#: aleksis/apps/alsijil/models.py:471 aleksis/apps/alsijil/tables.py:116 +#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:96 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:126 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:223 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:189 @@ -152,20 +152,20 @@ msgid "You can't select a group and a teacher both." msgstr "" #: aleksis/apps/alsijil/forms.py:193 aleksis/apps/alsijil/forms.py:291 -#: aleksis/apps/alsijil/models.py:609 aleksis/apps/alsijil/models.py:658 +#: aleksis/apps/alsijil/models.py:788 aleksis/apps/alsijil/models.py:879 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:63 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:27 msgid "Person" msgstr "Persona" #: aleksis/apps/alsijil/forms.py:194 aleksis/apps/alsijil/forms.py:372 -#: aleksis/apps/alsijil/models.py:730 +#: aleksis/apps/alsijil/models.py:960 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:64 msgid "Start date" msgstr "" #: aleksis/apps/alsijil/forms.py:195 aleksis/apps/alsijil/forms.py:373 -#: aleksis/apps/alsijil/models.py:734 +#: aleksis/apps/alsijil/models.py:964 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:65 msgid "End date" msgstr "" @@ -178,8 +178,8 @@ msgstr "" msgid "End period" msgstr "" -#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/models.py:623 -#: aleksis/apps/alsijil/tables.py:117 aleksis/apps/alsijil/tables.py:138 +#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/tables.py:97 +#: aleksis/apps/alsijil/tables.py:118 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:50 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:392 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:28 @@ -188,7 +188,7 @@ msgstr "" msgid "Absent" msgstr "" -#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:146 +#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:126 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:54 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:135 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:30 @@ -198,8 +198,8 @@ msgstr "" msgid "Excused" msgstr "" -#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:79 -#: aleksis/apps/alsijil/models.py:255 +#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:85 +#: aleksis/apps/alsijil/models.py:261 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:31 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:72 msgid "Excuse type" @@ -220,7 +220,7 @@ msgstr "" msgid "Has lesson documentation" msgstr "" -#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:130 +#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:110 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:172 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:236 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:311 @@ -228,7 +228,7 @@ msgstr "" #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:21 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:375 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:455 -#: aleksis/apps/alsijil/util/alsijil_helpers.py:330 +#: aleksis/apps/alsijil/util/alsijil_helpers.py:331 msgid "Event" msgstr "" @@ -272,43 +272,41 @@ msgstr "" msgid "Can register an absence for a person" msgstr "" -#: aleksis/apps/alsijil/models.py:58 aleksis/apps/alsijil/models.py:432 +#: aleksis/apps/alsijil/models.py:64 aleksis/apps/alsijil/models.py:438 #, fuzzy #| msgid "First name" msgid "Short name" msgstr "Primus nomen" -#: aleksis/apps/alsijil/models.py:59 aleksis/apps/alsijil/models.py:433 -#: aleksis/apps/alsijil/models.py:694 +#: aleksis/apps/alsijil/models.py:65 aleksis/apps/alsijil/models.py:439 +#: aleksis/apps/alsijil/models.py:924 #: aleksis/apps/alsijil/templates/alsijil/class_register/groups.html:20 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:12 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:25 msgid "Name" msgstr "" -#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/tables.py:41 +#: aleksis/apps/alsijil/models.py:69 aleksis/apps/alsijil/tables.py:21 msgid "Count as absent" msgstr "" -#: aleksis/apps/alsijil/models.py:65 +#: aleksis/apps/alsijil/models.py:71 msgid "If checked, this excuse type will be counted as a missed lesson. If not checked,it won't show up in the absence report." msgstr "" -#: aleksis/apps/alsijil/models.py:80 +#: aleksis/apps/alsijil/models.py:86 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:9 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:30 msgid "Excuse types" msgstr "" -#: aleksis/apps/alsijil/models.py:235 aleksis/apps/alsijil/models.py:334 +#: aleksis/apps/alsijil/models.py:241 aleksis/apps/alsijil/models.py:340 msgid "Year" msgstr "" -#: aleksis/apps/alsijil/models.py:260 aleksis/apps/alsijil/models.py:450 -#: aleksis/apps/alsijil/tables.py:120 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:8 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:9 +#: aleksis/apps/alsijil/models.py:266 aleksis/apps/alsijil/models.py:456 +#: aleksis/apps/alsijil/tables.py:100 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:57 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:32 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:19 @@ -316,20 +314,20 @@ msgstr "" msgid "Extra marks" msgstr "" -#: aleksis/apps/alsijil/models.py:294 +#: aleksis/apps/alsijil/models.py:300 #, fuzzy #| msgid "Person" msgid "Personal note" msgstr "Persona" -#: aleksis/apps/alsijil/models.py:295 +#: aleksis/apps/alsijil/models.py:301 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:47 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:370 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:21 msgid "Personal notes" msgstr "" -#: aleksis/apps/alsijil/models.py:346 +#: aleksis/apps/alsijil/models.py:352 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:128 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:259 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:337 @@ -338,7 +336,7 @@ msgstr "" msgid "Lesson topic" msgstr "" -#: aleksis/apps/alsijil/models.py:347 aleksis/apps/alsijil/models.py:483 +#: aleksis/apps/alsijil/models.py:353 aleksis/apps/alsijil/models.py:491 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:129 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:265 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:342 @@ -347,7 +345,7 @@ msgstr "" msgid "Homework" msgstr "" -#: aleksis/apps/alsijil/models.py:348 +#: aleksis/apps/alsijil/models.py:354 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:130 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:271 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:346 @@ -357,117 +355,135 @@ msgstr "" msgid "Group note" msgstr "Grex" -#: aleksis/apps/alsijil/models.py:398 +#: aleksis/apps/alsijil/models.py:404 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:16 msgid "Lesson documentation" msgstr "" -#: aleksis/apps/alsijil/models.py:399 +#: aleksis/apps/alsijil/models.py:405 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:43 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:77 msgid "Lesson documentations" msgstr "" -#: aleksis/apps/alsijil/models.py:435 +#: aleksis/apps/alsijil/models.py:441 msgid "Foreground colour" msgstr "" -#: aleksis/apps/alsijil/models.py:436 +#: aleksis/apps/alsijil/models.py:442 msgid "Background colour" msgstr "" -#: aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:444 msgid "Show in coursebook" msgstr "" -#: aleksis/apps/alsijil/models.py:449 +#: aleksis/apps/alsijil/models.py:455 msgid "Extra mark" msgstr "" -#: aleksis/apps/alsijil/models.py:467 +#: aleksis/apps/alsijil/models.py:475 msgid "Course" msgstr "" -#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:111 +#: aleksis/apps/alsijil/models.py:487 aleksis/apps/alsijil/tables.py:91 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:127 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:253 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:331 msgid "Teachers" msgstr "" -#: aleksis/apps/alsijil/models.py:482 +#: aleksis/apps/alsijil/models.py:490 msgid "Lesson Topic" msgstr "" -#: aleksis/apps/alsijil/models.py:484 +#: aleksis/apps/alsijil/models.py:492 #, fuzzy #| msgid "Group" msgid "Group Note" msgstr "Grex" -#: aleksis/apps/alsijil/models.py:512 aleksis/apps/alsijil/models.py:619 -#: aleksis/apps/alsijil/models.py:665 +#: aleksis/apps/alsijil/models.py:496 +msgid "Participation touched at" +msgstr "" + +#: aleksis/apps/alsijil/models.py:525 aleksis/apps/alsijil/models.py:798 +#: aleksis/apps/alsijil/models.py:886 msgid "Documentation" msgstr "" -#: aleksis/apps/alsijil/models.py:513 +#: aleksis/apps/alsijil/models.py:526 msgid "Documentations" msgstr "" -#: aleksis/apps/alsijil/models.py:612 +#: aleksis/apps/alsijil/models.py:791 #, fuzzy #| msgid "Group" msgid "Groups of Person" msgstr "Grex" -#: aleksis/apps/alsijil/models.py:625 +#: aleksis/apps/alsijil/models.py:804 msgid "Absence Reason" msgstr "" -#: aleksis/apps/alsijil/models.py:634 +#: aleksis/apps/alsijil/models.py:816 msgid "Base Absence" msgstr "" -#: aleksis/apps/alsijil/models.py:641 aleksis/apps/alsijil/models.py:642 +#: aleksis/apps/alsijil/models.py:819 aleksis/apps/alsijil/tables.py:98 +#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 +#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 +#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 +msgid "Tardiness" +msgstr "" + +#: aleksis/apps/alsijil/models.py:862 aleksis/apps/alsijil/models.py:863 msgid "Participation Status" msgstr "" -#: aleksis/apps/alsijil/models.py:670 +#: aleksis/apps/alsijil/models.py:891 msgid "Note" msgstr "" -#: aleksis/apps/alsijil/models.py:672 +#: aleksis/apps/alsijil/models.py:893 msgid "Extra Mark" msgstr "" -#: aleksis/apps/alsijil/models.py:679 +#: aleksis/apps/alsijil/models.py:900 #, fuzzy #| msgid "Person" msgid "Personal Note" msgstr "Persona" -#: aleksis/apps/alsijil/models.py:680 +#: aleksis/apps/alsijil/models.py:901 #, fuzzy #| msgid "Person" msgid "Personal Notes" msgstr "Persona" -#: aleksis/apps/alsijil/models.py:695 +#: aleksis/apps/alsijil/models.py:912 +msgid "A person got assigned the same extra mark multiple times per documentation." +msgstr "" + +#: aleksis/apps/alsijil/models.py:925 msgid "Icon" msgstr "" -#: aleksis/apps/alsijil/models.py:696 +#: aleksis/apps/alsijil/models.py:926 msgid "Colour" msgstr "" -#: aleksis/apps/alsijil/models.py:702 aleksis/apps/alsijil/models.py:717 +#: aleksis/apps/alsijil/models.py:932 aleksis/apps/alsijil/models.py:947 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:62 #, fuzzy #| msgid "Group" msgid "Group role" msgstr "Grex" -#: aleksis/apps/alsijil/models.py:703 +#: aleksis/apps/alsijil/models.py:933 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:90 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:9 @@ -476,15 +492,15 @@ msgstr "Grex" msgid "Group roles" msgstr "Grex" -#: aleksis/apps/alsijil/models.py:704 +#: aleksis/apps/alsijil/models.py:934 msgid "Can assign group role" msgstr "" -#: aleksis/apps/alsijil/models.py:723 +#: aleksis/apps/alsijil/models.py:953 msgid "Assigned person" msgstr "" -#: aleksis/apps/alsijil/models.py:728 aleksis/apps/alsijil/tables.py:105 +#: aleksis/apps/alsijil/models.py:958 aleksis/apps/alsijil/tables.py:85 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:124 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:242 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:321 @@ -493,171 +509,176 @@ msgstr "" msgid "Groups" msgstr "Grex" -#: aleksis/apps/alsijil/models.py:735 +#: aleksis/apps/alsijil/models.py:965 msgid "Can be left empty if end date is not clear yet" msgstr "" -#: aleksis/apps/alsijil/models.py:750 +#: aleksis/apps/alsijil/models.py:980 msgid "Group role assignment" msgstr "" -#: aleksis/apps/alsijil/models.py:751 +#: aleksis/apps/alsijil/models.py:981 msgid "Group role assignments" msgstr "" -#: aleksis/apps/alsijil/models.py:758 +#: aleksis/apps/alsijil/models.py:988 msgid "Can view lesson overview" msgstr "" -#: aleksis/apps/alsijil/models.py:759 +#: aleksis/apps/alsijil/models.py:989 msgid "Can view week overview" msgstr "" -#: aleksis/apps/alsijil/models.py:760 +#: aleksis/apps/alsijil/models.py:990 msgid "Can view full register" msgstr "" -#: aleksis/apps/alsijil/models.py:761 +#: aleksis/apps/alsijil/models.py:991 msgid "Can register absence" msgstr "" -#: aleksis/apps/alsijil/models.py:762 +#: aleksis/apps/alsijil/models.py:992 msgid "Can list all personal note filters" msgstr "" -#: aleksis/apps/alsijil/preferences.py:9 +#: aleksis/apps/alsijil/preferences.py:16 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:16 msgid "Class register" msgstr "" -#: aleksis/apps/alsijil/preferences.py:17 +#: aleksis/apps/alsijil/preferences.py:24 msgid "Block adding personal notes for cancelled lessons" msgstr "" -#: aleksis/apps/alsijil/preferences.py:25 +#: aleksis/apps/alsijil/preferences.py:32 msgid "Allow users to view their own personal notes" msgstr "" -#: aleksis/apps/alsijil/preferences.py:34 +#: aleksis/apps/alsijil/preferences.py:41 msgid "Allow primary group owners to register future absences for students in their groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:44 +#: aleksis/apps/alsijil/preferences.py:51 msgid "Grant the owner of a parent group the same privileges as the owners of the respective child groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:54 +#: aleksis/apps/alsijil/preferences.py:61 msgid "Allow original teachers to edit their lessons although they are substituted" msgstr "" -#: aleksis/apps/alsijil/preferences.py:63 +#: aleksis/apps/alsijil/preferences.py:70 msgid "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods" msgstr "" -#: aleksis/apps/alsijil/preferences.py:66 +#: aleksis/apps/alsijil/preferences.py:73 msgid "This will carry over data only if the data in the following periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:75 +#: aleksis/apps/alsijil/preferences.py:82 msgid "Allow carrying over data from any lesson period to all other lesson periods with the same lesson and in the same week" msgstr "" -#: aleksis/apps/alsijil/preferences.py:79 +#: aleksis/apps/alsijil/preferences.py:86 msgid "This will carry over data only if the data in the aforementioned periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:88 +#: aleksis/apps/alsijil/preferences.py:95 msgid "Carry over personal notes to all following lesson periods on the same day." msgstr "" -#: aleksis/apps/alsijil/preferences.py:97 +#: aleksis/apps/alsijil/preferences.py:104 msgid "Allow teachers to open lesson periods on the same day and not just at the beginning of the period" msgstr "" -#: aleksis/apps/alsijil/preferences.py:101 +#: aleksis/apps/alsijil/preferences.py:108 msgid "Lessons in the past are not affected by this setting, you can open them whenever you want." msgstr "" -#: aleksis/apps/alsijil/preferences.py:110 +#: aleksis/apps/alsijil/preferences.py:117 msgid "Allow teachers to add data for lessons in holidays" msgstr "" -#: aleksis/apps/alsijil/preferences.py:119 +#: aleksis/apps/alsijil/preferences.py:126 msgid "Allow group owners to assign group roles to the parents of the group's members" msgstr "" -#: aleksis/apps/alsijil/preferences.py:128 +#: aleksis/apps/alsijil/preferences.py:135 msgid "Show assigned group roles in week view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:129 +#: aleksis/apps/alsijil/preferences.py:136 msgid "Only week view of groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:137 +#: aleksis/apps/alsijil/preferences.py:144 msgid "Show assigned group roles in lesson view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:147 +#: aleksis/apps/alsijil/preferences.py:154 msgid "Items per page in lessons table" msgstr "" -#: aleksis/apps/alsijil/preferences.py:151 +#: aleksis/apps/alsijil/preferences.py:158 msgid "Each page must show at least one item." msgstr "" -#: aleksis/apps/alsijil/preferences.py:159 +#: aleksis/apps/alsijil/preferences.py:166 msgid "Filter lessons by existence of their lesson documentation on default" msgstr "" -#: aleksis/apps/alsijil/preferences.py:170 +#: aleksis/apps/alsijil/preferences.py:177 msgid "Allow editing of all future documentations" msgstr "" -#: aleksis/apps/alsijil/preferences.py:173 +#: aleksis/apps/alsijil/preferences.py:180 msgid "Allow editing of all documentations up to and including those on the current day" msgstr "" -#: aleksis/apps/alsijil/preferences.py:178 +#: aleksis/apps/alsijil/preferences.py:185 msgid "Allow editing of all documentations up to and including those on the current date and time" msgstr "" -#: aleksis/apps/alsijil/preferences.py:183 +#: aleksis/apps/alsijil/preferences.py:190 msgid "Set time range for which documentations may be edited" msgstr "" -#: aleksis/apps/alsijil/tables.py:23 aleksis/apps/alsijil/tables.py:47 -#: aleksis/apps/alsijil/tables.py:72 +#: aleksis/apps/alsijil/preferences.py:201 +msgid "User is allowed to register absences for members of groups the user is an owner of with these group types" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:205 +msgid "If you leave it empty, all member of groups the user is an owner of will be shown." +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:217 +msgid "Group type of groups to be shown first in the group select field on the coursebook overview page" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:220 +msgid "If you leave it empty, no group type will be used." +msgstr "" + +#: aleksis/apps/alsijil/tables.py:27 aleksis/apps/alsijil/tables.py:52 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:13 msgid "Edit" msgstr "" -#: aleksis/apps/alsijil/tables.py:96 +#: aleksis/apps/alsijil/tables.py:76 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:348 msgid "Date" msgstr "dies" -#: aleksis/apps/alsijil/tables.py:99 +#: aleksis/apps/alsijil/tables.py:79 #: aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html:30 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:122 msgid "Period" msgstr "" -#: aleksis/apps/alsijil/tables.py:118 -#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 -#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 -#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 -msgid "Tardiness" -msgstr "" - -#: aleksis/apps/alsijil/tables.py:119 +#: aleksis/apps/alsijil/tables.py:99 msgid "Excuse" msgstr "" -#: aleksis/apps/alsijil/tables.py:156 +#: aleksis/apps/alsijil/tables.py:136 #, python-brace-format msgid "{value}' tardiness" msgstr "" @@ -992,17 +1013,6 @@ msgid "" " " msgstr "" -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:7 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:14 -msgid "Create extra mark" -msgstr "" - -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:7 -msgid "Edit extra mark" -msgstr "" - #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:9 #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:16 #, python-format @@ -1500,99 +1510,87 @@ msgstr "" msgid "Notes" msgstr "" -#: aleksis/apps/alsijil/views.py:114 +#: aleksis/apps/alsijil/views.py:112 msgid "You either selected an invalid lesson or there is currently no lesson in progress." msgstr "" -#: aleksis/apps/alsijil/views.py:147 +#: aleksis/apps/alsijil/views.py:145 msgid "You are not allowed to create a lesson documentation for a lesson in the future." msgstr "" -#: aleksis/apps/alsijil/views.py:264 +#: aleksis/apps/alsijil/views.py:262 msgid "The lesson documentation has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:298 +#: aleksis/apps/alsijil/views.py:296 msgid "The personal notes have been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:658 +#: aleksis/apps/alsijil/views.py:656 msgid "Generate full register printout for {}" msgstr "" -#: aleksis/apps/alsijil/views.py:659 +#: aleksis/apps/alsijil/views.py:657 msgid "Generate full register printout …" msgstr "" -#: aleksis/apps/alsijil/views.py:660 +#: aleksis/apps/alsijil/views.py:658 msgid "The printout has been generated successfully." msgstr "" -#: aleksis/apps/alsijil/views.py:661 +#: aleksis/apps/alsijil/views.py:659 msgid "There was a problem while generating the printout." msgstr "" -#: aleksis/apps/alsijil/views.py:664 +#: aleksis/apps/alsijil/views.py:662 msgid "Download PDF" msgstr "" -#: aleksis/apps/alsijil/views.py:1030 +#: aleksis/apps/alsijil/views.py:1028 msgid "The absence has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1051 +#: aleksis/apps/alsijil/views.py:1049 msgid "The personal note has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1074 -msgid "The extra mark has been created." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1086 -msgid "The extra mark has been saved." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1097 -msgid "The extra mark has been deleted." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1119 +#: aleksis/apps/alsijil/views.py:1072 msgid "The excuse type has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1131 +#: aleksis/apps/alsijil/views.py:1084 msgid "The excuse type has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1142 +#: aleksis/apps/alsijil/views.py:1095 msgid "The excuse type has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1164 +#: aleksis/apps/alsijil/views.py:1117 msgid "The group role has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1176 +#: aleksis/apps/alsijil/views.py:1129 msgid "The group role has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1187 +#: aleksis/apps/alsijil/views.py:1140 msgid "The group role has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1221 aleksis/apps/alsijil/views.py:1253 +#: aleksis/apps/alsijil/views.py:1174 aleksis/apps/alsijil/views.py:1206 msgid "The group role has been assigned." msgstr "" -#: aleksis/apps/alsijil/views.py:1272 +#: aleksis/apps/alsijil/views.py:1225 msgid "The group role assignment has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1293 +#: aleksis/apps/alsijil/views.py:1246 msgid "The group role assignment has been stopped." msgstr "" -#: aleksis/apps/alsijil/views.py:1306 +#: aleksis/apps/alsijil/views.py:1259 msgid "The group role assignment has been deleted." msgstr "" diff --git a/aleksis/apps/alsijil/locale/nb_NO/LC_MESSAGES/django.po b/aleksis/apps/alsijil/locale/nb_NO/LC_MESSAGES/django.po index 4a23675366e43a10b5190e5dfd31b46a442dd86f..40892069d224a5e6ef62ed3a0ce7fe80720ca876 100644 --- a/aleksis/apps/alsijil/locale/nb_NO/LC_MESSAGES/django.po +++ b/aleksis/apps/alsijil/locale/nb_NO/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-23 21:13+0200\n" +"POT-Creation-Date: 2024-08-18 16:34+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -30,8 +30,8 @@ msgstr "" msgid "Mark as {excuse_type.name}" msgstr "" -#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:29 -#: aleksis/apps/alsijil/tables.py:53 aleksis/apps/alsijil/tables.py:78 +#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:33 +#: aleksis/apps/alsijil/tables.py:58 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:29 msgid "Delete" msgstr "" @@ -110,7 +110,7 @@ msgid "Before" msgstr "" #: aleksis/apps/alsijil/filters.py:14 aleksis/apps/alsijil/forms.py:371 -#: aleksis/apps/alsijil/models.py:471 aleksis/apps/alsijil/tables.py:116 +#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:96 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:126 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:223 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:189 @@ -151,20 +151,20 @@ msgid "You can't select a group and a teacher both." msgstr "" #: aleksis/apps/alsijil/forms.py:193 aleksis/apps/alsijil/forms.py:291 -#: aleksis/apps/alsijil/models.py:609 aleksis/apps/alsijil/models.py:658 +#: aleksis/apps/alsijil/models.py:788 aleksis/apps/alsijil/models.py:879 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:63 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:27 msgid "Person" msgstr "" #: aleksis/apps/alsijil/forms.py:194 aleksis/apps/alsijil/forms.py:372 -#: aleksis/apps/alsijil/models.py:730 +#: aleksis/apps/alsijil/models.py:960 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:64 msgid "Start date" msgstr "" #: aleksis/apps/alsijil/forms.py:195 aleksis/apps/alsijil/forms.py:373 -#: aleksis/apps/alsijil/models.py:734 +#: aleksis/apps/alsijil/models.py:964 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:65 msgid "End date" msgstr "" @@ -177,8 +177,8 @@ msgstr "" msgid "End period" msgstr "" -#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/models.py:623 -#: aleksis/apps/alsijil/tables.py:117 aleksis/apps/alsijil/tables.py:138 +#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/tables.py:97 +#: aleksis/apps/alsijil/tables.py:118 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:50 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:392 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:28 @@ -187,7 +187,7 @@ msgstr "" msgid "Absent" msgstr "" -#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:146 +#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:126 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:54 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:135 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:30 @@ -197,8 +197,8 @@ msgstr "" msgid "Excused" msgstr "" -#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:79 -#: aleksis/apps/alsijil/models.py:255 +#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:85 +#: aleksis/apps/alsijil/models.py:261 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:31 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:72 msgid "Excuse type" @@ -219,7 +219,7 @@ msgstr "" msgid "Has lesson documentation" msgstr "" -#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:130 +#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:110 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:172 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:236 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:311 @@ -227,7 +227,7 @@ msgstr "" #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:21 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:375 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:455 -#: aleksis/apps/alsijil/util/alsijil_helpers.py:330 +#: aleksis/apps/alsijil/util/alsijil_helpers.py:331 msgid "Event" msgstr "" @@ -271,41 +271,39 @@ msgstr "" msgid "Can register an absence for a person" msgstr "" -#: aleksis/apps/alsijil/models.py:58 aleksis/apps/alsijil/models.py:432 +#: aleksis/apps/alsijil/models.py:64 aleksis/apps/alsijil/models.py:438 msgid "Short name" msgstr "" -#: aleksis/apps/alsijil/models.py:59 aleksis/apps/alsijil/models.py:433 -#: aleksis/apps/alsijil/models.py:694 +#: aleksis/apps/alsijil/models.py:65 aleksis/apps/alsijil/models.py:439 +#: aleksis/apps/alsijil/models.py:924 #: aleksis/apps/alsijil/templates/alsijil/class_register/groups.html:20 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:12 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:25 msgid "Name" msgstr "" -#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/tables.py:41 +#: aleksis/apps/alsijil/models.py:69 aleksis/apps/alsijil/tables.py:21 msgid "Count as absent" msgstr "" -#: aleksis/apps/alsijil/models.py:65 +#: aleksis/apps/alsijil/models.py:71 msgid "If checked, this excuse type will be counted as a missed lesson. If not checked,it won't show up in the absence report." msgstr "" -#: aleksis/apps/alsijil/models.py:80 +#: aleksis/apps/alsijil/models.py:86 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:9 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:30 msgid "Excuse types" msgstr "" -#: aleksis/apps/alsijil/models.py:235 aleksis/apps/alsijil/models.py:334 +#: aleksis/apps/alsijil/models.py:241 aleksis/apps/alsijil/models.py:340 msgid "Year" msgstr "" -#: aleksis/apps/alsijil/models.py:260 aleksis/apps/alsijil/models.py:450 -#: aleksis/apps/alsijil/tables.py:120 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:8 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:9 +#: aleksis/apps/alsijil/models.py:266 aleksis/apps/alsijil/models.py:456 +#: aleksis/apps/alsijil/tables.py:100 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:57 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:32 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:19 @@ -313,18 +311,18 @@ msgstr "" msgid "Extra marks" msgstr "" -#: aleksis/apps/alsijil/models.py:294 +#: aleksis/apps/alsijil/models.py:300 msgid "Personal note" msgstr "" -#: aleksis/apps/alsijil/models.py:295 +#: aleksis/apps/alsijil/models.py:301 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:47 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:370 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:21 msgid "Personal notes" msgstr "" -#: aleksis/apps/alsijil/models.py:346 +#: aleksis/apps/alsijil/models.py:352 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:128 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:259 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:337 @@ -333,7 +331,7 @@ msgstr "" msgid "Lesson topic" msgstr "" -#: aleksis/apps/alsijil/models.py:347 aleksis/apps/alsijil/models.py:483 +#: aleksis/apps/alsijil/models.py:353 aleksis/apps/alsijil/models.py:491 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:129 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:265 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:342 @@ -342,7 +340,7 @@ msgstr "" msgid "Homework" msgstr "" -#: aleksis/apps/alsijil/models.py:348 +#: aleksis/apps/alsijil/models.py:354 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:130 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:271 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:346 @@ -350,293 +348,316 @@ msgstr "" msgid "Group note" msgstr "" -#: aleksis/apps/alsijil/models.py:398 +#: aleksis/apps/alsijil/models.py:404 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:16 msgid "Lesson documentation" msgstr "" -#: aleksis/apps/alsijil/models.py:399 +#: aleksis/apps/alsijil/models.py:405 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:43 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:77 msgid "Lesson documentations" msgstr "" -#: aleksis/apps/alsijil/models.py:435 +#: aleksis/apps/alsijil/models.py:441 msgid "Foreground colour" msgstr "" -#: aleksis/apps/alsijil/models.py:436 +#: aleksis/apps/alsijil/models.py:442 msgid "Background colour" msgstr "" -#: aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:444 msgid "Show in coursebook" msgstr "" -#: aleksis/apps/alsijil/models.py:449 +#: aleksis/apps/alsijil/models.py:455 msgid "Extra mark" msgstr "" -#: aleksis/apps/alsijil/models.py:467 +#: aleksis/apps/alsijil/models.py:475 msgid "Course" msgstr "" -#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:111 +#: aleksis/apps/alsijil/models.py:487 aleksis/apps/alsijil/tables.py:91 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:127 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:253 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:331 msgid "Teachers" msgstr "" -#: aleksis/apps/alsijil/models.py:482 +#: aleksis/apps/alsijil/models.py:490 msgid "Lesson Topic" msgstr "" -#: aleksis/apps/alsijil/models.py:484 +#: aleksis/apps/alsijil/models.py:492 msgid "Group Note" msgstr "" -#: aleksis/apps/alsijil/models.py:512 aleksis/apps/alsijil/models.py:619 -#: aleksis/apps/alsijil/models.py:665 +#: aleksis/apps/alsijil/models.py:496 +msgid "Participation touched at" +msgstr "" + +#: aleksis/apps/alsijil/models.py:525 aleksis/apps/alsijil/models.py:798 +#: aleksis/apps/alsijil/models.py:886 msgid "Documentation" msgstr "" -#: aleksis/apps/alsijil/models.py:513 +#: aleksis/apps/alsijil/models.py:526 msgid "Documentations" msgstr "" -#: aleksis/apps/alsijil/models.py:612 +#: aleksis/apps/alsijil/models.py:791 msgid "Groups of Person" msgstr "" -#: aleksis/apps/alsijil/models.py:625 +#: aleksis/apps/alsijil/models.py:804 msgid "Absence Reason" msgstr "" -#: aleksis/apps/alsijil/models.py:634 +#: aleksis/apps/alsijil/models.py:816 msgid "Base Absence" msgstr "" -#: aleksis/apps/alsijil/models.py:641 aleksis/apps/alsijil/models.py:642 +#: aleksis/apps/alsijil/models.py:819 aleksis/apps/alsijil/tables.py:98 +#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 +#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 +#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 +msgid "Tardiness" +msgstr "" + +#: aleksis/apps/alsijil/models.py:862 aleksis/apps/alsijil/models.py:863 msgid "Participation Status" msgstr "" -#: aleksis/apps/alsijil/models.py:670 +#: aleksis/apps/alsijil/models.py:891 msgid "Note" msgstr "" -#: aleksis/apps/alsijil/models.py:672 +#: aleksis/apps/alsijil/models.py:893 msgid "Extra Mark" msgstr "" -#: aleksis/apps/alsijil/models.py:679 +#: aleksis/apps/alsijil/models.py:900 msgid "Personal Note" msgstr "" -#: aleksis/apps/alsijil/models.py:680 +#: aleksis/apps/alsijil/models.py:901 msgid "Personal Notes" msgstr "" -#: aleksis/apps/alsijil/models.py:695 +#: aleksis/apps/alsijil/models.py:912 +msgid "A person got assigned the same extra mark multiple times per documentation." +msgstr "" + +#: aleksis/apps/alsijil/models.py:925 msgid "Icon" msgstr "" -#: aleksis/apps/alsijil/models.py:696 +#: aleksis/apps/alsijil/models.py:926 msgid "Colour" msgstr "" -#: aleksis/apps/alsijil/models.py:702 aleksis/apps/alsijil/models.py:717 +#: aleksis/apps/alsijil/models.py:932 aleksis/apps/alsijil/models.py:947 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:62 msgid "Group role" msgstr "" -#: aleksis/apps/alsijil/models.py:703 +#: aleksis/apps/alsijil/models.py:933 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:90 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:9 msgid "Group roles" msgstr "" -#: aleksis/apps/alsijil/models.py:704 +#: aleksis/apps/alsijil/models.py:934 msgid "Can assign group role" msgstr "" -#: aleksis/apps/alsijil/models.py:723 +#: aleksis/apps/alsijil/models.py:953 msgid "Assigned person" msgstr "" -#: aleksis/apps/alsijil/models.py:728 aleksis/apps/alsijil/tables.py:105 +#: aleksis/apps/alsijil/models.py:958 aleksis/apps/alsijil/tables.py:85 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:124 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:242 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:321 msgid "Groups" msgstr "" -#: aleksis/apps/alsijil/models.py:735 +#: aleksis/apps/alsijil/models.py:965 msgid "Can be left empty if end date is not clear yet" msgstr "" -#: aleksis/apps/alsijil/models.py:750 +#: aleksis/apps/alsijil/models.py:980 msgid "Group role assignment" msgstr "" -#: aleksis/apps/alsijil/models.py:751 +#: aleksis/apps/alsijil/models.py:981 msgid "Group role assignments" msgstr "" -#: aleksis/apps/alsijil/models.py:758 +#: aleksis/apps/alsijil/models.py:988 msgid "Can view lesson overview" msgstr "" -#: aleksis/apps/alsijil/models.py:759 +#: aleksis/apps/alsijil/models.py:989 msgid "Can view week overview" msgstr "" -#: aleksis/apps/alsijil/models.py:760 +#: aleksis/apps/alsijil/models.py:990 msgid "Can view full register" msgstr "" -#: aleksis/apps/alsijil/models.py:761 +#: aleksis/apps/alsijil/models.py:991 msgid "Can register absence" msgstr "" -#: aleksis/apps/alsijil/models.py:762 +#: aleksis/apps/alsijil/models.py:992 msgid "Can list all personal note filters" msgstr "" -#: aleksis/apps/alsijil/preferences.py:9 +#: aleksis/apps/alsijil/preferences.py:16 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:16 msgid "Class register" msgstr "" -#: aleksis/apps/alsijil/preferences.py:17 +#: aleksis/apps/alsijil/preferences.py:24 msgid "Block adding personal notes for cancelled lessons" msgstr "" -#: aleksis/apps/alsijil/preferences.py:25 +#: aleksis/apps/alsijil/preferences.py:32 msgid "Allow users to view their own personal notes" msgstr "" -#: aleksis/apps/alsijil/preferences.py:34 +#: aleksis/apps/alsijil/preferences.py:41 msgid "Allow primary group owners to register future absences for students in their groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:44 +#: aleksis/apps/alsijil/preferences.py:51 msgid "Grant the owner of a parent group the same privileges as the owners of the respective child groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:54 +#: aleksis/apps/alsijil/preferences.py:61 msgid "Allow original teachers to edit their lessons although they are substituted" msgstr "" -#: aleksis/apps/alsijil/preferences.py:63 +#: aleksis/apps/alsijil/preferences.py:70 msgid "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods" msgstr "" -#: aleksis/apps/alsijil/preferences.py:66 +#: aleksis/apps/alsijil/preferences.py:73 msgid "This will carry over data only if the data in the following periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:75 +#: aleksis/apps/alsijil/preferences.py:82 msgid "Allow carrying over data from any lesson period to all other lesson periods with the same lesson and in the same week" msgstr "" -#: aleksis/apps/alsijil/preferences.py:79 +#: aleksis/apps/alsijil/preferences.py:86 msgid "This will carry over data only if the data in the aforementioned periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:88 +#: aleksis/apps/alsijil/preferences.py:95 msgid "Carry over personal notes to all following lesson periods on the same day." msgstr "" -#: aleksis/apps/alsijil/preferences.py:97 +#: aleksis/apps/alsijil/preferences.py:104 msgid "Allow teachers to open lesson periods on the same day and not just at the beginning of the period" msgstr "" -#: aleksis/apps/alsijil/preferences.py:101 +#: aleksis/apps/alsijil/preferences.py:108 msgid "Lessons in the past are not affected by this setting, you can open them whenever you want." msgstr "" -#: aleksis/apps/alsijil/preferences.py:110 +#: aleksis/apps/alsijil/preferences.py:117 msgid "Allow teachers to add data for lessons in holidays" msgstr "" -#: aleksis/apps/alsijil/preferences.py:119 +#: aleksis/apps/alsijil/preferences.py:126 msgid "Allow group owners to assign group roles to the parents of the group's members" msgstr "" -#: aleksis/apps/alsijil/preferences.py:128 +#: aleksis/apps/alsijil/preferences.py:135 msgid "Show assigned group roles in week view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:129 +#: aleksis/apps/alsijil/preferences.py:136 msgid "Only week view of groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:137 +#: aleksis/apps/alsijil/preferences.py:144 msgid "Show assigned group roles in lesson view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:147 +#: aleksis/apps/alsijil/preferences.py:154 msgid "Items per page in lessons table" msgstr "" -#: aleksis/apps/alsijil/preferences.py:151 +#: aleksis/apps/alsijil/preferences.py:158 msgid "Each page must show at least one item." msgstr "" -#: aleksis/apps/alsijil/preferences.py:159 +#: aleksis/apps/alsijil/preferences.py:166 msgid "Filter lessons by existence of their lesson documentation on default" msgstr "" -#: aleksis/apps/alsijil/preferences.py:170 +#: aleksis/apps/alsijil/preferences.py:177 msgid "Allow editing of all future documentations" msgstr "" -#: aleksis/apps/alsijil/preferences.py:173 +#: aleksis/apps/alsijil/preferences.py:180 msgid "Allow editing of all documentations up to and including those on the current day" msgstr "" -#: aleksis/apps/alsijil/preferences.py:178 +#: aleksis/apps/alsijil/preferences.py:185 msgid "Allow editing of all documentations up to and including those on the current date and time" msgstr "" -#: aleksis/apps/alsijil/preferences.py:183 +#: aleksis/apps/alsijil/preferences.py:190 msgid "Set time range for which documentations may be edited" msgstr "" -#: aleksis/apps/alsijil/tables.py:23 aleksis/apps/alsijil/tables.py:47 -#: aleksis/apps/alsijil/tables.py:72 +#: aleksis/apps/alsijil/preferences.py:201 +msgid "User is allowed to register absences for members of groups the user is an owner of with these group types" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:205 +msgid "If you leave it empty, all member of groups the user is an owner of will be shown." +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:217 +msgid "Group type of groups to be shown first in the group select field on the coursebook overview page" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:220 +msgid "If you leave it empty, no group type will be used." +msgstr "" + +#: aleksis/apps/alsijil/tables.py:27 aleksis/apps/alsijil/tables.py:52 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:13 msgid "Edit" msgstr "" -#: aleksis/apps/alsijil/tables.py:96 +#: aleksis/apps/alsijil/tables.py:76 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:348 msgid "Date" msgstr "" -#: aleksis/apps/alsijil/tables.py:99 +#: aleksis/apps/alsijil/tables.py:79 #: aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html:30 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:122 msgid "Period" msgstr "" -#: aleksis/apps/alsijil/tables.py:118 -#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 -#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 -#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 -msgid "Tardiness" -msgstr "" - -#: aleksis/apps/alsijil/tables.py:119 +#: aleksis/apps/alsijil/tables.py:99 msgid "Excuse" msgstr "" -#: aleksis/apps/alsijil/tables.py:156 +#: aleksis/apps/alsijil/tables.py:136 #, python-brace-format msgid "{value}' tardiness" msgstr "" @@ -963,17 +984,6 @@ msgid "" " " msgstr "" -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:7 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:14 -msgid "Create extra mark" -msgstr "" - -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:7 -msgid "Edit extra mark" -msgstr "" - #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:9 #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:16 #, python-format @@ -1467,98 +1477,86 @@ msgstr "" msgid "Notes" msgstr "" -#: aleksis/apps/alsijil/views.py:114 +#: aleksis/apps/alsijil/views.py:112 msgid "You either selected an invalid lesson or there is currently no lesson in progress." msgstr "" -#: aleksis/apps/alsijil/views.py:147 +#: aleksis/apps/alsijil/views.py:145 msgid "You are not allowed to create a lesson documentation for a lesson in the future." msgstr "" -#: aleksis/apps/alsijil/views.py:264 +#: aleksis/apps/alsijil/views.py:262 msgid "The lesson documentation has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:298 +#: aleksis/apps/alsijil/views.py:296 msgid "The personal notes have been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:658 +#: aleksis/apps/alsijil/views.py:656 msgid "Generate full register printout for {}" msgstr "" -#: aleksis/apps/alsijil/views.py:659 +#: aleksis/apps/alsijil/views.py:657 msgid "Generate full register printout …" msgstr "" -#: aleksis/apps/alsijil/views.py:660 +#: aleksis/apps/alsijil/views.py:658 msgid "The printout has been generated successfully." msgstr "" -#: aleksis/apps/alsijil/views.py:661 +#: aleksis/apps/alsijil/views.py:659 msgid "There was a problem while generating the printout." msgstr "" -#: aleksis/apps/alsijil/views.py:664 +#: aleksis/apps/alsijil/views.py:662 msgid "Download PDF" msgstr "" -#: aleksis/apps/alsijil/views.py:1030 +#: aleksis/apps/alsijil/views.py:1028 msgid "The absence has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1051 +#: aleksis/apps/alsijil/views.py:1049 msgid "The personal note has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1074 -msgid "The extra mark has been created." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1086 -msgid "The extra mark has been saved." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1097 -msgid "The extra mark has been deleted." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1119 +#: aleksis/apps/alsijil/views.py:1072 msgid "The excuse type has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1131 +#: aleksis/apps/alsijil/views.py:1084 msgid "The excuse type has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1142 +#: aleksis/apps/alsijil/views.py:1095 msgid "The excuse type has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1164 +#: aleksis/apps/alsijil/views.py:1117 msgid "The group role has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1176 +#: aleksis/apps/alsijil/views.py:1129 msgid "The group role has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1187 +#: aleksis/apps/alsijil/views.py:1140 msgid "The group role has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1221 aleksis/apps/alsijil/views.py:1253 +#: aleksis/apps/alsijil/views.py:1174 aleksis/apps/alsijil/views.py:1206 msgid "The group role has been assigned." msgstr "" -#: aleksis/apps/alsijil/views.py:1272 +#: aleksis/apps/alsijil/views.py:1225 msgid "The group role assignment has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1293 +#: aleksis/apps/alsijil/views.py:1246 msgid "The group role assignment has been stopped." msgstr "" -#: aleksis/apps/alsijil/views.py:1306 +#: aleksis/apps/alsijil/views.py:1259 msgid "The group role assignment has been deleted." msgstr "" diff --git a/aleksis/apps/alsijil/locale/ru/LC_MESSAGES/django.po b/aleksis/apps/alsijil/locale/ru/LC_MESSAGES/django.po index e1467925c5f0b0d1b4d9eebf9a8eea986c3785f3..b5a37983138f9498ff9cea509867a17a8c920ab0 100644 --- a/aleksis/apps/alsijil/locale/ru/LC_MESSAGES/django.po +++ b/aleksis/apps/alsijil/locale/ru/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-23 21:13+0200\n" +"POT-Creation-Date: 2024-08-18 16:34+0200\n" "PO-Revision-Date: 2023-05-26 04:38+0000\n" "Last-Translator: Serhii Horichenko <m@sgg.im>\n" "Language-Team: Russian <https://translate.edugit.org/projects/aleksis/aleksis-app-alsijil/ru/>\n" @@ -31,8 +31,8 @@ msgstr "Отметить без уважительной причины" msgid "Mark as {excuse_type.name}" msgstr "Отметить как {excuse_type.name}" -#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:29 -#: aleksis/apps/alsijil/tables.py:53 aleksis/apps/alsijil/tables.py:78 +#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:33 +#: aleksis/apps/alsijil/tables.py:58 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:29 msgid "Delete" msgstr "Удалить" @@ -111,7 +111,7 @@ msgid "Before" msgstr "До" #: aleksis/apps/alsijil/filters.py:14 aleksis/apps/alsijil/forms.py:371 -#: aleksis/apps/alsijil/models.py:471 aleksis/apps/alsijil/tables.py:116 +#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:96 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:126 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:223 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:189 @@ -152,20 +152,20 @@ msgid "You can't select a group and a teacher both." msgstr "Ð’Ñ‹ не можете одновременно выбрать группу и преподавателÑ." #: aleksis/apps/alsijil/forms.py:193 aleksis/apps/alsijil/forms.py:291 -#: aleksis/apps/alsijil/models.py:609 aleksis/apps/alsijil/models.py:658 +#: aleksis/apps/alsijil/models.py:788 aleksis/apps/alsijil/models.py:879 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:63 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:27 msgid "Person" msgstr "Физлицо" #: aleksis/apps/alsijil/forms.py:194 aleksis/apps/alsijil/forms.py:372 -#: aleksis/apps/alsijil/models.py:730 +#: aleksis/apps/alsijil/models.py:960 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:64 msgid "Start date" msgstr "Дата начала" #: aleksis/apps/alsijil/forms.py:195 aleksis/apps/alsijil/forms.py:373 -#: aleksis/apps/alsijil/models.py:734 +#: aleksis/apps/alsijil/models.py:964 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:65 msgid "End date" msgstr "Дата окончаниÑ" @@ -178,8 +178,8 @@ msgstr "Ðачало уроков" msgid "End period" msgstr "Окончание уроков" -#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/models.py:623 -#: aleksis/apps/alsijil/tables.py:117 aleksis/apps/alsijil/tables.py:138 +#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/tables.py:97 +#: aleksis/apps/alsijil/tables.py:118 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:50 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:392 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:28 @@ -188,7 +188,7 @@ msgstr "Окончание уроков" msgid "Absent" msgstr "ОтÑутÑтвует" -#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:146 +#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:126 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:54 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:135 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:30 @@ -198,8 +198,8 @@ msgstr "ОтÑутÑтвует" msgid "Excused" msgstr "Уважительно" -#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:79 -#: aleksis/apps/alsijil/models.py:255 +#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:85 +#: aleksis/apps/alsijil/models.py:261 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:31 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:72 msgid "Excuse type" @@ -220,7 +220,7 @@ msgstr "Учебный год" msgid "Has lesson documentation" msgstr "Имеет в наличии учебный материал" -#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:130 +#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:110 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:172 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:236 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:311 @@ -228,7 +228,7 @@ msgstr "Имеет в наличии учебный материал" #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:21 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:375 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:455 -#: aleksis/apps/alsijil/util/alsijil_helpers.py:330 +#: aleksis/apps/alsijil/util/alsijil_helpers.py:331 msgid "Event" msgstr "Событие" @@ -272,41 +272,39 @@ msgstr "Может назначать роль группы Ð´Ð»Ñ Ñтой гр msgid "Can register an absence for a person" msgstr "Может региÑтрировать отÑутÑтвиÑ" -#: aleksis/apps/alsijil/models.py:58 aleksis/apps/alsijil/models.py:432 +#: aleksis/apps/alsijil/models.py:64 aleksis/apps/alsijil/models.py:438 msgid "Short name" msgstr "Короткое имÑ" -#: aleksis/apps/alsijil/models.py:59 aleksis/apps/alsijil/models.py:433 -#: aleksis/apps/alsijil/models.py:694 +#: aleksis/apps/alsijil/models.py:65 aleksis/apps/alsijil/models.py:439 +#: aleksis/apps/alsijil/models.py:924 #: aleksis/apps/alsijil/templates/alsijil/class_register/groups.html:20 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:12 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:25 msgid "Name" msgstr "Полное имÑ" -#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/tables.py:41 +#: aleksis/apps/alsijil/models.py:69 aleksis/apps/alsijil/tables.py:21 msgid "Count as absent" msgstr "КоличеÑтво отÑутÑтвующих" -#: aleksis/apps/alsijil/models.py:65 +#: aleksis/apps/alsijil/models.py:71 msgid "If checked, this excuse type will be counted as a missed lesson. If not checked,it won't show up in the absence report." msgstr "ЕÑли отмечено, Ñтот тип объÑÑнительной будет заÑчитан как пропущенный урок. ЕÑли не отмечено, то без запиÑи в отчет о пропуÑках." -#: aleksis/apps/alsijil/models.py:80 +#: aleksis/apps/alsijil/models.py:86 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:9 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:30 msgid "Excuse types" msgstr "Типы объÑÑнительных" -#: aleksis/apps/alsijil/models.py:235 aleksis/apps/alsijil/models.py:334 +#: aleksis/apps/alsijil/models.py:241 aleksis/apps/alsijil/models.py:340 msgid "Year" msgstr "Год" -#: aleksis/apps/alsijil/models.py:260 aleksis/apps/alsijil/models.py:450 -#: aleksis/apps/alsijil/tables.py:120 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:8 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:9 +#: aleksis/apps/alsijil/models.py:266 aleksis/apps/alsijil/models.py:456 +#: aleksis/apps/alsijil/tables.py:100 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:57 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:32 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:19 @@ -314,18 +312,18 @@ msgstr "Год" msgid "Extra marks" msgstr "Дополнительные отметки" -#: aleksis/apps/alsijil/models.py:294 +#: aleksis/apps/alsijil/models.py:300 msgid "Personal note" msgstr "Ð›Ð¸Ñ‡Ð½Ð°Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ°" -#: aleksis/apps/alsijil/models.py:295 +#: aleksis/apps/alsijil/models.py:301 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:47 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:370 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:21 msgid "Personal notes" msgstr "Личные заметки" -#: aleksis/apps/alsijil/models.py:346 +#: aleksis/apps/alsijil/models.py:352 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:128 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:259 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:337 @@ -334,7 +332,7 @@ msgstr "Личные заметки" msgid "Lesson topic" msgstr "Тема урока" -#: aleksis/apps/alsijil/models.py:347 aleksis/apps/alsijil/models.py:483 +#: aleksis/apps/alsijil/models.py:353 aleksis/apps/alsijil/models.py:491 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:129 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:265 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:342 @@ -343,7 +341,7 @@ msgstr "Тема урока" msgid "Homework" msgstr "ДомашнÑÑ Ñ€Ð°Ð±Ð¾Ñ‚Ð°" -#: aleksis/apps/alsijil/models.py:348 +#: aleksis/apps/alsijil/models.py:354 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:130 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:271 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:346 @@ -351,315 +349,338 @@ msgstr "ДомашнÑÑ Ñ€Ð°Ð±Ð¾Ñ‚Ð°" msgid "Group note" msgstr "Ð“Ñ€ÑƒÐ¿Ð¿Ð¾Ð²Ð°Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ°" -#: aleksis/apps/alsijil/models.py:398 +#: aleksis/apps/alsijil/models.py:404 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:16 msgid "Lesson documentation" msgstr "Учебный материал" -#: aleksis/apps/alsijil/models.py:399 +#: aleksis/apps/alsijil/models.py:405 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:43 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:77 msgid "Lesson documentations" msgstr "Учебные материалы" -#: aleksis/apps/alsijil/models.py:435 +#: aleksis/apps/alsijil/models.py:441 msgid "Foreground colour" msgstr "" -#: aleksis/apps/alsijil/models.py:436 +#: aleksis/apps/alsijil/models.py:442 msgid "Background colour" msgstr "" -#: aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:444 msgid "Show in coursebook" msgstr "" -#: aleksis/apps/alsijil/models.py:449 +#: aleksis/apps/alsijil/models.py:455 msgid "Extra mark" msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ°" -#: aleksis/apps/alsijil/models.py:467 +#: aleksis/apps/alsijil/models.py:475 msgid "Course" msgstr "" -#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:111 +#: aleksis/apps/alsijil/models.py:487 aleksis/apps/alsijil/tables.py:91 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:127 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:253 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:331 msgid "Teachers" msgstr "Преподаватели" -#: aleksis/apps/alsijil/models.py:482 +#: aleksis/apps/alsijil/models.py:490 #, fuzzy #| msgid "Lesson topic" msgid "Lesson Topic" msgstr "Тема урока" -#: aleksis/apps/alsijil/models.py:484 +#: aleksis/apps/alsijil/models.py:492 #, fuzzy #| msgid "Group note" msgid "Group Note" msgstr "Ð“Ñ€ÑƒÐ¿Ð¿Ð¾Ð²Ð°Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ°" -#: aleksis/apps/alsijil/models.py:512 aleksis/apps/alsijil/models.py:619 -#: aleksis/apps/alsijil/models.py:665 +#: aleksis/apps/alsijil/models.py:496 +msgid "Participation touched at" +msgstr "" + +#: aleksis/apps/alsijil/models.py:525 aleksis/apps/alsijil/models.py:798 +#: aleksis/apps/alsijil/models.py:886 #, fuzzy #| msgid "Lesson documentation" msgid "Documentation" msgstr "Учебный материал" -#: aleksis/apps/alsijil/models.py:513 +#: aleksis/apps/alsijil/models.py:526 #, fuzzy #| msgid "Lesson documentations" msgid "Documentations" msgstr "Учебные материалы" -#: aleksis/apps/alsijil/models.py:612 +#: aleksis/apps/alsijil/models.py:791 #, fuzzy #| msgid "Group roles" msgid "Groups of Person" msgstr "Роли групп" -#: aleksis/apps/alsijil/models.py:625 +#: aleksis/apps/alsijil/models.py:804 #, fuzzy #| msgid "Absences" msgid "Absence Reason" msgstr "ПропуÑки" -#: aleksis/apps/alsijil/models.py:634 +#: aleksis/apps/alsijil/models.py:816 #, fuzzy #| msgid "Absences" msgid "Base Absence" msgstr "ПропуÑки" -#: aleksis/apps/alsijil/models.py:641 aleksis/apps/alsijil/models.py:642 +#: aleksis/apps/alsijil/models.py:819 aleksis/apps/alsijil/tables.py:98 +#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 +#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 +#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 +msgid "Tardiness" +msgstr "Опоздание" + +#: aleksis/apps/alsijil/models.py:862 aleksis/apps/alsijil/models.py:863 msgid "Participation Status" msgstr "" -#: aleksis/apps/alsijil/models.py:670 +#: aleksis/apps/alsijil/models.py:891 #, fuzzy #| msgid "Notes" msgid "Note" msgstr "Заметки" -#: aleksis/apps/alsijil/models.py:672 +#: aleksis/apps/alsijil/models.py:893 #, fuzzy #| msgid "Extra mark" msgid "Extra Mark" msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ°" -#: aleksis/apps/alsijil/models.py:679 +#: aleksis/apps/alsijil/models.py:900 #, fuzzy #| msgid "Personal note" msgid "Personal Note" msgstr "Ð›Ð¸Ñ‡Ð½Ð°Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ°" -#: aleksis/apps/alsijil/models.py:680 +#: aleksis/apps/alsijil/models.py:901 #, fuzzy #| msgid "Personal notes" msgid "Personal Notes" msgstr "Личные заметки" -#: aleksis/apps/alsijil/models.py:695 +#: aleksis/apps/alsijil/models.py:912 +msgid "A person got assigned the same extra mark multiple times per documentation." +msgstr "" + +#: aleksis/apps/alsijil/models.py:925 msgid "Icon" msgstr "Иконка" -#: aleksis/apps/alsijil/models.py:696 +#: aleksis/apps/alsijil/models.py:926 msgid "Colour" msgstr "Цвет" -#: aleksis/apps/alsijil/models.py:702 aleksis/apps/alsijil/models.py:717 +#: aleksis/apps/alsijil/models.py:932 aleksis/apps/alsijil/models.py:947 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:62 msgid "Group role" msgstr "Роль группы" -#: aleksis/apps/alsijil/models.py:703 +#: aleksis/apps/alsijil/models.py:933 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:90 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:9 msgid "Group roles" msgstr "Роли групп" -#: aleksis/apps/alsijil/models.py:704 +#: aleksis/apps/alsijil/models.py:934 msgid "Can assign group role" msgstr "Может назначать роль группы" -#: aleksis/apps/alsijil/models.py:723 +#: aleksis/apps/alsijil/models.py:953 msgid "Assigned person" msgstr "Ðазначенное физлицо" -#: aleksis/apps/alsijil/models.py:728 aleksis/apps/alsijil/tables.py:105 +#: aleksis/apps/alsijil/models.py:958 aleksis/apps/alsijil/tables.py:85 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:124 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:242 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:321 msgid "Groups" msgstr "Группы" -#: aleksis/apps/alsijil/models.py:735 +#: aleksis/apps/alsijil/models.py:965 msgid "Can be left empty if end date is not clear yet" msgstr "ЕÑли нет точной конечной даты, можно оÑтавить незаполненным" -#: aleksis/apps/alsijil/models.py:750 +#: aleksis/apps/alsijil/models.py:980 msgid "Group role assignment" msgstr "Ðазначение роли группы" -#: aleksis/apps/alsijil/models.py:751 +#: aleksis/apps/alsijil/models.py:981 msgid "Group role assignments" msgstr "Ðазначение ролей групп" -#: aleksis/apps/alsijil/models.py:758 +#: aleksis/apps/alsijil/models.py:988 msgid "Can view lesson overview" msgstr "Может проÑматривать обзор урока" -#: aleksis/apps/alsijil/models.py:759 +#: aleksis/apps/alsijil/models.py:989 msgid "Can view week overview" msgstr "Может проÑматривать недельный обзор" -#: aleksis/apps/alsijil/models.py:760 +#: aleksis/apps/alsijil/models.py:990 msgid "Can view full register" msgstr "Может проÑматривать веÑÑŒ журнал" -#: aleksis/apps/alsijil/models.py:761 +#: aleksis/apps/alsijil/models.py:991 msgid "Can register absence" msgstr "Может региÑтрировать отÑутÑтвие" -#: aleksis/apps/alsijil/models.py:762 +#: aleksis/apps/alsijil/models.py:992 msgid "Can list all personal note filters" msgstr "Может проÑматривать вÑе фильтры личных заметок" -#: aleksis/apps/alsijil/preferences.py:9 +#: aleksis/apps/alsijil/preferences.py:16 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:16 msgid "Class register" msgstr "КлаÑÑный журнал" -#: aleksis/apps/alsijil/preferences.py:17 +#: aleksis/apps/alsijil/preferences.py:24 msgid "Block adding personal notes for cancelled lessons" msgstr "Блокировать добавление личных заметок к отмененным урокам" -#: aleksis/apps/alsijil/preferences.py:25 +#: aleksis/apps/alsijil/preferences.py:32 msgid "Allow users to view their own personal notes" msgstr "Разрешить пользователÑм проÑматривать Ñвои личные заметки" -#: aleksis/apps/alsijil/preferences.py:34 +#: aleksis/apps/alsijil/preferences.py:41 msgid "Allow primary group owners to register future absences for students in their groups" msgstr "Разрешить владельцам оÑновных групп региÑтрировать будущие пропуÑки Ñтудентов в Ñвоих группах" -#: aleksis/apps/alsijil/preferences.py:44 +#: aleksis/apps/alsijil/preferences.py:51 msgid "Grant the owner of a parent group the same privileges as the owners of the respective child groups" msgstr "Ðаделить владельца родительÑкой группы такими же правами, как у владельца ÑоответÑтвующих дочерних групп" -#: aleksis/apps/alsijil/preferences.py:54 +#: aleksis/apps/alsijil/preferences.py:61 msgid "Allow original teachers to edit their lessons although they are substituted" msgstr "Разрешить изначальным преподавателÑм редактировать Ñвои уроки даже поÑле их замены" -#: aleksis/apps/alsijil/preferences.py:63 +#: aleksis/apps/alsijil/preferences.py:70 msgid "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods" msgstr "ПереноÑить данные Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ урока в раÑпиÑании на текущие уроки через неÑколько уроков" -#: aleksis/apps/alsijil/preferences.py:66 +#: aleksis/apps/alsijil/preferences.py:73 msgid "This will carry over data only if the data in the following periods are empty." msgstr "Ðто перенеÑёт данные только в Ñлучае отÑутÑÑ‚Ð²Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… в поÑледующих уроках." -#: aleksis/apps/alsijil/preferences.py:75 +#: aleksis/apps/alsijil/preferences.py:82 msgid "Allow carrying over data from any lesson period to all other lesson periods with the same lesson and in the same week" msgstr "Разрешить Ð¿ÐµÑ€ÐµÐ½Ð¾Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… Ñ Ð»ÑŽÐ±Ð¾Ð³Ð¾ урока на вÑе такие же уроки Ñ Ñ‚Ð°ÐºÐ¸Ð¼ же номером в раÑпиÑании на той же неделе" -#: aleksis/apps/alsijil/preferences.py:79 +#: aleksis/apps/alsijil/preferences.py:86 msgid "This will carry over data only if the data in the aforementioned periods are empty." msgstr "Ðто перенеÑёт данные только еÑли в упомÑнутых выше уроках данные не заполнены." -#: aleksis/apps/alsijil/preferences.py:88 +#: aleksis/apps/alsijil/preferences.py:95 msgid "Carry over personal notes to all following lesson periods on the same day." msgstr "ПереноÑить личные заметки на вÑе поÑледующие уроки того же днÑ." -#: aleksis/apps/alsijil/preferences.py:97 +#: aleksis/apps/alsijil/preferences.py:104 msgid "Allow teachers to open lesson periods on the same day and not just at the beginning of the period" msgstr "Разрешить преподавателÑм открывать уроки в тот же день, а не только в начале уроков" -#: aleksis/apps/alsijil/preferences.py:101 +#: aleksis/apps/alsijil/preferences.py:108 msgid "Lessons in the past are not affected by this setting, you can open them whenever you want." msgstr "Ðти наÑтройки не влиÑÑŽÑ‚ на прошлые уроки. Ð’Ñ‹ можете открывать их когда-угодно." -#: aleksis/apps/alsijil/preferences.py:110 +#: aleksis/apps/alsijil/preferences.py:117 msgid "Allow teachers to add data for lessons in holidays" msgstr "Разрешить преподавателÑм добавлÑть учебный материал (данные Ð´Ð»Ñ ÑƒÑ€Ð¾ÐºÐ¾Ð²) на выходных" -#: aleksis/apps/alsijil/preferences.py:119 +#: aleksis/apps/alsijil/preferences.py:126 msgid "Allow group owners to assign group roles to the parents of the group's members" msgstr "Разрешить владельцам групп назначать роли групп родителÑм учаÑтников групп" -#: aleksis/apps/alsijil/preferences.py:128 +#: aleksis/apps/alsijil/preferences.py:135 msgid "Show assigned group roles in week view" msgstr "Показать назначенные роли групп в недельном обзоре" -#: aleksis/apps/alsijil/preferences.py:129 +#: aleksis/apps/alsijil/preferences.py:136 msgid "Only week view of groups" msgstr "Только недельные обзоры групп" -#: aleksis/apps/alsijil/preferences.py:137 +#: aleksis/apps/alsijil/preferences.py:144 msgid "Show assigned group roles in lesson view" msgstr "Показать назначенные роли групп в обзоре урока" -#: aleksis/apps/alsijil/preferences.py:147 +#: aleksis/apps/alsijil/preferences.py:154 msgid "Items per page in lessons table" msgstr "КоличеÑтво запиÑей на Ñтраницу в таблице Ñ Ñ€Ð°ÑпиÑанием" -#: aleksis/apps/alsijil/preferences.py:151 +#: aleksis/apps/alsijil/preferences.py:158 msgid "Each page must show at least one item." msgstr "ÐšÐ°Ð¶Ð´Ð°Ñ Ñтраница должна Ñодержать Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одну Ñтроку." -#: aleksis/apps/alsijil/preferences.py:159 +#: aleksis/apps/alsijil/preferences.py:166 msgid "Filter lessons by existence of their lesson documentation on default" msgstr "По-умолчанию фильтровать уроки по наличию в них учебного материала" -#: aleksis/apps/alsijil/preferences.py:170 +#: aleksis/apps/alsijil/preferences.py:177 msgid "Allow editing of all future documentations" msgstr "" -#: aleksis/apps/alsijil/preferences.py:173 +#: aleksis/apps/alsijil/preferences.py:180 msgid "Allow editing of all documentations up to and including those on the current day" msgstr "" -#: aleksis/apps/alsijil/preferences.py:178 +#: aleksis/apps/alsijil/preferences.py:185 msgid "Allow editing of all documentations up to and including those on the current date and time" msgstr "" -#: aleksis/apps/alsijil/preferences.py:183 +#: aleksis/apps/alsijil/preferences.py:190 msgid "Set time range for which documentations may be edited" msgstr "" -#: aleksis/apps/alsijil/tables.py:23 aleksis/apps/alsijil/tables.py:47 -#: aleksis/apps/alsijil/tables.py:72 +#: aleksis/apps/alsijil/preferences.py:201 +msgid "User is allowed to register absences for members of groups the user is an owner of with these group types" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:205 +msgid "If you leave it empty, all member of groups the user is an owner of will be shown." +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:217 +msgid "Group type of groups to be shown first in the group select field on the coursebook overview page" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:220 +msgid "If you leave it empty, no group type will be used." +msgstr "" + +#: aleksis/apps/alsijil/tables.py:27 aleksis/apps/alsijil/tables.py:52 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:13 msgid "Edit" msgstr "Редактировать" -#: aleksis/apps/alsijil/tables.py:96 +#: aleksis/apps/alsijil/tables.py:76 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:348 msgid "Date" msgstr "Дата" -#: aleksis/apps/alsijil/tables.py:99 +#: aleksis/apps/alsijil/tables.py:79 #: aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html:30 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:122 msgid "Period" msgstr "Урок" -#: aleksis/apps/alsijil/tables.py:118 -#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 -#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 -#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 -msgid "Tardiness" -msgstr "Опоздание" - -#: aleksis/apps/alsijil/tables.py:119 +#: aleksis/apps/alsijil/tables.py:99 msgid "Excuse" msgstr "ОбъÑÑнительнаÑ" -#: aleksis/apps/alsijil/tables.py:156 +#: aleksis/apps/alsijil/tables.py:136 #, fuzzy, python-brace-format #| msgid "{value}' late" msgid "{value}' tardiness" @@ -1016,17 +1037,6 @@ msgstr "" " Ðе иÑпользуйте Ñтот функционал Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑŠÑÑнительной по-умолчанию или еÑли не ведёте разделение по типам.\n" " " -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:7 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:14 -msgid "Create extra mark" -msgstr "Создать дополнительную отметку" - -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:7 -msgid "Edit extra mark" -msgstr "Редактировать дополнительную отметку" - #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:9 #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:16 #, python-format @@ -1559,108 +1569,111 @@ msgstr "ÐеделÑ" msgid "Notes" msgstr "Заметки" -#: aleksis/apps/alsijil/views.py:114 +#: aleksis/apps/alsijil/views.py:112 msgid "You either selected an invalid lesson or there is currently no lesson in progress." msgstr "Ð’Ñ‹ или выбрали неправильный урок, или ÑÐµÐ¹Ñ‡Ð°Ñ ÑƒÑ€Ð¾ÐºÐ° нет." -#: aleksis/apps/alsijil/views.py:147 +#: aleksis/apps/alsijil/views.py:145 msgid "You are not allowed to create a lesson documentation for a lesson in the future." msgstr "Вам Ð½ÐµÐ»ÑŒÐ·Ñ Ñоздавать учебные материалы Ð´Ð»Ñ ÑƒÑ€Ð¾ÐºÐ¾Ð² в будущем." -#: aleksis/apps/alsijil/views.py:264 +#: aleksis/apps/alsijil/views.py:262 msgid "The lesson documentation has been saved." msgstr "Учебный материал Ñохранён." -#: aleksis/apps/alsijil/views.py:298 +#: aleksis/apps/alsijil/views.py:296 msgid "The personal notes have been saved." msgstr "Личные заметки Ñохранены." -#: aleksis/apps/alsijil/views.py:658 +#: aleksis/apps/alsijil/views.py:656 #, fuzzy #| msgid "Generate printout" msgid "Generate full register printout for {}" msgstr "Подготовить к печати" -#: aleksis/apps/alsijil/views.py:659 +#: aleksis/apps/alsijil/views.py:657 #, fuzzy #| msgid "Generate printout" msgid "Generate full register printout …" msgstr "Подготовить к печати" -#: aleksis/apps/alsijil/views.py:660 +#: aleksis/apps/alsijil/views.py:658 #, fuzzy #| msgid "The personal note has been deleted." msgid "The printout has been generated successfully." msgstr "Ð›Ð¸Ñ‡Ð½Ð°Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ° удалена." -#: aleksis/apps/alsijil/views.py:661 +#: aleksis/apps/alsijil/views.py:659 msgid "There was a problem while generating the printout." msgstr "" -#: aleksis/apps/alsijil/views.py:664 +#: aleksis/apps/alsijil/views.py:662 msgid "Download PDF" msgstr "" -#: aleksis/apps/alsijil/views.py:1030 +#: aleksis/apps/alsijil/views.py:1028 msgid "The absence has been saved." msgstr "ОтÑутÑтвие Ñохранено." -#: aleksis/apps/alsijil/views.py:1051 +#: aleksis/apps/alsijil/views.py:1049 msgid "The personal note has been deleted." msgstr "Ð›Ð¸Ñ‡Ð½Ð°Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ° удалена." -#: aleksis/apps/alsijil/views.py:1074 -msgid "The extra mark has been created." -msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ° Ñоздана." - -#: aleksis/apps/alsijil/views.py:1086 -msgid "The extra mark has been saved." -msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ° Ñохранена." - -#: aleksis/apps/alsijil/views.py:1097 -msgid "The extra mark has been deleted." -msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ° удалена." - -#: aleksis/apps/alsijil/views.py:1119 +#: aleksis/apps/alsijil/views.py:1072 msgid "The excuse type has been created." msgstr "Тип объÑÑнительной Ñоздан." -#: aleksis/apps/alsijil/views.py:1131 +#: aleksis/apps/alsijil/views.py:1084 msgid "The excuse type has been saved." msgstr "Тип объÑÑнительной Ñохранён." -#: aleksis/apps/alsijil/views.py:1142 +#: aleksis/apps/alsijil/views.py:1095 msgid "The excuse type has been deleted." msgstr "Тип объÑÑнительной удалён." -#: aleksis/apps/alsijil/views.py:1164 +#: aleksis/apps/alsijil/views.py:1117 msgid "The group role has been created." msgstr "Роль группы Ñоздана." -#: aleksis/apps/alsijil/views.py:1176 +#: aleksis/apps/alsijil/views.py:1129 msgid "The group role has been saved." msgstr "Роль группы Ñохранена." -#: aleksis/apps/alsijil/views.py:1187 +#: aleksis/apps/alsijil/views.py:1140 msgid "The group role has been deleted." msgstr "Роль группы удалена." -#: aleksis/apps/alsijil/views.py:1221 aleksis/apps/alsijil/views.py:1253 +#: aleksis/apps/alsijil/views.py:1174 aleksis/apps/alsijil/views.py:1206 msgid "The group role has been assigned." msgstr "Роль группы назначена." -#: aleksis/apps/alsijil/views.py:1272 +#: aleksis/apps/alsijil/views.py:1225 msgid "The group role assignment has been saved." msgstr "Ðазначение роли группы Ñохранено." -#: aleksis/apps/alsijil/views.py:1293 +#: aleksis/apps/alsijil/views.py:1246 msgid "The group role assignment has been stopped." msgstr "Ðазначение роли группы оÑтановлено." -#: aleksis/apps/alsijil/views.py:1306 +#: aleksis/apps/alsijil/views.py:1259 msgid "The group role assignment has been deleted." msgstr "Ðазначение роли группы удалено." +#~ msgid "Create extra mark" +#~ msgstr "Создать дополнительную отметку" + +#~ msgid "Edit extra mark" +#~ msgstr "Редактировать дополнительную отметку" + +#~ msgid "The extra mark has been created." +#~ msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ° Ñоздана." + +#~ msgid "The extra mark has been saved." +#~ msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ° Ñохранена." + +#~ msgid "The extra mark has been deleted." +#~ msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ° удалена." + #~ msgid "Current lesson" #~ msgstr "Текущий урок" diff --git a/aleksis/apps/alsijil/locale/tr_TR/LC_MESSAGES/django.po b/aleksis/apps/alsijil/locale/tr_TR/LC_MESSAGES/django.po index 4a23675366e43a10b5190e5dfd31b46a442dd86f..40892069d224a5e6ef62ed3a0ce7fe80720ca876 100644 --- a/aleksis/apps/alsijil/locale/tr_TR/LC_MESSAGES/django.po +++ b/aleksis/apps/alsijil/locale/tr_TR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-23 21:13+0200\n" +"POT-Creation-Date: 2024-08-18 16:34+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -30,8 +30,8 @@ msgstr "" msgid "Mark as {excuse_type.name}" msgstr "" -#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:29 -#: aleksis/apps/alsijil/tables.py:53 aleksis/apps/alsijil/tables.py:78 +#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:33 +#: aleksis/apps/alsijil/tables.py:58 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:29 msgid "Delete" msgstr "" @@ -110,7 +110,7 @@ msgid "Before" msgstr "" #: aleksis/apps/alsijil/filters.py:14 aleksis/apps/alsijil/forms.py:371 -#: aleksis/apps/alsijil/models.py:471 aleksis/apps/alsijil/tables.py:116 +#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:96 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:126 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:223 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:189 @@ -151,20 +151,20 @@ msgid "You can't select a group and a teacher both." msgstr "" #: aleksis/apps/alsijil/forms.py:193 aleksis/apps/alsijil/forms.py:291 -#: aleksis/apps/alsijil/models.py:609 aleksis/apps/alsijil/models.py:658 +#: aleksis/apps/alsijil/models.py:788 aleksis/apps/alsijil/models.py:879 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:63 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:27 msgid "Person" msgstr "" #: aleksis/apps/alsijil/forms.py:194 aleksis/apps/alsijil/forms.py:372 -#: aleksis/apps/alsijil/models.py:730 +#: aleksis/apps/alsijil/models.py:960 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:64 msgid "Start date" msgstr "" #: aleksis/apps/alsijil/forms.py:195 aleksis/apps/alsijil/forms.py:373 -#: aleksis/apps/alsijil/models.py:734 +#: aleksis/apps/alsijil/models.py:964 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:65 msgid "End date" msgstr "" @@ -177,8 +177,8 @@ msgstr "" msgid "End period" msgstr "" -#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/models.py:623 -#: aleksis/apps/alsijil/tables.py:117 aleksis/apps/alsijil/tables.py:138 +#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/tables.py:97 +#: aleksis/apps/alsijil/tables.py:118 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:50 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:392 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:28 @@ -187,7 +187,7 @@ msgstr "" msgid "Absent" msgstr "" -#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:146 +#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:126 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:54 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:135 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:30 @@ -197,8 +197,8 @@ msgstr "" msgid "Excused" msgstr "" -#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:79 -#: aleksis/apps/alsijil/models.py:255 +#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:85 +#: aleksis/apps/alsijil/models.py:261 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:31 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:72 msgid "Excuse type" @@ -219,7 +219,7 @@ msgstr "" msgid "Has lesson documentation" msgstr "" -#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:130 +#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:110 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:172 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:236 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:311 @@ -227,7 +227,7 @@ msgstr "" #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:21 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:375 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:455 -#: aleksis/apps/alsijil/util/alsijil_helpers.py:330 +#: aleksis/apps/alsijil/util/alsijil_helpers.py:331 msgid "Event" msgstr "" @@ -271,41 +271,39 @@ msgstr "" msgid "Can register an absence for a person" msgstr "" -#: aleksis/apps/alsijil/models.py:58 aleksis/apps/alsijil/models.py:432 +#: aleksis/apps/alsijil/models.py:64 aleksis/apps/alsijil/models.py:438 msgid "Short name" msgstr "" -#: aleksis/apps/alsijil/models.py:59 aleksis/apps/alsijil/models.py:433 -#: aleksis/apps/alsijil/models.py:694 +#: aleksis/apps/alsijil/models.py:65 aleksis/apps/alsijil/models.py:439 +#: aleksis/apps/alsijil/models.py:924 #: aleksis/apps/alsijil/templates/alsijil/class_register/groups.html:20 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:12 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:25 msgid "Name" msgstr "" -#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/tables.py:41 +#: aleksis/apps/alsijil/models.py:69 aleksis/apps/alsijil/tables.py:21 msgid "Count as absent" msgstr "" -#: aleksis/apps/alsijil/models.py:65 +#: aleksis/apps/alsijil/models.py:71 msgid "If checked, this excuse type will be counted as a missed lesson. If not checked,it won't show up in the absence report." msgstr "" -#: aleksis/apps/alsijil/models.py:80 +#: aleksis/apps/alsijil/models.py:86 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:9 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:30 msgid "Excuse types" msgstr "" -#: aleksis/apps/alsijil/models.py:235 aleksis/apps/alsijil/models.py:334 +#: aleksis/apps/alsijil/models.py:241 aleksis/apps/alsijil/models.py:340 msgid "Year" msgstr "" -#: aleksis/apps/alsijil/models.py:260 aleksis/apps/alsijil/models.py:450 -#: aleksis/apps/alsijil/tables.py:120 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:8 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:9 +#: aleksis/apps/alsijil/models.py:266 aleksis/apps/alsijil/models.py:456 +#: aleksis/apps/alsijil/tables.py:100 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:57 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:32 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:19 @@ -313,18 +311,18 @@ msgstr "" msgid "Extra marks" msgstr "" -#: aleksis/apps/alsijil/models.py:294 +#: aleksis/apps/alsijil/models.py:300 msgid "Personal note" msgstr "" -#: aleksis/apps/alsijil/models.py:295 +#: aleksis/apps/alsijil/models.py:301 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:47 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:370 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:21 msgid "Personal notes" msgstr "" -#: aleksis/apps/alsijil/models.py:346 +#: aleksis/apps/alsijil/models.py:352 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:128 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:259 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:337 @@ -333,7 +331,7 @@ msgstr "" msgid "Lesson topic" msgstr "" -#: aleksis/apps/alsijil/models.py:347 aleksis/apps/alsijil/models.py:483 +#: aleksis/apps/alsijil/models.py:353 aleksis/apps/alsijil/models.py:491 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:129 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:265 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:342 @@ -342,7 +340,7 @@ msgstr "" msgid "Homework" msgstr "" -#: aleksis/apps/alsijil/models.py:348 +#: aleksis/apps/alsijil/models.py:354 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:130 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:271 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:346 @@ -350,293 +348,316 @@ msgstr "" msgid "Group note" msgstr "" -#: aleksis/apps/alsijil/models.py:398 +#: aleksis/apps/alsijil/models.py:404 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:16 msgid "Lesson documentation" msgstr "" -#: aleksis/apps/alsijil/models.py:399 +#: aleksis/apps/alsijil/models.py:405 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:43 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:77 msgid "Lesson documentations" msgstr "" -#: aleksis/apps/alsijil/models.py:435 +#: aleksis/apps/alsijil/models.py:441 msgid "Foreground colour" msgstr "" -#: aleksis/apps/alsijil/models.py:436 +#: aleksis/apps/alsijil/models.py:442 msgid "Background colour" msgstr "" -#: aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:444 msgid "Show in coursebook" msgstr "" -#: aleksis/apps/alsijil/models.py:449 +#: aleksis/apps/alsijil/models.py:455 msgid "Extra mark" msgstr "" -#: aleksis/apps/alsijil/models.py:467 +#: aleksis/apps/alsijil/models.py:475 msgid "Course" msgstr "" -#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:111 +#: aleksis/apps/alsijil/models.py:487 aleksis/apps/alsijil/tables.py:91 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:127 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:253 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:331 msgid "Teachers" msgstr "" -#: aleksis/apps/alsijil/models.py:482 +#: aleksis/apps/alsijil/models.py:490 msgid "Lesson Topic" msgstr "" -#: aleksis/apps/alsijil/models.py:484 +#: aleksis/apps/alsijil/models.py:492 msgid "Group Note" msgstr "" -#: aleksis/apps/alsijil/models.py:512 aleksis/apps/alsijil/models.py:619 -#: aleksis/apps/alsijil/models.py:665 +#: aleksis/apps/alsijil/models.py:496 +msgid "Participation touched at" +msgstr "" + +#: aleksis/apps/alsijil/models.py:525 aleksis/apps/alsijil/models.py:798 +#: aleksis/apps/alsijil/models.py:886 msgid "Documentation" msgstr "" -#: aleksis/apps/alsijil/models.py:513 +#: aleksis/apps/alsijil/models.py:526 msgid "Documentations" msgstr "" -#: aleksis/apps/alsijil/models.py:612 +#: aleksis/apps/alsijil/models.py:791 msgid "Groups of Person" msgstr "" -#: aleksis/apps/alsijil/models.py:625 +#: aleksis/apps/alsijil/models.py:804 msgid "Absence Reason" msgstr "" -#: aleksis/apps/alsijil/models.py:634 +#: aleksis/apps/alsijil/models.py:816 msgid "Base Absence" msgstr "" -#: aleksis/apps/alsijil/models.py:641 aleksis/apps/alsijil/models.py:642 +#: aleksis/apps/alsijil/models.py:819 aleksis/apps/alsijil/tables.py:98 +#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 +#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 +#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 +msgid "Tardiness" +msgstr "" + +#: aleksis/apps/alsijil/models.py:862 aleksis/apps/alsijil/models.py:863 msgid "Participation Status" msgstr "" -#: aleksis/apps/alsijil/models.py:670 +#: aleksis/apps/alsijil/models.py:891 msgid "Note" msgstr "" -#: aleksis/apps/alsijil/models.py:672 +#: aleksis/apps/alsijil/models.py:893 msgid "Extra Mark" msgstr "" -#: aleksis/apps/alsijil/models.py:679 +#: aleksis/apps/alsijil/models.py:900 msgid "Personal Note" msgstr "" -#: aleksis/apps/alsijil/models.py:680 +#: aleksis/apps/alsijil/models.py:901 msgid "Personal Notes" msgstr "" -#: aleksis/apps/alsijil/models.py:695 +#: aleksis/apps/alsijil/models.py:912 +msgid "A person got assigned the same extra mark multiple times per documentation." +msgstr "" + +#: aleksis/apps/alsijil/models.py:925 msgid "Icon" msgstr "" -#: aleksis/apps/alsijil/models.py:696 +#: aleksis/apps/alsijil/models.py:926 msgid "Colour" msgstr "" -#: aleksis/apps/alsijil/models.py:702 aleksis/apps/alsijil/models.py:717 +#: aleksis/apps/alsijil/models.py:932 aleksis/apps/alsijil/models.py:947 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:62 msgid "Group role" msgstr "" -#: aleksis/apps/alsijil/models.py:703 +#: aleksis/apps/alsijil/models.py:933 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:90 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:9 msgid "Group roles" msgstr "" -#: aleksis/apps/alsijil/models.py:704 +#: aleksis/apps/alsijil/models.py:934 msgid "Can assign group role" msgstr "" -#: aleksis/apps/alsijil/models.py:723 +#: aleksis/apps/alsijil/models.py:953 msgid "Assigned person" msgstr "" -#: aleksis/apps/alsijil/models.py:728 aleksis/apps/alsijil/tables.py:105 +#: aleksis/apps/alsijil/models.py:958 aleksis/apps/alsijil/tables.py:85 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:124 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:242 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:321 msgid "Groups" msgstr "" -#: aleksis/apps/alsijil/models.py:735 +#: aleksis/apps/alsijil/models.py:965 msgid "Can be left empty if end date is not clear yet" msgstr "" -#: aleksis/apps/alsijil/models.py:750 +#: aleksis/apps/alsijil/models.py:980 msgid "Group role assignment" msgstr "" -#: aleksis/apps/alsijil/models.py:751 +#: aleksis/apps/alsijil/models.py:981 msgid "Group role assignments" msgstr "" -#: aleksis/apps/alsijil/models.py:758 +#: aleksis/apps/alsijil/models.py:988 msgid "Can view lesson overview" msgstr "" -#: aleksis/apps/alsijil/models.py:759 +#: aleksis/apps/alsijil/models.py:989 msgid "Can view week overview" msgstr "" -#: aleksis/apps/alsijil/models.py:760 +#: aleksis/apps/alsijil/models.py:990 msgid "Can view full register" msgstr "" -#: aleksis/apps/alsijil/models.py:761 +#: aleksis/apps/alsijil/models.py:991 msgid "Can register absence" msgstr "" -#: aleksis/apps/alsijil/models.py:762 +#: aleksis/apps/alsijil/models.py:992 msgid "Can list all personal note filters" msgstr "" -#: aleksis/apps/alsijil/preferences.py:9 +#: aleksis/apps/alsijil/preferences.py:16 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:16 msgid "Class register" msgstr "" -#: aleksis/apps/alsijil/preferences.py:17 +#: aleksis/apps/alsijil/preferences.py:24 msgid "Block adding personal notes for cancelled lessons" msgstr "" -#: aleksis/apps/alsijil/preferences.py:25 +#: aleksis/apps/alsijil/preferences.py:32 msgid "Allow users to view their own personal notes" msgstr "" -#: aleksis/apps/alsijil/preferences.py:34 +#: aleksis/apps/alsijil/preferences.py:41 msgid "Allow primary group owners to register future absences for students in their groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:44 +#: aleksis/apps/alsijil/preferences.py:51 msgid "Grant the owner of a parent group the same privileges as the owners of the respective child groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:54 +#: aleksis/apps/alsijil/preferences.py:61 msgid "Allow original teachers to edit their lessons although they are substituted" msgstr "" -#: aleksis/apps/alsijil/preferences.py:63 +#: aleksis/apps/alsijil/preferences.py:70 msgid "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods" msgstr "" -#: aleksis/apps/alsijil/preferences.py:66 +#: aleksis/apps/alsijil/preferences.py:73 msgid "This will carry over data only if the data in the following periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:75 +#: aleksis/apps/alsijil/preferences.py:82 msgid "Allow carrying over data from any lesson period to all other lesson periods with the same lesson and in the same week" msgstr "" -#: aleksis/apps/alsijil/preferences.py:79 +#: aleksis/apps/alsijil/preferences.py:86 msgid "This will carry over data only if the data in the aforementioned periods are empty." msgstr "" -#: aleksis/apps/alsijil/preferences.py:88 +#: aleksis/apps/alsijil/preferences.py:95 msgid "Carry over personal notes to all following lesson periods on the same day." msgstr "" -#: aleksis/apps/alsijil/preferences.py:97 +#: aleksis/apps/alsijil/preferences.py:104 msgid "Allow teachers to open lesson periods on the same day and not just at the beginning of the period" msgstr "" -#: aleksis/apps/alsijil/preferences.py:101 +#: aleksis/apps/alsijil/preferences.py:108 msgid "Lessons in the past are not affected by this setting, you can open them whenever you want." msgstr "" -#: aleksis/apps/alsijil/preferences.py:110 +#: aleksis/apps/alsijil/preferences.py:117 msgid "Allow teachers to add data for lessons in holidays" msgstr "" -#: aleksis/apps/alsijil/preferences.py:119 +#: aleksis/apps/alsijil/preferences.py:126 msgid "Allow group owners to assign group roles to the parents of the group's members" msgstr "" -#: aleksis/apps/alsijil/preferences.py:128 +#: aleksis/apps/alsijil/preferences.py:135 msgid "Show assigned group roles in week view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:129 +#: aleksis/apps/alsijil/preferences.py:136 msgid "Only week view of groups" msgstr "" -#: aleksis/apps/alsijil/preferences.py:137 +#: aleksis/apps/alsijil/preferences.py:144 msgid "Show assigned group roles in lesson view" msgstr "" -#: aleksis/apps/alsijil/preferences.py:147 +#: aleksis/apps/alsijil/preferences.py:154 msgid "Items per page in lessons table" msgstr "" -#: aleksis/apps/alsijil/preferences.py:151 +#: aleksis/apps/alsijil/preferences.py:158 msgid "Each page must show at least one item." msgstr "" -#: aleksis/apps/alsijil/preferences.py:159 +#: aleksis/apps/alsijil/preferences.py:166 msgid "Filter lessons by existence of their lesson documentation on default" msgstr "" -#: aleksis/apps/alsijil/preferences.py:170 +#: aleksis/apps/alsijil/preferences.py:177 msgid "Allow editing of all future documentations" msgstr "" -#: aleksis/apps/alsijil/preferences.py:173 +#: aleksis/apps/alsijil/preferences.py:180 msgid "Allow editing of all documentations up to and including those on the current day" msgstr "" -#: aleksis/apps/alsijil/preferences.py:178 +#: aleksis/apps/alsijil/preferences.py:185 msgid "Allow editing of all documentations up to and including those on the current date and time" msgstr "" -#: aleksis/apps/alsijil/preferences.py:183 +#: aleksis/apps/alsijil/preferences.py:190 msgid "Set time range for which documentations may be edited" msgstr "" -#: aleksis/apps/alsijil/tables.py:23 aleksis/apps/alsijil/tables.py:47 -#: aleksis/apps/alsijil/tables.py:72 +#: aleksis/apps/alsijil/preferences.py:201 +msgid "User is allowed to register absences for members of groups the user is an owner of with these group types" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:205 +msgid "If you leave it empty, all member of groups the user is an owner of will be shown." +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:217 +msgid "Group type of groups to be shown first in the group select field on the coursebook overview page" +msgstr "" + +#: aleksis/apps/alsijil/preferences.py:220 +msgid "If you leave it empty, no group type will be used." +msgstr "" + +#: aleksis/apps/alsijil/tables.py:27 aleksis/apps/alsijil/tables.py:52 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:13 msgid "Edit" msgstr "" -#: aleksis/apps/alsijil/tables.py:96 +#: aleksis/apps/alsijil/tables.py:76 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:348 msgid "Date" msgstr "" -#: aleksis/apps/alsijil/tables.py:99 +#: aleksis/apps/alsijil/tables.py:79 #: aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html:30 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:122 msgid "Period" msgstr "" -#: aleksis/apps/alsijil/tables.py:118 -#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 -#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 -#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 -msgid "Tardiness" -msgstr "" - -#: aleksis/apps/alsijil/tables.py:119 +#: aleksis/apps/alsijil/tables.py:99 msgid "Excuse" msgstr "" -#: aleksis/apps/alsijil/tables.py:156 +#: aleksis/apps/alsijil/tables.py:136 #, python-brace-format msgid "{value}' tardiness" msgstr "" @@ -963,17 +984,6 @@ msgid "" " " msgstr "" -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:7 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:14 -msgid "Create extra mark" -msgstr "" - -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:7 -msgid "Edit extra mark" -msgstr "" - #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:9 #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:16 #, python-format @@ -1467,98 +1477,86 @@ msgstr "" msgid "Notes" msgstr "" -#: aleksis/apps/alsijil/views.py:114 +#: aleksis/apps/alsijil/views.py:112 msgid "You either selected an invalid lesson or there is currently no lesson in progress." msgstr "" -#: aleksis/apps/alsijil/views.py:147 +#: aleksis/apps/alsijil/views.py:145 msgid "You are not allowed to create a lesson documentation for a lesson in the future." msgstr "" -#: aleksis/apps/alsijil/views.py:264 +#: aleksis/apps/alsijil/views.py:262 msgid "The lesson documentation has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:298 +#: aleksis/apps/alsijil/views.py:296 msgid "The personal notes have been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:658 +#: aleksis/apps/alsijil/views.py:656 msgid "Generate full register printout for {}" msgstr "" -#: aleksis/apps/alsijil/views.py:659 +#: aleksis/apps/alsijil/views.py:657 msgid "Generate full register printout …" msgstr "" -#: aleksis/apps/alsijil/views.py:660 +#: aleksis/apps/alsijil/views.py:658 msgid "The printout has been generated successfully." msgstr "" -#: aleksis/apps/alsijil/views.py:661 +#: aleksis/apps/alsijil/views.py:659 msgid "There was a problem while generating the printout." msgstr "" -#: aleksis/apps/alsijil/views.py:664 +#: aleksis/apps/alsijil/views.py:662 msgid "Download PDF" msgstr "" -#: aleksis/apps/alsijil/views.py:1030 +#: aleksis/apps/alsijil/views.py:1028 msgid "The absence has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1051 +#: aleksis/apps/alsijil/views.py:1049 msgid "The personal note has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1074 -msgid "The extra mark has been created." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1086 -msgid "The extra mark has been saved." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1097 -msgid "The extra mark has been deleted." -msgstr "" - -#: aleksis/apps/alsijil/views.py:1119 +#: aleksis/apps/alsijil/views.py:1072 msgid "The excuse type has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1131 +#: aleksis/apps/alsijil/views.py:1084 msgid "The excuse type has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1142 +#: aleksis/apps/alsijil/views.py:1095 msgid "The excuse type has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1164 +#: aleksis/apps/alsijil/views.py:1117 msgid "The group role has been created." msgstr "" -#: aleksis/apps/alsijil/views.py:1176 +#: aleksis/apps/alsijil/views.py:1129 msgid "The group role has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1187 +#: aleksis/apps/alsijil/views.py:1140 msgid "The group role has been deleted." msgstr "" -#: aleksis/apps/alsijil/views.py:1221 aleksis/apps/alsijil/views.py:1253 +#: aleksis/apps/alsijil/views.py:1174 aleksis/apps/alsijil/views.py:1206 msgid "The group role has been assigned." msgstr "" -#: aleksis/apps/alsijil/views.py:1272 +#: aleksis/apps/alsijil/views.py:1225 msgid "The group role assignment has been saved." msgstr "" -#: aleksis/apps/alsijil/views.py:1293 +#: aleksis/apps/alsijil/views.py:1246 msgid "The group role assignment has been stopped." msgstr "" -#: aleksis/apps/alsijil/views.py:1306 +#: aleksis/apps/alsijil/views.py:1259 msgid "The group role assignment has been deleted." msgstr "" diff --git a/aleksis/apps/alsijil/locale/uk/LC_MESSAGES/django.po b/aleksis/apps/alsijil/locale/uk/LC_MESSAGES/django.po index 6353e21e708c593793b756827d3f056ba5edb008..6eeacbadcf3cccf7d38c4e8e09458e8f66ba0338 100644 --- a/aleksis/apps/alsijil/locale/uk/LC_MESSAGES/django.po +++ b/aleksis/apps/alsijil/locale/uk/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-23 21:13+0200\n" -"PO-Revision-Date: 2023-01-25 05:58+0000\n" +"POT-Creation-Date: 2024-08-18 16:34+0200\n" +"PO-Revision-Date: 2024-08-27 15:25+0000\n" "Last-Translator: Serhii Horichenko <m@sgg.im>\n" "Language-Team: Ukrainian <https://translate.edugit.org/projects/aleksis/aleksis-app-alsijil/uk/>\n" "Language: uk\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" -"X-Generator: Weblate 4.12.1\n" +"X-Generator: Weblate 5.0.2\n" #: aleksis/apps/alsijil/actions.py:18 msgid "Mark as excused" @@ -31,8 +31,8 @@ msgstr "Позначити Ñк непоÑÑнений" msgid "Mark as {excuse_type.name}" msgstr "Позначити Ñк {excuse_type.name}" -#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:29 -#: aleksis/apps/alsijil/tables.py:53 aleksis/apps/alsijil/tables.py:78 +#: aleksis/apps/alsijil/actions.py:48 aleksis/apps/alsijil/tables.py:33 +#: aleksis/apps/alsijil/tables.py:58 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:29 msgid "Delete" msgstr "Видалити" @@ -111,7 +111,7 @@ msgid "Before" msgstr "Перед" #: aleksis/apps/alsijil/filters.py:14 aleksis/apps/alsijil/forms.py:371 -#: aleksis/apps/alsijil/models.py:471 aleksis/apps/alsijil/tables.py:116 +#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:96 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:126 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:223 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:189 @@ -152,20 +152,20 @@ msgid "You can't select a group and a teacher both." msgstr "Ви не можете обрати одночаÑно групу та викладача." #: aleksis/apps/alsijil/forms.py:193 aleksis/apps/alsijil/forms.py:291 -#: aleksis/apps/alsijil/models.py:609 aleksis/apps/alsijil/models.py:658 +#: aleksis/apps/alsijil/models.py:788 aleksis/apps/alsijil/models.py:879 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:63 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:27 msgid "Person" msgstr "ОÑоба" #: aleksis/apps/alsijil/forms.py:194 aleksis/apps/alsijil/forms.py:372 -#: aleksis/apps/alsijil/models.py:730 +#: aleksis/apps/alsijil/models.py:960 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:64 msgid "Start date" msgstr "Дата початку" #: aleksis/apps/alsijil/forms.py:195 aleksis/apps/alsijil/forms.py:373 -#: aleksis/apps/alsijil/models.py:734 +#: aleksis/apps/alsijil/models.py:964 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:65 msgid "End date" msgstr "Дата закінченнÑ" @@ -178,8 +178,8 @@ msgstr "Початок уроків" msgid "End period" msgstr "Ð—Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ ÑƒÑ€Ð¾ÐºÑ–Ð²" -#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/models.py:623 -#: aleksis/apps/alsijil/tables.py:117 aleksis/apps/alsijil/tables.py:138 +#: aleksis/apps/alsijil/forms.py:198 aleksis/apps/alsijil/tables.py:97 +#: aleksis/apps/alsijil/tables.py:118 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:50 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:392 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:28 @@ -188,7 +188,7 @@ msgstr "Ð—Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ ÑƒÑ€Ð¾ÐºÑ–Ð²" msgid "Absent" msgstr "ВідÑутній(-Ñ)" -#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:146 +#: aleksis/apps/alsijil/forms.py:199 aleksis/apps/alsijil/tables.py:126 #: aleksis/apps/alsijil/templates/alsijil/absences/register_confirm.html:54 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:135 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:30 @@ -198,8 +198,8 @@ msgstr "ВідÑутній(-Ñ)" msgid "Excused" msgstr "ПоÑÑнено" -#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:79 -#: aleksis/apps/alsijil/models.py:255 +#: aleksis/apps/alsijil/forms.py:201 aleksis/apps/alsijil/models.py:85 +#: aleksis/apps/alsijil/models.py:261 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:31 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:72 msgid "Excuse type" @@ -220,7 +220,7 @@ msgstr "Ðавчальний рік" msgid "Has lesson documentation" msgstr "Має учбовий матеріал" -#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:130 +#: aleksis/apps/alsijil/managers.py:91 aleksis/apps/alsijil/tables.py:110 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:172 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:236 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:311 @@ -228,7 +228,7 @@ msgstr "Має учбовий матеріал" #: aleksis/apps/alsijil/templates/alsijil/partials/lesson_status.html:21 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:375 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:455 -#: aleksis/apps/alsijil/util/alsijil_helpers.py:330 +#: aleksis/apps/alsijil/util/alsijil_helpers.py:331 msgid "Event" msgstr "ПодіÑ" @@ -272,41 +272,39 @@ msgstr "Може призначати роль групи Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гру msgid "Can register an absence for a person" msgstr "Може реєÑтрувати відÑутніÑть оÑоби" -#: aleksis/apps/alsijil/models.py:58 aleksis/apps/alsijil/models.py:432 +#: aleksis/apps/alsijil/models.py:64 aleksis/apps/alsijil/models.py:438 msgid "Short name" msgstr "Коротке ім'Ñ" -#: aleksis/apps/alsijil/models.py:59 aleksis/apps/alsijil/models.py:433 -#: aleksis/apps/alsijil/models.py:694 +#: aleksis/apps/alsijil/models.py:65 aleksis/apps/alsijil/models.py:439 +#: aleksis/apps/alsijil/models.py:924 #: aleksis/apps/alsijil/templates/alsijil/class_register/groups.html:20 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:12 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:25 msgid "Name" msgstr "Повне ім'Ñ" -#: aleksis/apps/alsijil/models.py:63 aleksis/apps/alsijil/tables.py:41 +#: aleksis/apps/alsijil/models.py:69 aleksis/apps/alsijil/tables.py:21 msgid "Count as absent" msgstr "КількіÑть відÑутніх" -#: aleksis/apps/alsijil/models.py:65 +#: aleksis/apps/alsijil/models.py:71 msgid "If checked, this excuse type will be counted as a missed lesson. If not checked,it won't show up in the absence report." msgstr "Якщо відмічено, цей тип поÑÑÐ½ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ зарахований Ñк пропущений урок. Якщо не відмічено, то без запиÑу у звіт відÑутноÑті." -#: aleksis/apps/alsijil/models.py:80 +#: aleksis/apps/alsijil/models.py:86 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html:9 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:30 msgid "Excuse types" msgstr "Типи поÑÑнень" -#: aleksis/apps/alsijil/models.py:235 aleksis/apps/alsijil/models.py:334 +#: aleksis/apps/alsijil/models.py:241 aleksis/apps/alsijil/models.py:340 msgid "Year" msgstr "Рік" -#: aleksis/apps/alsijil/models.py:260 aleksis/apps/alsijil/models.py:450 -#: aleksis/apps/alsijil/tables.py:120 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:8 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:9 +#: aleksis/apps/alsijil/models.py:266 aleksis/apps/alsijil/models.py:456 +#: aleksis/apps/alsijil/tables.py:100 #: aleksis/apps/alsijil/templates/alsijil/partials/legend.html:57 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:32 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:19 @@ -314,18 +312,18 @@ msgstr "Рік" msgid "Extra marks" msgstr "Додаткові відмітки" -#: aleksis/apps/alsijil/models.py:294 +#: aleksis/apps/alsijil/models.py:300 msgid "Personal note" msgstr "ОÑобиÑта нотатка" -#: aleksis/apps/alsijil/models.py:295 +#: aleksis/apps/alsijil/models.py:301 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:47 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:370 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:21 msgid "Personal notes" msgstr "ОÑобиÑті нотатки" -#: aleksis/apps/alsijil/models.py:346 +#: aleksis/apps/alsijil/models.py:352 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:128 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:259 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:337 @@ -334,7 +332,7 @@ msgstr "ОÑобиÑті нотатки" msgid "Lesson topic" msgstr "Тема уроку" -#: aleksis/apps/alsijil/models.py:347 aleksis/apps/alsijil/models.py:483 +#: aleksis/apps/alsijil/models.py:353 aleksis/apps/alsijil/models.py:491 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:129 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:265 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:342 @@ -343,7 +341,7 @@ msgstr "Тема уроку" msgid "Homework" msgstr "Ð”Ð¾Ð¼Ð°ÑˆÐ½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð°" -#: aleksis/apps/alsijil/models.py:348 +#: aleksis/apps/alsijil/models.py:354 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:130 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:271 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:346 @@ -351,355 +349,351 @@ msgstr "Ð”Ð¾Ð¼Ð°ÑˆÐ½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð°" msgid "Group note" msgstr "Групова нотатка" -#: aleksis/apps/alsijil/models.py:398 +#: aleksis/apps/alsijil/models.py:404 #: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/documentation.html:16 msgid "Lesson documentation" msgstr "Учбовий матеріал" -#: aleksis/apps/alsijil/models.py:399 +#: aleksis/apps/alsijil/models.py:405 #: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:43 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:77 msgid "Lesson documentations" msgstr "Учбові матеріали" -#: aleksis/apps/alsijil/models.py:435 +#: aleksis/apps/alsijil/models.py:441 msgid "Foreground colour" -msgstr "" +msgstr "Колір переднього плану" -#: aleksis/apps/alsijil/models.py:436 +#: aleksis/apps/alsijil/models.py:442 msgid "Background colour" -msgstr "" +msgstr "Колір фону" -#: aleksis/apps/alsijil/models.py:438 +#: aleksis/apps/alsijil/models.py:444 msgid "Show in coursebook" -msgstr "" +msgstr "Показати у курÑовій книзі" -#: aleksis/apps/alsijil/models.py:449 +#: aleksis/apps/alsijil/models.py:455 msgid "Extra mark" -msgstr "Додаткова відмітка" +msgstr "Додаткова позначка" -#: aleksis/apps/alsijil/models.py:467 +#: aleksis/apps/alsijil/models.py:475 msgid "Course" -msgstr "" +msgstr "КурÑ" -#: aleksis/apps/alsijil/models.py:479 aleksis/apps/alsijil/tables.py:111 +#: aleksis/apps/alsijil/models.py:487 aleksis/apps/alsijil/tables.py:91 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:127 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:253 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:331 msgid "Teachers" msgstr "Викладачі" -#: aleksis/apps/alsijil/models.py:482 -#, fuzzy -#| msgid "Lesson topic" +#: aleksis/apps/alsijil/models.py:490 msgid "Lesson Topic" msgstr "Тема уроку" -#: aleksis/apps/alsijil/models.py:484 -#, fuzzy -#| msgid "Group note" +#: aleksis/apps/alsijil/models.py:492 msgid "Group Note" msgstr "Групова нотатка" -#: aleksis/apps/alsijil/models.py:512 aleksis/apps/alsijil/models.py:619 -#: aleksis/apps/alsijil/models.py:665 -#, fuzzy -#| msgid "Lesson documentation" +#: aleksis/apps/alsijil/models.py:496 +msgid "Participation touched at" +msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ ÑƒÑ‡Ð°Ñті Ñтворений о" + +#: aleksis/apps/alsijil/models.py:525 aleksis/apps/alsijil/models.py:798 +#: aleksis/apps/alsijil/models.py:886 msgid "Documentation" -msgstr "Учбовий матеріал" +msgstr "ДокументаціÑ" -#: aleksis/apps/alsijil/models.py:513 -#, fuzzy -#| msgid "Lesson documentations" +#: aleksis/apps/alsijil/models.py:526 msgid "Documentations" -msgstr "Учбові матеріали" +msgstr "ДокументаціÑ" -#: aleksis/apps/alsijil/models.py:612 -#, fuzzy -#| msgid "Group roles" +#: aleksis/apps/alsijil/models.py:791 msgid "Groups of Person" -msgstr "Ролі груп" +msgstr "Групи оÑіб" -#: aleksis/apps/alsijil/models.py:625 -#, fuzzy -#| msgid "Absences" +#: aleksis/apps/alsijil/models.py:804 msgid "Absence Reason" -msgstr "ВідÑутноÑті" +msgstr "Причина відÑутноÑті" -#: aleksis/apps/alsijil/models.py:634 -#, fuzzy -#| msgid "Absences" +#: aleksis/apps/alsijil/models.py:816 msgid "Base Absence" -msgstr "ВідÑутноÑті" +msgstr "ОÑновна відÑутніÑть" + +#: aleksis/apps/alsijil/models.py:819 aleksis/apps/alsijil/tables.py:98 +#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 +#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 +#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 +#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 +msgid "Tardiness" +msgstr "ЗапізненнÑ" -#: aleksis/apps/alsijil/models.py:641 aleksis/apps/alsijil/models.py:642 +#: aleksis/apps/alsijil/models.py:862 aleksis/apps/alsijil/models.py:863 msgid "Participation Status" -msgstr "" +msgstr "Стан учаÑті" -#: aleksis/apps/alsijil/models.py:670 -#, fuzzy -#| msgid "Notes" +#: aleksis/apps/alsijil/models.py:891 msgid "Note" -msgstr "Ðотатки" +msgstr "Ðотатка" -#: aleksis/apps/alsijil/models.py:672 -#, fuzzy -#| msgid "Extra mark" +#: aleksis/apps/alsijil/models.py:893 msgid "Extra Mark" -msgstr "Додаткова відмітка" +msgstr "Додаткова позначка" -#: aleksis/apps/alsijil/models.py:679 -#, fuzzy -#| msgid "Personal note" +#: aleksis/apps/alsijil/models.py:900 msgid "Personal Note" msgstr "ОÑобиÑта нотатка" -#: aleksis/apps/alsijil/models.py:680 -#, fuzzy -#| msgid "Personal notes" +#: aleksis/apps/alsijil/models.py:901 msgid "Personal Notes" msgstr "ОÑобиÑті нотатки" -#: aleksis/apps/alsijil/models.py:695 +#: aleksis/apps/alsijil/models.py:912 +msgid "A person got assigned the same extra mark multiple times per documentation." +msgstr "ОÑоба отримувала в документації однакову додаткову позначку неодноразово." + +#: aleksis/apps/alsijil/models.py:925 msgid "Icon" msgstr "Піктограма" -#: aleksis/apps/alsijil/models.py:696 +#: aleksis/apps/alsijil/models.py:926 msgid "Colour" msgstr "Колір" -#: aleksis/apps/alsijil/models.py:702 aleksis/apps/alsijil/models.py:717 +#: aleksis/apps/alsijil/models.py:932 aleksis/apps/alsijil/models.py:947 #: aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html:62 msgid "Group role" msgstr "Роль групи" -#: aleksis/apps/alsijil/models.py:703 +#: aleksis/apps/alsijil/models.py:933 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:90 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:8 #: aleksis/apps/alsijil/templates/alsijil/group_role/list.html:9 msgid "Group roles" msgstr "Ролі груп" -#: aleksis/apps/alsijil/models.py:704 +#: aleksis/apps/alsijil/models.py:934 msgid "Can assign group role" msgstr "Може призначати роль групи" -#: aleksis/apps/alsijil/models.py:723 +#: aleksis/apps/alsijil/models.py:953 msgid "Assigned person" msgstr "Призначена оÑоба" -#: aleksis/apps/alsijil/models.py:728 aleksis/apps/alsijil/tables.py:105 +#: aleksis/apps/alsijil/models.py:958 aleksis/apps/alsijil/tables.py:85 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:124 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:242 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:321 msgid "Groups" msgstr "Групи" -#: aleksis/apps/alsijil/models.py:735 +#: aleksis/apps/alsijil/models.py:965 msgid "Can be left empty if end date is not clear yet" msgstr "Якщо немає точної кінцевої дати, можна залишити порожнім" -#: aleksis/apps/alsijil/models.py:750 +#: aleksis/apps/alsijil/models.py:980 msgid "Group role assignment" msgstr "ÐŸÑ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ð¾Ð»Ñ– групи" -#: aleksis/apps/alsijil/models.py:751 +#: aleksis/apps/alsijil/models.py:981 msgid "Group role assignments" msgstr "ÐŸÑ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ð¾Ð»Ñ– групи" -#: aleksis/apps/alsijil/models.py:758 +#: aleksis/apps/alsijil/models.py:988 msgid "Can view lesson overview" msgstr "Може бачити оглÑд уроку" -#: aleksis/apps/alsijil/models.py:759 +#: aleksis/apps/alsijil/models.py:989 msgid "Can view week overview" msgstr "Може бачити оглÑд тижнÑ" -#: aleksis/apps/alsijil/models.py:760 +#: aleksis/apps/alsijil/models.py:990 msgid "Can view full register" msgstr "Може бачити веÑÑŒ журнал" -#: aleksis/apps/alsijil/models.py:761 +#: aleksis/apps/alsijil/models.py:991 msgid "Can register absence" msgstr "Може реєÑтрувати пропуÑк" -#: aleksis/apps/alsijil/models.py:762 +#: aleksis/apps/alsijil/models.py:992 msgid "Can list all personal note filters" msgstr "Може бачити уÑÑ– фільтри оÑобиÑтих нотаток" -#: aleksis/apps/alsijil/preferences.py:9 +#: aleksis/apps/alsijil/preferences.py:16 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:16 msgid "Class register" msgstr "КлаÑний журнал" -#: aleksis/apps/alsijil/preferences.py:17 +#: aleksis/apps/alsijil/preferences.py:24 msgid "Block adding personal notes for cancelled lessons" msgstr "Блокувати Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¾ÑобиÑтих нотаток до ÑкаÑованих уроків" -#: aleksis/apps/alsijil/preferences.py:25 +#: aleksis/apps/alsijil/preferences.py:32 msgid "Allow users to view their own personal notes" msgstr "Дозволити кориÑтувачам переглÑдати влаÑні оÑобиÑті нотатки" -#: aleksis/apps/alsijil/preferences.py:34 +#: aleksis/apps/alsijil/preferences.py:41 msgid "Allow primary group owners to register future absences for students in their groups" msgstr "Дозволити влаÑникам оÑновних груп реєÑтрувати майбутні пропуÑки Ñтудентів у Ñвоїх групах" -#: aleksis/apps/alsijil/preferences.py:44 +#: aleksis/apps/alsijil/preferences.py:51 msgid "Grant the owner of a parent group the same privileges as the owners of the respective child groups" msgstr "Ðадати влаÑнику батьківÑької групи такі Ñамі повноваженнÑ, Ñк Ñ– влаÑникам відповідних підлеглих груп" -#: aleksis/apps/alsijil/preferences.py:54 +#: aleksis/apps/alsijil/preferences.py:61 msgid "Allow original teachers to edit their lessons although they are substituted" msgstr "Дозволити початковим викладачам редагувати Ñвої уроки навіть піÑÐ»Ñ Ñ—Ñ… заміни" -#: aleksis/apps/alsijil/preferences.py:63 +#: aleksis/apps/alsijil/preferences.py:70 msgid "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods" msgstr "ПереноÑити дані з першого уроку в розкладі на поточні уроки через декілька уроків" -#: aleksis/apps/alsijil/preferences.py:66 +#: aleksis/apps/alsijil/preferences.py:73 msgid "This will carry over data only if the data in the following periods are empty." msgstr "Це перенеÑе дані лише в тому разі, коли в поточних уроках даних немає." -#: aleksis/apps/alsijil/preferences.py:75 +#: aleksis/apps/alsijil/preferences.py:82 msgid "Allow carrying over data from any lesson period to all other lesson periods with the same lesson and in the same week" msgstr "Дозволити переноÑити дані з будь-Ñкого уроку на уÑÑ– інші уроки з таким Ñамим номером урока на тому Ñамому тижні" -#: aleksis/apps/alsijil/preferences.py:79 +#: aleksis/apps/alsijil/preferences.py:86 msgid "This will carry over data only if the data in the aforementioned periods are empty." msgstr "Це перенеÑе дані лише в тому разі, коли у вищезгаданих уроках даних немає." -#: aleksis/apps/alsijil/preferences.py:88 +#: aleksis/apps/alsijil/preferences.py:95 msgid "Carry over personal notes to all following lesson periods on the same day." msgstr "ПереноÑити оÑобиÑті нотатки до вÑÑ–Ñ… наÑтупних уроків того ж днÑ." -#: aleksis/apps/alsijil/preferences.py:97 +#: aleksis/apps/alsijil/preferences.py:104 msgid "Allow teachers to open lesson periods on the same day and not just at the beginning of the period" msgstr "Дозволити викладачам відкривати уроки того Ñамого Ð´Ð½Ñ Ñ– не лише на початку уроків" -#: aleksis/apps/alsijil/preferences.py:101 +#: aleksis/apps/alsijil/preferences.py:108 msgid "Lessons in the past are not affected by this setting, you can open them whenever you want." msgstr "Ці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ впливають на минулі уроки. Ви можете відкривати Ñ—Ñ… будь-коли." -#: aleksis/apps/alsijil/preferences.py:110 +#: aleksis/apps/alsijil/preferences.py:117 msgid "Allow teachers to add data for lessons in holidays" msgstr "Дозволити викладачам додавати навчальний матеріал (дані Ð´Ð»Ñ ÑƒÑ€Ð¾ÐºÑ–Ð²) на вихідних" -#: aleksis/apps/alsijil/preferences.py:119 +#: aleksis/apps/alsijil/preferences.py:126 msgid "Allow group owners to assign group roles to the parents of the group's members" msgstr "Дозволити влаÑникам груп призначати ролі груп батькам учаÑників груп" -#: aleksis/apps/alsijil/preferences.py:128 +#: aleksis/apps/alsijil/preferences.py:135 msgid "Show assigned group roles in week view" msgstr "Показати призначені ролі груп у тижневому оглÑді" -#: aleksis/apps/alsijil/preferences.py:129 +#: aleksis/apps/alsijil/preferences.py:136 msgid "Only week view of groups" msgstr "Лише тижневі оглÑди груп" -#: aleksis/apps/alsijil/preferences.py:137 +#: aleksis/apps/alsijil/preferences.py:144 msgid "Show assigned group roles in lesson view" msgstr "Показати призначені ролі груп в оглÑді уроку" -#: aleksis/apps/alsijil/preferences.py:147 +#: aleksis/apps/alsijil/preferences.py:154 msgid "Items per page in lessons table" msgstr "КількіÑть запиÑів у розкладі на Ñторінку" -#: aleksis/apps/alsijil/preferences.py:151 +#: aleksis/apps/alsijil/preferences.py:158 msgid "Each page must show at least one item." msgstr "Кожна Ñторінка повинна мати принаймні один запиÑ." -#: aleksis/apps/alsijil/preferences.py:159 +#: aleksis/apps/alsijil/preferences.py:166 msgid "Filter lessons by existence of their lesson documentation on default" msgstr "Типово фільтувати уроки за наÑвніÑтю у них учбового матеріалу" -#: aleksis/apps/alsijil/preferences.py:170 +#: aleksis/apps/alsijil/preferences.py:177 msgid "Allow editing of all future documentations" -msgstr "" +msgstr "Дозволити редагувати уÑÑŽ майбутню документацію" -#: aleksis/apps/alsijil/preferences.py:173 +#: aleksis/apps/alsijil/preferences.py:180 msgid "Allow editing of all documentations up to and including those on the current day" -msgstr "" +msgstr "Дозволити редагувати уÑÑŽ попередню документацію, Ñьогоднішній день включно" -#: aleksis/apps/alsijil/preferences.py:178 +#: aleksis/apps/alsijil/preferences.py:185 msgid "Allow editing of all documentations up to and including those on the current date and time" -msgstr "" +msgstr "Дозволити редагувати уÑÑŽ попередню документацію, по теперішній Ñ‡Ð°Ñ Ð²ÐºÐ»ÑŽÑ‡Ð½Ð¾" -#: aleksis/apps/alsijil/preferences.py:183 +#: aleksis/apps/alsijil/preferences.py:190 msgid "Set time range for which documentations may be edited" -msgstr "" +msgstr "Ð’Ñтановити інтервал чаÑу, за Ñкий можна змінювати документацію" -#: aleksis/apps/alsijil/tables.py:23 aleksis/apps/alsijil/tables.py:47 -#: aleksis/apps/alsijil/tables.py:72 +#: aleksis/apps/alsijil/preferences.py:201 +msgid "User is allowed to register absences for members of groups the user is an owner of with these group types" +msgstr "КориÑтувачу дозволено реєÑтрувати відÑутніÑть Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників в групах вказаних типів, де він/вона Ñ” влаÑником" + +#: aleksis/apps/alsijil/preferences.py:205 +msgid "If you leave it empty, all member of groups the user is an owner of will be shown." +msgstr "Якщо залишити незаповненим, будуть показані уÑÑ– учаÑники уÑÑ–Ñ… груп, де кориÑтувач Ñ” влаÑником." + +#: aleksis/apps/alsijil/preferences.py:217 +msgid "Group type of groups to be shown first in the group select field on the coursebook overview page" +msgstr "Тип груп, Ñкий Ñлід показувати першим у полі вибору груп на Ñторінці оглÑду курÑової книги" + +#: aleksis/apps/alsijil/preferences.py:220 +msgid "If you leave it empty, no group type will be used." +msgstr "Якщо залишити порожнім, жодний тип групи не буде викориÑтаний." + +#: aleksis/apps/alsijil/tables.py:27 aleksis/apps/alsijil/tables.py:52 #: aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html:13 msgid "Edit" msgstr "Редагувати" -#: aleksis/apps/alsijil/tables.py:96 +#: aleksis/apps/alsijil/tables.py:76 #: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:348 msgid "Date" msgstr "Дата" -#: aleksis/apps/alsijil/tables.py:99 +#: aleksis/apps/alsijil/tables.py:79 #: aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html:30 #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:122 msgid "Period" msgstr "Урок" -#: aleksis/apps/alsijil/tables.py:118 -#: aleksis/apps/alsijil/templates/alsijil/class_register/person.html:161 -#: aleksis/apps/alsijil/templates/alsijil/partials/lesson/tabs/notes.html:29 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:21 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:46 -#: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:123 -#: aleksis/apps/alsijil/templates/alsijil/print/full_register.html:323 -msgid "Tardiness" -msgstr "ЗапізненнÑ" - -#: aleksis/apps/alsijil/tables.py:119 +#: aleksis/apps/alsijil/tables.py:99 msgid "Excuse" msgstr "ПоÑÑненнÑ" -#: aleksis/apps/alsijil/tables.py:156 -#, fuzzy, python-brace-format -#| msgid "{value}' late" +#: aleksis/apps/alsijil/tables.py:136 +#, python-brace-format msgid "{value}' tardiness" -msgstr "{value}' затримка" +msgstr "{value}' запізненнÑ" #: aleksis/apps/alsijil/tasks.py:26 msgid "Load data ..." -msgstr "" +msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… ..." #: aleksis/apps/alsijil/tasks.py:49 -#, fuzzy -#| msgid "Start date" msgid "Sort data ..." -msgstr "Дата початку" +msgstr "Ð¡Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… ..." #: aleksis/apps/alsijil/tasks.py:64 msgid "Load lesson data ..." -msgstr "" +msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… уроку ..." #: aleksis/apps/alsijil/tasks.py:104 msgid "Sort lesson data ..." -msgstr "" +msgstr "Ð¡Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… уроку ..." #: aleksis/apps/alsijil/tasks.py:133 -#, fuzzy -#| msgid "Statistics" msgid "Load statistics ..." -msgstr "СтатиÑтика" +msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑтатиÑтики ..." #: aleksis/apps/alsijil/tasks.py:173 msgid "Generate template ..." -msgstr "" +msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ñƒ ..." #: aleksis/apps/alsijil/tasks.py:179 msgid "Generate PDF ..." -msgstr "" +msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ PDF ..." #: aleksis/apps/alsijil/tasks.py:185 msgid "PDF generation failed" -msgstr "" +msgstr "Створити PDF не вдалоÑÑ" #: aleksis/apps/alsijil/templates/alsijil/absences/register.html:5 #: aleksis/apps/alsijil/templates/alsijil/absences/register.html:6 @@ -967,7 +961,7 @@ msgstr "ПереглÑд Ð²Ñ–Ð´Ð²Ñ–Ð´ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÑ€Ð¾ÐºÑƒ" #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:393 msgid "unexcused" -msgstr "непоÑÑнене" +msgstr "необґрунтоване" #: aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html:396 msgid "Summed up tardiness" @@ -1016,17 +1010,6 @@ msgstr "" " Ðе кориÑтуйтеÑÑ Ñ†Ð¸Ð¼ Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð¸Ð¿Ð¾Ð²Ð¾Ð³Ð¾ поÑÑÐ½ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ Ñкщо не розділÑєте на типи поÑÑнень.\n" " " -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html:7 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html:14 -msgid "Create extra mark" -msgstr "Створити додаткову позначку" - -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:6 -#: aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html:7 -msgid "Edit extra mark" -msgstr "Редагувати додаткову позначку" - #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:9 #: aleksis/apps/alsijil/templates/alsijil/group_role/assign.html:16 #, python-format @@ -1356,7 +1339,7 @@ msgstr "Ðемає доÑтупних Ñтудентів." #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:13 #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:26 msgid "Primary group" -msgstr "ОÑновна група" +msgstr "Первинна група" #: aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html:16 msgid "Uncounted Absences" @@ -1559,108 +1542,105 @@ msgstr "Тиждень" msgid "Notes" msgstr "Ðотатки" -#: aleksis/apps/alsijil/views.py:114 +#: aleksis/apps/alsijil/views.py:112 msgid "You either selected an invalid lesson or there is currently no lesson in progress." msgstr "Ðбо Ви обрали неправильний урок, або зараз уроку немає." -#: aleksis/apps/alsijil/views.py:147 +#: aleksis/apps/alsijil/views.py:145 msgid "You are not allowed to create a lesson documentation for a lesson in the future." msgstr "Вам не дозволено Ñтворювати учбові матеріали Ð´Ð»Ñ ÑƒÑ€Ð¾ÐºÑƒ у майбутньому." -#: aleksis/apps/alsijil/views.py:264 +#: aleksis/apps/alsijil/views.py:262 msgid "The lesson documentation has been saved." msgstr "Учбовий матеріал збережений." -#: aleksis/apps/alsijil/views.py:298 +#: aleksis/apps/alsijil/views.py:296 msgid "The personal notes have been saved." msgstr "ОÑобиÑті нотатки збережені." -#: aleksis/apps/alsijil/views.py:658 -#, fuzzy -#| msgid "Generate printout" +#: aleksis/apps/alsijil/views.py:656 msgid "Generate full register printout for {}" -msgstr "Підготувати Ð´Ð»Ñ Ð´Ñ€ÑƒÐºÑƒ" +msgstr "Підготувати до друку клаÑний журнал Ð´Ð»Ñ {}" -#: aleksis/apps/alsijil/views.py:659 -#, fuzzy -#| msgid "Generate printout" +#: aleksis/apps/alsijil/views.py:657 msgid "Generate full register printout …" -msgstr "Підготувати Ð´Ð»Ñ Ð´Ñ€ÑƒÐºÑƒ" +msgstr "ГотуєтьÑÑ Ð´Ð¾ друку клаÑний журнал …" -#: aleksis/apps/alsijil/views.py:660 -#, fuzzy -#| msgid "The personal note has been deleted." +#: aleksis/apps/alsijil/views.py:658 msgid "The printout has been generated successfully." -msgstr "ОÑобиÑта нотатка видалена." +msgstr "Друкована форма уÑпішно Ñтворена." -#: aleksis/apps/alsijil/views.py:661 +#: aleksis/apps/alsijil/views.py:659 msgid "There was a problem while generating the printout." -msgstr "" +msgstr "Під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð´Ñ€ÑƒÐºÐ¾Ð²Ð°Ð½Ð¾Ñ— форми виникла помилка." -#: aleksis/apps/alsijil/views.py:664 +#: aleksis/apps/alsijil/views.py:662 msgid "Download PDF" -msgstr "" +msgstr "Звантажити PDF" -#: aleksis/apps/alsijil/views.py:1030 +#: aleksis/apps/alsijil/views.py:1028 msgid "The absence has been saved." msgstr "ПропуÑк збережений." -#: aleksis/apps/alsijil/views.py:1051 +#: aleksis/apps/alsijil/views.py:1049 msgid "The personal note has been deleted." msgstr "ОÑобиÑта нотатка видалена." -#: aleksis/apps/alsijil/views.py:1074 -msgid "The extra mark has been created." -msgstr "Додаткова позначка Ñторена." - -#: aleksis/apps/alsijil/views.py:1086 -msgid "The extra mark has been saved." -msgstr "Додаткова позначка збережена." - -#: aleksis/apps/alsijil/views.py:1097 -msgid "The extra mark has been deleted." -msgstr "Додаткова позначка видалена." - -#: aleksis/apps/alsijil/views.py:1119 +#: aleksis/apps/alsijil/views.py:1072 msgid "The excuse type has been created." msgstr "Тип поÑÑÐ½ÐµÐ½Ð½Ñ Ñтворений." -#: aleksis/apps/alsijil/views.py:1131 +#: aleksis/apps/alsijil/views.py:1084 msgid "The excuse type has been saved." msgstr "Тип поÑÑÐ½ÐµÐ½Ð½Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð¸Ð¹." -#: aleksis/apps/alsijil/views.py:1142 +#: aleksis/apps/alsijil/views.py:1095 msgid "The excuse type has been deleted." msgstr "Тип поÑÑÐ½ÐµÐ½Ð½Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð¸Ð¹." -#: aleksis/apps/alsijil/views.py:1164 +#: aleksis/apps/alsijil/views.py:1117 msgid "The group role has been created." msgstr "Роль групи Ñтворена." -#: aleksis/apps/alsijil/views.py:1176 +#: aleksis/apps/alsijil/views.py:1129 msgid "The group role has been saved." msgstr "Роль групи збережена." -#: aleksis/apps/alsijil/views.py:1187 +#: aleksis/apps/alsijil/views.py:1140 msgid "The group role has been deleted." msgstr "Роль групи видалена." -#: aleksis/apps/alsijil/views.py:1221 aleksis/apps/alsijil/views.py:1253 +#: aleksis/apps/alsijil/views.py:1174 aleksis/apps/alsijil/views.py:1206 msgid "The group role has been assigned." msgstr "Роль групи призначена." -#: aleksis/apps/alsijil/views.py:1272 +#: aleksis/apps/alsijil/views.py:1225 msgid "The group role assignment has been saved." msgstr "ÐŸÑ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ð¾Ð»Ñ– групи збережене." -#: aleksis/apps/alsijil/views.py:1293 +#: aleksis/apps/alsijil/views.py:1246 msgid "The group role assignment has been stopped." msgstr "ÐŸÑ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ð¾Ð»Ñ– групи зупинене." -#: aleksis/apps/alsijil/views.py:1306 +#: aleksis/apps/alsijil/views.py:1259 msgid "The group role assignment has been deleted." msgstr "ÐŸÑ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ð¾Ð»Ñ– групи видалене." +#~ msgid "Create extra mark" +#~ msgstr "Створити додаткову позначку" + +#~ msgid "Edit extra mark" +#~ msgstr "Редагувати додаткову позначку" + +#~ msgid "The extra mark has been created." +#~ msgstr "Додаткова позначка Ñторена." + +#~ msgid "The extra mark has been saved." +#~ msgstr "Додаткова позначка збережена." + +#~ msgid "The extra mark has been deleted." +#~ msgstr "Додаткова позначка видалена." + #~ msgid "Current lesson" #~ msgstr "Поточний урок" diff --git a/aleksis/apps/alsijil/managers.py b/aleksis/apps/alsijil/managers.py index 7d0130805275359672d1337133eacd1b0a2b62ad..dc29fae25c189c7c2250279a6e8d86206f52e520 100644 --- a/aleksis/apps/alsijil/managers.py +++ b/aleksis/apps/alsijil/managers.py @@ -11,7 +11,7 @@ from django.utils.translation import gettext as _ from calendarweek import CalendarWeek from aleksis.apps.chronos.managers import DateRangeQuerySetMixin -from aleksis.core.managers import AlekSISBaseManagerWithoutMigrations, PolymorphicBaseManager +from aleksis.core.managers import AlekSISBaseManagerWithoutMigrations, RecurrencePolymorphicManager if TYPE_CHECKING: from aleksis.core.models import Group @@ -189,7 +189,7 @@ class GroupRoleAssignmentQuerySet(DateRangeQuerySetMixin, QuerySet): return self.filter(Q(groups=group) | Q(groups__child_groups=group)) -class DocumentationManager(PolymorphicBaseManager): +class DocumentationManager(RecurrencePolymorphicManager): """Manager adding specific methods to documentations.""" def get_queryset(self): @@ -205,9 +205,7 @@ class DocumentationManager(PolymorphicBaseManager): ) -class ParticipationStatusManager(PolymorphicBaseManager): +class ParticipationStatusManager(RecurrencePolymorphicManager): """Manager adding specific methods to participation statuses.""" - def get_queryset(self): - """Ensure often used related data are loaded as well.""" - return super().get_queryset().select_related("person", "absence_reason", "base_absence") + pass diff --git a/aleksis/apps/alsijil/migrations/0023_add_tardiness_and_rework_constraints.py b/aleksis/apps/alsijil/migrations/0023_add_tardiness_and_rework_constraints.py new file mode 100644 index 0000000000000000000000000000000000000000..3ca24f5865ddf5d3fb02acbd0aa7522bbc8bda13 --- /dev/null +++ b/aleksis/apps/alsijil/migrations/0023_add_tardiness_and_rework_constraints.py @@ -0,0 +1,67 @@ +# Generated by Django 4.2.10 on 2024-07-01 13:44 +# Updated for more custom logic + +from django.db import migrations, models + + +def forwards__unique_extra_mark_documentation(apps, schema_editor): + NewPersonalNote = apps.get_model("alsijil", "NewPersonalNote") # noqa + db_alias = schema_editor.connection.alias + + duplicates = (NewPersonalNote.objects.using(db_alias) + .values("documentation", "extra_mark", "person") + .annotate(count=models.Count("id")) + .filter(count__gt=1, extra_mark__isnull=False)) + + # Iterate over duplicates and delete the extra instances + for duplicate in duplicates: + pks = (NewPersonalNote + .objects + .using(db_alias) + .filter(person=duplicate["person"], documentation=duplicate["documentation"], extra_mark=duplicate["extra_mark"]) + .values_list("pk", flat=True) + )[1:] + NewPersonalNote.objects.using(db_alias).filter(pk__in=pks).delete() + + +def reverse__unique_extra_mark_documentation(apps, schema_editor): + # Nothing to do, we cannot bring back the deleted objects, but they were duplicate data, so they are not needed anyway. + pass + + +class Migration(migrations.Migration): + dependencies = [ + ('alsijil', '0022_documentation_participation_touched_at'), + ] + + operations = [ + migrations.RemoveConstraint( + model_name='newpersonalnote', + name='unique_absence_per_documentation', + ), + migrations.AddField( + model_name='participationstatus', + name='tardiness', + field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Tardiness'), + ), + migrations.AlterField( + model_name='newpersonalnote', + name='note', + field=models.TextField(blank=True, default='', verbose_name='Note'), + ), + migrations.AddConstraint( + model_name='newpersonalnote', + constraint=models.CheckConstraint( + check=models.Q(models.Q(('note', ''), _negated=True), ('extra_mark__isnull', False), _connector='OR'), + name='either_note_or_extra_mark_per_note'), + ), + migrations.RunPython(forwards__unique_extra_mark_documentation, reverse__unique_extra_mark_documentation), + migrations.AddConstraint( + model_name='newpersonalnote', + constraint=models.UniqueConstraint( + condition=models.Q(('extra_mark', None), _negated=True), + fields=('person', 'documentation', 'extra_mark'), + name='unique_person_documentation_extra_mark', + violation_error_message='A person got assigned the same extra mark multiple times per documentation.'), + ), + ] diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py index 9e68ccd06773dc8b0f6ee65ccd16c81319b94a8b..5303a40e57e3bf7ac6bbeba98da2f6e206be6007 100644 --- a/aleksis/apps/alsijil/models.py +++ b/aleksis/apps/alsijil/models.py @@ -8,6 +8,7 @@ from django.db import models from django.db.models import QuerySet from django.db.models.constraints import CheckConstraint from django.db.models.query_utils import Q +from django.http import HttpRequest from django.urls import reverse from django.utils import timezone from django.utils.formats import date_format @@ -529,8 +530,12 @@ class Documentation(CalendarEvent): @classmethod def get_documentations_for_events( cls, + datetime_start: datetime, + datetime_end: datetime, events: list, incomplete: Optional[bool] = False, + absences_exist: Optional[bool] = False, + request: Optional[HttpRequest] = None, ) -> tuple: """Get all the documentations for the events. Create dummy documentations if none exist. @@ -538,22 +543,51 @@ class Documentation(CalendarEvent): """ docs = [] dummies = [] + + # Prefetch existing documentations to speed things up + existing_documentations = Documentation.objects.filter( + datetime_start__lte=datetime_end, + datetime_end__gte=datetime_start, + amends__in=[e["REFERENCE_OBJECT"] for e in events], + ).prefetch_related("participations") + for event in events: if incomplete and event["STATUS"] == "CANCELLED": continue event_reference_obj = event["REFERENCE_OBJECT"] - existing_documentations = event_reference_obj.amended_by.filter( - datetime_start=event["DTSTART"].dt, - datetime_end=event["DTEND"].dt, + existing_documentations_event = filter( + lambda d: ( + d.datetime_start == event["DTSTART"].dt + and d.datetime_end == event["DTEND"].dt + and d.amends.id == event_reference_obj.id + ), + existing_documentations, ) - if existing_documentations.exists(): - doc = existing_documentations.first() - if incomplete and doc.topic: + doc = next(existing_documentations_event, None) + if doc: + if ( + (incomplete and doc.topic) + or ( + not request.user.has_perm( + "alsijil.edit_participation_status_for_documentation_rule", doc + ) + and not doc.participations.filter( + person__pk=request.user.person.pk, absence_reason__isnull=False + ).exists() + ) + or ( + absences_exist + and ( + not doc.participations.all() + or not [d for d in doc.participations.all() if d.absence_reason] + ) + ) + ): continue docs.append(doc) - else: + elif not absences_exist: if event_reference_obj.amends: if event_reference_obj.course: course = event_reference_obj.course @@ -578,7 +612,7 @@ class Documentation(CalendarEvent): ) ) - return (docs, dummies) + return docs, dummies @classmethod def get_documentations_for_person( @@ -587,6 +621,7 @@ class Documentation(CalendarEvent): start: datetime, end: datetime, incomplete: Optional[bool] = False, + request: Optional[HttpRequest] = None, ) -> tuple: """Get all the documentations for the person from start to end datetime. Create dummy documentations if none exist. @@ -594,7 +629,7 @@ class Documentation(CalendarEvent): """ event_params = { "type": "PARTICIPANT", - "obj_id": person, + "id": person, } events = LessonEvent.get_single_events( @@ -605,7 +640,7 @@ class Documentation(CalendarEvent): with_reference_object=True, ) - return Documentation.get_documentations_for_events(events, incomplete) + return Documentation.get_documentations_for_events(start, end, events, incomplete, request) @classmethod def parse_dummy( @@ -687,7 +722,10 @@ class Documentation(CalendarEvent): *cls.parse_dummy(_id), ), True - return cls.objects.get(id=_id), False + obj = cls.objects.get(id=_id) + if not user.has_perm("alsijil.edit_documentation_rule", obj): + raise PermissionDenied() + return obj, False def touch(self): """Ensure that participation statuses are created for this documentation.""" @@ -695,6 +733,7 @@ class Documentation(CalendarEvent): self.participation_touched_at or not self.amends or self.value_start_datetime(self) > now() + or self.amends.cancelled ): # There is no source to update from or it's too early return @@ -790,6 +829,40 @@ class ParticipationStatus(CalendarEvent): verbose_name=_("Base Absence"), ) + tardiness = models.PositiveSmallIntegerField(blank=True, null=True, verbose_name=_("Tardiness")) + + @classmethod + def get_objects( + cls, request: HttpRequest | None = None, params: dict[str, any] | None = None, **kwargs + ) -> QuerySet: + qs = ( + super() + .get_objects(request, params, **kwargs) + .select_related("person", "absence_reason") + ) + if params: + if params.get("person"): + qs = qs.filter(person=params["person"]) + elif params.get("persons"): + qs = qs.filter(person__in=params["persons"]) + elif params.get("group"): + qs = qs.filter(groups_of_person__in=params.get("group")) + return qs + + @classmethod + def value_title( + cls, reference_object: "ParticipationStatus", request: HttpRequest | None = None + ) -> str: + """Return the title of the calendar event.""" + return f"{reference_object.person} ({reference_object.absence_reason})" + + @classmethod + def value_description( + cls, reference_object: "ParticipationStatus", request: HttpRequest | None = None + ) -> str: + """Return the title of the calendar event.""" + return "" + def fill_from_kolego(self, kolego_absence: KolegoAbsence): """Take over data from a Kolego absence.""" self.base_absence = kolego_absence @@ -828,7 +901,7 @@ class NewPersonalNote(ExtensibleModel): null=True, ) - note = models.TextField(blank=True, verbose_name=_("Note")) + note = models.TextField(blank=True, default="", verbose_name=_("Note")) extra_mark = models.ForeignKey( ExtraMark, on_delete=models.PROTECT, blank=True, null=True, verbose_name=_("Extra Mark") ) @@ -840,9 +913,18 @@ class NewPersonalNote(ExtensibleModel): verbose_name = _("Personal Note") verbose_name_plural = _("Personal Notes") constraints = [ + # This constraint could be dropped in future scenarios models.CheckConstraint( check=~Q(note="") | Q(extra_mark__isnull=False), - name="unique_absence_per_documentation", + name="either_note_or_extra_mark_per_note", + ), + models.UniqueConstraint( + fields=["person", "documentation", "extra_mark"], + name="unique_person_documentation_extra_mark", + violation_error_message=_( + "A person got assigned the same extra mark multiple times per documentation." + ), + condition=~Q(extra_mark=None), ), ] diff --git a/aleksis/apps/alsijil/preferences.py b/aleksis/apps/alsijil/preferences.py index b00d9277e507e284130340b84cbbca8c07597d1f..74ed22802286eaeccc4d92b6c1e255364c3503b2 100644 --- a/aleksis/apps/alsijil/preferences.py +++ b/aleksis/apps/alsijil/preferences.py @@ -2,8 +2,15 @@ from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ from dynamic_preferences.preferences import Section -from dynamic_preferences.types import BooleanPreference, ChoicePreference, IntegerPreference - +from dynamic_preferences.types import ( + BooleanPreference, + ChoicePreference, + IntegerPreference, + ModelChoicePreference, + ModelMultipleChoicePreference, +) + +from aleksis.core.models import GroupType from aleksis.core.registries import person_preferences_registry, site_preferences_registry alsijil = Section("alsijil", verbose_name=_("Class register")) @@ -181,3 +188,36 @@ class AllowEditFutureDocumentations(ChoicePreference): ), ) verbose_name = _("Set time range for which documentations may be edited") + + +@site_preferences_registry.register +class GroupTypesRegisterAbsence(ModelMultipleChoicePreference): + section = alsijil + name = "group_types_register_absence" + required = False + default = [] + model = GroupType + verbose_name = _( + "User is allowed to register absences for members " + "of groups the user is an owner of with these group types" + ) + help_text = _( + "If you leave it empty, all member of groups the user is an owner of will be shown." + ) + + +@site_preferences_registry.register +class GroupTypePriorityCoursebook(ModelChoicePreference): + section = alsijil + name = "group_type_priority_coursebook" + required = False + default = None + model = GroupType + verbose_name = _( + "Group type of groups to be shown first in the group " + "select field on the coursebook overview page" + ) + help_text = _("If you leave it empty, no group type will be used.") + + def get_queryset(self): + return GroupType.objects.managed_and_unmanaged() diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py index 9045598fdf362f0bedb57424fd73bb450d80d669..171a0765737f8b68164af78b3823c96481eef044 100644 --- a/aleksis/apps/alsijil/rules.py +++ b/aleksis/apps/alsijil/rules.py @@ -13,9 +13,13 @@ from aleksis.core.util.predicates import ( from .util.predicates import ( can_edit_documentation, can_edit_participation_status, + can_edit_personal_note, + can_register_absence_for_at_least_one_group, + can_register_absence_for_person, can_view_any_documentation, can_view_documentation, can_view_participation_status, + can_view_personal_note, has_lesson_group_object_perm, has_person_group_object_perm, has_personal_note_group_perm, @@ -169,19 +173,16 @@ add_perm("alsijil.view_week_personalnote_rule", view_week_personal_notes_predica # Register absence view_register_absence_predicate = has_person & ( - ( - is_person_group_owner - & is_site_preference_set("alsijil", "register_absence_as_primary_group_owner") - ) - | has_global_perm("alsijil.register_absence") + can_register_absence_for_at_least_one_group | has_global_perm("alsijil.register_absence") ) +add_perm("alsijil.view_register_absence_rule", view_register_absence_predicate) register_absence_predicate = has_person & ( - view_register_absence_predicate + can_register_absence_for_person + | has_global_perm("alsijil.register_absence") | has_object_perm("core.register_absence_person") | has_person_group_object_perm("core.register_absence_group") ) -add_perm("alsijil.view_register_absence_rule", view_register_absence_predicate) add_perm("alsijil.register_absence_rule", register_absence_predicate) # View full register for group @@ -281,6 +282,10 @@ add_perm("alsijil.delete_excusetype_rule", delete_excusetype_predicate) view_extramarks_predicate = has_person & has_global_perm("alsijil.view_extramark") add_perm("alsijil.view_extramarks_rule", view_extramarks_predicate) +# Fetch all extra marks +fetch_extramarks_predicate = has_person +add_perm("alsijil.fetch_extramarks_rule", fetch_extramarks_predicate) + # Add extra mark add_extramark_predicate = view_extramarks_predicate & has_global_perm("alsijil.add_extramark") add_perm("alsijil.add_extramark_rule", add_extramark_predicate) @@ -426,12 +431,38 @@ add_perm( view_participation_status_for_documentation_predicate, ) -edit_participation_status_for_documentation_predicate = ( +edit_participation_status_for_documentation_with_time_range_predicate = ( has_person & (has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status) & is_in_allowed_time_range_for_participation_status ) +add_perm( + "alsijil.edit_participation_status_for_documentation_with_time_range_rule", + edit_participation_status_for_documentation_with_time_range_predicate, +) + +edit_participation_status_for_documentation_predicate = has_person & ( + has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status +) add_perm( "alsijil.edit_participation_status_for_documentation_rule", edit_participation_status_for_documentation_predicate, ) + +view_personal_note_predicate = has_person & ( + has_global_perm("alsijil.change_newpersonalnote") | can_view_personal_note +) +add_perm( + "alsijil.view_personal_note_rule", + view_personal_note_predicate, +) + +edit_personal_note_predicate = ( + has_person + & (has_global_perm("alsijil.change_newpersonalnote") | can_edit_personal_note) + & is_in_allowed_time_range +) +add_perm( + "alsijil.edit_personal_note_rule", + edit_personal_note_predicate, +) diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py index 35cee89b0621978d03461d6a92f686924cb69712..d17fe665c35fd074d5c1f369f1942e5e8604408d 100644 --- a/aleksis/apps/alsijil/schema/__init__.py +++ b/aleksis/apps/alsijil/schema/__init__.py @@ -1,22 +1,25 @@ from datetime import datetime from django.core.exceptions import PermissionDenied -from django.db.models.query_utils import Q +from django.db.models import BooleanField, ExpressionWrapper, Q import graphene from aleksis.apps.chronos.models import LessonEvent from aleksis.apps.cursus.models import Course from aleksis.apps.cursus.schema import CourseType +from aleksis.apps.kolego.models import AbsenceReason +from aleksis.apps.kolego.schema.absence import AbsenceReasonType from aleksis.core.models import Group, Person, SchoolTerm from aleksis.core.schema.base import FilterOrderList from aleksis.core.schema.group import GroupType -from aleksis.core.util.core_helpers import has_person +from aleksis.core.schema.person import PersonType +from aleksis.core.util.core_helpers import get_site_preferences, has_person from ..model_extensions import annotate_person_statistics_for_school_term from ..models import Documentation from .absences import ( - AbsencesBatchCreateMutation, + AbsencesForPersonsCreateMutation, ) from .documentation import ( DocumentationBatchCreateOrUpdateMutation, @@ -24,6 +27,21 @@ from .documentation import ( LessonsForPersonType, TouchDocumentationMutation, ) +from .extra_marks import ( + ExtraMarkBatchCreateMutation, + ExtraMarkBatchDeleteMutation, + ExtraMarkBatchPatchMutation, + ExtraMarkType, +) +from .participation_status import ( + ExtendParticipationStatusToAbsenceBatchMutation, + ParticipationStatusBatchPatchMutation, +) +from .personal_note import ( + PersonalNoteBatchCreateMutation, + PersonalNoteBatchDeleteMutation, + PersonalNoteBatchPatchMutation, +) from .participation_status import ParticipationStatusBatchPatchMutation from .statistics import ( DocumentationByPersonType, @@ -44,18 +62,24 @@ class Query(graphene.ObjectType): date_start=graphene.Date(required=True), date_end=graphene.Date(required=True), incomplete=graphene.Boolean(required=False), + absences_exist=graphene.Boolean(required=False), ) groups_by_person = FilterOrderList(GroupType, person=graphene.ID()) courses_of_person = FilterOrderList(CourseType, person=graphene.ID()) + absence_creation_persons = graphene.List(PersonType) lessons_for_persons = graphene.List( LessonsForPersonType, persons=graphene.List(graphene.ID, required=True), - start=graphene.Date(required=True), - end=graphene.Date(required=True), + start=graphene.DateTime(required=True), + end=graphene.DateTime(required=True), ) + extra_marks = FilterOrderList(ExtraMarkType) + + coursebook_absence_reasons = FilterOrderList(AbsenceReasonType) + statistics_by_person = graphene.Field( StatisticsByPersonType, person=graphene.ID(required=True), @@ -87,6 +111,7 @@ class Query(graphene.ObjectType): obj_type=None, obj_id=None, incomplete=False, + absences_exist=False, **kwargs, ): if ( @@ -132,7 +157,14 @@ class Query(graphene.ObjectType): ) # Lookup or create documentations and return them all. - docs, dummies = Documentation.get_documentations_for_events(events, incomplete) + docs, dummies = Documentation.get_documentations_for_events( + datetime.combine(date_start, datetime.min.time()), + datetime.combine(date_end, datetime.max.time()), + events, + incomplete, + absences_exist, + info.context, + ) return docs + dummies @staticmethod @@ -146,8 +178,17 @@ class Query(graphene.ObjectType): else: raise PermissionDenied() - return Group.objects.filter( - Q(members=person) | Q(owners=person) | Q(parent_groups__owners=person) + return ( + Group.objects.for_current_school_term_or_all() + .filter(Q(members=person) | Q(owners=person) | Q(parent_groups__owners=person)) + .distinct() + .annotate( + is_priority=ExpressionWrapper( + Q(group_type=get_site_preferences()["alsijil__group_type_priority_coursebook"]), + output_field=BooleanField(), + ) + ) + .order_by("is_priority") ) @staticmethod @@ -160,13 +201,29 @@ class Query(graphene.ObjectType): person = info.context.user.person else: raise PermissionDenied() - return Course.objects.filter( - Q(teachers=person) - | Q(groups__members=person) - | Q(groups__owners=person) - | Q(groups__parent_groups__owners=person) - ) + ( + Q(teachers=person) + | Q(groups__members=person) + | Q(groups__owners=person) + | Q(groups__parent_groups__owners=person) + ) + & Q(groups__in=Group.objects.for_current_school_term_or_all()) + ).distinct() + + @staticmethod + def resolve_absence_creation_persons(root, info, **kwargs): + if not info.context.user.has_perm("alsijil.register_absence"): + group_types = get_site_preferences()["alsijil__group_types_register_absence"] + if group_types: + return Person.objects.filter( + member_of__in=Group.objects.filter( + owners=info.context.user.person, group_type__in=group_types + ) + ) + else: + return Person.objects.filter(member_of__owners=info.context.user.person) + return Person.objects.all() @staticmethod def resolve_lessons_for_persons( @@ -182,14 +239,21 @@ class Query(graphene.ObjectType): for person in persons: docs, dummies = Documentation.get_documentations_for_person( person, - datetime.combine(start, datetime.min.time()), - datetime.combine(end, datetime.max.time()), + start, + end, + info.context, ) - lessons_for_person.append(id=person, lessons=docs + dummies) + lessons_for_person.append(LessonsForPersonType(id=person, lessons=docs + dummies)) return lessons_for_person + @staticmethod + def resolve_coursebook_absence_reasons(root, info, **kwargs): + if not info.context.user.has_perm("kolego.fetch_absencereasons_rule"): + return [] + return AbsenceReason.objects.filter(tags__short_name="class_register") + @staticmethod def resolve_statistics_by_person(root, info, person, term): school_term = SchoolTerm.objects.get(id=term) @@ -214,4 +278,13 @@ class Mutation(graphene.ObjectType): create_or_update_documentations = DocumentationBatchCreateOrUpdateMutation.Field() touch_documentation = TouchDocumentationMutation.Field() update_participation_statuses = ParticipationStatusBatchPatchMutation.Field() - create_absences = AbsencesBatchCreateMutation.Field() + create_absences_for_persons = AbsencesForPersonsCreateMutation.Field() + extend_participation_statuses = ExtendParticipationStatusToAbsenceBatchMutation.Field() + + create_extra_marks = ExtraMarkBatchCreateMutation.Field() + update_extra_marks = ExtraMarkBatchPatchMutation.Field() + delete_extra_marks = ExtraMarkBatchDeleteMutation.Field() + + create_personal_notes = PersonalNoteBatchCreateMutation.Field() + update_personal_notes = PersonalNoteBatchPatchMutation.Field() + delete_personal_notes = PersonalNoteBatchDeleteMutation.Field() diff --git a/aleksis/apps/alsijil/schema/absences.py b/aleksis/apps/alsijil/schema/absences.py index cd79f6863a688b763993e556d1651937576508a6..ab006e1d875e053e061d04c9c800ae0c3ef15f2e 100644 --- a/aleksis/apps/alsijil/schema/absences.py +++ b/aleksis/apps/alsijil/schema/absences.py @@ -1,78 +1,83 @@ -from datetime import datetime +import datetime +from typing import List + +from django.core.exceptions import PermissionDenied +from django.db.models import Q import graphene from aleksis.apps.kolego.models import Absence +from aleksis.core.models import Person -from ..models import Documentation, ParticipationStatus +from ..models import ParticipationStatus +from .participation_status import ParticipationStatusType -class AbsencesBatchCreateMutation(graphene.Mutation): +class AbsencesForPersonsCreateMutation(graphene.Mutation): class Arguments: - persons = graphene.List(graphene.ID) - start = graphene.Date() - end = graphene.Date() - comment = graphene.String() - reason = graphene.ID() + persons = graphene.List(graphene.ID, required=True) + start = graphene.DateTime(required=True) + end = graphene.DateTime(required=True) + comment = graphene.String(required=False) + reason = graphene.ID(required=True) ok = graphene.Boolean() + participation_statuses = graphene.List(ParticipationStatusType) @classmethod - def mutate(cls, root, info, persons, start, end, comment, reason): # noqa - # TODO: Check permissions for ParticipationStatus & KolegoAbsence - # See MR 356 + def mutate( + cls, + root, + info, + persons: List[str | int], + start: datetime.datetime, + end: datetime.datetime, + comment: str, + reason: str | int, + ): + participation_statuses = [] - # DocumentationBatchCreateOrUpdateMutation.create_or_update - # at least already checks permissions. + persons = Person.objects.filter(pk__in=persons) for person in persons: - # Get all documentations for this person between start & end - docs, dummies = Documentation.get_documentations_for_person( - person, - datetime.combine(start, datetime.min.time()), - datetime.combine(end, datetime.max.time()), - ) - - # Create doc for dummies that are already in the past - future = False - for dummy in dummies: - lesson_event, dummy_start, dummy_end = Documentation.parse_dummy(dummy.id) + if not info.context.user.has_perm("alsijil.register_absence_rule", person): + raise PermissionDenied() - if dummy_start < datetime.now(): - # In the past -> Create a Documentation - docs.append( - Documentation.create_from_lesson_event( - info.context.user, - lesson_event, - dummy_start, - dummy_end, - ) - ) - else: - future = True - - # Create a ParticipationStatus for each documentation - for doc in docs: - # Set person & absence_reason directly from id - ParticipationStatus.objects.create( - person_id=person, - related_documentation=doc, - absence_reason_id=reason, - ) + # Check if there is an existing absence with overlapping datetime + absences = Absence.objects.filter( + Q(datetime_start__lte=start) | Q(date_start__lte=start.date()), + Q(datetime_end__gte=end) | Q(date_end__gte=end.date()), + reason_id=reason, + person=person, + ) - # If there are still dummy documentations in the future - # create a Kolego Absence - if future: - # TODO: Are date_start & date_end from CalendarEvent enough - # or more needed? - # Set reason & person directly from id - Absence.objects.create( - date_start=datetime.now().date(), - date_end=end, + if len(absences) > 0: + kolego_absence = absences.first() + else: + # Check for same times and create otherwise + kolego_absence, __ = Absence.objects.get_or_create( + datetime_start=start, + datetime_end=end, reason_id=reason, - person_id=person, - comment=comment, + person=person, + defaults={"comment": comment}, ) - # Return ok=True if everything went well. - return AbsencesBatchCreateMutation(ok=True) + events = ParticipationStatus.get_single_events( + start, + end, + None, + {"person": person}, + with_reference_object=True, + ) + + for event in events: + participation_status = event["REFERENCE_OBJECT"] + participation_status.absence_reason_id = reason + participation_status.base_absence = kolego_absence + participation_status.save() + participation_statuses.append(participation_status) + + return AbsencesForPersonsCreateMutation( + ok=True, participation_statuses=participation_statuses + ) diff --git a/aleksis/apps/alsijil/schema/documentation.py b/aleksis/apps/alsijil/schema/documentation.py index 4a0055064abd0a9cc1bb79850390da318a808b4a..cdb2eaca122330f70bd75023a463f2dc1dc0e8e7 100644 --- a/aleksis/apps/alsijil/schema/documentation.py +++ b/aleksis/apps/alsijil/schema/documentation.py @@ -4,7 +4,14 @@ import graphene from graphene_django.types import DjangoObjectType from reversion import create_revision, set_comment, set_user -from aleksis.apps.alsijil.util.predicates import can_edit_documentation, is_in_allowed_time_range +from aleksis.apps.alsijil.util.predicates import ( + can_edit_documentation, + is_in_allowed_time_range, + is_in_allowed_time_range_for_participation_status, +) +from aleksis.apps.alsijil.util.predicates import ( + can_edit_participation_status as can_edit_participation_status_predicate, +) from aleksis.apps.chronos.schema import LessonEventType from aleksis.apps.cursus.models import Subject from aleksis.apps.cursus.schema import CourseType, SubjectType @@ -13,6 +20,7 @@ from aleksis.core.schema.base import ( DjangoFilterMixin, PermissionsTypeMixin, ) +from aleksis.core.util.core_helpers import has_person from ..models import Documentation from .participation_status import ParticipationStatusType @@ -34,7 +42,6 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp "date_start", "date_end", "teachers", - "participations", ) filter_fields = { "id": ["exact", "lte", "gte"], @@ -47,6 +54,10 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp participations = graphene.List(ParticipationStatusType, required=False) future_notice = graphene.Boolean(required=False) + future_notice_participation_status = graphene.Boolean(required=False) + + can_edit_participation_status = graphene.Boolean(required=False) + can_view_participation_status = graphene.Boolean(required=False) old_id = graphene.ID(required=False) @@ -69,16 +80,37 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp ) @staticmethod - def resolve_participations(root: Documentation, info, **kwargs): - if not info.context.user.has_perm( - "alsijil.view_participation_status_for_documentation", root - ): - return [] + def resolve_future_notice_participation_status(root: Documentation, info, **kwargs): + """Shows whether the user can edit all participation statuses based on the current time. + + This checks whether the documentation is in the future. + """ + return not is_in_allowed_time_range_for_participation_status(info.context.user, root) + + @staticmethod + def resolve_can_edit_participation_status(root: Documentation, info, **kwargs): + """Shows whether the user can edit all participation statuses of the documentation""" + return can_edit_participation_status_predicate(info.context.user, root) + @staticmethod + def resolve_can_view_participation_status(root: Documentation, info, **kwargs): + """Shows whether the user can view all participation statuses of the documentation""" + return info.context.user.has_perm( + "alsijil.view_participation_status_for_documentation_rule", root + ) + + @staticmethod + def resolve_participations(root: Documentation, info, **kwargs): # A dummy documentation will not have any participations if str(root.pk).startswith("DUMMY") or not hasattr(root, "participations"): return [] - return root.participations.select_related("absence_reason", "base_absence").all() + elif not info.context.user.has_perm( + "alsijil.view_participation_status_for_documentation_rule", root + ): + if has_person(info.context.user): + return root.participations.filter(person=info.context.user.person) + return [] + return root.participations.all() class DocumentationInputType(graphene.InputObjectType): @@ -111,9 +143,6 @@ class DocumentationBatchCreateOrUpdateMutation(graphene.Mutation): # is only introduced in Django 5.0 obj, __ = Documentation.get_or_create_by_id(_id, info.context.user) - if not info.context.user.has_perm("alsijil.edit_documentation_rule", obj): - raise PermissionDenied() - if doc.topic is not None: obj.topic = doc.topic if doc.homework is not None: @@ -151,7 +180,8 @@ class TouchDocumentationMutation(graphene.Mutation): ) if not info.context.user.has_perm( - "alsijil.edit_participation_status_for_documentation_rule", documentation + "alsijil.edit_participation_status_for_documentation_with_time_range_rule", + documentation, ): raise PermissionDenied() diff --git a/aleksis/apps/alsijil/schema/extra_marks.py b/aleksis/apps/alsijil/schema/extra_marks.py new file mode 100644 index 0000000000000000000000000000000000000000..2b1e3723d2c559e70ddd6793f5f2a89d9c1e6abe --- /dev/null +++ b/aleksis/apps/alsijil/schema/extra_marks.py @@ -0,0 +1,66 @@ +from django.core.exceptions import PermissionDenied + +from graphene_django import DjangoObjectType + +from aleksis.apps.alsijil.models import ExtraMark +from aleksis.core.schema.base import ( + BaseBatchCreateMutation, + BaseBatchDeleteMutation, + BaseBatchPatchMutation, + DjangoFilterMixin, + OptimisticResponseTypeMixin, + PermissionsTypeMixin, +) + + +class ExtraMarkType( + OptimisticResponseTypeMixin, + PermissionsTypeMixin, + DjangoFilterMixin, + DjangoObjectType, +): + class Meta: + model = ExtraMark + fields = ("id", "short_name", "name", "colour_fg", "colour_bg", "show_in_coursebook") + + @classmethod + def get_queryset(cls, queryset, info): + if info.context.user.has_perm("alsijil.fetch_extramarks_rule"): + return queryset + raise PermissionDenied() + + +class ExtraMarkBatchCreateMutation(BaseBatchCreateMutation): + class Meta: + model = ExtraMark + fields = ("short_name", "name", "colour_fg", "colour_bg", "show_in_coursebook") + optional_fields = ("name",) + + @classmethod + def check_permissions(cls, root, info, input): # noqa + if info.context.user.has_perm("alsijil.create_extramark_rule"): + return + raise PermissionDenied() + + +class ExtraMarkBatchDeleteMutation(BaseBatchDeleteMutation): + class Meta: + model = ExtraMark + + @classmethod + def check_permissions(cls, root, info, input): # noqa + if info.context.user.has_perm("alsijil.delete_extramark_rule"): + return + raise PermissionDenied() + + +class ExtraMarkBatchPatchMutation(BaseBatchPatchMutation): + class Meta: + model = ExtraMark + fields = ("id", "short_name", "name", "colour_fg", "colour_bg", "show_in_coursebook") + + @classmethod + def check_permissions(cls, root, info, input): # noqa + if info.context.user.has_perm("alsijil.edit_extramark_rule"): + return + raise PermissionDenied() diff --git a/aleksis/apps/alsijil/schema/participation_status.py b/aleksis/apps/alsijil/schema/participation_status.py index 246ae52a0aab7e7bf57f102ccd7e6558d4639496..fcf15df815619fcc808770116347458d8f7daf02 100644 --- a/aleksis/apps/alsijil/schema/participation_status.py +++ b/aleksis/apps/alsijil/schema/participation_status.py @@ -1,8 +1,16 @@ +import datetime + from django.core.exceptions import PermissionDenied +from django.utils.translation import gettext_lazy as _ +import graphene from graphene_django import DjangoObjectType +from reversion import create_revision, set_comment, set_user -from aleksis.apps.alsijil.models import ParticipationStatus +from aleksis.apps.alsijil.models import NewPersonalNote, ParticipationStatus +from aleksis.apps.alsijil.schema.personal_note import PersonalNoteType +from aleksis.apps.kolego.models import Absence +from aleksis.apps.kolego.schema.absence import AbsenceType from aleksis.core.schema.base import ( BaseBatchPatchMutation, DjangoFilterMixin, @@ -25,13 +33,37 @@ class ParticipationStatusType( "absence_reason", "related_documentation", "base_absence", + "tardiness", + ) + + notes_with_extra_mark = graphene.List(PersonalNoteType) + notes_with_note = graphene.List(PersonalNoteType) + + @staticmethod + def resolve_notes_with_extra_mark(root: ParticipationStatus, info, **kwargs): + return NewPersonalNote.objects.filter( + person=root.person, + documentation=root.related_documentation, + extra_mark__isnull=False, ) + @staticmethod + def resolve_notes_with_note(root: ParticipationStatus, info, **kwargs): + return NewPersonalNote.objects.filter( + person=root.person, + documentation=root.related_documentation, + note__isnull=False, + ).exclude(note="") + class ParticipationStatusBatchPatchMutation(BaseBatchPatchMutation): class Meta: model = ParticipationStatus - fields = ("id", "absence_reason") # Only the reason can be updated after creation + fields = ( + "id", + "absence_reason", + "tardiness", + ) # Only the reason and tardiness can be updated after creation return_field_name = "participationStatuses" @classmethod @@ -41,6 +73,81 @@ class ParticipationStatusBatchPatchMutation(BaseBatchPatchMutation): @classmethod def after_update_obj(cls, root, info, input, obj, full_input): # noqa: A002 if not info.context.user.has_perm( - "alsijil.edit_participation_status_for_documentation_rule", obj.related_documentation + "alsijil.edit_participation_status_for_documentation_with_time_range_rule", + obj.related_documentation, ): raise PermissionDenied() + + +class ExtendParticipationStatusToAbsenceBatchMutation(graphene.Mutation): + class Arguments: + input = graphene.List(graphene.ID, description=_("List of ParticipationStatus IDs")) + + participations = graphene.List(ParticipationStatusType) + absences = graphene.List(AbsenceType) + + @classmethod + def create_absence(cls, info, participation_id): + participation = ParticipationStatus.objects.get(pk=participation_id) + + if participation.date_end: + end_date = participation.date_end + else: + end_date = ParticipationStatus.value_end_datetime(participation).date() + + end_datetime = datetime.datetime.combine( + end_date, datetime.time.max, participation.timezone + ) + + if participation.base_absence: + # Update the base absence to increase length if needed + absence = participation.base_absence + + if absence.date_end: + if absence.date_end < end_date: + absence.date_end = end_date + absence.save() + + return participation, absence + + # Absence uses a datetime + if absence.datetime_end.astimezone(absence.timezone) < end_datetime: + # The end date ends after the previous absence end + absence.datetime_end = end_datetime + absence.save() + + return participation, absence + + else: + # No base absence, simply create one + data = dict( + reason_id=participation.absence_reason.id, + person=participation.person, + ) + + if participation.date_start: + data["date_start"] = participation.date_start + data["date_end"] = end_date + else: + data["datetime_start"] = ParticipationStatus.value_start_datetime(participation) + data["datetime_end"] = end_datetime + + absence, __ = Absence.objects.get_or_create(**data) + + participation.base_absence = absence + participation.save() + + return participation, absence + + @classmethod + def mutate(cls, root, info, input): # noqa + with create_revision(): + set_user(info.context.user) + set_comment(_("Extended absence reason from coursebook.")) + participations, absences = zip( + *[cls.create_absence(info, participation_id) for participation_id in input] + ) + + return ExtendParticipationStatusToAbsenceBatchMutation( + participations=participations, absences=absences + ) diff --git a/aleksis/apps/alsijil/schema/personal_note.py b/aleksis/apps/alsijil/schema/personal_note.py index afd44904e69ac9998fc49444c9d1422fae74e68e..dfe36359d87345a0b51992e689627065638fcd4e 100644 --- a/aleksis/apps/alsijil/schema/personal_note.py +++ b/aleksis/apps/alsijil/schema/personal_note.py @@ -1,23 +1,50 @@ -from graphene_django.types import DjangoObjectType -from guardian.shortcuts import get_objects_for_user +from graphene_django import DjangoObjectType +from aleksis.apps.alsijil.models import NewPersonalNote from aleksis.core.schema.base import ( + BaseBatchCreateMutation, + BaseBatchDeleteMutation, + BaseBatchPatchMutation, DjangoFilterMixin, + OptimisticResponseTypeMixin, PermissionsTypeMixin, ) -from ..models import ExtraMark + +class PersonalNoteType( + OptimisticResponseTypeMixin, + PermissionsTypeMixin, + DjangoFilterMixin, + DjangoObjectType, +): + class Meta: + model = NewPersonalNote + fields = ( + "id", + "note", + "extra_mark", + ) + + +class PersonalNoteBatchCreateMutation(BaseBatchCreateMutation): + class Meta: + model = NewPersonalNote + type_name = "BatchCreatePersonalNoteInput" + return_field_name = "personalNotes" + fields = ("note", "extra_mark", "documentation", "person") + permissions = ("alsijil.edit_personal_note_rule",) + + +class PersonalNoteBatchPatchMutation(BaseBatchPatchMutation): + class Meta: + model = NewPersonalNote + type_name = "BatchPatchPersonalNoteInput" + return_field_name = "personalNotes" + fields = ("id", "note", "extra_mark", "documentation", "person") + permissions = ("alsijil.edit_personal_note_rule",) -class ExtraMarkType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType): +class PersonalNoteBatchDeleteMutation(BaseBatchDeleteMutation): class Meta: - model = ExtraMark - fields = ("id", "short_name", "name", "colour_fg", "colour_bg", "show_in_coursebook") - filter_fields = { - "short_name": ["icontains", "exact"], - "name": ["icontains", "exact"], - } - - @classmethod - def get_queryset(cls, queryset, info): - return get_objects_for_user(info.context.user, "alsijil.view_extramark", queryset) + model = NewPersonalNote + permissions = ("alsijil.edit_personal_note_rule",) diff --git a/aleksis/apps/alsijil/schema/statistics.py b/aleksis/apps/alsijil/schema/statistics.py index d7f89e0f96f14477cc6fb9ac5a603e3bb030fb91..2788fcfebb9f7a863d8809bfc3b2694bde751f18 100644 --- a/aleksis/apps/alsijil/schema/statistics.py +++ b/aleksis/apps/alsijil/schema/statistics.py @@ -8,7 +8,7 @@ from aleksis.core.models import Person from aleksis.core.schema.person import PersonType from ..models import ExtraMark -from .personal_note import ExtraMarkType +from .extra_marks import ExtraMarkType class AbsenceReasonWithCountType(graphene.ObjectType): diff --git a/aleksis/apps/alsijil/tables.py b/aleksis/apps/alsijil/tables.py index a0ef1734e5eea326fd9a8fd0f858b71a89089082..f17a214930f2d7f2e40a1662b491eab587bda0ad 100644 --- a/aleksis/apps/alsijil/tables.py +++ b/aleksis/apps/alsijil/tables.py @@ -11,26 +11,6 @@ from aleksis.core.util.tables import SelectColumn from .models import PersonalNote -class ExtraMarkTable(tables.Table): - class Meta: - attrs = {"class": "highlight"} - - name = tables.LinkColumn("edit_extra_mark", args=[A("id")]) - short_name = tables.Column() - edit = tables.LinkColumn( - "edit_extra_mark", - args=[A("id")], - text=_("Edit"), - attrs={"a": {"class": "btn-flat waves-effect waves-orange orange-text"}}, - ) - delete = tables.LinkColumn( - "delete_extra_mark", - args=[A("id")], - text=_("Delete"), - attrs={"a": {"class": "btn-flat waves-effect waves-red red-text"}}, - ) - - class ExcuseTypeTable(tables.Table): class Meta: attrs = {"class": "highlight"} diff --git a/aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html b/aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html deleted file mode 100644 index d0ee3a9055561df1f468692f79d794404a60c1d1..0000000000000000000000000000000000000000 --- a/aleksis/apps/alsijil/templates/alsijil/extra_mark/create.html +++ /dev/null @@ -1,17 +0,0 @@ - {# -*- engine:django -*- #} - - {% extends "core/base.html" %} - {% load material_form i18n %} - - {% block browser_title %}{% blocktrans %}Create extra mark{% endblocktrans %}{% endblock %} - {% block page_title %}{% blocktrans %}Create extra mark{% endblocktrans %}{% endblock %} - - {% block content %} - - <form method="post"> - {% csrf_token %} - {% form form=form %}{% endform %} - {% include "core/partials/save_button.html" %} - </form> - - {% endblock %} diff --git a/aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html b/aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html deleted file mode 100644 index 7adee30a1cfd30256d70b2a823827384de331e05..0000000000000000000000000000000000000000 --- a/aleksis/apps/alsijil/templates/alsijil/extra_mark/edit.html +++ /dev/null @@ -1,17 +0,0 @@ -{# -*- engine:django -*- #} - -{% extends "core/base.html" %} -{% load material_form i18n %} - -{% block browser_title %}{% blocktrans %}Edit extra mark{% endblocktrans %}{% endblock %} -{% block page_title %}{% blocktrans %}Edit extra mark{% endblocktrans %}{% endblock %} - -{% block content %} - - <form method="post"> - {% csrf_token %} - {% form form=form %}{% endform %} - {% include "core/partials/save_button.html" %} - </form> - -{% endblock %} diff --git a/aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html b/aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html deleted file mode 100644 index 9eeb63b1a81162e6490072ca7184059be7a5193a..0000000000000000000000000000000000000000 --- a/aleksis/apps/alsijil/templates/alsijil/extra_mark/list.html +++ /dev/null @@ -1,18 +0,0 @@ -{# -*- engine:django -*- #} - -{% extends "core/base.html" %} - -{% load i18n %} -{% load render_table from django_tables2 %} - -{% block browser_title %}{% blocktrans %}Extra marks{% endblocktrans %}{% endblock %} -{% block page_title %}{% blocktrans %}Extra marks{% endblocktrans %}{% endblock %} - -{% block content %} - <a class="btn green waves-effect waves-light" href="{% url 'create_extra_mark' %}"> - <i class="material-icons iconify left" data-icon="mdi:plus"></i> - {% trans "Create extra mark" %} - </a> - - {% render_table table %} -{% endblock %} diff --git a/aleksis/apps/alsijil/urls.py b/aleksis/apps/alsijil/urls.py index edc0b4fa81cfb50e1f268d9dd21b3d9dda2c033a..cd7367ce84973bb4eb62791e9ce5b2c7eb3a5f85 100644 --- a/aleksis/apps/alsijil/urls.py +++ b/aleksis/apps/alsijil/urls.py @@ -3,22 +3,6 @@ from django.urls import path from . import views urlpatterns = [ - path("extra_marks/", views.ExtraMarkListView.as_view(), name="extra_marks"), - path( - "extra_marks/create/", - views.ExtraMarkCreateView.as_view(), - name="create_extra_mark", - ), - path( - "extra_marks/<int:pk>/edit/", - views.ExtraMarkEditView.as_view(), - name="edit_extra_mark", - ), - path( - "extra_marks/<int:pk>/delete/", - views.ExtraMarkDeleteView.as_view(), - name="delete_extra_mark", - ), path("group_roles/", views.GroupRoleListView.as_view(), name="group_roles"), path("group_roles/create/", views.GroupRoleCreateView.as_view(), name="create_group_role"), path( diff --git a/aleksis/apps/alsijil/util/alsijil_helpers.py b/aleksis/apps/alsijil/util/alsijil_helpers.py index 8e203e8f61f023af2c812efe0f21cf9a34511c60..118b70af8e1a71f9d5e56a8d251c5a319cae0e02 100644 --- a/aleksis/apps/alsijil/util/alsijil_helpers.py +++ b/aleksis/apps/alsijil/util/alsijil_helpers.py @@ -15,6 +15,7 @@ from aleksis.apps.alsijil.forms import FilterRegisterObjectForm from aleksis.apps.alsijil.models import LessonDocumentation from aleksis.apps.chronos.models import Event, ExtraLesson, Holiday, LessonPeriod from aleksis.apps.chronos.util.chronos_helpers import get_el_by_pk +from aleksis.apps.kolego.models import AbsenceReasonTag from aleksis.core.models import Group from aleksis.core.util.core_helpers import get_site_preferences @@ -401,3 +402,11 @@ def generate_list_of_all_register_objects(filter_dict: Dict[str, Any]) -> List[D register_objects = sorted(register_objects, key=itemgetter("date_sort", "period_sort")) return register_objects return [] + + +def get_absence_reason_tag(): + return AbsenceReasonTag.objects.managed_by_app("alsijil").get_or_create( + managed_by_app_label="alsijil", + short_name="class_register", + defaults={"name": "Class Register"}, + ) diff --git a/aleksis/apps/alsijil/util/predicates.py b/aleksis/apps/alsijil/util/predicates.py index 9f06195e279b6e9bc9564731146d33ea7995498d..5966a7459bc8a32f7e7468f20de2e7da0044441e 100644 --- a/aleksis/apps/alsijil/util/predicates.py +++ b/aleksis/apps/alsijil/util/predicates.py @@ -12,7 +12,7 @@ from aleksis.core.models import Group, Person from aleksis.core.util.core_helpers import get_site_preferences from aleksis.core.util.predicates import check_object_permission -from ..models import Documentation, PersonalNote +from ..models import Documentation, NewPersonalNote, PersonalNote @predicate @@ -93,19 +93,34 @@ def is_group_owner(user: User, obj: Union[Group, Person]) -> bool: @predicate -def is_person_group_owner(user: User, obj: Person) -> bool: +def is_person_group_owner(user: User, obj) -> bool: """ Predicate for group owners of any group. Checks whether the person linked to the user is the owner of any group of the given person. """ - if obj: - for group in use_prefetched(obj, "member_of"): - if user.person in use_prefetched(group, "owners"): - return True - return False - return False + return Group.objects.filter(owners=user.person).exists() + + +@predicate +def can_register_absence_for_at_least_one_group(user: User, obj) -> bool: + """Predicate for registering absence for at least one group.""" + group_types = get_site_preferences()["alsijil__group_types_register_absence"] + qs = Group.objects.filter(owners=user.person) + if not group_types: + return qs.exists() + return qs.filter(group_type__in=group_types).exists() + + +@predicate +def can_register_absence_for_person(user: User, obj: Person) -> bool: + """Predicate for registering absence for person.""" + group_types = get_site_preferences()["alsijil__group_types_register_absence"] + qs = obj.member_of.filter(owners=user.person) + if not group_types: + return qs.exists() + return qs.filter(group_type__in=group_types).exists() def use_prefetched(obj, attr): @@ -450,6 +465,8 @@ def can_edit_documentation(user: User, obj: Documentation): def can_view_participation_status(user: User, obj: Documentation): """Predicate which checks if the user is allowed to view participation for a documentation.""" if obj: + if obj.amends and obj.amends.cancelled: + return False if is_documentation_teacher(user, obj): return True if obj.amends: @@ -465,6 +482,8 @@ def can_view_participation_status(user: User, obj: Documentation): def can_edit_participation_status(user: User, obj: Documentation): """Predicate which checks if the user is allowed to edit participation for a documentation.""" if obj: + if obj.amends and obj.amends.cancelled: + return False if is_documentation_teacher(user, obj): return True if obj.amends: @@ -475,8 +494,14 @@ def can_edit_participation_status(user: User, obj: Documentation): @predicate -def is_in_allowed_time_range(user: User, obj: Documentation): - """Predicate which checks if the documentation is in the allowed time range for editing.""" +def is_in_allowed_time_range(user: User, obj: Union[Documentation, NewPersonalNote]): + """Predicate for documentations or new personal notes with linked documentation. + + Predicate which checks if the given documentation or the documentation linked + to the given NewPersonalNote is in the allowed time range for editing. + """ + if isinstance(obj, NewPersonalNote): + obj = obj.documentation if obj and ( get_site_preferences()["alsijil__allow_edit_future_documentations"] == "all" or ( @@ -498,3 +523,31 @@ def is_in_allowed_time_range_for_participation_status(user: User, obj: Documenta if obj and obj.value_start_datetime(obj) <= now(): return True return False + + +@predicate +def can_view_personal_note(user: User, obj: NewPersonalNote): + """Predicate which checks if the user is allowed to view a personal note.""" + if obj.documentation: + if is_documentation_teacher(user, obj.documentation): + return True + if obj.documentation.amends: + return is_lesson_event_teacher( + user, obj.documentation.amends + ) | is_lesson_event_group_owner(user, obj.documentation.amends) + if obj.documentation.course: + return is_course_teacher(user, obj.documentation.course) + return False + + +@predicate +def can_edit_personal_note(user: User, obj: NewPersonalNote): + """Predicate which checks if the user is allowed to edit a personal note.""" + if obj.documentation: + if is_documentation_teacher(user, obj.documentation): + return True + if obj.documentation.amends: + return is_lesson_event_teacher( + user, obj.documentation.amends + ) | is_lesson_event_group_owner(user, obj.documentation.amends) + return False diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py index dd010383b83ae7e28c6d98fd7de34bf9aa5432ba..0395a8bfbc54fcab81dfea092f431045d15ae134 100644 --- a/aleksis/apps/alsijil/views.py +++ b/aleksis/apps/alsijil/views.py @@ -48,7 +48,6 @@ from .filters import PersonalNoteFilter from .forms import ( AssignGroupRoleForm, ExcuseTypeForm, - ExtraMarkForm, FilterRegisterObjectForm, GroupRoleAssignmentEditForm, GroupRoleForm, @@ -62,7 +61,6 @@ from .forms import ( from .models import ExcuseType, ExtraMark, GroupRole, GroupRoleAssignment, PersonalNote from .tables import ( ExcuseTypeTable, - ExtraMarkTable, GroupRoleTable, PersonalNoteTable, RegisterObjectSelectTable, @@ -1052,51 +1050,6 @@ class DeletePersonalNoteView(PermissionRequiredMixin, DetailView): return redirect("overview_person", note.person.pk) -@method_decorator(pwa_cache, "dispatch") -class ExtraMarkListView(PermissionRequiredMixin, SingleTableView): - """Table of all extra marks.""" - - model = ExtraMark - table_class = ExtraMarkTable - permission_required = "alsijil.view_extramarks_rule" - template_name = "alsijil/extra_mark/list.html" - - -@method_decorator(never_cache, name="dispatch") -class ExtraMarkCreateView(PermissionRequiredMixin, AdvancedCreateView): - """Create view for extra marks.""" - - model = ExtraMark - form_class = ExtraMarkForm - permission_required = "alsijil.add_extramark_rule" - template_name = "alsijil/extra_mark/create.html" - success_url = reverse_lazy("extra_marks") - success_message = _("The extra mark has been created.") - - -@method_decorator(never_cache, name="dispatch") -class ExtraMarkEditView(PermissionRequiredMixin, AdvancedEditView): - """Edit view for extra marks.""" - - model = ExtraMark - form_class = ExtraMarkForm - permission_required = "alsijil.edit_extramark_rule" - template_name = "alsijil/extra_mark/edit.html" - success_url = reverse_lazy("extra_marks") - success_message = _("The extra mark has been saved.") - - -@method_decorator(never_cache, name="dispatch") -class ExtraMarkDeleteView(PermissionRequiredMixin, RevisionMixin, AdvancedDeleteView): - """Delete view for extra marks.""" - - model = ExtraMark - permission_required = "alsijil.delete_extramark_rule" - template_name = "core/pages/delete.html" - success_url = reverse_lazy("extra_marks") - success_message = _("The extra mark has been deleted.") - - @method_decorator(pwa_cache, "dispatch") class ExcuseTypeListView(PermissionRequiredMixin, SingleTableView): """Table of all excuse types.""" diff --git a/pyproject.toml b/pyproject.toml index 03a0772bee8aa34ffc35dc565a1762b87745abbb..3bbbbc8096e676c9522ab1308502dae104dc50c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "AlekSIS-App-Alsijil" -version = "4.0.0.dev1" +version = "4.0.0.dev5" packages = [ { include = "aleksis" } ] @@ -49,10 +49,10 @@ priority = "supplemental" [tool.poetry.dependencies] python = "^3.10" -aleksis-core = "^4.0.0.dev7" -aleksis-app-chronos = "^4.0.0.dev3" +aleksis-core = "^4.0.0.dev11" +aleksis-app-chronos = "^4.0.0.dev5" aleksis-app-stoelindeling = { version = "^3.0.dev1", optional = true } -aleksis-app-kolego = "^0.1.0.dev2" +aleksis-app-kolego = "^0.1.0.dev3" [tool.poetry.extras] seatingplans = ["aleksis-app-stoelindeling"]