feat: refs #6919 add oneRecord option to data store and update related components
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
parent
43fc2e2312
commit
d573389871
|
@ -136,13 +136,7 @@ onMounted(async () => {
|
|||
|
||||
if (!$props.formInitialData) {
|
||||
if ($props.autoLoad && $props.url) await fetch();
|
||||
else if (arrayData.store.data)
|
||||
updateAndEmit(
|
||||
'onFetch',
|
||||
Array.isArray(arrayData.store.data)
|
||||
? arrayData.store.data[0]
|
||||
: arrayData.store.data
|
||||
);
|
||||
else if (arrayData.store.data) updateAndEmit('onFetch', arrayData.store.data);
|
||||
}
|
||||
if ($props.observeFormChanges) {
|
||||
watch(
|
||||
|
@ -163,7 +157,6 @@ if (!$props.url)
|
|||
watch(
|
||||
() => arrayData.store.data,
|
||||
(val) => {
|
||||
if (Array.isArray(val)) val = val[0] ?? {};
|
||||
updateAndEmit('onFetch', val);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { onBeforeMount, computed } from 'vue';
|
||||
import { onBeforeMount } from 'vue';
|
||||
import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
|
@ -9,8 +9,8 @@ import VnSubToolbar from '../ui/VnSubToolbar.vue';
|
|||
|
||||
const props = defineProps({
|
||||
dataKey: { type: String, required: true },
|
||||
baseUrl: { type: String, default: undefined },
|
||||
customUrl: { type: String, default: undefined },
|
||||
url: { type: String, default: undefined },
|
||||
idInWhere: { type: Boolean, default: false },
|
||||
filter: { type: Object, default: () => {} },
|
||||
descriptor: { type: Object, required: true },
|
||||
filterPanel: { type: Object, default: undefined },
|
||||
|
@ -22,21 +22,20 @@ const props = defineProps({
|
|||
const stateStore = useStateStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const url = computed(() => {
|
||||
if (props.baseUrl) {
|
||||
return `${props.baseUrl}/${route.params.id}`;
|
||||
}
|
||||
return props.customUrl;
|
||||
});
|
||||
const regex = /(\/\d+)/;
|
||||
|
||||
const arrayData = useArrayData(props.dataKey, {
|
||||
url: url.value,
|
||||
url: props.url,
|
||||
filter: props.filter,
|
||||
oneRecord: true,
|
||||
});
|
||||
|
||||
onBeforeMount(async () => {
|
||||
try {
|
||||
if (!props.baseUrl) arrayData.store.filter.where = { id: route.params.id };
|
||||
if (props.idInWhere) arrayData.store.filter.where = { id: route.params.id };
|
||||
else if (!regex.test(props.url))
|
||||
arrayData.store.url = `${props.url}/${route.params.id}`;
|
||||
console.log('fetching data', arrayData.store.url, route.params.id);
|
||||
await arrayData.fetch({ append: false, updateRouter: false });
|
||||
} catch {
|
||||
const { matched: matches } = router.currentRoute.value;
|
||||
|
@ -45,14 +44,14 @@ onBeforeMount(async () => {
|
|||
}
|
||||
});
|
||||
|
||||
if (props.baseUrl) {
|
||||
onBeforeRouteUpdate(async (to, from) => {
|
||||
onBeforeRouteUpdate(async (to, from) => {
|
||||
if (to.params.id !== from.params.id) {
|
||||
arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
|
||||
await arrayData.fetch({ append: false, updateRouter: false });
|
||||
if (props.idInWhere) arrayData.store.filter.where = { id: to.params.id };
|
||||
else arrayData.store.url = `${props.url}/${to.params.id}`;
|
||||
console.log('fetching data', arrayData.store.url, to.params.id);
|
||||
await arrayData.fetch({ updateRouter: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<Teleport to="#left-panel" v-if="stateStore.isHeaderMounted()">
|
||||
|
|
|
@ -55,10 +55,11 @@ onBeforeMount(async () => {
|
|||
url: $props.url,
|
||||
filter: $props.filter,
|
||||
skip: 0,
|
||||
oneRecord: true,
|
||||
});
|
||||
store = arrayData.store;
|
||||
entity = computed(() => {
|
||||
const data = (Array.isArray(store.data) ? store.data[0] : store.data) ?? {};
|
||||
const data = store.data ?? {};
|
||||
if (data) emit('onFetch', data);
|
||||
return data;
|
||||
});
|
||||
|
@ -80,7 +81,7 @@ async function getData() {
|
|||
try {
|
||||
const { data } = await arrayData.fetch({ append: false, updateRouter: false });
|
||||
state.set($props.dataKey, data);
|
||||
emit('onFetch', Array.isArray(data) ? data[0] : data);
|
||||
emit('onFetch', data);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
|
|
@ -35,9 +35,10 @@ const arrayData = useArrayData(props.dataKey, {
|
|||
url: props.url,
|
||||
filter: props.filter,
|
||||
skip: 0,
|
||||
oneRecord: true,
|
||||
});
|
||||
const { store } = arrayData;
|
||||
const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
|
||||
const entity = computed(() => store.data);
|
||||
const isLoading = ref(false);
|
||||
|
||||
const stateStore = useStateStore();
|
||||
|
@ -60,7 +61,7 @@ async function fetch() {
|
|||
store.filter = props.filter ?? {};
|
||||
isLoading.value = true;
|
||||
const { data } = await arrayData.fetch({ append: false, updateRouter: false });
|
||||
emit('onFetch', Array.isArray(data) ? data[0] : data);
|
||||
emit('onFetch', data);
|
||||
isLoading.value = false;
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -54,6 +54,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
'navigate',
|
||||
'mapKey',
|
||||
'keepData',
|
||||
'oneRecord',
|
||||
];
|
||||
if (typeof userOptions === 'object') {
|
||||
for (const option in userOptions) {
|
||||
|
@ -104,13 +105,17 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
|
||||
store.hasMoreData = limit && response.data.length >= limit;
|
||||
|
||||
processData(response.data, { map: !!store.mapKey, append });
|
||||
processData(response.data, {
|
||||
map: !!store.mapKey,
|
||||
append,
|
||||
oneRecord: store.oneRecord,
|
||||
});
|
||||
if (!append && !isDialogOpened()) updateRouter && updateStateParams();
|
||||
|
||||
store.isLoading = false;
|
||||
canceller = null;
|
||||
|
||||
return response;
|
||||
return store.data;
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
|
@ -296,7 +301,11 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
return { filter, params, limit: filter.limit };
|
||||
}
|
||||
|
||||
function processData(data, { map = true, append = true }) {
|
||||
function processData(data, { map = true, append = true, oneRecord = false }) {
|
||||
if (oneRecord) {
|
||||
store.data = Array.isArray(data) ? data[0] : data;
|
||||
return;
|
||||
}
|
||||
if (!append) {
|
||||
store.data = [];
|
||||
store.map = new Map();
|
||||
|
|
|
@ -5,13 +5,7 @@ import FormModel from 'components/FormModel.vue';
|
|||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
</script>
|
||||
<template>
|
||||
<FormModel
|
||||
ref="formModelRef"
|
||||
:url-update="`VnUsers/${$route.params.id}/update-user`"
|
||||
model="Account"
|
||||
auto-load
|
||||
@on-data-saved="$refs.formModelRef.fetch()"
|
||||
>
|
||||
<FormModel :url-update="`VnUsers/${$route.params.id}/update-user`" model="Account">
|
||||
<template #form="{ data }">
|
||||
<div class="q-gutter-y-sm">
|
||||
<VnInput v-model="data.name" :label="$t('account.card.nickname')" />
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
<script setup>
|
||||
import VnCardBeta from 'components/common/VnCardBeta.vue';
|
||||
import AccountDescriptor from './AccountDescriptor.vue';
|
||||
import exprBuilder from '../AccountExprBuilder.js';
|
||||
import filter from './AccountFilter.js';
|
||||
</script>
|
||||
<template>
|
||||
<VnCardBeta data-key="AccountId" :descriptor="AccountDescriptor" />
|
||||
<VnCardBeta
|
||||
url="VnUsers/preview"
|
||||
:id-in-where="true"
|
||||
data-key="Account"
|
||||
:descriptor="AccountDescriptor"
|
||||
:filter="filter"
|
||||
:searchbar-props="{
|
||||
url: 'VnUsers/preview',
|
||||
label: $t('account.search'),
|
||||
info: $t('account.searchInfo'),
|
||||
exprBuilder,
|
||||
filter: {
|
||||
include: { relation: 'role', scope: { fields: ['id', 'name'] } },
|
||||
},
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -8,19 +8,12 @@ import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
|
|||
import FetchData from 'src/components/FetchData.vue';
|
||||
import VnImg from 'src/components/ui/VnImg.vue';
|
||||
import filter from './AccountFilter.js';
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const $props = defineProps({ id: { type: Number, default: null } });
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const entityId = computed(() => {
|
||||
return $props.id || route.params.id;
|
||||
});
|
||||
const entityId = computed(() => $props.id || route.params.id);
|
||||
const hasAccount = ref(false);
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,13 +1,3 @@
|
|||
export default {
|
||||
fields: [
|
||||
'id',
|
||||
'email',
|
||||
'nickname',
|
||||
'name',
|
||||
'accountStateFk',
|
||||
'packages',
|
||||
'pickup',
|
||||
'role',
|
||||
],
|
||||
include: { relation: 'role', scope: { fields: ['id', 'name'] } },
|
||||
};
|
||||
|
|
|
@ -1,33 +1,25 @@
|
|||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import CardSummary from 'components/ui/CardSummary.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import filter from './AccountFilter.js';
|
||||
|
||||
const $props = defineProps({ id: { type: Number, default: 0 } });
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const entityId = computed(() => $props.id || route.params.id);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CardSummary
|
||||
data-key="AccountId"
|
||||
data-key="Account"
|
||||
ref="AccountSummary"
|
||||
url="VnUsers/preview"
|
||||
:filter="filter"
|
||||
@on-fetch="(data) => (account = data)"
|
||||
>
|
||||
<template #header>{{ account.id }} - {{ account.nickname }}</template>
|
||||
<template #body>
|
||||
<template #header="{ entity }">{{ entity.id }} - {{ entity.nickname }}</template>
|
||||
<template #body="{ entity }">
|
||||
<QCard class="vn-one">
|
||||
<QCardSection class="q-pa-none">
|
||||
<router-link
|
||||
|
|
|
@ -5,7 +5,7 @@ import VnTable from 'components/VnTable/VnTable.vue';
|
|||
import { useRoute } from 'vue-router';
|
||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||
import RoleSummary from './Card/RoleSummary.vue';
|
||||
import exprBuilder from './AccountExprBuilder.js';
|
||||
import exprBuilder from './RoleExprBuilder.js';
|
||||
import VnSection from 'src/components/common/VnSection.vue';
|
||||
|
||||
const route = useRoute();
|
||||
|
|
|
@ -3,5 +3,5 @@ import VnCardBeta from 'components/common/VnCardBeta.vue';
|
|||
import RoleDescriptor from './RoleDescriptor.vue';
|
||||
</script>
|
||||
<template>
|
||||
<VnCardBeta data-key="Role" :descriptor="RoleDescriptor" />
|
||||
<VnCardBeta data-key="Role" :id-in-where="true" :descriptor="RoleDescriptor" />
|
||||
</template>
|
||||
|
|
|
@ -5,7 +5,8 @@ import VnCardBeta from 'src/components/common/VnCardBeta.vue';
|
|||
<template>
|
||||
<VnCardBeta
|
||||
data-key="Worker"
|
||||
custom-url="Workers/summary"
|
||||
url="Workers/summary"
|
||||
:id-in-where="true"
|
||||
:descriptor="WorkerDescriptor"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -19,6 +19,7 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
|
|||
page: 1,
|
||||
mapKey: 'id',
|
||||
keepData: false,
|
||||
oneRecord: false,
|
||||
};
|
||||
|
||||
function get(key) {
|
||||
|
@ -62,5 +63,6 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
|
|||
clear,
|
||||
reset,
|
||||
resetPagination,
|
||||
state,
|
||||
};
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue