diff options
Diffstat (limited to 'packages/frontend/src/pages/admin/roles.role.vue')
| -rw-r--r-- | packages/frontend/src/pages/admin/roles.role.vue | 121 |
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> |