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