summaryrefslogtreecommitdiff
path: root/packages/frontend/src/pages/admin/roles.role.vue
blob: 0365165b5d8d0a0fb0e7cf0382ad1a3e79ed7f7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<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 v-if="role.target === 'manual'" 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>
				<MkInfo v-else>{{ i18n.ts._role.isConditionalRole }}</MkInfo>
			</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';
import MkInfo from '@/components/MkInfo.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({
		includeSelf: true,
	}).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>