Skip to content

Commit ab0cc6b

Browse files
committed
fix: slim project group list and hydrate on selection
Signed-off-by: Yeganathan S <63534555+skwowet@users.noreply.github.com>
1 parent 7c5a0bb commit ab0cc6b

11 files changed

Lines changed: 117 additions & 62 deletions

File tree

backend/src/database/repositories/segmentRepository.ts

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,11 @@ class SegmentRepository extends RepositoryBase<
463463
if (adminSegments.length === 0) {
464464
return { count: 0, rows: [], limit: criteria.limit, offset: criteria.offset }
465465
}
466-
segmentsSearchQuery += `AND sp.id IN (:adminSegments)`
466+
segmentsSearchQuery += `AND EXISTS (
467+
SELECT 1 FROM segments sp
468+
WHERE sp."grandparentSlug" = f.slug
469+
AND sp.id IN (:adminSegments)
470+
)`
467471
replacements.adminSegments = adminSegments
468472
}
469473

@@ -474,51 +478,24 @@ class SegmentRepository extends RepositoryBase<
474478
SELECT
475479
f.id AS foundation_id,
476480
f.name AS foundation_name,
477-
f.status,
478-
f."createdAt",
479-
f."updatedAt",
480-
f."sourceId",
481-
f."sourceParentId",
482-
f.slug,
483-
p.name AS project_name,
484-
p.id AS project_id,
485-
p.status AS project_status,
486-
p.slug AS project_slug,
487-
COUNT(DISTINCT sp.id) AS subproject_count,
488-
JSONB_AGG(JSONB_BUILD_OBJECT(
489-
'id', sp.id,
490-
'name', sp.name,
491-
'status', sp.status,
492-
'slug', sp.slug
493-
)) AS subprojects
481+
COUNT(DISTINCT p.id)::int AS project_count
494482
FROM segments f
495-
JOIN segments p
483+
LEFT JOIN segments p
496484
ON p."parentSlug" = f."slug"
497485
AND p."grandparentSlug" IS NULL
498486
AND p."tenantId" = f."tenantId"
499-
JOIN segments sp
500-
ON sp."parentSlug" = p."slug"
501-
AND sp."grandparentSlug" = f.slug
502-
AND sp."tenantId" = f."tenantId"
503487
WHERE f."parentSlug" IS NULL
504488
AND f."tenantId" = :tenantId
505489
${segmentsSearchQuery}
506-
GROUP BY f."id", p.id
490+
GROUP BY f.id
507491
)
508492
SELECT
509493
s.*,
510494
COUNT(*) OVER () AS "totalCount",
511-
JSONB_AGG(JSONB_BUILD_OBJECT(
512-
'id', f.project_id,
513-
'name', f.project_name,
514-
'status', f.project_status,
515-
'slug', f.project_slug,
516-
'subprojects', f.subprojects
517-
)) AS projects
495+
f.project_count AS "projectCount"
518496
FROM segments s
519497
JOIN foundations f ON s.id = f.foundation_id
520498
${searchQuery}
521-
GROUP BY s.id, f.foundation_name
522499
ORDER BY f.foundation_name
523500
${this.getPaginationString(criteria)};
524501
`,

frontend/src/app.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ export default {
6060
if (tenant?.id && tenant.id !== oldTenant?.id) {
6161
this.fetchActivityTypes();
6262
this.fetchActivityChannels();
63+
this.listProjectGroups({
64+
limit: 20,
65+
reset: true,
66+
});
6367
}
6468
},
6569
},
@@ -72,10 +76,6 @@ export default {
7276
if (queryParameters.get('state') === 'noconnect' && window.location.pathname.includes('/integration')) {
7377
return;
7478
}
75-
this.listProjectGroups({
76-
limit: null,
77-
reset: true,
78-
});
7979
if (['/auth/callback'].includes(window.location.pathname)) {
8080
return;
8181
}

frontend/src/modules/activity/components/activity-timeline.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,8 @@ const selectedSegment = ref(props.selectedSegment || null);
275275
const isMemberEntity = computed(() => props.entityType === 'member');
276276
277277
const subprojects = computed(() => projectGroups.value.list.reduce((acc, projectGroup) => {
278-
projectGroup.projects.forEach((project) => {
279-
project.subprojects.forEach((subproject) => {
278+
(projectGroup.projects || []).forEach((project) => {
279+
(project.subprojects || []).forEach((subproject) => {
280280
acc[subproject.id] = {
281281
id: subproject.id,
282282
name: subproject.name,

frontend/src/modules/admin/modules/projects/components/view/lf-project-groups-table.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
</div>
2727
</lf-table-cell>
2828
<lf-table-cell>
29-
<app-lf-project-column :projects="projectGroup.projects" />
29+
<app-lf-project-column
30+
:projects="projectGroup.projects || []"
31+
:project-count="projectGroup.projectCount"
32+
/>
3033
</lf-table-cell>
3134
<lf-table-cell class="pr-2 flex justify-end">
3235
<app-lf-project-groups-dropdown

frontend/src/modules/admin/modules/projects/pages/project-groups-list.page.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484

8585
<div class="mb-8 flex flex-wrap gap-2.5">
8686
<div class="bg-gray-200 text-gray-900 text-2xs px-2 h-6 flex items-center w-fit rounded-md">
87-
{{ pluralize('project', projectGroup.projects.length, true) }}
87+
{{ pluralize('project', projectGroup.projectCount ?? projectGroup.projects?.length ?? 0, true) }}
8888
</div>
8989
</div>
9090

frontend/src/modules/lf/layout/components/lf-menu-project-group-selection.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
{{ projectGroup.name }}
6565
</div>
6666
<div class="text-tiny text-gray-400">
67-
{{ pluralize("project", projectGroup.projects.length, true) }}
67+
{{ pluralize("project", projectGroup.projectCount ?? projectGroup.projects?.length ?? 0, true) }}
6868
</div>
6969
</div>
7070
</div>
@@ -230,18 +230,18 @@ onMounted(() => {
230230
});
231231
});
232232
233-
const onOptionClick = ({ id, name }: ProjectGroup) => {
233+
const onOptionClick = (projectGroup: ProjectGroup) => {
234234
trackEvent({
235235
key: FeatureEventKey.SELECT_PROJECT_GROUP,
236236
type: EventType.FEATURE,
237237
properties: {
238-
projectGroupId: id,
239-
projectName: name,
238+
projectGroupId: projectGroup.id,
239+
projectName: projectGroup.name,
240240
},
241241
});
242242
243243
isPopoverVisible.value = false;
244-
updateSelectedProjectGroup(id);
244+
updateSelectedProjectGroup(projectGroup);
245245
};
246246
247247
onBeforeUnmount(() => {

frontend/src/modules/lf/segments/store/actions.js

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,32 @@ const isAdminOnly = () => {
1414
return roles.value.includes(LfRole.projectAdmin);
1515
};
1616

17+
const hasNestedProjects = (projectGroup) => Array.isArray(projectGroup?.projects)
18+
&& projectGroup.projects.some((p) => Array.isArray(p.subprojects) && p.subprojects.length > 0);
19+
20+
const resolveProjectGroupForSelection = async (projectGroupOrId, list) => {
21+
if (!projectGroupOrId) {
22+
return null;
23+
}
24+
25+
const id = typeof projectGroupOrId === 'string' ? projectGroupOrId : projectGroupOrId.id;
26+
if (!id) {
27+
return null;
28+
}
29+
30+
const fromArg = typeof projectGroupOrId === 'object' ? projectGroupOrId : null;
31+
const fromList = list.find((p) => p.id === id) || null;
32+
33+
if (hasNestedProjects(fromArg)) {
34+
return fromArg;
35+
}
36+
if (hasNestedProjects(fromList)) {
37+
return fromList;
38+
}
39+
40+
return LfService.findSegment(id);
41+
};
42+
1743
export default {
1844
// Project Groups
1945
listProjectGroups({
@@ -270,19 +296,44 @@ export default {
270296

271297
this.listProjects();
272298
},
273-
updateSelectedProjectGroup(projectGroupId, sendToDashboard = true) {
274-
if (projectGroupId) {
275-
const projectGroup = this.projectGroups.list.find((p) => p.id === projectGroupId);
299+
async updateSelectedProjectGroup(projectGroupOrId, sendToDashboard = true) {
300+
if (!projectGroupOrId) {
301+
this.selectedProjectGroup = null;
302+
return;
303+
}
304+
305+
try {
306+
const projectGroup = await resolveProjectGroupForSelection(
307+
projectGroupOrId,
308+
this.projectGroups.list,
309+
);
310+
311+
if (!projectGroup?.id) {
312+
this.selectedProjectGroup = null;
313+
ToastStore.error('Project group could not be loaded');
314+
return;
315+
}
276316

277317
this.selectedProjectGroup = projectGroup;
278318

319+
const idx = this.projectGroups.list.findIndex((p) => p.id === projectGroup.id);
320+
if (idx >= 0) {
321+
this.projectGroups.list[idx] = {
322+
...this.projectGroups.list[idx],
323+
...projectGroup,
324+
};
325+
} else {
326+
this.projectGroups.list = [...this.projectGroups.list, projectGroup];
327+
}
328+
279329
if (sendToDashboard) {
280330
router.push({
281331
name: 'member',
282332
});
283333
}
284-
} else {
334+
} catch (e) {
285335
this.selectedProjectGroup = null;
336+
ToastStore.error('Something went wrong while selecting the project group');
286337
}
287338
},
288339
doChangeProjectGroupCurrentPage(currentPage) {

frontend/src/modules/overview/components/fragments/project-group-filter.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,18 @@ watch(error, (err) => {
185185
}
186186
});
187187
188-
watch(selectedProjectGroupId, (newVal) => {
188+
watch(selectedProjectGroupId, async (newVal) => {
189189
if (newVal && newVal !== '') {
190-
selectedProjectGroup.value = projectGroupsList.value.find((pg) => pg.id === newVal) || null;
190+
const fromList = projectGroupsList.value.find((pg) => pg.id === newVal) || null;
191+
selectedProjectGroup.value = fromList;
192+
193+
if (!fromList?.projects?.length) {
194+
try {
195+
selectedProjectGroup.value = await segmentService.getSegmentById(newVal) as ProjectGroup;
196+
} catch (e) {
197+
ToastStore.error('Something went wrong while loading the project group');
198+
}
199+
}
191200
} else {
192201
selectedProjectGroup.value = null;
193202
selectedProjectId.value = '';

frontend/src/router/index.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const createRouter = () => {
6262
router.beforeEach(async (to, from, next) => {
6363
const lsSegmentsStore = useLfSegmentsStore();
6464
const { selectedProjectGroup } = storeToRefs(lsSegmentsStore);
65-
const { listProjectGroups, updateSelectedProjectGroup } = lsSegmentsStore;
65+
const { updateSelectedProjectGroup } = lsSegmentsStore;
6666

6767
// Set title to pages
6868
document.title = `LFX Community Data Platform${to.meta.title ? ` | ${to.meta.title}` : ''}`;
@@ -111,12 +111,11 @@ export const createRouter = () => {
111111

112112
if (!selectedProjectGroup.value) {
113113
try {
114-
await listProjectGroups({
115-
limit: null,
116-
reset: true,
117-
});
118-
119-
updateSelectedProjectGroup(to.query.projectGroup, false);
114+
await updateSelectedProjectGroup(to.query.projectGroup, false);
115+
if (!selectedProjectGroup.value) {
116+
next('/project-groups');
117+
return;
118+
}
120119
} catch (e) {
121120
next('/project-groups');
122121
return;

frontend/src/shared/project-column/lf-project-column.vue

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<template>
2-
<div v-if="props.projects.length" class="flex flex-wrap gap-2">
2+
<div v-if="displayCount > 0" class="flex flex-wrap gap-2">
33
<el-popover
4+
v-if="projects.length"
45
placement="top"
56
:width="250"
67
trigger="hover"
78
>
89
<template #reference>
9-
<app-lf-project-count :title="props.title" :icon="props.icon" :count="projects.length" />
10+
<app-lf-project-count :title="props.title" :icon="props.icon" :count="displayCount" />
1011
</template>
1112
<template #default>
1213
<div class="flex flex-wrap gap-1 overflow-hidden">
@@ -22,25 +23,36 @@
2223
</div>
2324
</template>
2425
</el-popover>
26+
<app-lf-project-count
27+
v-else
28+
:title="props.title"
29+
:icon="props.icon"
30+
:count="displayCount"
31+
/>
2532
</div>
2633
<span v-else class="text-gray-500 text-sm">No {{ props.title }}</span>
2734
</template>
2835

2936
<script lang="ts" setup>
37+
import { computed } from 'vue';
3038
import AppLfProjectCount from './lf-project-count.vue';
3139
3240
const props = withDefaults(defineProps<{
33-
projects: {
41+
projects?: {
3442
id: string;
3543
name: string;
3644
}[];
45+
projectCount?: number;
3746
icon?: string;
3847
title?: string;
3948
}>(), {
4049
projects: () => [],
50+
projectCount: undefined,
4151
title: () => 'Projects',
4252
icon: () => 'layer-group',
4353
});
54+
55+
const displayCount = computed(() => props.projectCount ?? props.projects?.length ?? 0);
4456
</script>
4557

4658
<script lang="ts">

0 commit comments

Comments
 (0)