Skip to content

Commit fa9a8ae

Browse files
authored
feat: handle API cache for list insights project API (#3075)
1 parent 9f8456a commit fa9a8ae

6 files changed

Lines changed: 284 additions & 208 deletions

File tree

frontend/src/modules/admin/modules/collections/pages/collection.page.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ const {
168168
queryFn,
169169
getNextPageParam: (lastPage) => {
170170
const nextPage = lastPage.offset + lastPage.limit;
171-
const totalRows = lastPage.count;
171+
const totalRows = lastPage.total || lastPage.count;
172172
return nextPage < totalRows ? nextPage : undefined;
173173
},
174174
initialPageParam: 0,
@@ -186,7 +186,7 @@ const collections = computed((): CollectionModel[] => {
186186
187187
const total = computed((): number => {
188188
if (isSuccess.value && data.value) {
189-
return data.value.pages[0].count;
189+
return data.value.pages[0].total || data.value.pages[0].count;
190190
}
191191
return 0;
192192
});

frontend/src/modules/admin/modules/insights-projects/components/lf-insights-project-add.vue

Lines changed: 111 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
>
99
<template #header>
1010
<section class="flex items-center">
11-
<lf-button v-if="displayBackButton" type="secondary" :icon-only="true" class="mr-4" @click="onCancel">
11+
<lf-button
12+
v-if="displayBackButton"
13+
type="secondary"
14+
:icon-only="true"
15+
class="mr-4"
16+
@click="onCancel"
17+
>
1218
<lf-icon name="arrow-left" />
1319
</lf-button>
1420
<div class="flex flex-col">
@@ -30,7 +36,11 @@
3036
</section>
3137
</template>
3238
<template #content>
33-
<div v-if="loading" v-loading="loading" class="app-page-spinner h-16 !relative !min-h-5" />
39+
<div
40+
v-if="isLoading"
41+
v-loading="isLoading"
42+
class="app-page-spinner h-16 !relative !min-h-5"
43+
/>
3444
<div v-else>
3545
<!-- Subproject selection -->
3646
<lf-cm-sub-project-list-dropdown
@@ -39,7 +49,10 @@
3949
@on-change="onProjectSelection"
4050
/>
4151
<div class="relative">
42-
<div v-if="!form.segmentId" class="absolute left-0 top-0 w-full h-full bg-white opacity-50 z-20" />
52+
<div
53+
v-if="!form.segmentId"
54+
class="absolute left-0 top-0 w-full h-full bg-white opacity-50 z-20"
55+
/>
4356
<lf-tabs v-model="activeTab" :fragment="false">
4457
<lf-tab name="details">
4558
Details
@@ -56,14 +69,24 @@
5669
</lf-tabs>
5770
<div class="pt-6">
5871
<div class="tab-content">
59-
<lf-insights-project-add-details-tab v-if="activeTab === 'details'" :form="form" :rules="rules" />
72+
<lf-insights-project-add-details-tab
73+
v-if="activeTab === 'details'"
74+
:form="form"
75+
:rules="rules"
76+
/>
6077
<lf-insights-project-add-repository-tab
6178
v-else-if="activeTab === 'repositories'"
6279
:form="form"
6380
:repositories="form.repositories"
6481
/>
65-
<lf-insights-project-add-widgets-tab v-else-if="activeTab === 'widgets'" :form="form" />
66-
<lf-insights-project-add-advanced-tab v-else-if="activeTab === 'advanced'" :form="form" />
82+
<lf-insights-project-add-widgets-tab
83+
v-else-if="activeTab === 'widgets'"
84+
:form="form"
85+
/>
86+
<lf-insights-project-add-advanced-tab
87+
v-else-if="activeTab === 'advanced'"
88+
:form="form"
89+
/>
6790
</div>
6891
</div>
6992
</div>
@@ -73,10 +96,14 @@
7396
<lf-button type="secondary-ghost" class="mr-2" @click="onCancel">
7497
Cancel
7598
</lf-button>
76-
<!-- <lf-button type="secondary" class="mr-2" :disabled="!hasFormChanged || $v.$invalid || loading" @click="onSubmit">
99+
<!-- <lf-button type="secondary" class="mr-2" :disabled="!hasFormChanged || $v.$invalid || isLoading" @click="onSubmit">
77100
{{ isEditForm ? 'Update' : 'Add project' }}
78101
</lf-button> -->
79-
<lf-button type="primary" :disabled="!hasFormChanged || $v.$invalid || loading" @click="onSubmit">
102+
<lf-button
103+
type="primary"
104+
:disabled="!hasFormChanged || $v.$invalid || isLoading"
105+
@click="onSubmit"
106+
>
80107
{{ isEditForm ? "Update" : "Add project" }}
81108
</lf-button>
82109
</template>
@@ -88,7 +115,7 @@ import formChangeDetector from '@/shared/form/form-change';
88115
import useVuelidate from '@vuelidate/core';
89116
import { required } from '@vuelidate/validators';
90117
import {
91-
computed, onMounted, reactive, ref,
118+
computed, onMounted, reactive, ref, watch,
92119
} from 'vue';
93120
import LfButton from '@/ui-kit/button/Button.vue';
94121
import LfIcon from '@/ui-kit/icon/Icon.vue';
@@ -98,13 +125,21 @@ import LfAvatar from '@/ui-kit/avatar/Avatar.vue';
98125
import cloneDeep from 'lodash/cloneDeep';
99126
import Message from '@/shared/message/message';
100127
import LfInsightsProjectAddAdvancedTab from '@/modules/admin/modules/insights-projects/components/lf-insights-project-add-advanced-tab.vue';
128+
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query';
129+
import { TanstackKey } from '@/shared/types/tanstack';
101130
import LfInsightsProjectAddDetailsTab from './lf-insights-project-add-details-tab.vue';
102131
import LfInsightsProjectAddRepositoryTab from './lf-insights-project-add-repository-tab.vue';
103-
import { InsightsProjectModel } from '../models/insights-project.model';
132+
import {
133+
InsightsProjectModel,
134+
InsightsProjectRequest,
135+
} from '../models/insights-project.model';
104136
import { InsightsProjectAddFormModel } from '../models/insights-project-add-form.model';
105137
import LfInsightsProjectAddWidgetsTab from './lf-insights-project-add-widgets-tab.vue';
106138
import { defaultWidgetsValues } from '../widgets';
107-
import { InsightsProjectsService } from '../services/insights-projects.service';
139+
import {
140+
INSIGHTS_PROJECTS_SERVICE,
141+
InsightsProjectsService,
142+
} from '../services/insights-projects.service';
108143
import {
109144
buildForm,
110145
buildRepositories,
@@ -125,7 +160,6 @@ const props = defineProps<{
125160
126161
const activeTab = ref('details');
127162
128-
const loading = ref(false);
129163
const submitLoading = ref(false);
130164
const insightsProject = ref<InsightsProjectModel | null>(null);
131165
@@ -188,31 +222,40 @@ const fillForm = (record?: InsightsProjectAddFormModel) => {
188222
};
189223
190224
onMounted(() => {
191-
if (props.insightsProjectId) {
192-
loading.value = true;
193-
openModalEditMode(props.insightsProjectId);
194-
} else {
225+
if (!props.insightsProjectId) {
195226
fillForm();
196227
}
197228
});
198229
199-
const openModalEditMode = (insightsProjectId: string) => {
200-
InsightsProjectsService.getById(insightsProjectId).then((res) => {
201-
insightsProject.value = res;
230+
const { isLoading, isSuccess, data } = useQuery({
231+
queryKey: [TanstackKey.ADMIN_INSIGHTS_PROJECTS, props.insightsProjectId],
232+
queryFn: () => {
233+
if (props.insightsProjectId === undefined) {
234+
return Promise.resolve(null);
235+
}
236+
return INSIGHTS_PROJECTS_SERVICE.getById(props.insightsProjectId);
237+
},
238+
enabled: !!props.insightsProjectId,
239+
});
202240
203-
if (res.segment.id) {
204-
fetchRepositories(res.segment.id, () => {
205-
const form = buildForm(res, initialFormState.repositories);
241+
watch(
242+
data,
243+
() => {
244+
if (isSuccess.value && data.value) {
245+
insightsProject.value = data.value;
246+
if (data.value.segment.id) {
247+
fetchRepositories(data.value.segment.id, () => {
248+
const form = buildForm(data.value!, initialFormState.repositories);
249+
fillForm(form);
250+
});
251+
} else {
252+
const form = buildForm(data.value, []);
206253
fillForm(form);
207-
loading.value = false;
208-
});
209-
} else {
210-
const form = buildForm(res, []);
211-
fillForm(form);
212-
loading.value = false;
254+
}
213255
}
214-
});
215-
};
256+
},
257+
{ immediate: true },
258+
);
216259
217260
const onProjectSelection = ({ project }: any) => {
218261
fetchRepositories(project.id, () => {
@@ -234,50 +277,54 @@ const onCancel = () => {
234277
235278
const onSubmit = () => {
236279
submitLoading.value = true;
237-
280+
const request = buildRequest({
281+
...form,
282+
});
238283
if (isEditForm.value) {
239-
handleUpdate();
284+
updateMutation.mutate({
285+
id: props.insightsProjectId as string,
286+
form: request,
287+
});
240288
} else {
241-
handleCreate();
289+
createMutation.mutate(request);
242290
}
243291
};
244292
245-
const handleCreate = () => {
246-
const request = buildRequest({
247-
...form,
248-
});
249-
Message.info(null, {
250-
title: 'Insights project is being created',
293+
const queryClient = useQueryClient();
294+
const onSuccess = (res: InsightsProjectModel) => {
295+
queryClient.invalidateQueries({
296+
queryKey: [TanstackKey.ADMIN_INSIGHTS_PROJECTS],
251297
});
252-
InsightsProjectsService.create(request)
253-
.then((res) => {
254-
Message.closeAll();
255-
Message.success('Insights project successfully created');
256-
emit('onInsightsProjectCreated', res);
257-
})
258-
.catch(() => {
259-
Message.closeAll();
260-
Message.error('Something went wrong');
261-
});
298+
Message.closeAll();
299+
Message.success(
300+
`Insights project ${isEditForm.value ? 'updated' : 'created'} successfully`,
301+
);
302+
if (isEditForm.value) {
303+
emit('onInsightsProjectEdited', res);
304+
} else {
305+
emit('onInsightsProjectCreated', res);
306+
}
262307
};
263308
264-
const handleUpdate = () => {
265-
const request = buildRequest(form);
266-
Message.info(null, {
267-
title: 'Insights project is being updated',
268-
});
269-
InsightsProjectsService.update(props.insightsProjectId!, request)
270-
.then((res) => {
271-
Message.closeAll();
272-
Message.success('Insights project successfully updated');
273-
emit('onInsightsProjectEdited', res);
274-
})
275-
.catch(() => {
276-
Message.closeAll();
277-
Message.error('Something went wrong');
278-
});
309+
const onError = () => {
310+
Message.closeAll();
311+
Message.error(
312+
`Something went wrong while ${isEditForm.value ? 'updating' : 'creating'} the project`,
313+
);
279314
};
280315
316+
const createMutation = useMutation({
317+
mutationFn: (form: InsightsProjectRequest) => INSIGHTS_PROJECTS_SERVICE.create(form),
318+
onSuccess,
319+
onError,
320+
});
321+
322+
const updateMutation = useMutation({
323+
mutationFn: ({ id, form }: { id: string; form: InsightsProjectRequest }) => INSIGHTS_PROJECTS_SERVICE.update(id, form),
324+
onSuccess,
325+
onError,
326+
});
327+
281328
const fetchRepositories = async (segmentId: string, callback?: () => void) => {
282329
InsightsProjectsService.getRepositories(segmentId).then((res) => {
283330
initialFormState.repositories = buildRepositories(res);

frontend/src/modules/admin/modules/insights-projects/insight-project-helper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { InsightsProjectAddFormModel } from './models/insights-project-add-form.model';
2-
import { InsightsProjectModel } from './models/insights-project.model';
2+
import { InsightsProjectModel, InsightsProjectRequest } from './models/insights-project.model';
33
import { defaultWidgetsValues } from './widgets';
44

5-
export const buildRequest = (form: InsightsProjectAddFormModel) => ({
5+
export const buildRequest = (form: InsightsProjectAddFormModel): InsightsProjectRequest => ({
66
segmentId: form.segmentId,
77
name: form.name,
88
slug: form.slug,

frontend/src/modules/admin/modules/insights-projects/models/insights-project.model.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,20 @@ export interface InsightsProjectModel {
2828
widgets: string[];
2929
keywords: string[];
3030
}
31+
32+
export interface InsightsProjectRequest {
33+
segmentId: string;
34+
name: string;
35+
slug: string;
36+
description: string;
37+
logoUrl: string;
38+
collections: string[]; // assuming collectionsIds is a string array
39+
organizationId?: string;
40+
website: string;
41+
github: string;
42+
twitter: string;
43+
linkedin: string;
44+
repositories: string[]; // assuming url is a string
45+
keywords: string[];
46+
widgets: string[]; // enabled widget keys
47+
}

0 commit comments

Comments
 (0)