-
Notifications
You must be signed in to change notification settings - Fork 740
Fix activity pagination, load more functionality #2671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,6 +79,7 @@ | |
/> | ||
<lf-contributor-details-activities | ||
v-else-if="tabs === 'activities'" | ||
ref="activities" | ||
:contributor="contributor" | ||
/> | ||
<lf-contributor-details-notes | ||
|
@@ -132,6 +133,7 @@ const route = useRoute(); | |
const tabs = ref('overview'); | ||
|
||
const notes = ref<any>(null); | ||
const activities = ref<any>(null); | ||
|
||
const { id } = route.params; | ||
|
||
|
@@ -153,6 +155,8 @@ const controlScroll = (e) => { | |
if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) { | ||
if (tabs.value === 'notes') { | ||
notes.value.loadMore(); | ||
} else if (tabs.value === 'activities') { | ||
activities.value.loadMore(); | ||
Comment on lines
+158
to
+159
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add safeguards to the scroll handling The current implementation could benefit from additional safeguards:
+import { debounce } from 'lodash-es';
-const controlScroll = (e) => {
+const controlScroll = debounce((e) => {
if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) {
if (tabs.value === 'notes') {
- notes.value.loadMore();
+ notes.value?.loadMore?.();
} else if (tabs.value === 'activities') {
- activities.value.loadMore();
+ activities.value?.loadMore?.();
}
}
-};
+}, 200);
|
||
} | ||
} | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
<div v-if="loading" class="flex justify-center py-20"> | ||
<lf-spinner /> | ||
</div> | ||
<div v-else-if="mergeSuggestions.length > 0"> | ||
<lf-scroll-controll v-else-if="mergeSuggestions.length > 0" class="scroll-container -mb-4" @bottom="loadMore()"> | ||
<lf-data-quality-organization-merge-suggestions-item | ||
v-for="(suggestion, si) of mergeSuggestions" | ||
:key="suggestion.id" | ||
|
@@ -25,7 +25,7 @@ | |
Load more | ||
</lf-button> | ||
</div> | ||
</div> | ||
</lf-scroll-controll> | ||
<div v-else class="flex flex-col items-center pt-16"> | ||
<div | ||
class="ri-shuffle-line text-gray-200 text-10xl h-40 flex items-center mb-8" | ||
|
@@ -62,6 +62,7 @@ import AppOrganizationMergeSuggestionsDialog | |
from '@/modules/organization/components/organization-merge-suggestions-dialog.vue'; | ||
import { storeToRefs } from 'pinia'; | ||
import { useLfSegmentsStore } from '@/modules/lf/segments/store'; | ||
import LfScrollControll from '@/ui-kit/scrollcontroll/ScrollControll.vue'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Prevent race conditions in loadMore function. The current implementation doesn't prevent multiple simultaneous calls to Consider adding a guard clause: const loadMore = () => {
+ if (loading.value) return;
offset.value = mergeSuggestions.value.length;
loadMergeSuggestions();
}; Also applies to: 108-112 |
||
|
||
const props = defineProps<{ | ||
projectGroup: string, | ||
|
@@ -131,3 +132,9 @@ export default { | |
name: 'LfDataQualityOrganizationMergeSuggestions', | ||
}; | ||
</script> | ||
|
||
<style lang="scss"> | ||
.scroll-container{ | ||
max-height: calc(100vh - 228px); | ||
} | ||
</style> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
<template> | ||
<app-page-wrapper> | ||
<app-page-wrapper class="!pb-0"> | ||
<div> | ||
<!-- Header --> | ||
<div class="mb-6"> | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -22,6 +22,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<app-activity-timeline | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
v-else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ref="timeline" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
:entity="{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...props.organization, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
organizations: [props.organization], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -36,10 +37,21 @@ import { Organization } from '@/modules/organization/types/Organization'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import AppActivityTimeline from '@/modules/activity/components/activity-timeline.vue'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import LfIconOld from '@/ui-kit/icon/IconOld.vue'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { MergeActionState } from '@/shared/modules/merge/types/MemberActions'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { ref } from 'vue'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const props = defineProps<{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
organization: Organization, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const timeline = ref<AppActivityTimeline | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const loadMore = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
timeline.value.fetchActivities(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defineExpose({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
loadMore, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+46
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling and null checks to loadMore method While the implementation is functional, it could benefit from additional safeguards to prevent runtime errors and improve user experience. Consider applying these improvements: const timeline = ref<AppActivityTimeline | null>(null);
-const loadMore = () => {
- timeline.value.fetchActivities();
-};
+const loading = ref(false);
+
+const loadMore = async () => {
+ if (!timeline.value || loading.value) return;
+
+ try {
+ loading.value = true;
+ await timeline.value.fetchActivities();
+ } catch (error) {
+ console.error('Failed to load more activities:', error);
+ // Consider adding user feedback for the error
+ } finally {
+ loading.value = false;
+ }
+};
defineExpose({
loadMore,
}); This implementation:
📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</script> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<script lang="ts"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -91,6 +91,7 @@ | |||||||||||||||||||
/> | ||||||||||||||||||||
<lf-organization-details-activities | ||||||||||||||||||||
v-else-if="tabs === 'activities'" | ||||||||||||||||||||
ref="activities" | ||||||||||||||||||||
:organization="organization" | ||||||||||||||||||||
/> | ||||||||||||||||||||
</div> | ||||||||||||||||||||
|
@@ -135,7 +136,8 @@ const { selectedProjectGroup } = storeToRefs(lsSegmentsStore); | |||||||||||||||||||
const route = useRoute(); | ||||||||||||||||||||
|
||||||||||||||||||||
const tabs = ref('overview'); | ||||||||||||||||||||
const contributors = ref('overview'); | ||||||||||||||||||||
const contributors = ref(null); | ||||||||||||||||||||
const activities = ref(null); | ||||||||||||||||||||
const scrollContainer = ref(null); | ||||||||||||||||||||
|
||||||||||||||||||||
const { id } = route.params; | ||||||||||||||||||||
|
@@ -161,6 +163,8 @@ const controlScroll = (e: any) => { | |||||||||||||||||||
if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) { | ||||||||||||||||||||
if (tabs.value === 'people') { | ||||||||||||||||||||
contributors.value.loadMore(); | ||||||||||||||||||||
} else if (tabs.value === 'activities') { | ||||||||||||||||||||
activities.value.loadMore(); | ||||||||||||||||||||
Comment on lines
+166
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for loadMore calls. The scroll control logic should handle potential errors when calling loadMore: } else if (tabs.value === 'activities') {
- activities.value.loadMore();
+ try {
+ activities.value?.loadMore();
+ } catch (error) {
+ console.error('Failed to load more activities:', error);
+ // Consider showing a user-friendly error message
+ } This ensures:
📝 Committable suggestion
Suggested change
|
||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
}; | ||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,21 @@ | ||||||||||||||||||||||
<template> | ||||||||||||||||||||||
<div class="relative overflow-auto" v-bind="$attrs" @scroll="controlScroll"> | ||||||||||||||||||||||
<slot /> | ||||||||||||||||||||||
</div> | ||||||||||||||||||||||
</template> | ||||||||||||||||||||||
|
||||||||||||||||||||||
<script setup lang="ts"> | ||||||||||||||||||||||
const emit = defineEmits<{(e: 'bottom'): void}>(); | ||||||||||||||||||||||
|
||||||||||||||||||||||
const controlScroll = (e: any) => { | ||||||||||||||||||||||
if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) { | ||||||||||||||||||||||
emit('bottom'); | ||||||||||||||||||||||
} | ||||||||||||||||||||||
}; | ||||||||||||||||||||||
</script> | ||||||||||||||||||||||
Comment on lines
+7
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve type safety and scroll handling efficiency. The current implementation has several areas for improvement:
<script setup lang="ts">
-const emit = defineEmits<{(e: 'bottom'): void}>();
+interface Props {
+ threshold?: number;
+ debounceMs?: number;
+}
-const controlScroll = (e: any) => {
- if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) {
- emit('bottom');
- }
+const props = withDefaults(defineProps<Props>(), {
+ threshold: 10,
+ debounceMs: 200
+});
+
+const emit = defineEmits<{(e: 'bottom'): void}>();
+
+const controlScroll = (e: UIEvent) => {
+ const target = e.target as HTMLElement;
+ if (
+ Math.ceil(target.scrollTop + target.clientHeight) >=
+ target.scrollHeight - props.threshold
+ ) {
+ debounce(() => emit('bottom'), props.debounceMs)();
+ }
};
</script> You'll need to import the debounce utility: import { debounce } from 'lodash-es'; |
||||||||||||||||||||||
|
||||||||||||||||||||||
<script lang="ts"> | ||||||||||||||||||||||
export default { | ||||||||||||||||||||||
name: 'LfScrollControll', | ||||||||||||||||||||||
}; | ||||||||||||||||||||||
</script> | ||||||||||||||||||||||
Comment on lines
+17
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fix component naming and modernize component definition.
-<script lang="ts">
-export default {
- name: 'LfScrollControll',
-};
-</script>
+<script setup lang="ts">
+defineOptions({
+ name: 'LfScrollControl'
+}); 📝 Committable suggestion
Suggested change
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling and loading state
The loadMore method should include error handling and loading state management.