Merge branch 'dev' into improve_shortcut_directive
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:
commit
841195eca0
|
@ -17,7 +17,7 @@ import { useSession } from 'src/composables/useSession';
|
|||
const route = useRoute();
|
||||
const quasar = useQuasar();
|
||||
const { t } = useI18n();
|
||||
const rows = ref();
|
||||
const rows = ref([]);
|
||||
const dmsRef = ref();
|
||||
const formDialog = ref({});
|
||||
const token = useSession().getTokenMultimedia();
|
||||
|
@ -389,6 +389,14 @@ defineExpose({
|
|||
</div>
|
||||
</template>
|
||||
</QTable>
|
||||
<div
|
||||
v-else
|
||||
class="info-row q-pa-md text-center"
|
||||
>
|
||||
<h5>
|
||||
{{ t('No data to display') }}
|
||||
</h5>
|
||||
</div>
|
||||
</template>
|
||||
</VnPaginate>
|
||||
<QDialog v-model="formDialog.show">
|
||||
|
|
|
@ -1,51 +1,78 @@
|
|||
import { describe, it, expect, vi, beforeAll, afterEach, beforeEach } from 'vitest';
|
||||
import {
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
vi,
|
||||
beforeAll,
|
||||
afterEach,
|
||||
beforeEach,
|
||||
afterAll,
|
||||
} from 'vitest';
|
||||
import { createWrapper, axios } from 'app/test/vitest/helper';
|
||||
import VnNotes from 'src/components/ui/VnNotes.vue';
|
||||
import vnDate from 'src/boot/vnDate';
|
||||
|
||||
describe('VnNotes', () => {
|
||||
let vm;
|
||||
let wrapper;
|
||||
let spyFetch;
|
||||
let postMock;
|
||||
let expectedBody;
|
||||
const mockData= {name: 'Tony', lastName: 'Stark', text: 'Test Note', observationTypeFk: 1};
|
||||
|
||||
function generateExpectedBody() {
|
||||
expectedBody = {...vm.$props.body, ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk }};
|
||||
}
|
||||
|
||||
async function setTestParams(text, observationType, type){
|
||||
vm.newNote.text = text;
|
||||
vm.newNote.observationTypeFk = observationType;
|
||||
wrapper.setProps({ selectType: type });
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.spyOn(axios, 'get').mockReturnValue({ data: [] });
|
||||
|
||||
let patchMock;
|
||||
let expectedInsertBody;
|
||||
let expectedUpdateBody;
|
||||
const defaultOptions = {
|
||||
url: '/test',
|
||||
body: { name: 'Tony', lastName: 'Stark' },
|
||||
selectType: false,
|
||||
saveUrl: null,
|
||||
justInput: false,
|
||||
};
|
||||
function generateWrapper(
|
||||
options = defaultOptions,
|
||||
text = null,
|
||||
observationType = null,
|
||||
) {
|
||||
vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
|
||||
wrapper = createWrapper(VnNotes, {
|
||||
propsData: {
|
||||
url: '/test',
|
||||
body: { name: 'Tony', lastName: 'Stark' },
|
||||
}
|
||||
propsData: options,
|
||||
});
|
||||
wrapper = wrapper.wrapper;
|
||||
vm = wrapper.vm;
|
||||
});
|
||||
vm.newNote.text = text;
|
||||
vm.newNote.observationTypeFk = observationType;
|
||||
}
|
||||
|
||||
function createSpyFetch() {
|
||||
spyFetch = vi.spyOn(vm.$refs.vnPaginateRef, 'fetch');
|
||||
}
|
||||
|
||||
function generateExpectedBody() {
|
||||
expectedInsertBody = {
|
||||
...vm.$props.body,
|
||||
...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk },
|
||||
};
|
||||
expectedUpdateBody = { ...vm.$props.body, ...{ notes: vm.newNote.text } };
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
postMock = vi.spyOn(axios, 'post').mockResolvedValue(mockData);
|
||||
spyFetch = vi.spyOn(vm.vnPaginateRef, 'fetch').mockImplementation(() => vi.fn());
|
||||
postMock = vi.spyOn(axios, 'post');
|
||||
patchMock = vi.spyOn(axios, 'patch');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
expectedBody = {};
|
||||
expectedInsertBody = {};
|
||||
expectedUpdateBody = {};
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('insert', () => {
|
||||
it('should not call axios.post and vnPaginateRef.fetch if newNote.text is null', async () => {
|
||||
await setTestParams( null, null, true );
|
||||
it('should not call axios.post and vnPaginateRef.fetch when newNote.text is null', async () => {
|
||||
generateWrapper({ selectType: true });
|
||||
createSpyFetch();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
|
@ -53,8 +80,9 @@ describe('VnNotes', () => {
|
|||
expect(spyFetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call axios.post and vnPaginateRef.fetch if newNote.text is empty', async () => {
|
||||
await setTestParams( "", null, false );
|
||||
it('should not call axios.post and vnPaginateRef.fetch when newNote.text is empty', async () => {
|
||||
generateWrapper(null, '');
|
||||
createSpyFetch();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
|
@ -62,8 +90,9 @@ describe('VnNotes', () => {
|
|||
expect(spyFetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is true', async () => {
|
||||
await setTestParams( "Test Note", null, true );
|
||||
it('should not call axios.post and vnPaginateRef.fetch when observationTypeFk is null and selectType is true', async () => {
|
||||
generateWrapper({ selectType: true }, 'Test Note');
|
||||
createSpyFetch();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
|
@ -71,37 +100,57 @@ describe('VnNotes', () => {
|
|||
expect(spyFetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is false', async () => {
|
||||
await setTestParams( "Test Note", null, false );
|
||||
|
||||
it('should call axios.post and vnPaginateRef.fetch when observationTypeFk is missing and selectType is false', async () => {
|
||||
generateWrapper(null, 'Test Note');
|
||||
createSpyFetch();
|
||||
generateExpectedBody();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
|
||||
expect(spyFetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is setted and selectType is false', async () => {
|
||||
await setTestParams( "Test Note", 1, false );
|
||||
|
||||
generateExpectedBody();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
|
||||
expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
|
||||
expect(spyFetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call axios.post and vnPaginateRef.fetch when newNote is valid', async () => {
|
||||
await setTestParams( "Test Note", 1, true );
|
||||
|
||||
generateWrapper({ selectType: true }, 'Test Note', 1);
|
||||
createSpyFetch();
|
||||
generateExpectedBody();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
|
||||
expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
|
||||
expect(spyFetch).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('should call axios.patch with saveUrl when saveUrl is set and justInput is true', async () => {
|
||||
generateWrapper({
|
||||
url: '/business',
|
||||
justInput: true,
|
||||
saveUrl: '/saveUrlTest',
|
||||
});
|
||||
generateExpectedBody();
|
||||
|
||||
await vm.update();
|
||||
|
||||
expect(patchMock).toHaveBeenCalledWith(vm.$props.saveUrl, expectedUpdateBody);
|
||||
});
|
||||
|
||||
it('should call axios.patch with url when saveUrl is not set and justInput is true', async () => {
|
||||
generateWrapper({
|
||||
url: '/business',
|
||||
body: { workerFk: 1110 },
|
||||
justInput: true,
|
||||
});
|
||||
generateExpectedBody();
|
||||
|
||||
await vm.update();
|
||||
|
||||
expect(patchMock).toHaveBeenCalledWith(
|
||||
`${vm.$props.url}/${vm.$props.body.workerFk}`,
|
||||
expectedUpdateBody,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import axios from 'axios';
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ref, reactive, useAttrs, computed } from 'vue';
|
||||
import { onBeforeRouteLeave } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
@ -16,12 +16,22 @@ import VnSelect from 'components/common/VnSelect.vue';
|
|||
import FetchData from 'components/FetchData.vue';
|
||||
import VnInput from 'components/common/VnInput.vue';
|
||||
|
||||
const emit = defineEmits(['onFetch']);
|
||||
|
||||
const $attrs = useAttrs();
|
||||
|
||||
const isRequired = computed(() => {
|
||||
return Object.keys($attrs).includes('required')
|
||||
});
|
||||
|
||||
const $props = defineProps({
|
||||
url: { type: String, default: null },
|
||||
saveUrl: {type: String, default: null},
|
||||
filter: { type: Object, default: () => {} },
|
||||
body: { type: Object, default: () => {} },
|
||||
addNote: { type: Boolean, default: false },
|
||||
selectType: { type: Boolean, default: false },
|
||||
justInput: { type: Boolean, default: false },
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
@ -29,6 +39,13 @@ const quasar = useQuasar();
|
|||
const newNote = reactive({ text: null, observationTypeFk: null });
|
||||
const observationTypes = ref([]);
|
||||
const vnPaginateRef = ref();
|
||||
let originalText;
|
||||
|
||||
function handleClick(e) {
|
||||
if (e.shiftKey && e.key === 'Enter') return;
|
||||
if ($props.justInput) confirmAndUpdate();
|
||||
else insert();
|
||||
}
|
||||
|
||||
async function insert() {
|
||||
if (!newNote.text || ($props.selectType && !newNote.observationTypeFk)) return;
|
||||
|
@ -41,8 +58,36 @@ async function insert() {
|
|||
await axios.post($props.url, newBody);
|
||||
await vnPaginateRef.value.fetch();
|
||||
}
|
||||
|
||||
function confirmAndUpdate() {
|
||||
if(!newNote.text && originalText)
|
||||
quasar
|
||||
.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
title: t('New note is empty'),
|
||||
message: t('Are you sure remove this note?'),
|
||||
},
|
||||
})
|
||||
.onOk(update)
|
||||
.onCancel(() => {
|
||||
newNote.text = originalText;
|
||||
});
|
||||
else update();
|
||||
}
|
||||
|
||||
async function update() {
|
||||
originalText = newNote.text;
|
||||
const body = $props.body;
|
||||
const newBody = {
|
||||
...body,
|
||||
...{ notes: newNote.text },
|
||||
};
|
||||
await axios.patch(`${$props.saveUrl ?? `${$props.url}/${$props.body.workerFk}`}`, newBody);
|
||||
}
|
||||
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
if (newNote.text)
|
||||
if ((newNote.text && !$props.justInput) || (newNote.text !== originalText) && $props.justInput)
|
||||
quasar.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
|
@ -53,6 +98,13 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
});
|
||||
else next();
|
||||
});
|
||||
|
||||
function fetchData([ data ]) {
|
||||
newNote.text = data?.notes;
|
||||
originalText = data?.notes;
|
||||
emit('onFetch', data);
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
|
@ -62,8 +114,19 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
auto-load
|
||||
@on-fetch="(data) => (observationTypes = data)"
|
||||
/>
|
||||
<QCard class="q-pa-xs q-mb-lg full-width" v-if="$props.addNote">
|
||||
<QCardSection horizontal>
|
||||
<FetchData
|
||||
v-if="justInput"
|
||||
:url="url"
|
||||
:filter="filter"
|
||||
@on-fetch="fetchData"
|
||||
auto-load
|
||||
/>
|
||||
<QCard
|
||||
class="q-pa-xs q-mb-lg full-width"
|
||||
:class="{ 'just-input': $props.justInput }"
|
||||
v-if="$props.addNote || $props.justInput"
|
||||
>
|
||||
<QCardSection horizontal v-if="!$props.justInput">
|
||||
{{ t('New note') }}
|
||||
</QCardSection>
|
||||
<QCardSection class="q-px-xs q-my-none q-py-none">
|
||||
|
@ -75,19 +138,19 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
v-model="newNote.observationTypeFk"
|
||||
option-label="description"
|
||||
style="flex: 0.15"
|
||||
:required="true"
|
||||
:required="isRequired"
|
||||
@keyup.enter.stop="insert"
|
||||
/>
|
||||
<VnInput
|
||||
v-model.trim="newNote.text"
|
||||
type="textarea"
|
||||
:label="t('Add note here...')"
|
||||
:label="$props.justInput && newNote.text ? '' : t('Add note here...')"
|
||||
filled
|
||||
size="lg"
|
||||
autogrow
|
||||
@keyup.enter.stop="insert"
|
||||
@keyup.enter.stop="handleClick"
|
||||
:required="isRequired"
|
||||
clearable
|
||||
:required="true"
|
||||
>
|
||||
<template #append>
|
||||
<QBtn
|
||||
|
@ -95,7 +158,7 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
icon="save"
|
||||
color="primary"
|
||||
flat
|
||||
@click="insert"
|
||||
@click="handleClick"
|
||||
class="q-mb-xs"
|
||||
dense
|
||||
data-cy="saveNote"
|
||||
|
@ -106,6 +169,7 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
</QCardSection>
|
||||
</QCard>
|
||||
<VnPaginate
|
||||
v-if="!$props.justInput"
|
||||
:data-key="$props.url"
|
||||
:url="$props.url"
|
||||
order="created DESC"
|
||||
|
@ -198,6 +262,11 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
.just-input {
|
||||
padding-right: 18px;
|
||||
margin-bottom: 2px;
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
<i18n>
|
||||
es:
|
||||
|
@ -205,4 +274,6 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
New note: Nueva nota
|
||||
Save (Enter): Guardar (Intro)
|
||||
Observation type: Tipo de observación
|
||||
New note is empty: La nueva nota esta vacia
|
||||
Are you sure remove this note?: Estas seguro de quitar esta nota?
|
||||
</i18n>
|
||||
|
|
|
@ -19,23 +19,26 @@ onMounted(() => {
|
|||
const observer = new MutationObserver(
|
||||
() =>
|
||||
(hasContent.value =
|
||||
actions.value?.childNodes?.length + data.value?.childNodes?.length)
|
||||
actions.value?.childNodes?.length + data.value?.childNodes?.length),
|
||||
);
|
||||
if (actions.value) observer.observe(actions.value, opts);
|
||||
if (data.value) observer.observe(data.value, opts);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => stateStore.toggleSubToolbar());
|
||||
const actionsChildCount = () => !!actions.value?.childNodes?.length;
|
||||
|
||||
onBeforeUnmount(() => stateStore.toggleSubToolbar() && hasSubToolbar);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QToolbar
|
||||
id="subToolbar"
|
||||
class="justify-end sticky"
|
||||
v-show="hasContent || $slots['st-actions'] || $slots['st-data']"
|
||||
class="justify-end sticky"
|
||||
>
|
||||
<slot name="st-data">
|
||||
<div id="st-data"></div>
|
||||
<div id="st-data" :class="{ 'full-width': !actionsChildCount() }">
|
||||
</div>
|
||||
</slot>
|
||||
<QSpace />
|
||||
<slot name="st-actions">
|
||||
|
|
|
@ -23,5 +23,6 @@ const noteFilter = computed(() => {
|
|||
:body="{ clientFk: route.params.id }"
|
||||
style="overflow-y: auto"
|
||||
:select-type="true"
|
||||
required
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -293,7 +293,7 @@ const columns = computed(() => [
|
|||
title: t('globals.preview'),
|
||||
icon: 'preview',
|
||||
color: 'primary',
|
||||
action: (row) => viewSummary(row.id, TicketSummary),
|
||||
action: (row) => viewSummary(row.id, TicketSummary, 'lg-width'),
|
||||
isPrimary: true,
|
||||
attrs: {
|
||||
flat: true,
|
||||
|
|
|
@ -244,7 +244,7 @@ onMounted(async () => {
|
|||
<QCard class="vn-one" v-if="entity.notes.length">
|
||||
<VnTitle
|
||||
:url="toTicketUrl('observation')"
|
||||
:text="t('ticket.pageTitles.notes')"
|
||||
:text="t('globals.pageTitles.notes')"
|
||||
/>
|
||||
<QVirtualScroll
|
||||
:items="entity.notes"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script setup>
|
||||
import { nextTick, ref, watch } from 'vue';
|
||||
import { nextTick, ref, watch, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useAcl } from 'src/composables/useAcl';
|
||||
|
||||
import WorkerCalendarFilter from 'pages/Worker/Card/WorkerCalendarFilter.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
|
@ -9,10 +10,17 @@ import WorkerCalendarItem from 'pages/Worker/Card/WorkerCalendarItem.vue';
|
|||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
|
||||
import axios from 'axios';
|
||||
import VnNotes from 'src/components/ui/VnNotes.vue';
|
||||
import { useStateStore } from 'src/stores/useStateStore';
|
||||
const stateStore = useStateStore();
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const acl = useAcl();
|
||||
const canSeeNotes = computed(() =>
|
||||
acl.hasAny([{ model: 'Worker', props: '__get__business', accessType: 'READ' }]),
|
||||
);
|
||||
const workerIsFreelance = ref();
|
||||
const WorkerFreelanceRef = ref();
|
||||
const workerCalendarFilterRef = ref(null);
|
||||
|
@ -26,6 +34,10 @@ const contractHolidays = ref(null);
|
|||
const yearHolidays = ref(null);
|
||||
const eventsMap = ref({});
|
||||
const festiveEventsMap = ref({});
|
||||
const saveUrl = ref();
|
||||
const body = {
|
||||
workerFk: route.params.id,
|
||||
};
|
||||
|
||||
const onFetchActiveContract = (data) => {
|
||||
if (!data) return;
|
||||
|
@ -67,7 +79,7 @@ const onFetchAbsences = (data) => {
|
|||
name: holidayName,
|
||||
isFestive: true,
|
||||
},
|
||||
true
|
||||
true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -146,7 +158,7 @@ watch(
|
|||
async () => {
|
||||
await nextTick();
|
||||
await activeContractRef.value.fetch();
|
||||
}
|
||||
},
|
||||
);
|
||||
watch([year, businessFk], () => refreshData());
|
||||
</script>
|
||||
|
@ -181,6 +193,20 @@ watch([year, businessFk], () => refreshData());
|
|||
/>
|
||||
</template>
|
||||
</RightMenu>
|
||||
<Teleport to="#st-data" v-if="stateStore.isSubToolbarShown() && canSeeNotes">
|
||||
<VnNotes
|
||||
:just-input="true"
|
||||
:url="`Workers/${route.params.id}/business`"
|
||||
:filter="{ fields: ['id', 'notes', 'workerFk'] }"
|
||||
:save-url="saveUrl"
|
||||
@on-fetch="
|
||||
(data) => {
|
||||
saveUrl = `Businesses/${data.id}`;
|
||||
}
|
||||
"
|
||||
:body="body"
|
||||
/>
|
||||
</Teleport>
|
||||
<QPage class="column items-center">
|
||||
<QCard v-if="workerIsFreelance">
|
||||
<QCardSection class="text-center">
|
||||
|
|
|
@ -180,8 +180,6 @@ const yearList = ref(generateYears());
|
|||
:is-clearable="false"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnSelect
|
||||
:label="t('Contract')"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
|
@ -19,6 +19,7 @@ const trainsData = ref([]);
|
|||
const machinesData = ref([]);
|
||||
const route = useRoute();
|
||||
const routeId = computed(() => route.params.id);
|
||||
const selected = ref([]);
|
||||
|
||||
const initialData = computed(() => {
|
||||
return {
|
||||
|
@ -41,6 +42,21 @@ async function insert() {
|
|||
await axios.post('Operators', initialData.value);
|
||||
crudModelRef.value.reload();
|
||||
}
|
||||
|
||||
watch(
|
||||
() => crudModelRef.value?.formData,
|
||||
(formData) => {
|
||||
if (formData && formData.length) {
|
||||
if (JSON.stringify(selected.value) !== JSON.stringify(formData)) {
|
||||
selected.value = formData;
|
||||
}
|
||||
} else if (selected.value.length > 0) {
|
||||
selected.value = [];
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -67,6 +83,7 @@ async function insert() {
|
|||
:data-required="{ workerFk: route.params.id }"
|
||||
ref="crudModelRef"
|
||||
search-url="operator"
|
||||
:selected="selected"
|
||||
auto-load
|
||||
>
|
||||
<template #body="{ rows }">
|
||||
|
|
Loading…
Reference in New Issue