Files
RenewCMS/web/src/components/RolePicker.vue
T

85 lines
2.1 KiB
Vue

<script setup lang="ts">
import { t } from '@/i18n'
import { computed } from 'vue'
import type { RoleItem } from '@/lib/roles'
const props = withDefaults(
defineProps<{
roles: RoleItem[]
sourceId?: number
canAssign: (role: RoleItem) => boolean
showLocked?: boolean
currentId?: number
cards?: boolean
label?: string
}>(),
{ sourceId: 0, showLocked: false, currentId: undefined, cards: false, label: undefined },
)
const selected = defineModel<number | undefined>('selected', { default: undefined })
function reasonFor(role: RoleItem): string | undefined {
if (role.locked) {
return t('There is one owner. Transfer ownership to change who it is.')
}
return props.canAssign(role)
? undefined
: t("Your role can't assign a role with more power than yours.")
}
const items = computed(() =>
props.roles
.filter((role) => (props.showLocked || !role.locked) && role.id !== props.sourceId)
.map((role) => {
const reason = reasonFor(role)
return {
label: role.name,
value: role.id,
description: reason ?? role.description,
disabled: reason !== undefined,
current: role.id === props.currentId,
}
}),
)
</script>
<template>
<URadioGroup
v-if="cards"
v-model="selected"
:items="items"
variant="card"
color="primary"
:aria-label="label"
:ui="{
item: 'rounded-none has-data-[state=checked]:border-primary has-data-[state=checked]:bg-(--rc-sand) has-data-[state=checked]:text-(--rc-on-sand)',
fieldset: 'gap-2',
description: 'text-xs',
}"
>
<template #label="{ item }">
<span class="flex items-center gap-2">
{{ item.label }}
<span v-if="item.current" class="text-xs font-medium">· {{ t('Current') }}</span>
</span>
</template>
</URadioGroup>
<USelectMenu
v-else
v-model="selected"
:items="items"
value-key="value"
:search-input="false"
:placeholder="t('Choose a role')"
:portal="false"
:content="{ position: 'inline' }"
class="w-full"
:ui="{
base: 'h-11 rounded-none md:h-8',
content: 'rounded-none border border-default',
item: 'min-h-12 gap-2 px-2 py-1 md:min-h-9',
itemDescription: 'text-xs text-muted',
}"
/>
</template>