summaryrefslogtreecommitdiff
path: root/packages/frontend/src/pages/admin/roles.role.vue
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/pages/admin/roles.role.vue')
-rw-r--r--packages/frontend/src/pages/admin/roles.role.vue121
1 files changed, 121 insertions, 0 deletions
diff --git a/packages/frontend/src/pages/admin/roles.role.vue b/packages/frontend/src/pages/admin/roles.role.vue
new file mode 100644
index 0000000000..8c18b02632
--- /dev/null
+++ b/packages/frontend/src/pages/admin/roles.role.vue
@@ -0,0 +1,121 @@
+<template>
+<div>
+ <MkStickyContainer>
+ <template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
+ <MkSpacer :content-max="700">
+ <div class="_gaps">
+ <div class="_buttons">
+ <MkButton primary rounded @click="edit"><i class="ti ti-pencil"></i> {{ i18n.ts.edit }}</MkButton>
+ <MkButton danger rounded @click="del"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
+ </div>
+ <MkFolder>
+ <template #icon><i class="ti ti-info-circle"></i></template>
+ <template #label>{{ i18n.ts.info }}</template>
+ <XEditor :role="role" readonly/>
+ </MkFolder>
+ <MkFolder default-open>
+ <template #icon><i class="ti ti-users"></i></template>
+ <template #label>{{ i18n.ts.users }}</template>
+ <template #suffix>{{ role.users.length }}</template>
+ <div class="_gaps">
+ <MkButton primary rounded @click="assign"><i class="ti ti-plus"></i> {{ i18n.ts.assign }}</MkButton>
+
+ <div v-for="user in role.users" :key="user.id" :class="$style.userItem">
+ <MkA :class="$style.user" :to="`/user-info/${user.id}`">
+ <MkUserCardMini :user="user"/>
+ </MkA>
+ <button class="_button" :class="$style.unassign" @click="unassign(user, $event)"><i class="ti ti-x"></i></button>
+ </div>
+ </div>
+ </MkFolder>
+ </div>
+ </MkSpacer>
+ </MkStickyContainer>
+</div>
+</template>
+
+<script lang="ts" setup>
+import { computed, reactive } from 'vue';
+import XHeader from './_header_.vue';
+import XEditor from './roles.editor.vue';
+import MkFolder from '@/components/MkFolder.vue';
+import * as os from '@/os';
+import { i18n } from '@/i18n';
+import { definePageMetadata } from '@/scripts/page-metadata';
+import { useRouter } from '@/router';
+import MkButton from '@/components/MkButton.vue';
+import MkUserCardMini from '@/components/MkUserCardMini.vue';
+
+const router = useRouter();
+
+const props = defineProps<{
+ id?: string;
+}>();
+
+const role = reactive(await os.api('admin/roles/show', {
+ roleId: props.id,
+}));
+
+function edit() {
+ router.push('/admin/roles/' + role.id + '/edit');
+}
+
+async function del() {
+ const { canceled } = await os.confirm({
+ type: 'warning',
+ text: i18n.t('deleteAreYouSure', { x: role.name }),
+ });
+ if (canceled) return;
+
+ await os.apiWithDialog('admin/roles/delete', {
+ roleId: role.id,
+ });
+
+ router.push('/admin/roles');
+}
+
+function assign() {
+ os.selectUser().then(async (user) => {
+ await os.apiWithDialog('admin/roles/assign', { roleId: role.id, userId: user.id });
+ role.users.push(user);
+ });
+}
+
+async function unassign(user, ev) {
+ os.popupMenu([{
+ text: i18n.ts.unassign,
+ icon: 'ti ti-x',
+ danger: true,
+ action: async () => {
+ await os.apiWithDialog('admin/roles/unassign', { roleId: role.id, userId: user.id });
+ role.users = role.users.filter(u => u.id !== user.id);
+ },
+ }], ev.currentTarget ?? ev.target);
+}
+
+const headerActions = $computed(() => []);
+
+const headerTabs = $computed(() => []);
+
+definePageMetadata(computed(() => ({
+ title: i18n.ts.role + ': ' + role.name,
+ icon: 'ti ti-badge',
+})));
+</script>
+
+<style lang="scss" module>
+.userItem {
+ display: flex;
+}
+
+.user {
+ flex: 1;
+}
+
+.unassign {
+ width: 32px;
+ height: 32px;
+ margin-left: 8px;
+ align-self: center;
+}
+</style>