Skip to content

Commit 66ef96a

Browse files
authored
Fix activity pagination, load more functionality (#2671)
1 parent 6875221 commit 66ef96a

File tree

10 files changed

+107
-23
lines changed

10 files changed

+107
-23
lines changed

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

+25-14
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
</div>
8585
<div>
8686
<el-timeline>
87-
<template v-if="activities.length && !loading">
87+
<template v-if="activities.length">
8888
<el-timeline-item
8989
v-for="activity in activities"
9090
:key="activity.id"
@@ -217,14 +217,13 @@
217217
class="app-page-spinner"
218218
/>
219219
<div v-if="!noMore" class="flex justify-center pt-4">
220-
<el-button
221-
class="btn btn-link btn-link--primary"
220+
<lf-button
221+
type="primary-ghost"
222222
:disabled="loading"
223223
@click="fetchActivities()"
224224
>
225-
<i class="ri-arrow-down-line mr-2" />Load
226-
more
227-
</el-button>
225+
Load more
226+
</lf-button>
228227
</div>
229228
</div>
230229
</div>
@@ -262,6 +261,7 @@ import { getSegmentsFromProjectGroup } from '@/utils/segments';
262261
import { Platform } from '@/shared/modules/platform/types/Platform';
263262
import LfActivityDisplay from '@/shared/modules/activity/components/activity-display.vue';
264263
import moment from 'moment';
264+
import LfButton from '@/ui-kit/button/Button.vue';
265265
import { ActivityService } from '../activity-service';
266266
267267
const SearchIcon = h(
@@ -305,12 +305,12 @@ const enabledPlatforms = computed(() => CrowdIntegrations.enabledConfigs.concat(
305305
label: i.name,
306306
})));
307307
308-
const loading = ref(true);
308+
const loading = ref(false);
309309
const platform = ref(null);
310310
const query = ref('');
311311
const activities = ref([]);
312-
const limit = ref(50);
313-
const timestamp = ref(moment().toISOString());
312+
const limit = ref(10);
313+
const timestamp = ref(moment(props.entity.lastActive).toISOString());
314314
const noMore = ref(false);
315315
const selectedSegment = ref(props.selectedSegment || null);
316316
@@ -343,6 +343,9 @@ const segments = computed(() => {
343343
});
344344
345345
const fetchActivities = async ({ reset } = { reset: false }) => {
346+
if (loading.value) {
347+
return;
348+
}
346349
const filterToApply = {
347350
platform: platform.value ? { in: [platform.value] } : undefined,
348351
};
@@ -373,12 +376,12 @@ const fetchActivities = async ({ reset } = { reset: false }) => {
373376
filterToApply.and = [
374377
{
375378
timestamp: {
376-
lte: props.entity?.lastActive ?? timestamp.value,
379+
lte: timestamp.value,
377380
},
378381
},
379-
...(props.entity?.lastActive ? [{
382+
...(timestamp.value ? [{
380383
timestamp: {
381-
gte: moment(props.entity?.lastActive).subtract(1, 'month').toISOString(),
384+
gte: moment(timestamp.value).subtract(1, 'month').toISOString(),
382385
},
383386
}] : []),
384387
];
@@ -406,12 +409,16 @@ const fetchActivities = async ({ reset } = { reset: false }) => {
406409
407410
const activityIds = activities.value.map((a) => a.id);
408411
const rows = data.rows.filter((a) => !activityIds.includes(a.id));
409-
if (rows.length === 0) {
412+
if (rows.length >= props.entity.activityCount) {
410413
noMore.value = true;
411414
}
412415
activities.value = reset ? rows : [...activities.value, ...rows];
413416
414-
timestamp.value = moment(data.rows.at(-1).timestamp).toISOString();
417+
if (data.rows.length === 0) {
418+
timestamp.value = moment(timestamp.value).subtract(1, 'month').toISOString();
419+
} else {
420+
timestamp.value = moment(data.rows.at(-1).timestamp).toISOString();
421+
}
415422
};
416423
417424
const reloadActivities = async () => {
@@ -443,6 +450,10 @@ onMounted(async () => {
443450
await store.dispatch('integration/doFetch', segments.value.map((s) => s.id));
444451
await fetchActivities();
445452
});
453+
454+
defineExpose({
455+
fetchActivities,
456+
});
446457
</script>
447458
448459
<script>

frontend/src/modules/contributor/components/details/contributor-details-activities.vue

+12-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
</div>
2828
<app-activity-timeline
2929
v-else
30+
ref="timeline"
3031
:entity="props.contributor"
3132
entity-type="member"
3233
:show-affiliations="true"
@@ -42,7 +43,7 @@ import { useRoute } from 'vue-router';
4243
import { MergeActionState } from '@/shared/modules/merge/types/MemberActions';
4344
import LfIconOld from '@/ui-kit/icon/IconOld.vue';
4445
import useContributorHelpers from '@/modules/contributor/helpers/contributor.helpers';
45-
import { computed } from 'vue';
46+
import { computed, ref } from 'vue';
4647
import LfIcon from '@/ui-kit/icon/Icon.vue';
4748
4849
const props = defineProps<{
@@ -53,9 +54,19 @@ const route = useRoute();
5354
5455
const { isMasked } = useContributorHelpers();
5556
57+
const timeline = ref(null);
58+
5659
const { subProjectId } = route.query;
5760
5861
const masked = computed(() => isMasked(props.contributor));
62+
63+
const loadMore = () => {
64+
timeline.value.fetchActivities();
65+
};
66+
67+
defineExpose({
68+
loadMore,
69+
});
5970
</script>
6071

6172
<script lang="ts">

frontend/src/modules/contributor/pages/contributor-details.page.vue

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
/>
8080
<lf-contributor-details-activities
8181
v-else-if="tabs === 'activities'"
82+
ref="activities"
8283
:contributor="contributor"
8384
/>
8485
<lf-contributor-details-notes
@@ -132,6 +133,7 @@ const route = useRoute();
132133
const tabs = ref('overview');
133134
134135
const notes = ref<any>(null);
136+
const activities = ref<any>(null);
135137
136138
const { id } = route.params;
137139
@@ -153,6 +155,8 @@ const controlScroll = (e) => {
153155
if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) {
154156
if (tabs.value === 'notes') {
155157
notes.value.loadMore();
158+
} else if (tabs.value === 'activities') {
159+
activities.value.loadMore();
156160
}
157161
}
158162
};

frontend/src/modules/data-quality/components/member/data-quality-member-issues.vue

+9-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div v-if="loading && offset === 0" class="flex justify-center py-20">
44
<lf-spinner />
55
</div>
6-
<div v-else-if="members.length > 0">
6+
<lf-scroll-controll v-else-if="members.length > 0" class="scroll-container -mb-4" @bottom="loadMore()">
77
<lf-data-quality-member-issues-item
88
v-for="(member) of members"
99
:key="member.id"
@@ -36,7 +36,7 @@
3636
Load more
3737
</lf-button>
3838
</div>
39-
</div>
39+
</lf-scroll-controll>
4040
<div v-else class="flex flex-col items-center pt-16">
4141
<div
4242
class="ri-shuffle-line text-gray-200 text-10xl h-40 flex items-center mb-8"
@@ -64,6 +64,7 @@ import { storeToRefs } from 'pinia';
6464
import { useLfSegmentsStore } from '@/modules/lf/segments/store';
6565
import { EventType, FeatureEventKey } from '@/shared/modules/monitoring/types/event';
6666
import useProductTracking from '@/shared/modules/monitoring/useProductTracking';
67+
import LfScrollControll from '@/ui-kit/scrollcontroll/ScrollControll.vue';
6768
6869
const props = defineProps<{
6970
type: DataIssueType,
@@ -143,3 +144,9 @@ export default {
143144
name: 'LfDataQualityMemberIssues',
144145
};
145146
</script>
147+
148+
<style lang="scss">
149+
.scroll-container{
150+
max-height: calc(100vh - 228px);
151+
}
152+
</style>

frontend/src/modules/data-quality/components/member/data-quality-member-merge-suggestions.vue

+9-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div v-if="loading && offset === 0" class="flex justify-center py-20">
44
<lf-spinner />
55
</div>
6-
<div v-else-if="mergeSuggestions.length > 0">
6+
<lf-scroll-controll v-else-if="mergeSuggestions.length > 0" class="scroll-container -mb-4" @bottom="loadMore()">
77
<lf-data-quality-member-merge-suggestions-item
88
v-for="(suggestion, si) of mergeSuggestions"
99
:key="suggestion.id"
@@ -28,7 +28,7 @@
2828
Load more
2929
</lf-button>
3030
</div>
31-
</div>
31+
</lf-scroll-controll>
3232
<div v-else class="flex flex-col items-center pt-16">
3333
<div
3434
class="ri-shuffle-line text-gray-200 text-10xl h-40 flex items-center mb-8"
@@ -68,6 +68,7 @@ import { storeToRefs } from 'pinia';
6868
import { useLfSegmentsStore } from '@/modules/lf/segments/store';
6969
import LfMemberMergeSuggestionDropdown
7070
from '@/modules/member/components/suggestions/member-merge-suggestion-dropdown.vue';
71+
import LfScrollControll from '@/ui-kit/scrollcontroll/ScrollControll.vue';
7172
7273
const props = defineProps<{
7374
projectGroup: string,
@@ -148,3 +149,9 @@ export default {
148149
name: 'LfDataQualityMemberMergeSuggestions',
149150
};
150151
</script>
152+
153+
<style lang="scss">
154+
.scroll-container{
155+
max-height: calc(100vh - 228px);
156+
}
157+
</style>

frontend/src/modules/data-quality/components/organization/data-quality-organization-merge-suggestions.vue

+9-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div v-if="loading" class="flex justify-center py-20">
44
<lf-spinner />
55
</div>
6-
<div v-else-if="mergeSuggestions.length > 0">
6+
<lf-scroll-controll v-else-if="mergeSuggestions.length > 0" class="scroll-container -mb-4" @bottom="loadMore()">
77
<lf-data-quality-organization-merge-suggestions-item
88
v-for="(suggestion, si) of mergeSuggestions"
99
:key="suggestion.id"
@@ -25,7 +25,7 @@
2525
Load more
2626
</lf-button>
2727
</div>
28-
</div>
28+
</lf-scroll-controll>
2929
<div v-else class="flex flex-col items-center pt-16">
3030
<div
3131
class="ri-shuffle-line text-gray-200 text-10xl h-40 flex items-center mb-8"
@@ -62,6 +62,7 @@ import AppOrganizationMergeSuggestionsDialog
6262
from '@/modules/organization/components/organization-merge-suggestions-dialog.vue';
6363
import { storeToRefs } from 'pinia';
6464
import { useLfSegmentsStore } from '@/modules/lf/segments/store';
65+
import LfScrollControll from '@/ui-kit/scrollcontroll/ScrollControll.vue';
6566
6667
const props = defineProps<{
6768
projectGroup: string,
@@ -131,3 +132,9 @@ export default {
131132
name: 'LfDataQualityOrganizationMergeSuggestions',
132133
};
133134
</script>
135+
136+
<style lang="scss">
137+
.scroll-container{
138+
max-height: calc(100vh - 228px);
139+
}
140+
</style>

frontend/src/modules/data-quality/pages/data-quality.page.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<app-page-wrapper>
2+
<app-page-wrapper class="!pb-0">
33
<div>
44
<!-- Header -->
55
<div class="mb-6">

frontend/src/modules/organization/components/details/organization-details-activities.vue

+12
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
</div>
2323
<app-activity-timeline
2424
v-else
25+
ref="timeline"
2526
:entity="{
2627
...props.organization,
2728
organizations: [props.organization],
@@ -36,10 +37,21 @@ import { Organization } from '@/modules/organization/types/Organization';
3637
import AppActivityTimeline from '@/modules/activity/components/activity-timeline.vue';
3738
import LfIconOld from '@/ui-kit/icon/IconOld.vue';
3839
import { MergeActionState } from '@/shared/modules/merge/types/MemberActions';
40+
import { ref } from 'vue';
3941
4042
const props = defineProps<{
4143
organization: Organization,
4244
}>();
45+
46+
const timeline = ref<AppActivityTimeline | null>(null);
47+
48+
const loadMore = () => {
49+
timeline.value.fetchActivities();
50+
};
51+
52+
defineExpose({
53+
loadMore,
54+
});
4355
</script>
4456

4557
<script lang="ts">

frontend/src/modules/organization/pages/organization-details.page.vue

+5-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
/>
9292
<lf-organization-details-activities
9393
v-else-if="tabs === 'activities'"
94+
ref="activities"
9495
:organization="organization"
9596
/>
9697
</div>
@@ -135,7 +136,8 @@ const { selectedProjectGroup } = storeToRefs(lsSegmentsStore);
135136
const route = useRoute();
136137
137138
const tabs = ref('overview');
138-
const contributors = ref('overview');
139+
const contributors = ref(null);
140+
const activities = ref(null);
139141
const scrollContainer = ref(null);
140142
141143
const { id } = route.params;
@@ -161,6 +163,8 @@ const controlScroll = (e: any) => {
161163
if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) {
162164
if (tabs.value === 'people') {
163165
contributors.value.loadMore();
166+
} else if (tabs.value === 'activities') {
167+
activities.value.loadMore();
164168
}
165169
}
166170
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<template>
2+
<div class="relative overflow-auto" v-bind="$attrs" @scroll="controlScroll">
3+
<slot />
4+
</div>
5+
</template>
6+
7+
<script setup lang="ts">
8+
const emit = defineEmits<{(e: 'bottom'): void}>();
9+
10+
const controlScroll = (e: any) => {
11+
if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) {
12+
emit('bottom');
13+
}
14+
};
15+
</script>
16+
17+
<script lang="ts">
18+
export default {
19+
name: 'LfScrollControll',
20+
};
21+
</script>

0 commit comments

Comments
 (0)