refactor: enhance access control and visibility logic across various components
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 6s
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 6s
This commit is contained in:
parent
a59e0c5157
commit
c481266654
8 changed files with 43 additions and 30 deletions
|
|
@ -48,6 +48,7 @@ defineProps<{
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
onDrawer?: boolean;
|
onDrawer?: boolean;
|
||||||
inputOnly?: boolean;
|
inputOnly?: boolean;
|
||||||
|
disableToggle?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
|
|
@ -76,6 +77,7 @@ defineEmits<{
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
class="q-mr-sm"
|
class="q-mr-sm"
|
||||||
two-way
|
two-way
|
||||||
|
:disable="disableToggle"
|
||||||
:model-value="status !== 'INACTIVE'"
|
:model-value="status !== 'INACTIVE'"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -195,8 +197,8 @@ defineEmits<{
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(
|
:deep(
|
||||||
.q-item__section.column.q-item__section--side.justify-center.q-item__section--avatar.q-focusable.relative-position.cursor-pointer
|
.q-item__section.column.q-item__section--side.justify-center.q-item__section--avatar.q-focusable.relative-position.cursor-pointer
|
||||||
) {
|
) {
|
||||||
justify-content: start !important;
|
justify-content: start !important;
|
||||||
padding-right: 8px !important;
|
padding-right: 8px !important;
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
|
|
@ -208,15 +210,15 @@ defineEmits<{
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(
|
:deep(
|
||||||
i.q-icon.mdi.mdi-chevron-down-circle.q-expansion-item__toggle-icon.q-expansion-item__toggle-icon--rotated
|
i.q-icon.mdi.mdi-chevron-down-circle.q-expansion-item__toggle-icon.q-expansion-item__toggle-icon--rotated
|
||||||
) {
|
) {
|
||||||
color: var(--brand-1);
|
color: var(--brand-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(
|
:deep(
|
||||||
.q-item.q-item-type.row.no-wrap.q-item--dense.q-item--clickable.q-link.cursor-pointer.q-focusable.q-hoverable.expansion-rounded.surface-2
|
.q-item.q-item-type.row.no-wrap.q-item--dense.q-item--clickable.q-link.cursor-pointer.q-focusable.q-hoverable.expansion-rounded.surface-2
|
||||||
.q-focus-helper
|
.q-focus-helper
|
||||||
) {
|
) {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { BranchWithChildren } from 'stores/branch/types';
|
import { BranchWithChildren } from 'stores/branch/types';
|
||||||
import KebabAction from './shared/KebabAction.vue';
|
import KebabAction from './shared/KebabAction.vue';
|
||||||
import { isRoleInclude } from 'stores/utils';
|
|
||||||
|
|
||||||
const nodes = defineModel<(any | BranchWithChildren)[]>('nodes', {
|
const nodes = defineModel<(any | BranchWithChildren)[]>('nodes', {
|
||||||
default: [],
|
default: [],
|
||||||
|
|
@ -120,17 +119,7 @@ defineEmits<{
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="
|
v-if="node.isHeadOffice && typeTree === 'branch'"
|
||||||
node.isHeadOffice &&
|
|
||||||
typeTree === 'branch' &&
|
|
||||||
isRoleInclude([
|
|
||||||
'system',
|
|
||||||
'head_of_admin',
|
|
||||||
'admin',
|
|
||||||
'executive',
|
|
||||||
'accountant',
|
|
||||||
])
|
|
||||||
"
|
|
||||||
:id="`create-sub-branch-btn-${node.name}`"
|
:id="`create-sub-branch-btn-${node.name}`"
|
||||||
@click.stop="$emit('create', node)"
|
@click.stop="$emit('create', node)"
|
||||||
icon="mdi-file-plus-outline"
|
icon="mdi-file-plus-outline"
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import { FloatingActionButton, PaginationComponent } from 'src/components';
|
||||||
import PaginationPageSize from 'src/components/PaginationPageSize.vue';
|
import PaginationPageSize from 'src/components/PaginationPageSize.vue';
|
||||||
import PropertyDialog from './PropertyDialog.vue';
|
import PropertyDialog from './PropertyDialog.vue';
|
||||||
import { Property } from 'src/stores/property/types';
|
import { Property } from 'src/stores/property/types';
|
||||||
import { dialog, toCamelCase } from 'src/stores/utils';
|
import { dialog, toCamelCase, canAccess } from 'src/stores/utils';
|
||||||
import CreateButton from 'src/components/AddButton.vue';
|
import CreateButton from 'src/components/AddButton.vue';
|
||||||
import useOptionStore from 'stores/options';
|
import useOptionStore from 'stores/options';
|
||||||
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
|
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
|
||||||
|
|
@ -331,6 +331,7 @@ watch(
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FloatingActionButton
|
<FloatingActionButton
|
||||||
|
v-if="canAccess('workflow', 'edit')"
|
||||||
style="z-index: 999"
|
style="z-index: 999"
|
||||||
hide-icon
|
hide-icon
|
||||||
@click="triggerDialog('add')"
|
@click="triggerDialog('add')"
|
||||||
|
|
@ -536,11 +537,19 @@ watch(
|
||||||
class="col surface-2 flex items-center justify-center"
|
class="col surface-2 flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<NoData
|
<NoData
|
||||||
v-if="pageState.total !== 0 || pageState.searchDate.length > 0"
|
v-if="
|
||||||
|
pageState.total !== 0 ||
|
||||||
|
pageState.searchDate.length > 0 ||
|
||||||
|
!canAccess('workflow', 'edit')
|
||||||
|
"
|
||||||
:not-found="!!pageState.inputSearch"
|
:not-found="!!pageState.inputSearch"
|
||||||
/>
|
/>
|
||||||
<CreateButton
|
<CreateButton
|
||||||
v-if="pageState.total === 0 && pageState.searchDate.length === 0"
|
v-if="
|
||||||
|
pageState.total === 0 &&
|
||||||
|
pageState.searchDate.length === 0 &&
|
||||||
|
canAccess('workflow', 'edit')
|
||||||
|
"
|
||||||
@click="triggerDialog('add')"
|
@click="triggerDialog('add')"
|
||||||
label="general.add"
|
label="general.add"
|
||||||
:i18n-args="{ text: $t('flow.title') }"
|
:i18n-args="{ text: $t('flow.title') }"
|
||||||
|
|
@ -698,6 +707,7 @@ watch(
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<KebabAction
|
<KebabAction
|
||||||
|
v-if="canAccess('workflow', 'edit')"
|
||||||
:id-name="props.row.name"
|
:id-name="props.row.name"
|
||||||
:status="props.row.status"
|
:status="props.row.status"
|
||||||
@view="
|
@view="
|
||||||
|
|
@ -815,6 +825,7 @@ watch(
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<KebabAction
|
<KebabAction
|
||||||
|
v-if="canAccess('workflow', 'edit')"
|
||||||
:id-name="props.row.id"
|
:id-name="props.row.id"
|
||||||
:status="props.row.status"
|
:status="props.row.status"
|
||||||
@view="
|
@view="
|
||||||
|
|
@ -906,6 +917,7 @@ watch(
|
||||||
@drawer-undo="() => undo()"
|
@drawer-undo="() => undo()"
|
||||||
@close="() => resetForm()"
|
@close="() => resetForm()"
|
||||||
@submit="() => submit()"
|
@submit="() => submit()"
|
||||||
|
:hide-action="!canAccess('workflow', 'edit')"
|
||||||
:readonly="!pageState.isDrawerEdit"
|
:readonly="!pageState.isDrawerEdit"
|
||||||
:isEdit="pageState.isDrawerEdit"
|
:isEdit="pageState.isDrawerEdit"
|
||||||
v-model="pageState.addModal"
|
v-model="pageState.addModal"
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
isEdit?: boolean;
|
isEdit?: boolean;
|
||||||
|
hideAction?: boolean;
|
||||||
}>(),
|
}>(),
|
||||||
{ readonly: false, isEdit: false },
|
{ readonly: false, isEdit: false },
|
||||||
);
|
);
|
||||||
|
|
@ -151,7 +152,7 @@ defineEmits<{
|
||||||
style="position: absolute; z-index: 999; top: 0; right: 0"
|
style="position: absolute; z-index: 999; top: 0; right: 0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="propertyData.status !== 'INACTIVE'"
|
v-if="propertyData.status !== 'INACTIVE' && !hideAction"
|
||||||
class="surface-1 row rounded"
|
class="surface-1 row rounded"
|
||||||
>
|
>
|
||||||
<UndoButton
|
<UndoButton
|
||||||
|
|
@ -236,6 +237,7 @@ defineEmits<{
|
||||||
<FormProperty
|
<FormProperty
|
||||||
onDrawer
|
onDrawer
|
||||||
:readonly="!isEdit"
|
:readonly="!isEdit"
|
||||||
|
:disable-toggle="hideAction"
|
||||||
v-model:name="formProperty.name"
|
v-model:name="formProperty.name"
|
||||||
v-model:name-en="formProperty.nameEN"
|
v-model:name-en="formProperty.nameEN"
|
||||||
v-model:type="formProperty.type"
|
v-model:type="formProperty.type"
|
||||||
|
|
|
||||||
|
|
@ -480,7 +480,7 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- bill -->
|
<!-- bill -->
|
||||||
<span class="app-text-muted-2 q-pt-md">
|
<span class="app-text-muted-2 q-pt-md" v-if="paymentData.length > 0">
|
||||||
{{ $t('quotation.receiptDialog.billOfPayment') }}
|
{{ $t('quotation.receiptDialog.billOfPayment') }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
dialogWarningClose,
|
dialogWarningClose,
|
||||||
formatNumberDecimal,
|
formatNumberDecimal,
|
||||||
canAccess,
|
canAccess,
|
||||||
|
isRoleInclude,
|
||||||
} from 'stores/utils';
|
} from 'stores/utils';
|
||||||
import { ProductTree, quotationProductTree } from './utils';
|
import { ProductTree, quotationProductTree } from './utils';
|
||||||
|
|
||||||
|
|
@ -1736,7 +1737,7 @@ function covertToNode() {
|
||||||
:readonly="
|
:readonly="
|
||||||
{
|
{
|
||||||
quotation: quotationFormState.mode !== 'edit',
|
quotation: quotationFormState.mode !== 'edit',
|
||||||
invoice: false,
|
invoice: isRoleInclude(['sale', 'head_of_sale']),
|
||||||
accepted: true,
|
accepted: true,
|
||||||
}[view]
|
}[view]
|
||||||
"
|
"
|
||||||
|
|
@ -1940,6 +1941,7 @@ function covertToNode() {
|
||||||
view !== View.Receipt &&
|
view !== View.Receipt &&
|
||||||
view !== View.Complete
|
view !== View.Complete
|
||||||
"
|
"
|
||||||
|
:readonly="isRoleInclude(['sale', 'head_of_sale'])"
|
||||||
:data="quotationFormState.source"
|
:data="quotationFormState.source"
|
||||||
v-model:first-code-payment="firstCodePayment"
|
v-model:first-code-payment="firstCodePayment"
|
||||||
@fetch-status="
|
@fetch-status="
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ import {
|
||||||
import { RequestWork } from 'src/stores/request-list/types';
|
import { RequestWork } from 'src/stores/request-list/types';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import useOptionStore from 'src/stores/options';
|
import useOptionStore from 'src/stores/options';
|
||||||
import { dialogWarningClose, canAccess } from 'src/stores/utils';
|
import { dialogWarningClose, canAccess, isRoleInclude } from 'src/stores/utils';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { QForm } from 'quasar';
|
import { QForm } from 'quasar';
|
||||||
import { getName } from 'src/services/keycloak';
|
import { getName } from 'src/services/keycloak';
|
||||||
|
|
@ -728,7 +728,7 @@ onMounted(async () => {
|
||||||
|
|
||||||
<AdditionalFileExpansion
|
<AdditionalFileExpansion
|
||||||
v-if="view !== CreditNoteStatus.Success"
|
v-if="view !== CreditNoteStatus.Success"
|
||||||
:readonly="false"
|
:readonly="isRoleInclude(['sale', 'head_of_sale'])"
|
||||||
v-model:file-data="attachmentData"
|
v-model:file-data="attachmentData"
|
||||||
:transform-url="
|
:transform-url="
|
||||||
async (url: string) => {
|
async (url: string) => {
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,13 @@ import {
|
||||||
import { RequestWork } from 'src/stores/request-list/types';
|
import { RequestWork } from 'src/stores/request-list/types';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import useOptionStore from 'src/stores/options';
|
import useOptionStore from 'src/stores/options';
|
||||||
import { deleteItem, dialog, dialogWarningClose } from 'src/stores/utils';
|
import {
|
||||||
|
canAccess,
|
||||||
|
deleteItem,
|
||||||
|
dialog,
|
||||||
|
dialogWarningClose,
|
||||||
|
isRoleInclude,
|
||||||
|
} from 'src/stores/utils';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { Employee } from 'src/stores/employee/types';
|
import { Employee } from 'src/stores/employee/types';
|
||||||
import QuotationFormWorkerSelect from '../05_quotation/QuotationFormWorkerSelect.vue';
|
import QuotationFormWorkerSelect from '../05_quotation/QuotationFormWorkerSelect.vue';
|
||||||
|
|
@ -1071,6 +1077,7 @@ async function submitAccepted() {
|
||||||
<PaymentForm
|
<PaymentForm
|
||||||
v-if="view === QuotationStatus.PaymentPending"
|
v-if="view === QuotationStatus.PaymentPending"
|
||||||
is-debit-note
|
is-debit-note
|
||||||
|
:readonly="isRoleInclude(['sale', 'head_of_sale'])"
|
||||||
:data="debitNoteData"
|
:data="debitNoteData"
|
||||||
@fetch-status="
|
@fetch-status="
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -1126,7 +1133,6 @@ async function submitAccepted() {
|
||||||
view === QuotationStatus.Issued ||
|
view === QuotationStatus.Issued ||
|
||||||
view === QuotationStatus.Accepted
|
view === QuotationStatus.Accepted
|
||||||
"
|
"
|
||||||
readonly
|
|
||||||
:total-price="summaryPrice.finalPrice"
|
:total-price="summaryPrice.finalPrice"
|
||||||
class="q-mb-md"
|
class="q-mb-md"
|
||||||
v-model:pay-type="currentFormData.payCondition"
|
v-model:pay-type="currentFormData.payCondition"
|
||||||
|
|
@ -1144,7 +1150,7 @@ async function submitAccepted() {
|
||||||
view === QuotationStatus.Accepted ||
|
view === QuotationStatus.Accepted ||
|
||||||
view === QuotationStatus.PaymentPending
|
view === QuotationStatus.PaymentPending
|
||||||
"
|
"
|
||||||
:readonly
|
:readonly="isRoleInclude(['sale', 'head_of_sale'])"
|
||||||
v-model:file-data="attachmentData"
|
v-model:file-data="attachmentData"
|
||||||
:transform-url="
|
:transform-url="
|
||||||
async (url: string) => {
|
async (url: string) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue