214 lines
6.5 KiB
Vue
214 lines
6.5 KiB
Vue
<script setup>
|
|
import { onMounted, ref } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useState } from 'src/composables/useState';
|
|
import { useQuasar } from 'quasar';
|
|
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
|
|
import CreateDepartmentChild from './CreateDepartmentChild.vue';
|
|
import axios from 'axios';
|
|
import { useRouter } from 'vue-router';
|
|
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
|
|
|
const quasar = useQuasar();
|
|
const { t } = useI18n();
|
|
const state = useState();
|
|
const router = useRouter();
|
|
|
|
const treeRef = ref();
|
|
const showCreateNodeFormVal = ref(false);
|
|
const creationNodeSelectedId = ref(null);
|
|
const expanded = ref([]);
|
|
|
|
const nodes = ref([{ id: null, name: t('Departments'), sons: true, children: [{}] }]);
|
|
|
|
const fetchedChildrensSet = ref(new Set());
|
|
|
|
const onNodeExpanded = (nodeKeysArray) => {
|
|
if (!fetchedChildrensSet.value.has(nodeKeysArray.at(-1))) {
|
|
fetchedChildrensSet.value.add(nodeKeysArray.at(-1));
|
|
fetchNodeLeaves(nodeKeysArray.at(-1));
|
|
}
|
|
|
|
state.set('Tree', nodeKeysArray);
|
|
};
|
|
|
|
const fetchNodeLeaves = async (nodeKey) => {
|
|
const node = treeRef.value?.getNodeByKey(nodeKey);
|
|
|
|
if (!node || node.sons === 0) return;
|
|
|
|
const params = { parentId: node.id };
|
|
const response = await axios.get('/departments/getLeaves', { params });
|
|
if (response.data) {
|
|
node.children = response.data.map((n) => {
|
|
const hasChildrens = n.sons > 0;
|
|
|
|
n.children = hasChildrens ? [{}] : null;
|
|
n.clickable = true;
|
|
return n;
|
|
});
|
|
}
|
|
|
|
state.set('Tree', node);
|
|
};
|
|
|
|
const removeNode = (node) => {
|
|
const { id, parentFk } = node;
|
|
quasar
|
|
.dialog({
|
|
component: VnConfirm,
|
|
componentProps: {
|
|
title: t('Are you sure you want to delete it?'),
|
|
message: t('Delete department'),
|
|
promise: () => remove(id),
|
|
},
|
|
})
|
|
.onOk(async () => await fetchNodeLeaves(parentFk));
|
|
};
|
|
|
|
async function remove(id) {
|
|
await axios.post(`/Departments/${id}/removeChild`, { id });
|
|
quasar.notify({
|
|
message: t('department.departmentRemoved'),
|
|
type: 'positive',
|
|
});
|
|
}
|
|
|
|
const showCreateNodeForm = (nodeId) => {
|
|
showCreateNodeFormVal.value = true;
|
|
creationNodeSelectedId.value = nodeId;
|
|
};
|
|
|
|
const onNodeCreated = async () => {
|
|
await fetchNodeLeaves(creationNodeSelectedId.value);
|
|
};
|
|
|
|
onMounted(async () => {
|
|
const tree = [...state.get('Tree'), 1];
|
|
const lastStateTree = state.get('TreeState');
|
|
if (tree) {
|
|
for (let n of tree) {
|
|
await fetchNodeLeaves(n);
|
|
}
|
|
expanded.value = tree;
|
|
|
|
if (lastStateTree) {
|
|
tree.push(lastStateTree);
|
|
await fetchNodeLeaves(lastStateTree);
|
|
}
|
|
}
|
|
setTimeout(() => {
|
|
if (lastStateTree) {
|
|
document.getElementById(lastStateTree).scrollIntoView();
|
|
}
|
|
}, 1000);
|
|
});
|
|
|
|
function handleEvent(type, event, node) {
|
|
const isParent = node.sons > 0;
|
|
const lastId = isParent ? node.id : node.parentFk;
|
|
|
|
switch (type) {
|
|
case 'path':
|
|
state.set('TreeState', lastId);
|
|
node.id && router.push({ path: `/worker/department/${node.id}/summary` });
|
|
break;
|
|
|
|
case 'tab':
|
|
state.set('TreeState', lastId);
|
|
node.id && window.open(`#/worker/department/${node.id}/summary`, '_blank');
|
|
break;
|
|
|
|
default:
|
|
node.id && router.push({ path: `#/worker/department/${node.id}/summary` });
|
|
break;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<QCard class="full-width" style="max-width: 800px">
|
|
<QTree
|
|
ref="treeRef"
|
|
:nodes="nodes"
|
|
node-key="id"
|
|
label-key="name"
|
|
v-model:expanded="expanded"
|
|
@update:expanded="onNodeExpanded($event)"
|
|
:default-expand-all="true"
|
|
>
|
|
<template #default-header="{ node }">
|
|
<div
|
|
:id="node.id"
|
|
class="qtr row justify-between full-width q-pr-md cursor-pointer"
|
|
>
|
|
<div>
|
|
<span
|
|
@click="handleEvent('row', $event, node)"
|
|
class="cursor-pointer"
|
|
>
|
|
{{ node.name }}
|
|
<DepartmentDescriptorProxy :id="node.id" />
|
|
</span>
|
|
</div>
|
|
<div
|
|
@click.stop.exact="handleEvent('path', $event, node)"
|
|
@click.ctrl.stop="handleEvent('tab', $event, node)"
|
|
style="flex-grow: 1; width: 10px"
|
|
></div>
|
|
<div class="row justify-between" style="max-width: max-content">
|
|
<QIcon
|
|
v-if="node.id"
|
|
name="delete"
|
|
color="primary"
|
|
size="sm"
|
|
class="q-pr-xs cursor-pointer"
|
|
@click.stop="removeNode(node)"
|
|
>
|
|
<QTooltip>
|
|
{{ t('Remove') }}
|
|
</QTooltip>
|
|
</QIcon>
|
|
<QBtn
|
|
color="primary"
|
|
flat
|
|
icon="add"
|
|
shortcut="+"
|
|
class="cursor-pointer"
|
|
@click.stop="showCreateNodeForm(node.id)"
|
|
>
|
|
<QTooltip>
|
|
{{ t('Create') }}
|
|
</QTooltip>
|
|
</QBtn>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</QTree>
|
|
<QDialog
|
|
v-model="showCreateNodeFormVal"
|
|
transition-show="scale"
|
|
transition-hide="scale"
|
|
>
|
|
<CreateDepartmentChild
|
|
:parent-id="creationNodeSelectedId"
|
|
@on-data-saved="onNodeCreated()"
|
|
/>
|
|
</QDialog>
|
|
</QCard>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
span {
|
|
color: $primary;
|
|
}
|
|
</style>
|
|
<i18n>
|
|
es:
|
|
Departments: Departamentos
|
|
Remove: Quitar
|
|
Create: Crear
|
|
Are you sure you want to delete it?: ¿Seguro que quieres eliminarlo?
|
|
Delete department: Eliminar departamento
|
|
</i18n>
|