jws-frontend/src/pages/04_flow-managment/FlowDialog.vue
puriphatt 42e2f2b21d
feat: workflow template properties (#70)
* feat: add i18n

* refactor/feat: workflow attributes type

* refactor: workflow => gray stat card

* refactor: select menu with search => separator

* feat: workflow => workflow step properties

* fix: workflow type

* fix: dialog properties component => model data

* fix: form flow => prevent toggle expansion with keyboard

* refactor: workflow step data & change status

* fix: form flow properties btn

* refactor: side menu => hide sub index

* feat: workflow => avatar & status on table

* refactor: workflow => drawer id and dialog id

* feat: workflow => card

* fix: agencies => format address
2024-11-12 15:33:15 +07:00

333 lines
9.6 KiB
Vue

<script lang="ts" setup>
import { nextTick, reactive, ref } from 'vue';
import {
WorkflowUserInTable,
WorkflowTemplatePayload,
WorkFlowPayloadStep,
} from 'src/stores/workflow-template/types';
import FormFlow from 'src/components/04_flow-management/FormFlow.vue';
import DialogProperties from 'src/components/dialog/DialogProperties.vue';
import DialogForm from 'src/components/DialogForm.vue';
import SideMenu from 'src/components/SideMenu.vue';
import DrawerInfo from 'src/components/DrawerInfo.vue';
import {
UndoButton,
SaveButton,
EditButton,
DeleteButton,
} from 'src/components/button';
const model = defineModel<boolean>({ required: true, default: false });
const drawerModel = defineModel<boolean>('drawerModel', {
required: true,
default: false,
});
const registerBranchId = defineModel('registerBranchId', { default: '' });
const flowData = defineModel<WorkflowTemplatePayload>('flowData', {
required: true,
default: {
name: '',
step: [],
},
});
const userInTable = defineModel<WorkflowUserInTable[]>('userInTable', {
default: [],
});
const pageState = reactive({ propertiesModal: false });
const currStep = ref<WorkFlowPayloadStep[]>([]);
withDefaults(
defineProps<{
readonly?: boolean;
isEdit?: boolean;
}>(),
{ readonly: false, isEdit: false },
);
defineEmits<{
(e: 'submit'): void;
(e: 'close'): void;
(e: 'changeStatus'): void;
(e: 'drawerUndo'): void;
(e: 'drawerEdit'): void;
(e: 'drawerDelete'): void;
}>();
async function addStep() {
flowData.value.step.push({
responsibleInstitution: [],
responsiblePersonId: [],
value: [],
detail: '',
name: '',
attributes: { properties: [] },
});
await nextTick();
const scrollTarget = document.getElementById(
`input-flow-step-name-${flowData.value.step.length - 1}-${model.value ? 'dialog' : 'drawer'}`,
);
if (scrollTarget) {
scrollTarget.scrollIntoView({ behavior: 'instant', inline: 'start' });
}
}
function triggerPropertiesDialog(step: WorkFlowPayloadStep) {
currStep.value = flowData.value.step.filter((s) => s === step);
pageState.propertiesModal = true;
}
</script>
<template>
<DialogForm
:title="$t('flow.title')"
v-model:modal="model"
:submit="() => $emit('submit')"
:close="() => $emit('close')"
hide-footer
>
<div
class="col surface-1 rounded bordered scroll row relative-position"
:class="{
'q-mx-lg q-my-md': $q.screen.gt.sm,
'q-mx-md q-my-sm': !$q.screen.gt.sm,
}"
>
<div
class="rounded row"
style="position: absolute; z-index: 999; right: 0; top: 0"
:class="{
'q-py-md q-px-lg': $q.screen.gt.sm,
'q-py-sm q-px-lg': !$q.screen.gt.sm,
}"
>
<div class="surface-1 row rounded">
<SaveButton id="btn-info-basic-save" icon-only type="submit" />
</div>
</div>
<section
class="col"
style="height: 100%; max-height: 100; overflow-y: auto"
v-if="$q.screen.gt.sm"
>
<div class="q-py-md q-pl-md q-pr-sm">
<SideMenu
:menu="[
{
name: $t('general.name', { msg: $t('flow.template') }),
anchor: 'form-flow-template-dialog',
},
{
name: $t('flow.processStep'),
anchor: 'form-flow-step-dialog',
useBtn: true,
},
...flowData.step.map((_s, i) => ({
name: $t('flow.stepNo', { msg: i + 1 }),
anchor: `input-flow-step-name-${i}-dialog`,
sub: true,
hideSubIndex: true,
})),
]"
background="transparent"
:active="{
background: 'hsla(var(--blue-6-hsl) / .2)',
foreground: 'var(--blue-6)',
}"
scroll-element="#flow-form-dialog"
>
<template v-slot:btn-form-flow-step-dialog>
<q-btn
dense
flat
icon="mdi-plus"
size="sm"
rounded
id="btn-add-step"
padding="0px 0px"
style="color: var(--stone-9)"
@click.stop="addStep"
:disabled="readonly"
/>
</template>
</SideMenu>
</div>
</section>
<section
class="col-12 col-md-10"
:class="{
'q-py-md q-pr-md ': $q.screen.gt.sm,
'q-py-md q-px-lg': !$q.screen.gt.sm,
}"
style="height: 100%; max-height: 100%; overflow-y: auto"
id="flow-form-dialog"
>
<FormFlow
v-model:flow-data="flowData"
v-model:register-branch-id="registerBranchId"
@trigger-properties="triggerPropertiesDialog"
/>
</section>
</div>
</DialogForm>
<DrawerInfo
bg-on
hide-action
:is-edit="isEdit"
:title="flowData.name"
v-model:drawerOpen="drawerModel"
:submit="() => $emit('submit')"
:close="() => $emit('close')"
>
<div class="col column full-height">
<div
style="flex: 1; width: 100%; overflow-y: auto"
id="drawer-user-form"
:class="{
'q-px-lg q-py-md': $q.screen.gt.sm,
'q-px-md q-py-sm': !$q.screen.gt.sm,
}"
>
<div
class="col surface-1 full-height rounded bordered scroll row relative-position"
>
<div
class="rounded row"
:class="{
'q-py-md q-px-lg': $q.screen.gt.sm,
'q-py-sm q-px-lg': !$q.screen.gt.sm,
}"
style="position: absolute; z-index: 999; top: 0; right: 0"
>
<div
v-if="flowData.status !== 'INACTIVE'"
class="surface-1 row rounded"
>
<UndoButton
v-if="isEdit"
id="btn-info-basic-undo"
icon-only
@click="
() => {
$emit('drawerUndo');
}
"
type="button"
/>
<SaveButton
v-if="isEdit"
id="btn-info-basic-save"
icon-only
type="submit"
/>
<EditButton
v-if="!isEdit"
id="btn-info-basic-edit"
icon-only
@click="
() => {
$emit('drawerEdit');
// infoDrawerEdit = true;
// isImageEdit = true;
}
"
type="button"
/>
<DeleteButton
v-if="!isEdit"
id="btn-info-basic-delete"
icon-only
@click="
() => {
$emit('drawerDelete');
// onDelete(currentUser.id);
}
"
type="button"
/>
</div>
</div>
<section
class="col"
style="height: 100%; max-height: 100; overflow-y: auto"
v-if="$q.screen.gt.sm"
>
<div class="q-py-md q-pl-md q-pr-sm">
<SideMenu
:menu="[
{
name: $t('general.name', { msg: $t('flow.template') }),
anchor: 'form-flow-template-drawer',
},
{
name: $t('flow.processStep'),
anchor: 'form-flow-step-drawer',
useBtn: true,
},
...flowData.step.map((_s, i) => ({
name: $t('flow.stepNo', { msg: i + 1 }),
anchor: `input-flow-step-name-${i}-drawer`,
sub: true,
hideSubIndex: true,
})),
]"
background="transparent"
:active="{
background: 'hsla(var(--blue-6-hsl) / .2)',
foreground: 'var(--blue-6)',
}"
scroll-element="#flow-form-drawer"
>
<template v-slot:btn-form-flow-step-drawer>
<q-btn
dense
flat
icon="mdi-plus"
size="sm"
rounded
id="btn-add-step"
padding="0px 0px"
style="color: var(--stone-9)"
@click.stop="addStep"
:disabled="readonly"
/>
</template>
</SideMenu>
</div>
</section>
<section
class="col-12 col-md-10"
:class="{
'q-py-md q-pr-md ': $q.screen.gt.sm,
'q-py-md q-px-lg': !$q.screen.gt.sm,
}"
style="height: 100%; max-height: 100%; overflow-y: auto"
id="flow-form-drawer"
>
<FormFlow
:readonly
onDrawer
v-model:user-in-table="userInTable"
v-model:flow-data="flowData"
v-model:register-branch-id="registerBranchId"
@change-status="$emit('changeStatus')"
@trigger-properties="triggerPropertiesDialog"
/>
</section>
</div>
</div>
</div>
</DrawerInfo>
<DialogProperties
v-model="pageState.propertiesModal"
v-model:data-step="flowData.step"
:step-index="flowData.step.indexOf(currStep[0])"
/>
</template>
<style scoped></style>