#4074 useAcls #584
|
@ -105,7 +105,7 @@ async function setProvince(id, data) {
|
||||||
option-label="name"
|
option-label="name"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
:rules="validate('postcode.city')"
|
:rules="validate('postcode.city')"
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||||
:emit-value="false"
|
:emit-value="false"
|
||||||
clearable
|
clearable
|
||||||
>
|
>
|
||||||
|
|
|
@ -38,7 +38,7 @@ async function onProvinceCreated(_, data) {
|
||||||
hide-selected
|
hide-selected
|
||||||
v-model="provinceFk"
|
v-model="provinceFk"
|
||||||
:rules="validate && validate('postcode.provinceFk')"
|
:rules="validate && validate('postcode.provinceFk')"
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]"
|
||||||
>
|
>
|
||||||
<template #option="{ itemProps, opt }">
|
<template #option="{ itemProps, opt }">
|
||||||
<QItem v-bind="itemProps">
|
<QItem v-bind="itemProps">
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useRole } from 'src/composables/useRole';
|
||||||
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
|
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
@ -11,6 +12,10 @@ const $props = defineProps({
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => ['developer'],
|
default: () => ['developer'],
|
||||||
},
|
},
|
||||||
|
acls: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
actionIcon: {
|
actionIcon: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'add',
|
default: 'add',
|
||||||
|
@ -22,15 +27,13 @@ const $props = defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const role = useRole();
|
const role = useRole();
|
||||||
|
const acl = useAcl();
|
||||||
const showForm = ref(false);
|
const showForm = ref(false);
|
||||||
|
|
||||||
const isAllowedToCreate = computed(() => {
|
const isAllowedToCreate = computed(() => {
|
||||||
|
if ($props.acls.length) return acl.hasAny($props.acls);
|
||||||
return role.hasAny($props.rolesAllowedToCreate);
|
return role.hasAny($props.rolesAllowedToCreate);
|
||||||
|
|||||||
});
|
});
|
||||||
|
|
||||||
const toggleForm = () => {
|
|
||||||
showForm.value = !showForm.value;
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -41,7 +44,7 @@ const toggleForm = () => {
|
||||||
>
|
>
|
||||||
<template v-if="isAllowedToCreate" #append>
|
<template v-if="isAllowedToCreate" #append>
|
||||||
<QIcon
|
<QIcon
|
||||||
@click.stop.prevent="toggleForm()"
|
@click.stop.prevent="$refs.dialog.show()"
|
||||||
:name="actionIcon"
|
:name="actionIcon"
|
||||||
:size="actionIcon === 'add' ? 'xs' : 'sm'"
|
:size="actionIcon === 'add' ? 'xs' : 'sm'"
|
||||||
:class="['default-icon', { '--add-icon': actionIcon === 'add' }]"
|
:class="['default-icon', { '--add-icon': actionIcon === 'add' }]"
|
||||||
|
@ -51,7 +54,7 @@ const toggleForm = () => {
|
||||||
>
|
>
|
||||||
<QTooltip v-if="tooltip">{{ tooltip }}</QTooltip>
|
<QTooltip v-if="tooltip">{{ tooltip }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
<QDialog v-model="showForm" transition-show="scale" transition-hide="scale">
|
<QDialog ref="dialog" transition-show="scale" transition-hide="scale">
|
||||||
<slot name="form" />
|
<slot name="form" />
|
||||||
</QDialog>
|
</QDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -119,8 +119,8 @@ watch(
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => [props.url, props.filter],
|
() => [props.url, props.filter, props.userParams],
|
||||||
([url, filter]) => mounted.value && fetch({ url, filter })
|
([url, filter, userParams]) => mounted.value && fetch({ url, filter, userParams })
|
||||||
);
|
);
|
||||||
|
|
||||||
const addFilter = async (filter, params) => {
|
const addFilter = async (filter, params) => {
|
||||||
|
|
|
@ -16,13 +16,18 @@ export function useAcl() {
|
||||||
state.setAcls(acls);
|
state.setAcls(acls);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasAny(model, prop, accessType) {
|
function hasAny(acls) {
|
||||||
const acls = state.getAcls().value[model];
|
for (const acl of acls) {
|
||||||
if (acls)
|
let { model, props, accessType } = acl;
|
||||||
return ['*', prop].some((key) => {
|
const modelAcls = state.getAcls().value[model];
|
||||||
const acl = acls[key];
|
Array.isArray(props) || (props = [props]);
|
||||||
return acl && (acl['*'] || acl[accessType]);
|
if (modelAcls)
|
||||||
});
|
return ['*', ...props].some((key) => {
|
||||||
|
const acl = modelAcls[key];
|
||||||
|
return acl && (acl['*'] || acl[accessType]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -37,6 +37,10 @@ a {
|
||||||
.link {
|
.link {
|
||||||
color: $color-link;
|
color: $color-link;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
&--white {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tx-color-link {
|
.tx-color-link {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { computed, onBeforeMount, ref } from 'vue';
|
import { computed, onBeforeMount, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescr
|
||||||
const { openConfirmationModal } = useVnConfirm();
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
const { sendEmail } = usePrintService();
|
const { sendEmail } = usePrintService();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { hasAny } = useRole();
|
const { hasAny } = useAcl();
|
||||||
|
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
const tokenMultimedia = session.getTokenMultimedia();
|
const tokenMultimedia = session.getTokenMultimedia();
|
||||||
|
@ -284,7 +284,9 @@ const showBalancePdf = ({ id }) => {
|
||||||
>
|
>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="scope.value"
|
v-model="scope.value"
|
||||||
:disable="!hasAny(['administrative'])"
|
:disable="
|
||||||
|
!hasAny([{ model: 'Receipt', props: '*', accessType: 'WRITE' }])
|
||||||
|
"
|
||||||
@keypress.enter="scope.set"
|
@keypress.enter="scope.set"
|
||||||
autofocus
|
autofocus
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -70,7 +70,7 @@ const getBankEntities = (data, formData) => {
|
||||||
<VnSelectDialog
|
<VnSelectDialog
|
||||||
:label="t('Swift / BIC')"
|
:label="t('Swift / BIC')"
|
||||||
:options="bankEntitiesOptions"
|
:options="bankEntitiesOptions"
|
||||||
:roles-allowed-to-create="['salesAssistant', 'hr']"
|
:acls="[{ model: 'BankEntity', props: '*', accessType: 'WRITE' }]"
|
||||||
:rules="validate('Worker.bankEntity')"
|
:rules="validate('Worker.bankEntity')"
|
||||||
hide-selected
|
hide-selected
|
||||||
option-label="name"
|
option-label="name"
|
||||||
|
|
|
@ -93,7 +93,7 @@ function handleLocation(data, location) {
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:rules="validate('Worker.postcode')"
|
:rules="validate('Worker.postcode')"
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||||
v-model="data.postcode"
|
v-model="data.postcode"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -86,7 +86,7 @@ function handleLocation(data, location) {
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:rules="validate('Worker.postcode')"
|
:rules="validate('Worker.postcode')"
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||||
v-model="data.location"
|
v-model="data.location"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -412,7 +412,7 @@ function handleLocation(data, location) {
|
||||||
>
|
>
|
||||||
<template #more-create-dialog="{ data }">
|
<template #more-create-dialog="{ data }">
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]"
|
||||||
v-model="data.location"
|
v-model="data.location"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -92,7 +92,7 @@ function handleLocation(data, location) {
|
||||||
|
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:rules="validate('Worker.postcode')"
|
:rules="validate('Worker.postcode')"
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||||
v-model="data.location"
|
v-model="data.location"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -176,7 +176,7 @@ function handleLocation(data, location) {
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:rules="validate('Worker.postcode')"
|
:rules="validate('Worker.postcode')"
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||||
v-model="data.postalCode"
|
v-model="data.postalCode"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
></VnLocation>
|
></VnLocation>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
import { downloadFile } from 'src/composables/downloadFile';
|
import { downloadFile } from 'src/composables/downloadFile';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import { usePrintService } from 'composables/usePrintService';
|
import { usePrintService } from 'composables/usePrintService';
|
||||||
|
@ -24,7 +24,7 @@ const $props = defineProps({ id: { type: Number, default: null } });
|
||||||
const { push, currentRoute } = useRouter();
|
const { push, currentRoute } = useRouter();
|
||||||
|
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const { hasAny } = useRole();
|
const { hasAny } = useAcl();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openReport, sendEmail } = usePrintService();
|
const { openReport, sendEmail } = usePrintService();
|
||||||
const arrayData = useArrayData();
|
const arrayData = useArrayData();
|
||||||
|
@ -195,7 +195,8 @@ async function cloneInvoice() {
|
||||||
push({ path: `/invoice-in/${data.id}/summary` });
|
push({ path: `/invoice-in/${data.id}/summary` });
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAdministrative = () => hasAny(['administrative']);
|
const canEditProp = (props) =>
|
||||||
|
hasAny([{ model: 'InvoiceIn', props, accessType: 'WRITE' }]);
|
||||||
|
|
||||||
const isAgricultural = () => {
|
const isAgricultural = () => {
|
||||||
if (!config.value) return false;
|
if (!config.value) return false;
|
||||||
|
@ -283,7 +284,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
<InvoiceInToBook>
|
<InvoiceInToBook>
|
||||||
<template #content="{ book }">
|
<template #content="{ book }">
|
||||||
<QItem
|
<QItem
|
||||||
v-if="!entity?.isBooked && isAdministrative()"
|
v-if="!entity?.isBooked && canEditProp('toBook')"
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="book(entityId)"
|
@click="book(entityId)"
|
||||||
|
@ -293,7 +294,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
</template>
|
</template>
|
||||||
</InvoiceInToBook>
|
</InvoiceInToBook>
|
||||||
<QItem
|
<QItem
|
||||||
v-if="entity?.isBooked && isAdministrative()"
|
v-if="entity?.isBooked && canEditProp('toUnbook')"
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="triggerMenu('unbook')"
|
@click="triggerMenu('unbook')"
|
||||||
|
@ -303,7 +304,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem
|
<QItem
|
||||||
v-if="isAdministrative()"
|
v-if="canEditProp('deleteById')"
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="triggerMenu('delete')"
|
@click="triggerMenu('delete')"
|
||||||
|
@ -311,7 +312,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
<QItemSection>{{ t('Delete invoice') }}</QItemSection>
|
<QItemSection>{{ t('Delete invoice') }}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem
|
<QItem
|
||||||
v-if="isAdministrative()"
|
v-if="canEditProp('clone')"
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="triggerMenu('clone')"
|
@click="triggerMenu('clone')"
|
||||||
|
|
|
@ -7,8 +7,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
|
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
jsegarra
commented
Porque se modifica este componente reemplazando por VnTitle?? Porque se modifica este componente reemplazando <component /> por VnTitle??
jorgep
commented
Porque es un summary, los summary gastan VnTitle. Si te fijas, gasta un router-link o un span con la clase link... Porque es un summary, los summary gastan VnTitle. Si te fijas, gasta un router-link o un span con la clase link...
|
|||||||
import { useRole } from 'src/composables/useRole';
|
|
||||||
|
|
||||||
jorgep marked this conversation as resolved
jsegarra
commented
Porque no se hace con el archivo siguiente, crear una funcion llamada getUrl?? Porque no se hace con el archivo siguiente, crear una funcion llamada getUrl??
jorgep
commented
No veo la necesidad, pero te lo cambio. No veo la necesidad, pero te lo cambio.
|
|||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -19,23 +18,10 @@ const $props = defineProps({
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const roleState = useRole();
|
|
||||||
|
|
||||||
const entityId = computed(() => $props.id || route.params.id);
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
|
const getUrl = (id, param) => `#/Item/${id}/${param}`;
|
||||||
const isBuyer = computed(() => {
|
|
||||||
return roleState.hasAny(['buyer']);
|
|
||||||
});
|
|
||||||
|
|
||||||
const isReplenisher = computed(() => {
|
|
||||||
return roleState.hasAny(['replenisher']);
|
|
||||||
});
|
|
||||||
|
|
||||||
const isAdministrative = computed(() => {
|
|
||||||
return roleState.hasAny(['administrative']);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardSummary
|
<CardSummary
|
||||||
ref="summary"
|
ref="summary"
|
||||||
|
@ -44,13 +30,15 @@ const isAdministrative = computed(() => {
|
||||||
data-key="ItemSummary"
|
data-key="ItemSummary"
|
||||||
>
|
>
|
||||||
<template #header-left>
|
<template #header-left>
|
||||||
<router-link
|
<QBtn
|
||||||
v-if="route.name !== 'ItemSummary'"
|
v-if="$route.name !== 'ItemSummary'"
|
||||||
:to="{ name: 'ItemSummary', params: { id: entityId } }"
|
:to="{ name: 'ItemSummary', params: { id: entityId } }"
|
||||||
class="header link"
|
class="header link--white"
|
||||||
>
|
icon="open_in_new"
|
||||||
<QIcon name="open_in_new" color="white" size="sm" />
|
flat
|
||||||
</router-link>
|
dense
|
||||||
|
round
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #header="{ entity: { item } }">
|
<template #header="{ entity: { item } }">
|
||||||
{{ item.id }} - {{ item.name }}
|
{{ item.id }} - {{ item.name }}
|
||||||
|
@ -65,15 +53,10 @@ const isAdministrative = computed(() => {
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<component
|
<VnTitle
|
||||||
:is="isBuyer ? 'router-link' : 'span'"
|
:url="getUrl(entityId, 'basic-data')"
|
||||||
:to="{ name: 'ItemBasicData', params: { id: entityId } }"
|
:text="t('item.summary.basicData')"
|
||||||
class="header"
|
/>
|
||||||
:class="{ 'header-link': isBuyer }"
|
|
||||||
>
|
|
||||||
{{ t('item.summary.basicData') }}
|
|
||||||
<QIcon v-if="isBuyer" name="open_in_new" />
|
|
||||||
</component>
|
|
||||||
<VnLv :label="t('item.summary.name')" :value="item.name" />
|
<VnLv :label="t('item.summary.name')" :value="item.name" />
|
||||||
<VnLv :label="t('item.summary.completeName')" :value="item.longName" />
|
<VnLv :label="t('item.summary.completeName')" :value="item.longName" />
|
||||||
<VnLv :label="t('item.summary.family')" :value="item.itemType.name" />
|
<VnLv :label="t('item.summary.family')" :value="item.itemType.name" />
|
||||||
|
@ -104,15 +87,10 @@ const isAdministrative = computed(() => {
|
||||||
</VnLv>
|
</VnLv>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<component
|
<VnTitle
|
||||||
:is="isBuyer ? 'router-link' : 'span'"
|
:url="getUrl(entityId, 'basic-data')"
|
||||||
:to="{ name: 'ItemBasicData', params: { id: entityId } }"
|
:text="t('item.summary.otherData')"
|
||||||
class="header"
|
/>
|
||||||
:class="{ 'header-link': isBuyer }"
|
|
||||||
>
|
|
||||||
{{ t('item.summary.otherData') }}
|
|
||||||
<QIcon v-if="isBuyer" name="open_in_new" />
|
|
||||||
</component>
|
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('item.summary.intrastatCode')"
|
:label="t('item.summary.intrastatCode')"
|
||||||
:value="item.intrastat.id"
|
:value="item.intrastat.id"
|
||||||
|
@ -137,15 +115,7 @@ const isAdministrative = computed(() => {
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<component
|
<VnTitle :url="getUrl(entityId, 'tags')" :text="t('item.summary.tags')" />
|
||||||
:is="isBuyer || isReplenisher ? 'router-link' : 'span'"
|
|
||||||
:to="{ name: 'ItemTags', params: { id: entityId } }"
|
|
||||||
class="header"
|
|
||||||
:class="{ 'header-link': isBuyer || isReplenisher }"
|
|
||||||
>
|
|
||||||
{{ t('item.summary.tags') }}
|
|
||||||
<QIcon v-if="isBuyer || isReplenisher" name="open_in_new" />
|
|
||||||
</component>
|
|
||||||
<VnLv
|
<VnLv
|
||||||
v-for="(tag, index) in tags"
|
v-for="(tag, index) in tags"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
@ -154,29 +124,14 @@ const isAdministrative = computed(() => {
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one" v-if="item.description">
|
<QCard class="vn-one" v-if="item.description">
|
||||||
<component
|
<VnTitle
|
||||||
:is="isBuyer ? 'router-link' : 'span'"
|
:url="getUrl(entityId, 'basic-data')"
|
||||||
:to="{ name: 'ItemBasicData', params: { id: entityId } }"
|
:text="t('item.summary.description')"
|
||||||
class="header"
|
/>
|
||||||
:class="{ 'header-link': isBuyer }"
|
<p v-text="item.description" />
|
||||||
>
|
|
||||||
{{ t('item.summary.description') }}
|
|
||||||
<QIcon v-if="isBuyer" name="open_in_new" />
|
|
||||||
</component>
|
|
||||||
<p>
|
|
||||||
{{ item.description }}
|
|
||||||
</p>
|
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<component
|
<VnTitle :url="getUrl(entityId, 'tax')" :text="t('item.summary.tax')" />
|
||||||
:is="isBuyer || isAdministrative ? 'router-link' : 'span'"
|
|
||||||
:to="{ name: 'ItemTax', params: { id: entityId } }"
|
|
||||||
class="header"
|
|
||||||
:class="{ 'header-link': isBuyer || isAdministrative }"
|
|
||||||
>
|
|
||||||
{{ t('item.summary.tax') }}
|
|
||||||
<QIcon v-if="isBuyer || isAdministrative" name="open_in_new" />
|
|
||||||
</component>
|
|
||||||
<VnLv
|
<VnLv
|
||||||
v-for="(tax, index) in item.taxes"
|
v-for="(tax, index) in item.taxes"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
@ -185,15 +140,10 @@ const isAdministrative = computed(() => {
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<component
|
<VnTitle
|
||||||
:is="isBuyer ? 'router-link' : 'span'"
|
:url="getUrl(entityId, 'botanical')"
|
||||||
:to="{ name: 'ItemBotanical', params: { id: entityId } }"
|
:text="t('item.summary.botanical')"
|
||||||
class="header"
|
/>
|
||||||
:class="{ 'header-link': isBuyer }"
|
|
||||||
>
|
|
||||||
{{ t('item.summary.botanical') }}
|
|
||||||
<QIcon v-if="isBuyer" name="open_in_new" />
|
|
||||||
</component>
|
|
||||||
<VnLv :label="t('item.summary.genus')" :value="botanical?.genus?.name" />
|
<VnLv :label="t('item.summary.genus')" :value="botanical?.genus?.name" />
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('item.summary.specie')"
|
:label="t('item.summary.specie')"
|
||||||
|
@ -201,23 +151,19 @@ const isAdministrative = computed(() => {
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<component
|
<VnTitle
|
||||||
:is="isBuyer || isReplenisher ? 'router-link' : 'span'"
|
:url="getUrl(entityId, 'barcode')"
|
||||||
:to="{ name: 'ItemBarcode', params: { id: entityId } }"
|
:text="t('item.summary.barcode')"
|
||||||
class="header"
|
/>
|
||||||
:class="{ 'header-link': isBuyer || isReplenisher }"
|
<p
|
||||||
>
|
v-for="(barcode, index) in item.itemBarcode"
|
||||||
{{ t('item.summary.barcode') }}
|
:key="index"
|
||||||
<QIcon v-if="isBuyer || isReplenisher" name="open_in_new" />
|
v-text="barcode.code"
|
||||||
</component>
|
/>
|
||||||
<p v-for="(barcode, index) in item.itemBarcode" :key="index">
|
|
||||||
{{ barcode.code }}
|
|
||||||
</p>
|
|
||||||
</QCard>
|
</QCard>
|
||||||
</template>
|
</template>
|
||||||
</CardSummary>
|
</CardSummary>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
en:
|
en:
|
||||||
Este artículo necesita una foto: Este artículo necesita una foto
|
Este artículo necesita una foto: Este artículo necesita una foto
|
||||||
|
|
|
@ -83,7 +83,7 @@ function handleLocation(data, location) {
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:rules="validate('Worker.postcode')"
|
:rules="validate('Worker.postcode')"
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||||
v-model="data.location"
|
v-model="data.location"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -129,7 +129,7 @@ function handleLocation(data, location) {
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:rules="validate('Worker.postcode')"
|
:rules="validate('Worker.postcode')"
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||||
v-model="data.postCode"
|
v-model="data.postCode"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -4,13 +4,11 @@ import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import CardSummary from 'components/ui/CardSummary.vue';
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import { useRole } from 'src/composables/useRole';
|
|
||||||
import { dashIfEmpty } from 'src/filters';
|
import { dashIfEmpty } from 'src/filters';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const roleState = useRole();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
|
@ -32,13 +30,7 @@ async function setData(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAdministrative = computed(() => {
|
const getUrl = (section) => `#/supplier/${entityId.value}/${section}`;
|
||||||
return roleState.hasAny(['administrative']);
|
|
||||||
});
|
|
||||||
|
|
||||||
function getUrl(section) {
|
|
||||||
return isAdministrative.value && `#/supplier/${entityId.value}/${section}`;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
travel: {
|
travel: {
|
||||||
|
@ -21,7 +21,6 @@ const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
const role = useRole();
|
|
||||||
|
|
||||||
const redirectToCreateView = (queryParams) => {
|
const redirectToCreateView = (queryParams) => {
|
||||||
router.push({ name: 'TravelCreate', query: { travelData: queryParams } });
|
router.push({ name: 'TravelCreate', query: { travelData: queryParams } });
|
||||||
|
@ -42,9 +41,7 @@ const cloneTravelWithEntries = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isBuyer = computed(() => {
|
const canDelete = computed(() => useAcl().hasAny('Travel','*','WRITE'));
|
||||||
return role.hasAny(['buyer']);
|
|
||||||
});
|
|
||||||
|
|
||||||
const openDeleteEntryDialog = (id) => {
|
const openDeleteEntryDialog = (id) => {
|
||||||
quasar
|
quasar
|
||||||
|
@ -81,7 +78,7 @@ const deleteTravel = async (id) => {
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem
|
<QItem
|
||||||
v-if="isBuyer && travel.totalEntries === 0"
|
v-if="canDelete && travel.totalEntries === 0"
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="openDeleteEntryDialog(travel.id)"
|
@click="openDeleteEntryDialog(travel.id)"
|
||||||
|
|
|
@ -3,13 +3,13 @@ import { ref, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
import FormModel from 'components/FormModel.vue';
|
import FormModel from 'components/FormModel.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
|
||||||
const { hasAny } = useRole();
|
const { hasAny } = useAcl();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const fetchData = ref();
|
const fetchData = ref();
|
||||||
const originaLockerId = ref();
|
const originaLockerId = ref();
|
||||||
|
@ -57,7 +57,11 @@ const init = async (data) => {
|
||||||
option-label="code"
|
option-label="code"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
hide-selected
|
hide-selected
|
||||||
:readonly="!hasAny(['productionBoss', 'hr'])"
|
:readonly="
|
||||||
|
!hasAny([
|
||||||
|
{ model: 'Worker', props: '__get__locker', accessType: 'READ' },
|
||||||
|
])
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</FormModel>
|
</FormModel>
|
||||||
|
|
|
@ -13,6 +13,7 @@ import WorkerTimeControlCalendar from 'pages/Worker/Card/WorkerTimeControlCalend
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useRole } from 'src/composables/useRole';
|
||||||
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
|
@ -26,7 +27,6 @@ import { date } from 'quasar';
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
const { hasAny } = useRole();
|
|
||||||
const _state = useState();
|
const _state = useState();
|
||||||
const user = _state.getUser();
|
const user = _state.getUser();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
|
@ -66,9 +66,11 @@ const arrayData = useArrayData('workerData');
|
||||||
|
|
||||||
const worker = computed(() => arrayData.store?.data);
|
const worker = computed(() => arrayData.store?.data);
|
||||||
|
|
||||||
const isHr = computed(() => hasAny(['hr']));
|
const isHr = computed(() => useRole().hasAny(['hr']));
|
||||||
jsegarra
commented
duda: en router(index hemos rremplazado userole por useAcl, aqui proque no? duda: en router(index hemos rremplazado userole por useAcl, aqui proque no?
jorgep
commented
En este caso en concreto, no lo he tocado porque lo abordaré en otra tarea, ya que tengo que cambiar permisos y añadir otro acl. En el redmite está indicado. En este caso en concreto, no lo he tocado porque lo abordaré en otra tarea, ya que tengo que cambiar permisos y añadir otro acl. En el redmite está indicado.
|
|||||||
|
|
||||||
const isHimSelf = computed(() => user.value.id === Number(route.params.id));
|
const canSend = computed(() => useAcl().hasAny('WorkerTimeControl', 'sendMail', 'WRITE'));
|
||||||
|
|
||||||
|
const isHimself = computed(() => user.value.id === Number(route.params.id));
|
||||||
|
|
||||||
const columns = computed(() => {
|
const columns = computed(() => {
|
||||||
return weekdayStore.getLocales?.map((day, index) => {
|
return weekdayStore.getLocales?.map((day, index) => {
|
||||||
|
@ -447,7 +449,7 @@ onMounted(async () => {
|
||||||
<div>
|
<div>
|
||||||
<QBtnGroup push class="q-gutter-x-sm" flat>
|
<QBtnGroup push class="q-gutter-x-sm" flat>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="isHimSelf && state"
|
v-if="isHimself && state"
|
||||||
:label="t('Satisfied')"
|
:label="t('Satisfied')"
|
||||||
color="primary"
|
color="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -455,7 +457,7 @@ onMounted(async () => {
|
||||||
@click="isSatisfied()"
|
@click="isSatisfied()"
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="isHimSelf && state"
|
v-if="isHimself && state"
|
||||||
:label="t('Not satisfied')"
|
:label="t('Not satisfied')"
|
||||||
color="primary"
|
color="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -466,14 +468,14 @@ onMounted(async () => {
|
||||||
</QBtnGroup>
|
</QBtnGroup>
|
||||||
<QBtnGroup push class="q-gutter-x-sm q-ml-none" flat>
|
<QBtnGroup push class="q-gutter-x-sm q-ml-none" flat>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="reason && state && (isHimSelf || isHr)"
|
v-if="reason && state && (isHimself || isHr)"
|
||||||
:label="t('Reason')"
|
:label="t('Reason')"
|
||||||
color="primary"
|
color="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
@click="showReasonForm()"
|
@click="showReasonForm()"
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="isHr && state !== 'CONFIRMED' && canResend"
|
v-if="canSend && state !== 'CONFIRMED' && canResend"
|
||||||
:label="state ? t('Resend') : t('globals.send')"
|
:label="state ? t('Resend') : t('globals.send')"
|
||||||
color="primary"
|
color="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -603,7 +605,7 @@ onMounted(async () => {
|
||||||
<WorkerTimeReasonForm
|
<WorkerTimeReasonForm
|
||||||
@on-submit="isUnsatisfied($event)"
|
@on-submit="isUnsatisfied($event)"
|
||||||
:reason="reason"
|
:reason="reason"
|
||||||
:is-him-self="isHimSelf"
|
:is-himself="isHimself"
|
||||||
/>
|
/>
|
||||||
</QDialog>
|
</QDialog>
|
||||||
</QPage>
|
</QPage>
|
||||||
|
|
|
@ -9,7 +9,7 @@ const $props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
isHimSelf: {
|
isHimself: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
@ -40,7 +40,7 @@ const closeForm = () => {
|
||||||
v-model="reasonFormData"
|
v-model="reasonFormData"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
autogrow
|
autogrow
|
||||||
:disable="!isHimSelf"
|
:disable="!isHimself"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</FormPopup>
|
</FormPopup>
|
||||||
|
|
|
@ -262,7 +262,7 @@ async function autofillBic(worker) {
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:roles-allowed-to-create="['deliveryAssistant']"
|
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||||
:options="postcodesOptions"
|
:options="postcodesOptions"
|
||||||
v-model="data.location"
|
v-model="data.location"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
|
@ -311,7 +311,7 @@ async function autofillBic(worker) {
|
||||||
option-label="name"
|
option-label="name"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
hide-selected
|
hide-selected
|
||||||
:roles-allowed-to-create="['salesAssistant', 'hr']"
|
:acls="[{ model: 'BankEntity', props: '*', accessType: 'WRITE' }]"
|
||||||
:disable="data.isFreelance"
|
:disable="data.isFreelance"
|
||||||
@update:model-value="autofillBic(data)"
|
@update:model-value="autofillBic(data)"
|
||||||
:filter-options="['bic', 'name']"
|
:filter-options="['bic', 'name']"
|
||||||
|
|
|
@ -60,15 +60,12 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
await useTokenConfig().fetch();
|
await useTokenConfig().fetch();
|
||||||
}
|
}
|
||||||
const matches = to.matched;
|
const matches = to.matched;
|
||||||
const hasRequiredRoles = matches.every((route) => {
|
const hasRequiredAcls = matches.every((route) => {
|
||||||
const meta = route.meta;
|
const meta = route.meta;
|
||||||
if (meta && meta.roles) return useRole().hasAny(meta.roles);
|
if (!meta?.acls) return true;
|
||||||
return true;
|
return useAcl().hasAny(meta.acls);
|
||||||
});
|
});
|
||||||
|
if (!hasRequiredAcls) return next({ path: '/' });
|
||||||
if (!hasRequiredRoles) {
|
|
||||||
return next({ path: '/' });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|
|
@ -80,7 +80,7 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: 'accounts',
|
title: 'accounts',
|
||||||
icon: 'accessibility',
|
icon: 'accessibility',
|
||||||
roles: ['itManagement'],
|
acls: [{ model: 'Account', props: '*', accessType: '*' }],
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Account/AccountAccounts.vue'),
|
component: () => import('src/pages/Account/AccountAccounts.vue'),
|
||||||
},
|
},
|
||||||
|
@ -90,7 +90,7 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: 'ldap',
|
title: 'ldap',
|
||||||
icon: 'account_tree',
|
icon: 'account_tree',
|
||||||
roles: ['itManagement'],
|
acls: [{ model: 'LdapConfig', props: '*', accessType: '*' }],
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Account/AccountLdap.vue'),
|
component: () => import('src/pages/Account/AccountLdap.vue'),
|
||||||
},
|
},
|
||||||
|
@ -100,7 +100,7 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: 'samba',
|
title: 'samba',
|
||||||
icon: 'preview',
|
icon: 'preview',
|
||||||
roles: ['itManagement'],
|
acls: [{ model: 'SambaConfig', props: '*', accessType: '*' }],
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Account/AccountSamba.vue'),
|
component: () => import('src/pages/Account/AccountSamba.vue'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -62,7 +62,7 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: 'basicData',
|
title: 'basicData',
|
||||||
icon: 'vn:settings',
|
icon: 'vn:settings',
|
||||||
roles: ['salesPerson'],
|
acls: [{ model: 'Claim', props: 'findById', accessType: 'READ' }],
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Claim/Card/ClaimBasicData.vue'),
|
component: () => import('src/pages/Claim/Card/ClaimBasicData.vue'),
|
||||||
},
|
},
|
||||||
|
@ -99,7 +99,13 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: 'development',
|
title: 'development',
|
||||||
icon: 'vn:traceability',
|
icon: 'vn:traceability',
|
||||||
roles: ['claimManager'],
|
acls: [
|
||||||
|
{
|
||||||
|
model: 'ClaimDevelopment',
|
||||||
|
props: '*',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Claim/Card/ClaimDevelopment.vue'),
|
component: () => import('src/pages/Claim/Card/ClaimDevelopment.vue'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -84,7 +84,6 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: 'basicData',
|
title: 'basicData',
|
||||||
icon: 'vn:settings',
|
icon: 'vn:settings',
|
||||||
roles: ['salesPerson'],
|
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import('src/pages/InvoiceIn/Card/InvoiceInBasicData.vue'),
|
import('src/pages/InvoiceIn/Card/InvoiceInBasicData.vue'),
|
||||||
|
|
|
@ -76,7 +76,6 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: 'basicData',
|
title: 'basicData',
|
||||||
icon: 'vn:settings',
|
icon: 'vn:settings',
|
||||||
roles: ['salesPerson'],
|
|
||||||
jorgep
commented
No tiene sentido. Cualquier employee puede editarlo o verlo. No tiene sentido. Cualquier employee puede editarlo o verlo.
|
|||||||
},
|
},
|
||||||
component: () => import('pages/Shelving/Card/ShelvingForm.vue'),
|
component: () => import('pages/Shelving/Card/ShelvingForm.vue'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -54,7 +54,6 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: 'createTicket',
|
title: 'createTicket',
|
||||||
icon: 'vn:ticketAdd',
|
icon: 'vn:ticketAdd',
|
||||||
roles: ['developer'],
|
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Ticket/TicketCreate.vue'),
|
component: () => import('src/pages/Ticket/TicketCreate.vue'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,7 @@ import axios from 'axios';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { toLowerCamel } from 'src/filters';
|
import { toLowerCamel } from 'src/filters';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
import routes from 'src/router/modules';
|
import routes from 'src/router/modules';
|
||||||
|
|
||||||
export const useNavigationStore = defineStore('navigationStore', () => {
|
export const useNavigationStore = defineStore('navigationStore', () => {
|
||||||
|
@ -26,7 +26,7 @@ export const useNavigationStore = defineStore('navigationStore', () => {
|
||||||
'zone',
|
'zone',
|
||||||
];
|
];
|
||||||
const pinnedModules = ref([]);
|
const pinnedModules = ref([]);
|
||||||
const role = useRole();
|
const acl = useAcl();
|
||||||
|
|
||||||
function getModules() {
|
function getModules() {
|
||||||
const modulesRoutes = ref([]);
|
const modulesRoutes = ref([]);
|
||||||
|
@ -64,7 +64,7 @@ export const useNavigationStore = defineStore('navigationStore', () => {
|
||||||
title: `globals.pageTitles.${title}`,
|
title: `globals.pageTitles.${title}`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (meta && meta.roles && role.hasAny(meta.roles) === false) return;
|
if (meta && meta.acls && acl.hasAny(meta.acls) === false) return;
|
||||||
|
|
||||||
const item = {
|
const item = {
|
||||||
name: route.name,
|
name: route.name,
|
||||||
|
|
|
@ -52,9 +52,9 @@ describe('Login', () => {
|
||||||
cy.url().should('contain', '/login');
|
cy.url().should('contain', '/login');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should get redirected to dashboard since employee can't create tickets`, () => {
|
it(`should be redirected to dashboard since the employee is not enabled to see ldap`, () => {
|
||||||
cy.visit('/#/ticket/create', { failOnStatusCode: false });
|
cy.visit('/#/account/ldap', { failOnStatusCode: false });
|
||||||
jorgep
commented
Habían puesto que solo podía el role developer. Esto en Salix no estaba. Habían puesto que solo podía el role developer. Esto en Salix no estaba.
|
jorgep marked this conversation as resolved
jsegarra
commented
Hermos cambiado la URL pero no hemos cambiado el it del test... Hermos cambiado la URL pero no hemos cambiado el it del test...
|
||||||
cy.url().should('contain', '/#/login?redirect=/ticket/create');
|
cy.url().should('contain', '/#/login?redirect=/account/ldap');
|
||||||
cy.get('input[aria-label="Username"]').type('employee');
|
cy.get('input[aria-label="Username"]').type('employee');
|
||||||
cy.get('input[aria-label="Password"]').type('nightmare');
|
cy.get('input[aria-label="Password"]').type('nightmare');
|
||||||
cy.get('button[type="submit"]').click();
|
cy.get('button[type="submit"]').click();
|
||||||
|
|
|
@ -48,40 +48,62 @@ describe('useAcl', () => {
|
||||||
|
|
||||||
jsegarra
commented
Test maravilloso 🤌 Test maravilloso 🤌
|
|||||||
describe('hasAny', () => {
|
describe('hasAny', () => {
|
||||||
it('should return false if no roles matched', async () => {
|
it('should return false if no roles matched', async () => {
|
||||||
expect(acl.hasAny('Worker', 'updateAttributes', 'WRITE')).toBeFalsy();
|
expect(
|
||||||
|
acl.hasAny([
|
||||||
|
{ model: 'Worker', props: 'updateAttributes', accessType: 'WRITE' },
|
||||||
|
])
|
||||||
|
).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if no roles matched', async () => {
|
it('should return false if no roles matched', async () => {
|
||||||
expect(acl.hasAny('Worker', 'holidays', 'READ')).toBeTruthy();
|
expect(
|
||||||
|
acl.hasAny([{ model: 'Worker', props: 'holidays', accessType: 'READ' }])
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('*', () => {
|
describe('*', () => {
|
||||||
it('should return true if an acl matched', async () => {
|
it('should return true if an acl matched', async () => {
|
||||||
expect(acl.hasAny('Address', '*', 'WRITE')).toBeTruthy();
|
expect(
|
||||||
|
acl.hasAny([{ model: 'Address', props: '*', accessType: 'WRITE' }])
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if no acls matched', async () => {
|
it('should return false if no acls matched', async () => {
|
||||||
expect(acl.hasAny('Worker', '*', 'READ')).toBeFalsy();
|
expect(
|
||||||
|
acl.hasAny([{ model: 'Worker', props: '*', accessType: 'READ' }])
|
||||||
|
).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('$authenticated', () => {
|
describe('$authenticated', () => {
|
||||||
it('should return false if no acls matched', async () => {
|
it('should return false if no acls matched', async () => {
|
||||||
expect(acl.hasAny('Url', 'getByUser', '*')).toBeFalsy();
|
expect(
|
||||||
|
acl.hasAny([{ model: 'Url', props: 'getByUser', accessType: '*' }])
|
||||||
|
).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true if an acl matched', async () => {
|
it('should return true if an acl matched', async () => {
|
||||||
expect(acl.hasAny('Url', 'getByUser', 'READ')).toBeTruthy();
|
expect(
|
||||||
|
acl.hasAny([{ model: 'Url', props: 'getByUser', accessType: 'READ' }])
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('$everyone', () => {
|
describe('$everyone', () => {
|
||||||
it('should return false if no acls matched', async () => {
|
it('should return false if no acls matched', async () => {
|
||||||
expect(acl.hasAny('TpvTransaction', 'start', 'READ')).toBeFalsy();
|
expect(
|
||||||
|
acl.hasAny([
|
||||||
|
{ model: 'TpvTransaction', props: 'start', accessType: 'READ' },
|
||||||
|
])
|
||||||
|
).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if an acl matched', async () => {
|
it('should return false if an acl matched', async () => {
|
||||||
expect(acl.hasAny('TpvTransaction', 'start', 'WRITE')).toBeTruthy();
|
expect(
|
||||||
|
acl.hasAny([
|
||||||
|
{ model: 'TpvTransaction', props: 'start', accessType: 'WRITE' },
|
||||||
|
])
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Mantenemos retrocompatibilidad.