diff --git a/backend/src/database/repositories/memberRepository.ts b/backend/src/database/repositories/memberRepository.ts
index 38ae2e67dd..2a5e677185 100644
--- a/backend/src/database/repositories/memberRepository.ts
+++ b/backend/src/database/repositories/memberRepository.ts
@@ -410,6 +410,9 @@ class MemberRepository {
return { count: await getTotalCount() }
}
+ const pageLimit = args.limit
+ const queryLimit = pageLimit + 1
+
const mems = await options.database.sequelize.query(
`
SELECT
@@ -452,7 +455,7 @@ class MemberRepository {
{
replacements: {
segmentIds,
- limit: args.limit,
+ limit: queryLimit,
offset: args.offset,
displayName: args?.filter?.displayName ? `${args.filter.displayName}%` : undefined,
memberId: args?.filter?.memberId,
@@ -463,7 +466,10 @@ class MemberRepository {
},
)
- if (mems.length > 0) {
+ const hasMore = mems.length > pageLimit
+ const pageRows = hasMore ? mems.slice(0, pageLimit) : mems
+
+ if (pageRows.length > 0) {
let result
if (args.detail) {
@@ -522,7 +528,7 @@ class MemberRepository {
}
}
- for (const mem of mems) {
+ for (const mem of pageRows) {
memberPromises.push(findMemberInfo(mem.id))
toMergePromises.push(findMemberInfo(mem.toMergeId))
}
@@ -532,10 +538,10 @@ class MemberRepository {
result = memberResults.map((i, idx) => ({
members: [i, memberToMergeResults[idx]],
- similarity: mems[idx].similarity,
+ similarity: pageRows[idx].similarity,
}))
} else {
- result = mems.map((i) => ({
+ result = pageRows.map((i) => ({
members: [
{
id: i.id,
@@ -554,12 +560,12 @@ class MemberRepository {
}))
}
- return { rows: result, count: await getTotalCount(), limit: args.limit, offset: args.offset }
+ return { rows: result, hasMore, limit: args.limit, offset: args.offset }
}
return {
rows: [{ members: [], similarity: 0 }],
- count: await getTotalCount(),
+ hasMore: false,
limit: args.limit,
offset: args.offset,
}
diff --git a/backend/src/database/repositories/organizationRepository.ts b/backend/src/database/repositories/organizationRepository.ts
index 916701ee22..add23f6a41 100644
--- a/backend/src/database/repositories/organizationRepository.ts
+++ b/backend/src/database/repositories/organizationRepository.ts
@@ -944,6 +944,9 @@ class OrganizationRepository {
return { count: await getTotalCount() }
}
+ const pageLimit = args.limit
+ const queryLimit = pageLimit + 1
+
const orgs = await options.database.sequelize.query(
`
SELECT
@@ -990,7 +993,7 @@ class OrganizationRepository {
{
replacements: {
segmentIds,
- limit: args.limit,
+ limit: queryLimit,
offset: args.offset,
displayName: args?.filter?.displayName ? `${args.filter.displayName}%` : undefined,
mergeActionType: MergeActionType.ORG,
@@ -1001,14 +1004,17 @@ class OrganizationRepository {
},
)
- if (orgs.length > 0) {
+ const hasMore = orgs.length > pageLimit
+ const pageRows = hasMore ? orgs.slice(0, pageLimit) : orgs
+
+ if (pageRows.length > 0) {
let result
if (args.detail) {
const organizationPromises = []
const toMergePromises = []
- for (const org of orgs) {
+ for (const org of pageRows) {
organizationPromises.push(
OrganizationRepository.findById(org.id, options, org.primarySegmentId),
)
@@ -1022,10 +1028,10 @@ class OrganizationRepository {
result = organizationResults.map((i, idx) => ({
organizations: [i, organizationToMergeResults[idx]],
- similarity: orgs[idx].similarity,
+ similarity: pageRows[idx].similarity,
}))
} else {
- result = orgs.map((o) => ({
+ result = pageRows.map((o) => ({
organizations: [
{
id: o.id,
@@ -1055,7 +1061,7 @@ class OrganizationRepository {
return {
rows: result,
- count: await getTotalCount(),
+ hasMore,
limit: args.limit,
offset: args.offset,
}
@@ -1063,7 +1069,7 @@ class OrganizationRepository {
return {
rows: [{ organizations: [], similarity: 0 }],
- count: await getTotalCount(),
+ hasMore: false,
limit: args.limit,
offset: args.offset,
}
diff --git a/frontend/src/modules/data-quality/components/member/data-quality-member-merge-suggestions.vue b/frontend/src/modules/data-quality/components/member/data-quality-member-merge-suggestions.vue
index b63d52486b..3f5ef85569 100644
--- a/frontend/src/modules/data-quality/components/member/data-quality-member-merge-suggestions.vue
+++ b/frontend/src/modules/data-quality/components/member/data-quality-member-merge-suggestions.vue
@@ -18,7 +18,7 @@
-
+
([]);
const isModalOpen = ref(false);
@@ -91,7 +91,7 @@ const loadMergeSuggestions = () => {
segments: segments.value,
})
.then((res) => {
- total.value = +res.count;
+ hasMore.value = Boolean(res.hasMore);
const rows = res.rows.filter((s: any) => s.similarity > 0);
if (+res.offset > 0) {
mergeSuggestions.value = [...mergeSuggestions.value, ...rows];
diff --git a/frontend/src/modules/data-quality/components/organization/data-quality-organization-merge-suggestions.vue b/frontend/src/modules/data-quality/components/organization/data-quality-organization-merge-suggestions.vue
index 6e42332e16..0e1cfb9651 100644
--- a/frontend/src/modules/data-quality/components/organization/data-quality-organization-merge-suggestions.vue
+++ b/frontend/src/modules/data-quality/components/organization/data-quality-organization-merge-suggestions.vue
@@ -15,7 +15,7 @@
-
+
([]);
const isModalOpen = ref(false);
@@ -84,7 +84,7 @@ const loadMergeSuggestions = () => {
orderBy: ['similarity_DESC', 'activityCount_DESC'],
})
.then((res) => {
- total.value = +res.count;
+ hasMore.value = Boolean(res.hasMore);
const rows = res.rows.filter((s: any) => s.similarity > 0);
if (+res.offset > 0) {
mergeSuggestions.value = [...mergeSuggestions.value, ...rows];
diff --git a/frontend/src/modules/member/components/member-merge-suggestions.vue b/frontend/src/modules/member/components/member-merge-suggestions.vue
index c337504fd4..6f80b0b6f4 100644
--- a/frontend/src/modules/member/components/member-merge-suggestions.vue
+++ b/frontend/src/modules/member/components/member-merge-suggestions.vue
@@ -7,7 +7,7 @@
@@ -16,7 +16,7 @@
@@ -26,16 +26,10 @@
-
{{ offset + 1 }} of {{ Math.ceil(count) }} suggestions
-
-
-
1 suggestion
+
Suggestion {{ offset + 1 }}
@@ -56,7 +50,7 @@
@@ -66,7 +60,7 @@
-
+
@@ -170,7 +164,8 @@ const { getContributorMergeActions } = useContributorStore();
const membersToMerge = ref([]);
const primary = ref(0);
const offset = ref(props.offset);
-const count = ref(0);
+const hasMore = ref(false);
+const hasSuggestion = ref(false);
const loading = ref(false);
const sendingIgnore = ref(false);
@@ -204,25 +199,45 @@ const preview = computed(() => {
return mergedMembers;
});
-const fetch = (page) => {
+const updateSuggestionsState = (res) => {
+ hasMore.value = Boolean(res.hasMore);
+ const rows = res.rows.filter((suggestion) => suggestion.similarity > 0);
+
+ if (rows.length > 0) {
+ hasSuggestion.value = true;
+ [membersToMerge.value] = rows;
+ } else {
+ hasSuggestion.value = false;
+ membersToMerge.value = [];
+ }
+};
+
+const fetch = (page, trackNavigation = true) => {
if (page > -1) {
offset.value = page;
}
- trackEvent({
- key: FeatureEventKey.NAVIGATE_MEMBERS_MERGE_SUGGESTIONS,
- type: EventType.FEATURE,
- });
+ if (trackNavigation) {
+ trackEvent({
+ key: FeatureEventKey.NAVIGATE_MEMBERS_MERGE_SUGGESTIONS,
+ type: EventType.FEATURE,
+ });
+ }
loading.value = true;
- MemberService.fetchMergeSuggestions(1, offset.value, props.query ?? {})
+ return MemberService.fetchMergeSuggestions(1, offset.value, props.query ?? {})
.then((res) => {
offset.value = +res.offset;
- count.value = res.count;
- [membersToMerge.value] = res.rows;
+
+ updateSuggestionsState(res);
+
+ if (!hasSuggestion.value && offset.value > 0) {
+ return fetch(offset.value - 1, false);
+ }
primary.value = 0;
+ return undefined;
})
.catch(() => {
ToastStore.error(
@@ -252,8 +267,7 @@ const ignoreSuggestion = () => {
.then(() => {
ToastStore.success('Merging suggestion ignored successfully');
getContributorMergeActions();
- const nextIndex = offset.value >= (count.value - 1) ? Math.max(count.value - 2, 0) : offset.value;
- fetch(nextIndex);
+ fetch(offset.value);
changed.value = true;
})
.catch((error) => {
@@ -304,8 +318,7 @@ const mergeSuggestion = () => {
);
primary.value = 0;
- const nextIndex = offset.value >= (count.value - 1) ? Math.max(count.value - 2, 0) : offset.value;
- fetch(nextIndex);
+ fetch(offset.value);
changed.value = true;
})
.catch((error) => {
diff --git a/frontend/src/modules/member/pages/member-merge-suggestions-page.vue b/frontend/src/modules/member/pages/member-merge-suggestions-page.vue
index b3c6f2a263..4f18c510fe 100644
--- a/frontend/src/modules/member/pages/member-merge-suggestions-page.vue
+++ b/frontend/src/modules/member/pages/member-merge-suggestions-page.vue
@@ -114,7 +114,7 @@
-
+
Load more
@@ -158,7 +158,7 @@ const mergeSuggestions = ref
([]);
const isModalOpen = ref(false);
-const total = ref(0);
+const hasMore = ref(false);
const limit = ref(10);
const page = ref(1);
const loading = ref(false);
@@ -187,7 +187,7 @@ const loadMergeSuggestions = (sort: boolean = false) => {
detail: false,
})
.then((res) => {
- total.value = +res.count;
+ hasMore.value = Boolean(res.hasMore);
const rows = res.rows.filter((s: any) => s.similarity > 0);
if (+res.offset > 0) {
mergeSuggestions.value = [...mergeSuggestions.value, ...rows];
diff --git a/frontend/src/modules/organization/components/organization-merge-suggestions.vue b/frontend/src/modules/organization/components/organization-merge-suggestions.vue
index 6581b5088e..0461dfef03 100644
--- a/frontend/src/modules/organization/components/organization-merge-suggestions.vue
+++ b/frontend/src/modules/organization/components/organization-merge-suggestions.vue
@@ -7,7 +7,7 @@
@@ -16,7 +16,7 @@
@@ -26,16 +26,10 @@
-
{{ currentOffset + 1 }} of {{ Math.ceil(count) }} suggestions
-
-
-
1 suggestion
+
Suggestion {{ currentOffset + 1 }}
@@ -56,7 +50,7 @@
@@ -66,7 +60,7 @@
-
+
@@ -175,7 +169,8 @@ const { trackEvent } = useProductTracking();
const organizationsToMerge = ref([]);
const primary = ref(0);
const currentOffset = ref(0);
-const count = ref(0);
+const hasMore = ref(false);
+const hasSuggestion = ref(false);
const loading = ref(false);
const sendingIgnore = ref(false);
@@ -211,25 +206,45 @@ const preview = computed(() => {
return mergedOrganizations;
});
-const fetch = (page) => {
+const updateSuggestionsState = (res) => {
+ hasMore.value = Boolean(res.hasMore);
+ const rows = res.rows.filter((suggestion) => suggestion.similarity > 0);
+
+ if (rows.length > 0) {
+ hasSuggestion.value = true;
+ [organizationsToMerge.value] = rows;
+ } else {
+ hasSuggestion.value = false;
+ organizationsToMerge.value = [];
+ }
+};
+
+const fetch = (page, trackNavigation = true) => {
if (page > -1) {
currentOffset.value = page;
}
- trackEvent({
- key: FeatureEventKey.NAVIGATE_ORGANIZATIONS_MERGE_SUGGESTIONS,
- type: EventType.FEATURE,
- });
+ if (trackNavigation) {
+ trackEvent({
+ key: FeatureEventKey.NAVIGATE_ORGANIZATIONS_MERGE_SUGGESTIONS,
+ type: EventType.FEATURE,
+ });
+ }
loading.value = true;
- OrganizationService.fetchMergeSuggestions(1, currentOffset.value, props.query ?? {})
+ return OrganizationService.fetchMergeSuggestions(1, currentOffset.value, props.query ?? {})
.then((res) => {
currentOffset.value = +res.offset;
- count.value = res.count;
- [organizationsToMerge.value] = res.rows;
+
+ updateSuggestionsState(res);
+
+ if (!hasSuggestion.value && currentOffset.value > 0) {
+ return fetch(currentOffset.value - 1, false);
+ }
primary.value = 0;
+ return undefined;
})
.catch(() => {
ToastStore.error(
@@ -259,8 +274,7 @@ const ignoreSuggestion = () => {
.then(() => {
ToastStore.success('Merging suggestion ignored successfully');
- const nextIndex = currentOffset.value >= (count.value - 1) ? Math.max(count.value - 2, 0) : currentOffset.value;
- fetch(nextIndex);
+ fetch(currentOffset.value);
changed.value = true;
})
.catch((error) => {
@@ -307,8 +321,7 @@ const mergeSuggestion = () => {
loadingMessage();
- const nextIndex = currentOffset.value >= (count.value - 1) ? Math.max(count.value - 2, 0) : currentOffset.value;
- fetch(nextIndex);
+ fetch(currentOffset.value);
changed.value = true;
})
.catch((error) => {
diff --git a/frontend/src/modules/organization/pages/organization-merge-suggestions-page.vue b/frontend/src/modules/organization/pages/organization-merge-suggestions-page.vue
index 78f9504fe5..4ef0383ed3 100644
--- a/frontend/src/modules/organization/pages/organization-merge-suggestions-page.vue
+++ b/frontend/src/modules/organization/pages/organization-merge-suggestions-page.vue
@@ -160,7 +160,7 @@
-
+
Load more
@@ -209,7 +209,7 @@ const mergeSuggestions = ref
([]);
const isModalOpen = ref(false);
-const total = ref(0);
+const hasMore = ref(false);
const limit = ref(10);
const page = ref(1);
const loading = ref(false);
@@ -238,7 +238,7 @@ const loadMergeSuggestions = (sort: boolean = false) => {
detail: false,
})
.then((res) => {
- total.value = +res.count;
+ hasMore.value = Boolean(res.hasMore);
const rows = res.rows.filter((s: any) => s.similarity > 0);
if (+res.offset > 0) {
mergeSuggestions.value = [...mergeSuggestions.value, ...rows];