forked from verdnatura/salix-front
refs #5673 fix: VnSelect update model, feat(claimDevelopment) add reload function
This commit is contained in:
parent
685c835d13
commit
1637921fab
|
@ -7,7 +7,7 @@ module.exports = defineConfig({
|
|||
screenshotsFolder: 'test/cypress/screenshots',
|
||||
supportFile: 'test/cypress/support/index.js',
|
||||
videosFolder: 'test/cypress/videos',
|
||||
video: true,
|
||||
video: false,
|
||||
specPattern: 'test/cypress/integration/*.spec.js',
|
||||
experimentalRunAllSpecs: true,
|
||||
component: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import axios from 'axios';
|
||||
import { onMounted, onUnmounted, computed, ref, watch } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { useValidator } from 'src/composables/useValidator';
|
||||
|
@ -33,7 +33,7 @@ const $props = defineProps({
|
|||
},
|
||||
dataRequired: {
|
||||
type: Object,
|
||||
default: null,
|
||||
default: () => {},
|
||||
},
|
||||
defaultSave: {
|
||||
type: Boolean,
|
||||
|
@ -67,6 +67,7 @@ const formUrl = computed(() => $props.url);
|
|||
const emit = defineEmits(['onFetch', 'update:selected']);
|
||||
|
||||
defineExpose({
|
||||
reload,
|
||||
insert,
|
||||
remove,
|
||||
onSubmit,
|
||||
|
@ -91,8 +92,8 @@ async function fetch(data) {
|
|||
emit('onFetch', data);
|
||||
}
|
||||
|
||||
function reset() {
|
||||
fetch(originalData.value);
|
||||
async function reset() {
|
||||
await fetch(originalData.value);
|
||||
hasChanges.value = false;
|
||||
}
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
|
@ -215,6 +216,9 @@ function getChanges() {
|
|||
|
||||
function getDifferences(obj1, obj2) {
|
||||
let diff = {};
|
||||
delete obj1.$index;
|
||||
delete obj2.$index;
|
||||
|
||||
for (let key in obj1) {
|
||||
if (obj2[key] && obj1[key] !== obj2[key]) {
|
||||
diff[key] = obj2[key];
|
||||
|
@ -236,6 +240,10 @@ function isEmpty(obj) {
|
|||
if (obj.length > 0) return false;
|
||||
}
|
||||
|
||||
async function reload() {
|
||||
vnPaginateRef.value.fetch();
|
||||
}
|
||||
|
||||
watch(formUrl, async () => {
|
||||
originalData.value = null;
|
||||
reset();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { ref, toRefs, watch } from 'vue';
|
||||
import { ref, toRefs, watch, computed } from 'vue';
|
||||
const emit = defineEmits(['update:modelValue', 'update:options']);
|
||||
|
||||
const $props = defineProps({
|
||||
|
@ -16,8 +16,7 @@ const $props = defineProps({
|
|||
default: '',
|
||||
},
|
||||
});
|
||||
const updateValue = (newValue) => emit('update:modelValue', newValue);
|
||||
const { modelValue, optionLabel, options } = toRefs($props);
|
||||
const { optionLabel, options } = toRefs($props);
|
||||
const myOptions = ref([]);
|
||||
const myOptionsOriginal = ref([]);
|
||||
function setOptions(data) {
|
||||
|
@ -50,12 +49,20 @@ const filterHandler = (val, update) => {
|
|||
watch(options, (newValue) => {
|
||||
setOptions(newValue);
|
||||
});
|
||||
|
||||
const value = computed({
|
||||
get() {
|
||||
return $props.modelValue;
|
||||
},
|
||||
set(value) {
|
||||
emit('update:modelValue', value);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QSelect
|
||||
v-model="modelValue"
|
||||
@update:model-value="updateValue"
|
||||
v-model="value"
|
||||
:options="myOptions"
|
||||
:option-label="optionLabel"
|
||||
v-bind="$attrs"
|
||||
|
|
|
@ -29,12 +29,14 @@ const $props = defineProps({
|
|||
|
||||
const slots = useSlots();
|
||||
const { t } = useI18n();
|
||||
const entity = ref();
|
||||
|
||||
onMounted(() => fetch());
|
||||
onMounted(async () => {
|
||||
await fetch();
|
||||
});
|
||||
|
||||
const emit = defineEmits(['onFetch']);
|
||||
|
||||
const entity = ref();
|
||||
async function fetch() {
|
||||
const params = {};
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ import { ref, computed } from 'vue';
|
|||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { toDate } from 'src/filters';
|
||||
import { useState } from 'src/composables/useState';
|
||||
|
||||
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||
import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
|
||||
|
@ -19,6 +21,7 @@ const $props = defineProps({
|
|||
});
|
||||
|
||||
const route = useRoute();
|
||||
const state = useState();
|
||||
const { t } = useI18n();
|
||||
|
||||
const entityId = computed(() => {
|
||||
|
@ -67,6 +70,7 @@ function stateColor(code) {
|
|||
const data = ref(useCardDescription());
|
||||
const setData = (entity) => {
|
||||
data.value = useCardDescription(entity.client.name, entity.id);
|
||||
state.set('ClaimDescriptor', entity);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -120,67 +120,65 @@ const columns = computed(() => [
|
|||
@on-fetch="(data) => (workers = data)"
|
||||
auto-load
|
||||
/>
|
||||
<div class="column items-center">
|
||||
<CrudModel
|
||||
data-key="ClaimDevelopments"
|
||||
url="ClaimDevelopments"
|
||||
model="claimDevelopment"
|
||||
:filter="developmentsFilter"
|
||||
ref="claimDevelopmentForm"
|
||||
:data-required="{ claimFk: route.params.id }"
|
||||
v-model:selected="selected"
|
||||
auto-load
|
||||
>
|
||||
<template #body="{ rows }">
|
||||
<QTable
|
||||
:columns="columns"
|
||||
:rows="rows"
|
||||
:pagination="{ rowsPerPage: 0 }"
|
||||
row-key="$index"
|
||||
selection="multiple"
|
||||
hide-pagination
|
||||
v-model:selected="selected"
|
||||
:grid="$q.screen.lt.md"
|
||||
>
|
||||
<template #body-cell="{ row, col }">
|
||||
<QTd auto-width>
|
||||
<VnSelectFilter
|
||||
:label="col.label"
|
||||
v-model="row[col.model]"
|
||||
:options="col.options"
|
||||
:option-value="col.optionValue"
|
||||
:option-label="col.optionLabel"
|
||||
/>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #item="props">
|
||||
<div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
|
||||
<QCard bordered flat>
|
||||
<QCardSection>
|
||||
<QCheckbox v-model="props.selected" dense />
|
||||
</QCardSection>
|
||||
<QSeparator />
|
||||
<QList dense>
|
||||
<QItem v-for="col in props.cols" :key="col.name">
|
||||
<QItemSection>
|
||||
<VnSelectFilter
|
||||
:label="col.label"
|
||||
v-model="props.row[col.model]"
|
||||
:options="col.options"
|
||||
:option-value="col.optionValue"
|
||||
:option-label="col.optionLabel"
|
||||
dense
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QCard>
|
||||
</div>
|
||||
</template>
|
||||
</QTable>
|
||||
</template>
|
||||
</CrudModel>
|
||||
</div>
|
||||
<CrudModel
|
||||
data-key="ClaimDevelopments"
|
||||
url="ClaimDevelopments"
|
||||
model="claimDevelopment"
|
||||
:filter="developmentsFilter"
|
||||
ref="claimDevelopmentForm"
|
||||
:data-required="{ claimFk: route.params.id }"
|
||||
v-model:selected="selected"
|
||||
auto-load
|
||||
>
|
||||
<template #body="{ rows }">
|
||||
<QTable
|
||||
:columns="columns"
|
||||
:rows="rows"
|
||||
:pagination="{ rowsPerPage: 0 }"
|
||||
row-key="$index"
|
||||
selection="multiple"
|
||||
hide-pagination
|
||||
v-model:selected="selected"
|
||||
:grid="$q.screen.lt.md"
|
||||
>
|
||||
<template #body-cell="{ row, col }">
|
||||
<QTd auto-width>
|
||||
<VnSelectFilter
|
||||
:label="col.label"
|
||||
v-model="row[col.model]"
|
||||
:options="col.options"
|
||||
:option-value="col.optionValue"
|
||||
:option-label="col.optionLabel"
|
||||
/>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #item="props">
|
||||
<div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
|
||||
<QCard bordered flat>
|
||||
<QCardSection>
|
||||
<QCheckbox v-model="props.selected" dense />
|
||||
</QCardSection>
|
||||
<QSeparator />
|
||||
<QList dense>
|
||||
<QItem v-for="col in props.cols" :key="col.name">
|
||||
<QItemSection>
|
||||
<VnSelectFilter
|
||||
:label="col.label"
|
||||
v-model="props.row[col.model]"
|
||||
:options="col.options"
|
||||
:option-value="col.optionValue"
|
||||
:option-label="col.optionLabel"
|
||||
dense
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QCard>
|
||||
</div>
|
||||
</template>
|
||||
</QTable>
|
||||
</template>
|
||||
</CrudModel>
|
||||
<QPageSticky position="bottom-right" :offset="[25, 25]">
|
||||
<QBtn fab color="primary" icon="add" @click="claimDevelopmentForm.insert()" />
|
||||
</QPageSticky>
|
||||
|
|
|
@ -1,46 +1,34 @@
|
|||
<script setup>
|
||||
import axios from 'axios';
|
||||
import { ref } from 'vue';
|
||||
import { watch, ref, computed, onUnmounted, onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||
import CrudModel from 'components/CrudModel.vue';
|
||||
import { useState } from 'src/composables/useState';
|
||||
|
||||
import { toDate } from 'src/filters';
|
||||
|
||||
const quasar = useQuasar();
|
||||
const route = useRoute();
|
||||
const state = useState();
|
||||
const { t } = useI18n();
|
||||
const arrayData = useArrayData('ClaimRma');
|
||||
const selected = ref([]);
|
||||
const claimRmaRef = ref();
|
||||
const claim = computed(() => state.get('ClaimDescriptor'));
|
||||
|
||||
const claim = ref();
|
||||
const claimFilter = {
|
||||
fields: ['rma'],
|
||||
};
|
||||
|
||||
async function onFetch(data) {
|
||||
claim.value = data;
|
||||
|
||||
const filter = {
|
||||
include: {
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'user',
|
||||
},
|
||||
const claimRmaFilter = {
|
||||
include: {
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'user',
|
||||
},
|
||||
},
|
||||
order: 'created DESC',
|
||||
where: {
|
||||
code: claim.value.rma,
|
||||
},
|
||||
};
|
||||
|
||||
arrayData.applyFilter({ filter });
|
||||
}
|
||||
},
|
||||
order: 'created DESC',
|
||||
where: {
|
||||
code: claim.value?.rma,
|
||||
},
|
||||
};
|
||||
|
||||
async function addRow() {
|
||||
if (!claim.value.rma) {
|
||||
|
@ -54,7 +42,7 @@ async function addRow() {
|
|||
};
|
||||
|
||||
await axios.post(`ClaimRmas`, formData);
|
||||
await arrayData.refresh();
|
||||
await claimRmaRef.value.reload();
|
||||
|
||||
quasar.notify({
|
||||
type: 'positive',
|
||||
|
@ -63,38 +51,33 @@ async function addRow() {
|
|||
});
|
||||
}
|
||||
|
||||
function confirmRemove(id) {
|
||||
quasar
|
||||
.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
data: { id },
|
||||
promise: remove,
|
||||
},
|
||||
})
|
||||
.onOk(async () => await arrayData.refresh());
|
||||
}
|
||||
|
||||
async function remove({ id }) {
|
||||
await axios.delete(`ClaimRmas/${id}`);
|
||||
quasar.notify({
|
||||
type: 'positive',
|
||||
message: t('globals.rowRemoved'),
|
||||
});
|
||||
}
|
||||
onMounted(() => {
|
||||
if (claim.value) claimRmaRef.value.reload();
|
||||
});
|
||||
watch(
|
||||
claim,
|
||||
() => {
|
||||
claimRmaRef.value.reload();
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
:url="`Claims/${route.params.id}`"
|
||||
:filter="claimFilter"
|
||||
@on-fetch="onFetch"
|
||||
auto-load
|
||||
/>
|
||||
<div class="column items-center">
|
||||
<div class="list">
|
||||
<VnPaginate data-key="ClaimRma" url="ClaimRmas">
|
||||
<CrudModel
|
||||
data-key="ClaimRma"
|
||||
url="ClaimRmas"
|
||||
model="ClaimRma"
|
||||
:filter="claimRmaFilter"
|
||||
v-model:selected="selected"
|
||||
ref="claimRmaRef"
|
||||
:default-save="false"
|
||||
:default-reset="false"
|
||||
:default-remove="false"
|
||||
>
|
||||
<template #body="{ rows }">
|
||||
<QCard class="card">
|
||||
<QCard>
|
||||
<template v-for="(row, index) of rows" :key="row.id">
|
||||
<QItem class="q-pa-none items-start">
|
||||
<QItemSection class="q-pa-md">
|
||||
|
@ -105,7 +88,7 @@ async function remove({ id }) {
|
|||
{{ t('claim.rma.user') }}
|
||||
</QItemLabel>
|
||||
<QItemLabel>
|
||||
{{ row.worker.user.name }}
|
||||
{{ row?.worker?.user?.name }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
|
@ -131,7 +114,7 @@ async function remove({ id }) {
|
|||
round
|
||||
color="orange"
|
||||
icon="vn:bin"
|
||||
@click="confirmRemove(row.id)"
|
||||
@click="claimRmaRef.remove([row])"
|
||||
>
|
||||
<QTooltip>{{ t('globals.remove') }}</QTooltip>
|
||||
</QBtn>
|
||||
|
@ -141,24 +124,11 @@ async function remove({ id }) {
|
|||
</template>
|
||||
</QCard>
|
||||
</template>
|
||||
</VnPaginate>
|
||||
</CrudModel>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<QPageSticky position="bottom-right" :offset="[25, 25]">
|
||||
<label for="fileInput">
|
||||
<QBtn fab @click="inputFile.nativeEl.click()" icon="add" color="primary">
|
||||
<QInput
|
||||
ref="inputFile"
|
||||
type="file"
|
||||
style="display: none"
|
||||
multiple
|
||||
v-model="files"
|
||||
@update:model-value="create()"
|
||||
/>
|
||||
<QTooltip bottom> {{ t('globals.add') }} </QTooltip>
|
||||
</QBtn>
|
||||
</label>
|
||||
<QBtn fab color="primary" icon="add" @click="addRow()" />
|
||||
</QPageSticky>
|
||||
</template>
|
||||
|
||||
|
@ -167,16 +137,6 @@ async function remove({ id }) {
|
|||
width: 100%;
|
||||
max-width: 60em;
|
||||
}
|
||||
.q-toolbar {
|
||||
background-color: $grey-9;
|
||||
}
|
||||
.sticky-page {
|
||||
padding-top: 66px;
|
||||
}
|
||||
|
||||
.q-page-sticky {
|
||||
z-index: 2998;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
|
|
|
@ -15,7 +15,6 @@ describe('CrudModel', () => {
|
|||
'vue-i18n',
|
||||
],
|
||||
mocks: {
|
||||
fetch: vi.fn(),
|
||||
validate: vi.fn(),
|
||||
},
|
||||
},
|
||||
|
@ -31,7 +30,7 @@ describe('CrudModel', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vm.state.set('crudModel', []);
|
||||
vm.fetch([]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -50,24 +49,25 @@ describe('CrudModel', () => {
|
|||
|
||||
describe('getChanges()', () => {
|
||||
it('should return correct updates and creates', async () => {
|
||||
vm.originalData = [
|
||||
{ id: 1, name: 'Tony Starks', $index: 1 },
|
||||
{ id: 2, name: 'Jessica Jones', $index: 2 },
|
||||
{ id: 3, name: 'Bruce Wayne', $index: 3 },
|
||||
];
|
||||
vm.state.set('crudModel', [
|
||||
{ id: 1, name: 'New name one', $index: 1 },
|
||||
{ id: 2, name: 'New name two', $index: 2 },
|
||||
{ id: 3, name: 'Bruce Wayne', $index: 3 },
|
||||
vm.fetch([
|
||||
{ id: 1, name: 'New name one' },
|
||||
{ id: 2, name: 'New name two' },
|
||||
{ id: 3, name: 'Bruce Wayne' },
|
||||
]);
|
||||
|
||||
vm.originalData = [
|
||||
{ id: 1, name: 'Tony Starks' },
|
||||
{ id: 2, name: 'Jessica Jones' },
|
||||
{ id: 3, name: 'Bruce Wayne' },
|
||||
];
|
||||
|
||||
vm.insert();
|
||||
const result = vm.getChanges();
|
||||
|
||||
const expected = {
|
||||
creates: [
|
||||
{
|
||||
$index: 4,
|
||||
$index: 3,
|
||||
fk: 1,
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue