This commit is contained in:
Julian Krauser 2024-11-24 15:31:08 +01:00
parent 03710dfdae
commit 9a1ff79f66
43 changed files with 264 additions and 92 deletions

View file

@ -23,7 +23,8 @@ import deLocale from "@fullcalendar/core/locales/de";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import { useCalendarStore } from "../../../../stores/admin/calendar";
import { useCalendarStore } from "@/stores/admin/calendar";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -33,6 +34,7 @@ export default defineComponent({
},
computed: {
...mapState(useCalendarStore, ["formattedItems"]),
...mapState(useAbilityStore, ["can"]),
calendarOptions() {
return {
timeZone: "local",
@ -68,7 +70,7 @@ export default defineComponent({
...mapActions(useModalStore, ["openModal"]),
...mapActions(useCalendarStore, ["fetchCalendars"]),
select(e: any) {
console.log(e);
if (!this.can("create", "club", "calendar")) return;
this.openModal(
markRaw(defineAsyncComponent(() => import("@/components/admin/club/calendar/CreateCalendarModal.vue"))),
{
@ -79,6 +81,7 @@ export default defineComponent({
);
},
eventClick(e: any) {
if (!this.can("update", "club", "calendar")) return;
this.openModal(
markRaw(defineAsyncComponent(() => import("@/components/admin/club/calendar/UpdateCalendarModal.vue"))),
e.event.id

View file

@ -20,7 +20,9 @@
</Pagination>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Mitglied erstellen</button>
<button v-if="can('create', 'club', 'member')" primary class="!w-fit" @click="openCreateModal">
Mitglied erstellen
</button>
</div>
</div>
</template>
@ -35,8 +37,9 @@ import { ChevronRightIcon, ChevronLeftIcon } from "@heroicons/vue/20/solid";
import { useMemberStore } from "@/stores/admin/member";
import MemberListItem from "@/components/admin/club/member/MemberListItem.vue";
import { useModalStore } from "@/stores/modal";
import Pagination from "../../../components/Pagination.vue";
import type { MemberViewModel } from "../../../viewmodels/admin/member.models";
import Pagination from "@/components/Pagination.vue";
import type { MemberViewModel } from "@/viewmodels/admin/member.models";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -49,6 +52,7 @@ export default defineComponent({
},
computed: {
...mapState(useMemberStore, ["members", "totalCount", "loading"]),
...mapState(useAbilityStore, ["can"]),
entryCount() {
return this.totalCount ?? this.members.length;
},

View file

@ -7,7 +7,9 @@
<p v-else-if="loading == 'failed'" @click="fetchItem" class="cursor-pointer">&#8634; laden fehlgeschlagen</p>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Auszeichnung hinzufügen</button>
<button v-if="can('create', 'club', 'member')" primary class="!w-fit" @click="openCreateModal">
Auszeichnung hinzufügen
</button>
</div>
</template>
@ -18,6 +20,7 @@ import Spinner from "@/components/Spinner.vue";
import { useMemberAwardStore } from "@/stores/admin/memberAward";
import MemberAwardListItem from "@/components/admin/club/member/MemberAwardListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -27,6 +30,7 @@ export default defineComponent({
},
computed: {
...mapState(useMemberAwardStore, ["memberAwards", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchItem();

View file

@ -11,7 +11,9 @@
<p v-else-if="loading == 'failed'" @click="fetchItem" class="cursor-pointer">&#8634; laden fehlgeschlagen</p>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Kommunikation hinzufügen</button>
<button v-if="can('create', 'club', 'member')" primary class="!w-fit" @click="openCreateModal">
Kommunikation hinzufügen
</button>
</div>
</template>
@ -25,6 +27,7 @@ import type { CommunicationViewModel } from "@/viewmodels/admin/communication.mo
import { useCommunicationStore } from "@/stores/admin/communication";
import MemberCommunicationListItem from "@/components/admin/club/member/MemberCommunicationListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -34,6 +37,7 @@ export default defineComponent({
},
computed: {
...mapState(useCommunicationStore, ["communications", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchItem();

View file

@ -11,7 +11,9 @@
<p v-else-if="loading == 'failed'" @click="fetchItem" class="cursor-pointer">&#8634; laden fehlgeschlagen</p>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Vereinsamt hinzufügen</button>
<button v-if="can('create', 'club', 'member')" primary class="!w-fit" @click="openCreateModal">
Vereinsamt hinzufügen
</button>
</div>
</template>
@ -22,6 +24,7 @@ import Spinner from "@/components/Spinner.vue";
import { useMemberExecutivePositionStore } from "@/stores/admin/memberExecutivePosition";
import MemberExecutivePositionListItem from "@/components/admin/club/member/MemberExecutivePositionListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -31,6 +34,7 @@ export default defineComponent({
},
computed: {
...mapState(useMemberExecutivePositionStore, ["memberExecutivePositions", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchItem();

View file

@ -11,7 +11,9 @@
<p v-else-if="loading == 'failed'" @click="fetchItem" class="cursor-pointer">&#8634; laden fehlgeschlagen</p>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Qualifikation hinzufügen</button>
<button v-if="can('create', 'club', 'member')" primary class="!w-fit" @click="openCreateModal">
Qualifikation hinzufügen
</button>
</div>
</template>
@ -22,6 +24,7 @@ import Spinner from "@/components/Spinner.vue";
import { useMemberQualificationStore } from "@/stores/admin/memberQualification";
import MemberQualificationListItem from "@/components/admin/club/member/MemberQualificationListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -31,6 +34,7 @@ export default defineComponent({
},
computed: {
...mapState(useMemberQualificationStore, ["memberQualifications", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchItem();

View file

@ -9,10 +9,10 @@
{{ activeMemberObj?.lastname }}, {{ activeMemberObj?.firstname }}
{{ activeMemberObj?.nameaffix ? `- ${activeMemberObj?.nameaffix}` : "" }}
</h1>
<RouterLink :to="{ name: 'admin-club-member-edit' }">
<RouterLink v-if="can('update', 'club', 'member')" :to="{ name: 'admin-club-member-edit' }">
<PencilIcon class="w-5 h-5" />
</RouterLink>
<TrashIcon class="w-5 h-5 cursor-pointer" @click="openDeleteModal" />
<TrashIcon v-if="can('delete', 'club', 'member')" class="w-5 h-5 cursor-pointer" @click="openDeleteModal" />
</div>
</template>
<template #diffMain>
@ -51,6 +51,7 @@ import { RouterLink, RouterView } from "vue-router";
import { useMemberStore } from "@/stores/admin/member";
import { PencilIcon, TrashIcon } from "@heroicons/vue/24/outline";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -72,6 +73,7 @@ export default defineComponent({
},
computed: {
...mapState(useMemberStore, ["activeMemberObj"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchMemberByActiveId();

View file

@ -7,7 +7,9 @@
<p v-else-if="loading == 'failed'" @click="fetchItem" class="cursor-pointer">&#8634; laden fehlgeschlagen</p>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Mitgliedschaft hinzufügen</button>
<button v-if="can('create', 'club', 'member')" primary class="!w-fit" @click="openCreateModal">
Mitgliedschaft hinzufügen
</button>
</div>
</template>
@ -18,6 +20,7 @@ import Spinner from "@/components/Spinner.vue";
import { useMembershipStore } from "@/stores/admin/membership";
import { useModalStore } from "@/stores/modal";
import MembershipListItem from "@/components/admin/club/member/MembershipListItem.vue";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -27,6 +30,7 @@ export default defineComponent({
},
computed: {
...mapState(useMembershipStore, ["memberships", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchItem();

View file

@ -20,7 +20,9 @@
</Pagination>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Protokoll erstellen</button>
<button v-if="can('create', 'club', 'protocol')" primary class="!w-fit" @click="openCreateModal">
Protokoll erstellen
</button>
</div>
</div>
</template>
@ -35,8 +37,9 @@ import { ChevronRightIcon, ChevronLeftIcon } from "@heroicons/vue/20/solid";
import { useProtocolStore } from "@/stores/admin/protocol";
import ProtocolListItem from "@/components/admin/club/protocol/ProtocolListItem.vue";
import { useModalStore } from "@/stores/modal";
import Pagination from "../../../../components/Pagination.vue";
import type { ProtocolViewModel } from "../../../../viewmodels/admin/protocol.models";
import Pagination from "@/components/Pagination.vue";
import type { ProtocolViewModel } from "@/viewmodels/admin/protocol.models";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -49,6 +52,7 @@ export default defineComponent({
},
computed: {
...mapState(useProtocolStore, ["protocols", "totalCount", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchProtocols(0, this.maxEntriesPerPage, true);

View file

@ -27,6 +27,7 @@
autocomplete="off"
v-model="item.topic"
@keyup.prevent
:disabled="!can('create', 'club', 'protocol')"
/>
</summary>
<QuillEditor
@ -37,11 +38,15 @@
contentType="html"
:toolbar="toolbarOptions"
v-model:content="item.context"
:enable="can('create', 'club', 'protocol')"
:style="!can('create', 'club', 'protocol') ? 'opacity: 75%; background: rgb(243 244 246)' : ''"
/>
</details>
</div>
<button primary class="!w-fit" @click="createProtocolAgenda">Eintrag hinzufügen</button>
<button v-if="can('create', 'club', 'protocol')" primary class="!w-fit" @click="createProtocolAgenda">
Eintrag hinzufügen
</button>
</div>
</template>
@ -54,6 +59,7 @@ import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { toolbarOptions } from "@/helpers/quillConfig";
import { useProtocolAgendaStore } from "@/stores/admin/protocolAgenda";
import type { ProtocolAgendaViewModel } from "@/viewmodels/admin/protocolAgenda.models";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -63,6 +69,7 @@ export default defineComponent({
},
computed: {
...mapWritableState(useProtocolAgendaStore, ["agenda", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchProtocolAgenda();

View file

@ -27,6 +27,7 @@
autocomplete="off"
v-model="item.topic"
@keyup.prevent
:disabled="!can('create', 'club', 'protocol')"
/>
</summary>
<QuillEditor
@ -37,11 +38,15 @@
contentType="html"
:toolbar="toolbarOptions"
v-model:content="item.context"
:enable="can('create', 'club', 'protocol')"
:style="!can('create', 'club', 'protocol') ? 'opacity: 75%; background: rgb(243 244 246)' : ''"
/>
</details>
</div>
<button primary class="!w-fit" @click="createProtocolDecision">Eintrag hinzufügen</button>
<button v-if="can('create', 'club', 'protocol')" primary class="!w-fit" @click="createProtocolDecision">
Eintrag hinzufügen
</button>
</div>
</template>
@ -53,7 +58,8 @@ import { useProtocolStore } from "@/stores/admin/protocol";
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { toolbarOptions } from "@/helpers/quillConfig";
import { useProtocolDecisionStore } from "../../../../stores/admin/protocolDecision";
import { useProtocolDecisionStore } from "@/stores/admin/protocolDecision";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -63,6 +69,7 @@ export default defineComponent({
},
computed: {
...mapWritableState(useProtocolDecisionStore, ["decision", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchProtocolDecision();

View file

@ -3,20 +3,37 @@
<div v-if="activeProtocolObj != null" class="flex flex-col gap-2 w-full">
<div class="w-full">
<label for="title">Titel</label>
<input type="text" id="title" v-model="activeProtocolObj.title" />
<input
type="text"
id="title"
v-model="activeProtocolObj.title"
:disabled="!can('create', 'club', 'protocol')"
/>
</div>
<div class="w-full">
<label for="date">Datum</label>
<input type="date" id="date" v-model="activeProtocolObj.date" />
<input type="date" id="date" v-model="activeProtocolObj.date" :disabled="!can('create', 'club', 'protocol')" />
</div>
<div class="flex flex-row gap-2 w-full">
<div class="w-full">
<label for="starttime">Startzeit</label>
<input type="time" id="starttime" step="1" v-model="activeProtocolObj.starttime" />
<input
type="time"
id="starttime"
step="1"
v-model="activeProtocolObj.starttime"
:disabled="!can('create', 'club', 'protocol')"
/>
</div>
<div class="w-full">
<label for="endtime">Endzeit</label>
<input type="time" id="endtime" step="1" v-model="activeProtocolObj.endtime" />
<input
type="time"
id="endtime"
step="1"
v-model="activeProtocolObj.endtime"
:disabled="!can('create', 'club', 'protocol')"
/>
</div>
</div>
<div class="flex flex-col h-1/2">
@ -29,6 +46,8 @@
contentType="html"
:toolbar="toolbarOptions"
v-model:content="activeProtocolObj.summary"
:enable="can('create', 'club', 'protocol')"
:style="!can('create', 'club', 'protocol') ? 'opacity: 75%; background: rgb(243 244 246)' : ''"
/>
</div>
</div>
@ -48,6 +67,7 @@ import { useProtocolStore } from "@/stores/admin/protocol";
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { toolbarOptions } from "@/helpers/quillConfig";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -57,6 +77,7 @@ export default defineComponent({
},
computed: {
...mapWritableState(useProtocolStore, ["loadingActive", "activeProtocolObj"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchProtocolByActiveId();

View file

@ -6,7 +6,7 @@
</p>
<div class="w-full">
<Combobox v-model="presence" multiple>
<Combobox v-model="presence" :disabled="!can('create', 'club', 'protocol')" multiple>
<ComboboxLabel>Anwesende suchen</ComboboxLabel>
<div class="relative mt-1">
<ComboboxInput
@ -71,7 +71,11 @@
class="flex flex-row h-fit w-full border border-primary rounded-md bg-primary p-2 text-white justify-between items-center"
>
<p>{{ member.lastname }}, {{ member.firstname }} {{ member.nameaffix ? `- ${member.nameaffix}` : "" }}</p>
<TrashIcon class="w-5 h-5 p-1 box-content cursor-pointer" @click="removeSelected(member.id)" />
<TrashIcon
v-if="can('create', 'club', 'protocol')"
class="w-5 h-5 p-1 box-content cursor-pointer"
@click="removeSelected(member.id)"
/>
</div>
</div>
</div>
@ -96,6 +100,7 @@ import { useProtocolStore } from "@/stores/admin/protocol";
import { useMemberStore } from "@/stores/admin/member";
import type { MemberViewModel } from "@/viewmodels/admin/member.models";
import { useProtocolPresenceStore } from "@/stores/admin/protocolPresence";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -111,6 +116,7 @@ export default defineComponent({
computed: {
...mapWritableState(useProtocolPresenceStore, ["presence", "loading"]),
...mapState(useMemberStore, ["members"]),
...mapState(useAbilityStore, ["can"]),
filtered(): Array<MemberViewModel> {
return this.query === ""
? this.members

View file

@ -30,7 +30,13 @@
</div>
<div class="flex flex-row justify-start gap-2">
<button primary class="!w-fit" :disabled="printing != undefined" @click="createProtocolPrintout">
<button
v-if="can('create', 'club', 'protocol')"
primary
class="!w-fit"
:disabled="printing != undefined"
@click="createProtocolPrintout"
>
Ausdruck erstellen
</button>
<Spinner v-if="printing == 'loading'" class="my-auto" />
@ -49,6 +55,7 @@ import FailureXMark from "@/components/FailureXMark.vue";
import { useProtocolPrintoutStore } from "@/stores/admin/protocolPrintout";
import { ArrowDownTrayIcon, ViewfinderCircleIcon } from "@heroicons/vue/24/outline";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -58,6 +65,7 @@ export default defineComponent({
},
computed: {
...mapState(useProtocolPrintoutStore, ["printout", "loading", "printing"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchProtocolPrintout();

View file

@ -14,7 +14,6 @@
}
"
/>
<!-- <TrashIcon class="w-5 h-5 cursor-pointer" @click="openDeleteModal" /> -->
</div>
</template>
<template #diffMain>

View file

@ -27,6 +27,7 @@
autocomplete="off"
v-model="item.topic"
@keyup.prevent
:disabled="!can('create', 'club', 'protocol')"
/>
</summary>
<QuillEditor
@ -37,6 +38,8 @@
contentType="html"
:toolbar="toolbarOptions"
v-model:content="item.context"
:enable="can('create', 'club', 'protocol')"
:style="!can('create', 'club', 'protocol') ? 'opacity: 75%; background: rgb(243 244 246)' : ''"
/>
<div class="px-2 pb-2">
<p>Ergebnis:</p>
@ -58,7 +61,9 @@
</details>
</div>
<button primary class="!w-fit" @click="createProtocolVoting">Abstimmung hinzufügen</button>
<button v-if="can('create', 'club', 'protocol')" primary class="!w-fit" @click="createProtocolVoting">
Abstimmung hinzufügen
</button>
</div>
</template>
@ -70,7 +75,8 @@ import { useProtocolStore } from "@/stores/admin/protocol";
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { toolbarOptions } from "@/helpers/quillConfig";
import { useProtocolVotingStore } from "../../../../stores/admin/protocolVoting";
import { useProtocolVotingStore } from "@/stores/admin/protocolVoting";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
@ -80,6 +86,7 @@ export default defineComponent({
},
computed: {
...mapState(useProtocolVotingStore, ["voting", "loading"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchProtocolVoting();

View file

@ -11,7 +11,9 @@
<AwardListItem v-for="award in awards" :key="award.id" :award="award" />
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Auszeichnung erstellen</button>
<button v-if="can('create', 'settings', 'award')" primary class="!w-fit" @click="openCreateModal">
Auszeichnung erstellen
</button>
</div>
</div>
</template>
@ -25,12 +27,14 @@ import MainTemplate from "@/templates/Main.vue";
import { useAwardStore } from "@/stores/admin/award";
import AwardListItem from "@/components/admin/settings/award/AwardListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
export default defineComponent({
computed: {
...mapState(useAwardStore, ["awards"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchAwards();

View file

@ -15,7 +15,9 @@
/>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Termintyp erstellen</button>
<button v-if="can('create', 'settings', 'calendar_type')" primary class="!w-fit" @click="openCreateModal">
Termintyp erstellen
</button>
</div>
</div>
</template>
@ -29,12 +31,14 @@ import MainTemplate from "@/templates/Main.vue";
import { useCalendarTypeStore } from "@/stores/admin/calendarType";
import CalendarTypeListItem from "@/components/admin/settings/calendarType/CalendarTypeListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
export default defineComponent({
computed: {
...mapState(useCalendarTypeStore, ["calendarTypes"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchCalendarTypes();

View file

@ -15,7 +15,14 @@
/>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Kommunikationsart erstellen</button>
<button
v-if="can('create', 'settings', 'communication_type')"
primary
class="!w-fit"
@click="openCreateModal"
>
Kommunikationsart erstellen
</button>
</div>
</div>
</template>
@ -29,12 +36,14 @@ import MainTemplate from "@/templates/Main.vue";
import { useCommunicationTypeStore } from "@/stores/admin/communicationType";
import CommunicationTypeListItem from "@/components/admin/settings/communicationType/CommunicationTypeListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
export default defineComponent({
computed: {
...mapState(useCommunicationTypeStore, ["communicationTypes"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchCommunicationTypes();

View file

@ -15,7 +15,14 @@
/>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Vereinsämt erstellen</button>
<button
v-if="can('create', 'settings', 'executive_position')"
primary
class="!w-fit"
@click="openCreateModal"
>
Vereinsämt erstellen
</button>
</div>
</div>
</template>
@ -29,12 +36,14 @@ import MainTemplate from "@/templates/Main.vue";
import { useExecutivePositionStore } from "@/stores/admin/executivePosition";
import ExecutivePositionListItem from "@/components/admin/settings/executivePosition/ExecutivePositionListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
export default defineComponent({
computed: {
...mapState(useExecutivePositionStore, ["executivePositions"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchExecutivePositions();

View file

@ -11,7 +11,9 @@
<MembershipStatusListItem v-for="status in membershipStatus" :key="status.id" :membershipStatus="status" />
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Mitgliedsstatus erstellen</button>
<button v-if="can('create', 'settings', 'membership_status')" primary class="!w-fit" @click="openCreateModal">
Mitgliedsstatus erstellen
</button>
</div>
</div>
</template>
@ -25,12 +27,14 @@ import MainTemplate from "@/templates/Main.vue";
import { useMembershipStatusStore } from "@/stores/admin/membershipStatus";
import MembershipStatusListItem from "@/components/admin/settings/membershipStatus/MembershipStatusListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
export default defineComponent({
computed: {
...mapState(useMembershipStatusStore, ["membershipStatus"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchMembershipStatus();

View file

@ -15,7 +15,9 @@
/>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Qualifikation erstellen</button>
<button v-if="can('create', 'settings', 'qualification')" primary class="!w-fit" @click="openCreateModal">
Qualifikation erstellen
</button>
</div>
</div>
</template>
@ -29,12 +31,14 @@ import MainTemplate from "@/templates/Main.vue";
import { useQualificationStore } from "@/stores/admin/qualification";
import QualificationListItem from "@/components/admin/settings/qualification/QualificationListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
export default defineComponent({
computed: {
...mapState(useQualificationStore, ["qualifications"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchQualifications();

View file

@ -10,7 +10,7 @@
</template>
<template #diffMain>
<div class="flex flex-col gap-2 grow overflow-y-scroll px-7">
<InviteListItem v-for="invite in invites" :key="invite.id" :invite="invite" />
<InviteListItem v-for="invite in invites" :key="invite.username" :invite="invite" />
</div>
</template>
</MainTemplate>

View file

@ -11,7 +11,9 @@
<RoleListItem v-for="role in roles" :key="role.id" :role="role" />
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="openCreateModal">Rolle erstellen</button>
<button v-if="can('create', 'user', 'role')" primary class="!w-fit" @click="openCreateModal">
Rolle erstellen
</button>
</div>
</div>
</template>
@ -25,12 +27,14 @@ import MainTemplate from "@/templates/Main.vue";
import { useRoleStore } from "@/stores/admin/role";
import RoleListItem from "@/components/admin/user/role/RoleListItem.vue";
import { useModalStore } from "@/stores/modal";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
export default defineComponent({
computed: {
...mapState(useRoleStore, ["roles"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchRoles();

View file

@ -11,7 +11,9 @@
<UserListItem v-for="user in users" :key="user.id" :user="user" />
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="inviteUser">Nutzer einladen</button>
<button v-if="can('create', 'user', 'user')" primary class="!w-fit" @click="inviteUser">
Nutzer einladen
</button>
<RouterLink button primary-outline :to="{ name: 'admin-user-user-invites' }" class="!w-fit">
offene Einladungen
</RouterLink>
@ -29,12 +31,14 @@ import MainTemplate from "@/templates/Main.vue";
import { useUserStore } from "@/stores/admin/user";
import { useModalStore } from "@/stores/modal";
import UserListItem from "@/components/admin/user/user/UserListItem.vue";
import { useAbilityStore } from "@/stores/ability";
</script>
<script lang="ts">
export default defineComponent({
computed: {
...mapState(useUserStore, ["users"]),
...mapState(useAbilityStore, ["can"]),
},
mounted() {
this.fetchUsers();

View file

@ -9,6 +9,7 @@
</div>
</template>
<template #main>
<p>Hinweis: Berechtigungen von Nutzer und Rolle sind ergänzend.</p>
<Spinner v-if="loading == 'loading'" class="mx-auto" />
<p v-else-if="loading == 'failed'">laden fehlgeschlagen</p>
<Permission