refs #5673 fix: VnSelect update model, feat(claimDevelopment) add reload function
gitea/salix-front/pipeline/head This commit looks good Details

This commit is contained in:
Alex Moreno 2023-09-25 12:06:49 +02:00
parent 685c835d13
commit 1637921fab
8 changed files with 150 additions and 171 deletions

View File

@ -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: {

View File

@ -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();

View File

@ -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"

View File

@ -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 = {};

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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,
},
],