2025-06-30 18:58:24 +02:00
|
|
|
<!--
|
|
|
|
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
-->
|
2025-03-15 15:10:42 +01:00
|
|
|
<template>
|
2025-06-14 19:22:53 +02:00
|
|
|
<div>
|
2025-03-15 15:10:42 +01:00
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>id</th>
|
|
|
|
<th>name</th>
|
|
|
|
<th>description</th>
|
|
|
|
<th v-if="edit"></th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<template v-if="edit">
|
|
|
|
<tr
|
2025-06-14 19:22:53 +02:00
|
|
|
v-for="role in schedule.roles.values()"
|
2025-03-15 15:10:42 +01:00
|
|
|
:key="role.id"
|
2025-06-14 19:22:53 +02:00
|
|
|
:class="{ removed: role.deleted }"
|
2025-03-15 15:10:42 +01:00
|
|
|
>
|
|
|
|
<td>{{ role.id }}</td>
|
|
|
|
<td>
|
|
|
|
<input
|
|
|
|
type="text"
|
2025-06-23 22:46:39 +02:00
|
|
|
v-model="role.name"
|
2025-03-15 15:10:42 +01:00
|
|
|
>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<input
|
|
|
|
type="text"
|
2025-06-23 22:46:39 +02:00
|
|
|
v-model="role.description"
|
2025-03-15 15:10:42 +01:00
|
|
|
>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<button
|
|
|
|
type="button"
|
2025-06-14 19:22:53 +02:00
|
|
|
:disabled="role.deleted"
|
2025-06-23 22:46:39 +02:00
|
|
|
@click="role.deleted = true"
|
2025-03-15 15:10:42 +01:00
|
|
|
>Delete</button>
|
|
|
|
<button
|
2025-06-23 22:46:39 +02:00
|
|
|
v-if="role.isModified()"
|
2025-03-15 15:10:42 +01:00
|
|
|
type="button"
|
2025-06-23 22:46:39 +02:00
|
|
|
@click="schedule.roles.discardId(role.id)"
|
2025-03-15 15:10:42 +01:00
|
|
|
>Revert</button>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
2025-06-14 19:22:53 +02:00
|
|
|
<td>{{ schedule.nextClientId }}</td>
|
2025-03-15 15:10:42 +01:00
|
|
|
<td>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
v-model="newRoleName"
|
|
|
|
>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
v-model="newRoleDescription"
|
|
|
|
>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<button
|
|
|
|
v-if="roleExists(newRoleName)"
|
|
|
|
disabled
|
|
|
|
>Role already exists</button>
|
|
|
|
<button
|
|
|
|
v-else
|
|
|
|
type="button"
|
|
|
|
@click="newRole"
|
|
|
|
>Add Role</button>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</template>
|
|
|
|
<template v-else>
|
|
|
|
<tr
|
2025-06-14 19:22:53 +02:00
|
|
|
v-for="role in schedule.roles.values()"
|
2025-03-15 15:10:42 +01:00
|
|
|
:key="role.id"
|
|
|
|
>
|
|
|
|
<td>{{ role.id }}</td>
|
|
|
|
<td>{{ role.name }}</td>
|
|
|
|
<td>{{ role.description }}</td>
|
|
|
|
</tr>
|
|
|
|
</template>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-06-23 22:46:39 +02:00
|
|
|
import { Info } from '~/shared/utils/luxon';
|
2025-03-15 15:10:42 +01:00
|
|
|
import { toId } from '~/shared/utils/functions';
|
|
|
|
|
|
|
|
defineProps<{
|
|
|
|
edit?: boolean,
|
|
|
|
}>();
|
|
|
|
|
|
|
|
const schedule = await useSchedule();
|
2025-06-23 22:46:39 +02:00
|
|
|
const accountStore = useAccountStore();
|
2025-03-15 15:10:42 +01:00
|
|
|
|
|
|
|
const newRoleName = ref("");
|
|
|
|
const newRoleDescription = ref("");
|
2025-06-14 19:22:53 +02:00
|
|
|
|
2025-03-15 15:10:42 +01:00
|
|
|
function roleExists(name: string) {
|
2025-06-11 21:05:17 +02:00
|
|
|
name = toId(name);
|
2025-03-15 15:10:42 +01:00
|
|
|
return (
|
2025-06-14 19:22:53 +02:00
|
|
|
[...schedule.value.roles.values()].some(r => !r.deleted && toId(r.name) === name)
|
2025-03-15 15:10:42 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
function newRole() {
|
|
|
|
if (roleExists(newRoleName.value)) {
|
|
|
|
alert(`Role ${newRoleName.value} already exists`);
|
|
|
|
return;
|
|
|
|
}
|
2025-06-23 22:46:39 +02:00
|
|
|
const zone = Info.normalizeZone(accountStore.activeTimezone);
|
|
|
|
const locale = accountStore.activeLocale;
|
|
|
|
const role = ClientScheduleRole.create(
|
2025-06-14 19:22:53 +02:00
|
|
|
schedule.value.nextClientId--,
|
|
|
|
newRoleName.value,
|
|
|
|
newRoleDescription.value,
|
2025-06-23 22:46:39 +02:00
|
|
|
{ zone, locale },
|
2025-06-14 19:22:53 +02:00
|
|
|
);
|
2025-06-23 22:46:39 +02:00
|
|
|
schedule.value.roles.add(role);
|
2025-03-15 15:10:42 +01:00
|
|
|
newRoleName.value = "";
|
|
|
|
newRoleDescription.value = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
table {
|
|
|
|
border-spacing: 0;
|
|
|
|
}
|
|
|
|
table th {
|
|
|
|
text-align: left;
|
|
|
|
border-bottom: 1px solid var(--foreground);
|
|
|
|
}
|
|
|
|
table :is(th, td) + :is(th, td) {
|
|
|
|
padding-inline-start: 0.4em;
|
|
|
|
}
|
|
|
|
.removed :is(td, input) {
|
|
|
|
text-decoration: line-through;
|
|
|
|
}
|
|
|
|
</style>
|