Skip to content

Commit 4048452

Browse files
jardakotesovectouhidurabir
authored andcommitted
pkp/pkp-lib#1660 simplify with useForm, add spinner
1 parent 1618689 commit 4048452

File tree

5 files changed

+75
-79
lines changed

5 files changed

+75
-79
lines changed

src/components/Table/Table.vue

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
class="flex justify-between border-x border-t border-light bg-secondary p-4"
66
>
77
<div v-if="slots.label || slots.description">
8-
<span
9-
v-if="slots.label"
10-
:id="labelId"
11-
class="text-lg-bold text-heading"
12-
>
13-
<slot name="label" />
14-
</span>
8+
<div class="flex">
9+
<span
10+
v-if="slots.label"
11+
:id="labelId"
12+
class="text-lg-bold text-heading"
13+
>
14+
<slot name="label" />
15+
</span>
16+
<Spinner class="ms-2" :class="showSpinner ? '' : 'invisible'" />
17+
</div>
18+
1519
<div
1620
v-if="slots.description"
1721
:id="descriptionId"
@@ -53,6 +57,7 @@ import {
5357
computed,
5458
useId,
5559
} from 'vue';
60+
import Spinner from '@/components/Spinner/Spinner.vue';
5661
5762
const emit = defineEmits([
5863
/**
@@ -76,6 +81,7 @@ const props = defineProps({
7681
* {column: String, direction: String}, use useSorting composable to control sortDescriptor
7782
*/
7883
sortDescriptor: {type: Object, default: null, required: false},
84+
showSpinner: {type: Boolean, default: false},
7985
});
8086
8187
const {sortDescriptor} = toRefs(props);

src/composables/useForm.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,14 @@ export function useForm(_form, {customSubmit} = {}) {
286286
form.value.action = _action;
287287
}
288288

289+
/**
290+
* Set the form's action URL
291+
* @param {string} _action - The action URL
292+
*/
293+
function setMethod(_method) {
294+
form.value.method = _method;
295+
}
296+
289297
return {
290298
set,
291299
setValue,
@@ -299,6 +307,7 @@ export function useForm(_form, {customSubmit} = {}) {
299307
connectWithErrors,
300308
setLocalesForSubmission,
301309
setAction,
310+
setMethod,
302311
structuredErrors,
303312
};
304313
}

src/managers/ReviewerRecommendationManager/ReviewerRecommendationManager.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div data-cy="reviewer-recommendation-manager">
3-
<PkpTable>
3+
<PkpTable :show-spinner="store.isRecommendationsLoading">
44
<template #label>
55
<h3 class="text-3xl-bold">
66
{{ title }}

src/managers/ReviewerRecommendationManager/ReviewerRecommendationsEditModal.vue

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,30 @@
33
<template #title>
44
{{ title }}
55
</template>
6-
<SideModalLayoutBasic>
7-
<PkpForm
8-
ref="editRecommendation"
9-
class="recommendations__recommendationForm"
10-
v-bind="formProps"
11-
@success="(...args) => $emit('recommendationSaved', ...args)"
12-
@set="(...args) => $emit('updateForm', ...args)"
13-
></PkpForm>
14-
</SideModalLayoutBasic>
6+
<template #default="{closeModal}">
7+
<SideModalLayoutBasic>
8+
<PkpForm
9+
ref="editRecommendation"
10+
class="recommendations__recommendationForm"
11+
v-bind="formProps"
12+
@success="closeModal()"
13+
@set="set"
14+
></PkpForm>
15+
</SideModalLayoutBasic>
16+
</template>
1517
</SideModalBody>
1618
</template>
1719

1820
<script setup>
1921
import SideModalBody from '@/components/Modal/SideModalBody.vue';
2022
import SideModalLayoutBasic from '@/components/Modal/SideModalLayoutBasic.vue';
2123
import PkpForm from '@/components/Form/Form.vue';
24+
import {useForm} from '@/composables/useForm';
2225
23-
defineProps({
26+
const props = defineProps({
2427
title: {type: String, required: true},
2528
formProps: {type: Object, required: true},
2629
});
2730
28-
defineEmits(['recommendationSaved', 'updateForm']);
31+
const {set} = useForm(props.formProps);
2932
</script>

src/managers/ReviewerRecommendationManager/reviewerRecommendationManagerStore.js

Lines changed: 38 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {defineComponentStore} from '@/utils/defineComponentStore';
2-
import {computed, ref} from 'vue';
2+
import {computed} from 'vue';
33
import {useFetch} from '@/composables/useFetch';
44
import {useModal} from '@/composables/useModal';
55
import {useLocalize} from '@/composables/useLocalize';
@@ -14,11 +14,13 @@ export const useReviewerRecommendationManagerStore = defineComponentStore(
1414
'reviewerRecommendationManager',
1515
(props) => {
1616
const {apiUrl} = useUrl('reviewers/recommendations');
17-
const {data: recommendations, fetch: fetchRecommendations} =
18-
useFetch(apiUrl);
19-
const {openDialog, openSideModal, closeSideModal} = useModal();
17+
const {
18+
data: recommendations,
19+
fetch: fetchRecommendations,
20+
isLoading: isRecommendationsLoading,
21+
} = useFetch(apiUrl);
22+
const {openDialog, openSideModal} = useModal();
2023
const {t, localize} = useLocalize();
21-
const currentForm = ref({});
2224

2325
const items = computed({
2426
get: () => recommendations.value?.items || [],
@@ -125,74 +127,50 @@ export const useReviewerRecommendationManagerStore = defineComponentStore(
125127
});
126128
}
127129

128-
async function setupRecommendationForm(item = null) {
129-
let preparedForm = cloneDeep(props.form);
130-
131-
if (!item) {
132-
// Adding new recommendation
133-
preparedForm.action = apiUrl.value;
134-
preparedForm.method = 'POST';
135-
} else {
136-
// Editing existing recommendation
137-
preparedForm.action = `${apiUrl.value}/${item.id}`;
138-
preparedForm.method = 'PUT';
139-
preparedForm.fields = preparedForm.fields.map((field) => {
140-
const baseField = {...field};
141-
142-
if (field.isMultilingual) {
143-
baseField.value = {};
144-
if (item[field.name]) {
145-
Object.keys(item[field.name]).forEach((locale) => {
146-
baseField.value[locale] = item[field.name][locale];
147-
});
148-
}
149-
} else {
150-
baseField.value =
151-
item[field.name] !== undefined
152-
? item[field.name]
153-
: field.value || '';
154-
}
155-
156-
return baseField;
157-
});
158-
}
159-
160-
currentForm.value = preparedForm;
161-
}
162-
163-
function openRecommendationFormModal(title) {
164-
const {form} = useForm(currentForm);
165-
openSideModal(ReviewerRecommendationsEditModal, {
166-
title,
167-
formProps: form,
168-
onRecommendationSaved: recommendationSaved,
169-
onUpdateForm: (formId, data) => {
170-
Object.keys(data).forEach((key) => {
171-
form.value[key] = data[key];
172-
});
130+
function openRecommendationFormModal(title, form) {
131+
openSideModal(
132+
ReviewerRecommendationsEditModal,
133+
{
134+
title,
135+
formProps: form,
173136
},
174-
});
175-
}
176-
177-
async function recommendationSaved(recommendation) {
178-
closeSideModal(ReviewerRecommendationsEditModal);
179-
await fetchRecommendations();
137+
{
138+
onClose: async () => {
139+
await fetchRecommendations();
140+
},
141+
},
142+
);
180143
}
181144

182145
function handleAdd() {
183-
setupRecommendationForm();
184-
openRecommendationFormModal(t('grid.action.addReviewerRecommendation'));
146+
const newForm = cloneDeep(props.form);
147+
const {setAction, setMethod} = useForm(newForm);
148+
setAction(apiUrl.value);
149+
setMethod('POST');
150+
151+
openRecommendationFormModal(
152+
t('grid.action.addReviewerRecommendation'),
153+
newForm,
154+
);
185155
}
186156

187157
function handleEdit(item) {
188-
setupRecommendationForm(item);
189-
openRecommendationFormModal(t('grid.action.editReviewerRecommendation'));
158+
const editForm = cloneDeep(props.form);
159+
const {setValues, setAction, setMethod} = useForm(editForm);
160+
setAction(`${apiUrl.value}/${item.id}`);
161+
setMethod('PUT');
162+
setValues(item);
163+
openRecommendationFormModal(
164+
t('grid.action.editReviewerRecommendation'),
165+
editForm,
166+
);
190167
}
191168

192169
// Initial data fetch
193170
fetchRecommendations();
194171

195172
return {
173+
isRecommendationsLoading,
196174
items,
197175
itemsMax,
198176
handleStatusToggle,

0 commit comments

Comments
 (0)