8016-userRole #1677
|
@ -654,7 +654,7 @@ const rowCtrlClickFunction = computed(() => {
|
|||
:search-url="searchUrl"
|
||||
:disable-infinite-scroll="isTableMode"
|
||||
:before-save-fn="removeTextValue"
|
||||
@save-changes="reload"
|
||||
@save-changes="reload && emit('saveChanges')"
|
||||
:has-sub-toolbar="$props.hasSubToolbar ?? isEditable"
|
||||
:auto-load="hasParams || $attrs['auto-load']"
|
||||
>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script setup>
|
||||
import { onBeforeMount, computed, markRaw } from 'vue';
|
||||
import { onBeforeMount, computed, markRaw, watch } from 'vue';
|
||||
import { useRoute, useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import useCardSize from 'src/composables/useCardSize';
|
||||
import VnSubToolbar from '../ui/VnSubToolbar.vue';
|
||||
|
||||
const emit = defineEmits(['onFetch']);
|
||||
const emit = defineEmits(['onFetch', 'onChange']);
|
||||
|
||||
const props = defineProps({
|
||||
id: { type: Number, required: false, default: null },
|
||||
|
@ -68,6 +68,12 @@ function hasRouteParam(params, valueToCheck = ':addressId') {
|
|||
return Object.values(params).includes(valueToCheck);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => arrayData?.store?.data,
|
||||
(data) => {
|
||||
emit('onChange', data);
|
||||
},
|
||||
);
|
||||
function formatUrl(id) {
|
||||
const newId = id || entityId.value;
|
||||
const regex = /\/(\d+)/;
|
||||
|
|
|
@ -29,6 +29,12 @@ const entity = ref();
|
|||
emit('onFetch', data);
|
||||
}
|
||||
"
|
||||
@on-change="
|
||||
(data) => {
|
||||
entity = data;
|
||||
emit('onFetch', data);
|
||||
}
|
||||
"
|
||||
/>
|
||||
<VnDescriptor v-model="entity" v-bind="$attrs">
|
||||
<template v-for="(_, slotName) in $slots" #[slotName]="slotData" :key="slotName">
|
||||
|
|
|
@ -9,6 +9,7 @@ import filter from './Card/AccountFilter.js';
|
|||
import VnSection from 'src/components/common/VnSection.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import VnInputPassword from 'src/components/common/VnInputPassword.vue';
|
||||
import RoleJoin from './Role/RoleJoin';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
|
@ -58,7 +59,7 @@ const columns = computed(() => [
|
|||
columnField: {
|
||||
component: null,
|
||||
},
|
||||
format: ({ role }, dashIfEmpty) => dashIfEmpty(role?.name),
|
||||
format: ({ role }, dashIfEmpty) => dashIfEmpty(RoleJoin(role)),
|
||||
create: true,
|
||||
},
|
||||
{
|
||||
|
@ -149,12 +150,12 @@ const columns = computed(() => [
|
|||
:right-search="false"
|
||||
>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<VnInputPassword
|
||||
:label="t('Password')"
|
||||
v-model="data.password"
|
||||
:required="true"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<VnInputPassword
|
||||
:label="t('Password')"
|
||||
v-model="data.password"
|
||||
:required="true"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</template>
|
||||
</VnTable>
|
||||
</template>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
|
||||
import VnImg from 'src/components/ui/VnImg.vue';
|
||||
import filter from './AccountFilter.js';
|
||||
import useHasAccount from 'src/composables/useHasAccount.js';
|
||||
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
||||
import AccountCard from './AccountCard.vue';
|
||||
import RoleJoin from '../Role/RoleJoin';
|
||||
|
||||
const $props = defineProps({ id: { type: Number, default: null } });
|
||||
|
||||
|
@ -20,13 +21,7 @@ onMounted(async () => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<EntityDescriptor
|
||||
ref="descriptor"
|
||||
:url="`VnUsers/preview`"
|
||||
:filter="{ ...filter, where: { id: entityId } }"
|
||||
data-key="Account"
|
||||
title="nickname"
|
||||
>
|
||||
<CardDescriptor v-bind="$attrs" :id="entityId" :card="AccountCard" module="Account">
|
||||
<template #menu>
|
||||
<AccountDescriptorMenu :entity-id="entityId" />
|
||||
</template>
|
||||
|
@ -50,7 +45,7 @@ onMounted(async () => {
|
|||
</template>
|
||||
<template #body="{ entity }">
|
||||
<VnLv :label="$t('account.card.nickname')" :value="entity.name" />
|
||||
<VnLv :label="$t('account.card.role')" :value="entity.role?.name" />
|
||||
<VnLv :label="$t('account.card.role')" :value="RoleJoin(entity.role)" />
|
||||
</template>
|
||||
<template #actions="{ entity }">
|
||||
<QCardActions class="q-gutter-x-md">
|
||||
|
@ -78,7 +73,7 @@ onMounted(async () => {
|
|||
</QIcon>
|
||||
</QCardActions>
|
||||
</template>
|
||||
</EntityDescriptor>
|
||||
</CardDescriptor>
|
||||
</template>
|
||||
<style scoped>
|
||||
.q-item__label {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
export default {
|
||||
include: { relation: 'role', scope: { fields: ['id', 'name'] } },
|
||||
include: {
|
||||
relation: 'role',
|
||||
scope: {
|
||||
include: [{ relation: 'role', scope: { fields: ['id', 'name'] } }],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,49 +1,120 @@
|
|||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const arrayData = useArrayData('Account');
|
||||
|
||||
const vnTableRef = ref({});
|
||||
const rolesOptions = ref([]);
|
||||
const formModelRef = ref();
|
||||
watch(
|
||||
() => route.params.id,
|
||||
() => formModelRef.value.reset()
|
||||
);
|
||||
const roleRoleRef = ref();
|
||||
const suggestions = ref([]);
|
||||
const myRoleRoles = ref([]);
|
||||
const selectedRows = ref([]);
|
||||
const columns = computed(() => [
|
||||
{
|
||||
name: 'roleFk',
|
||||
label: t('account.card.role'),
|
||||
component: 'select',
|
||||
attrs: {
|
||||
options: rolesOptions,
|
||||
inputDebounce: 0,
|
||||
},
|
||||
format: (row) => rolesOptions.value?.find((role) => role.id === row.roleFk)?.name,
|
||||
create: true,
|
||||
columnCreate: {
|
||||
event: {
|
||||
'update:modelValue': (role) => suggestionNewRole(role),
|
||||
},
|
||||
},
|
||||
columnFilter: false,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
name: 'hasGrant',
|
||||
label: t('account.card.privileges.delegate'),
|
||||
component: 'checkbox',
|
||||
create: true,
|
||||
columnFilter: false,
|
||||
cardVisible: true,
|
||||
},
|
||||
]);
|
||||
|
||||
const suggestionColumns = computed(() => [
|
||||
{
|
||||
align: 'center',
|
||||
name: 'role',
|
||||
field: 'role',
|
||||
label: t('Suggestion for role change'),
|
||||
format: (row) => rolesOptions.value?.find((role) => role.id === row)?.name,
|
||||
},
|
||||
]);
|
||||
|
||||
async function suggestionNewRole(role) {
|
||||
const newRoleRole = await roleRoleRef.value.fetch({ where: { inheritsFrom: role } });
|
||||
|
||||
suggestions.value = newRoleRole.filter((value) =>
|
||||
myRoleRoles.value.includes(value.role),
|
||||
);
|
||||
}
|
||||
|
||||
async function getMyRoleRole(roles) {
|
||||
const myRoleRole = await roleRoleRef.value.fetch({
|
||||
where: { inheritsFrom: { inq: roles.map((role) => role.roleFk) } },
|
||||
});
|
||||
|
||||
myRoleRoles.value = myRoleRole.map((role) => role.role);
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<FetchData url="VnRoles" auto-load @on-fetch="(data) => (rolesOptions = data)" />
|
||||
<FormModel
|
||||
ref="formModelRef"
|
||||
model="AccountPrivileges"
|
||||
url="VnUsers/preview"
|
||||
:filter="{ where: { id: route.params.id } }"
|
||||
:url-create="`VnUsers/${route.params.id}/privileges`"
|
||||
:id="route.params.id"
|
||||
<FetchData url="VnRoles" @on-fetch="(data) => (rolesOptions = data)" auto-load />
|
||||
<FetchData ref="roleRoleRef" url="RoleRoles" />
|
||||
<VnTable
|
||||
ref="vnTableRef"
|
||||
data-key="AccountPrivileges"
|
||||
:url="`VnUsers/${route.params.id}/role`"
|
||||
save-url="userRoles/crud"
|
||||
v-model:selected="selectedRows"
|
||||
:table="{
|
||||
'row-key': 'id',
|
||||
selection: 'multiple',
|
||||
}"
|
||||
:create="{
|
||||
urlCreate: 'userRoles/crud',
|
||||
title: t('Add Privileges'),
|
||||
onDataSaved: () => {
|
||||
$refs.vnTableRef.reload();
|
||||
},
|
||||
showSaveAndContinueBtn: true,
|
||||
formInitialData: { hasGrant: false },
|
||||
mapper: (data) => {
|
||||
return { creates: [{ ...data, userFk: route.params.id }] };
|
||||
},
|
||||
}"
|
||||
:columns
|
||||
:right-search="false"
|
||||
:is-editable="true"
|
||||
@on-fetch="(data) => getMyRoleRole(data)"
|
||||
@save-changes="() => arrayData.fetch({})"
|
||||
auto-load
|
||||
>
|
||||
<template #form="{ data }">
|
||||
<div class="q-gutter-y-sm">
|
||||
<QCheckbox
|
||||
v-model="data.hasGrant"
|
||||
:label="t('account.card.privileges.delegate')"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('account.card.role')"
|
||||
v-model="data.roleFk"
|
||||
:options="rolesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
hide-selected
|
||||
:required="true"
|
||||
/>
|
||||
</div>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<QTable
|
||||
v-if="data.roleFk && suggestions.length > 0"
|
||||
:rows="suggestions"
|
||||
:columns="suggestionColumns"
|
||||
/>
|
||||
</template>
|
||||
</FormModel>
|
||||
</VnTable>
|
||||
</template>
|
||||
<i18n>
|
||||
es:
|
||||
Suggestion for role change: Sugerencia de cambio de rol
|
||||
Add Privileges: Añadir privilegios
|
||||
</i18n>
|
||||
|
|
|
@ -6,6 +6,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
|
|||
import filter from './AccountFilter.js';
|
||||
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
|
||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||
import RoleJoin from '../Role/RoleJoin';
|
||||
|
||||
const $props = defineProps({ id: { type: Number, default: 0 } });
|
||||
|
||||
|
@ -33,7 +34,7 @@ const entityId = computed(() => $props.id || route.params.id);
|
|||
/>
|
||||
</QCardSection>
|
||||
<VnLv :label="$t('account.card.nickname')" :value="entity.name" />
|
||||
<VnLv :label="$t('account.card.role')" :value="entity.role?.name" />
|
||||
<VnLv :label="$t('account.card.role')" :value="RoleJoin(entity.role)" />
|
||||
</QCard>
|
||||
</template>
|
||||
</CardSummary>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export default function (roles) {
|
||||
return roles.map((r) => r.role.name).join(', ');
|
||||
}
|
Loading…
Reference in New Issue