Merge pull request #28 from tainacan/infinite_scroll_on_collections_list

Infinite scroll on collections list #10.
This commit is contained in:
Mateus Machado Luna 2022-06-22 15:09:22 -03:00 committed by GitHub
commit 973bccbbfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 20199 additions and 84 deletions

20151
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@
"@vue/cli-plugin-router": "^5.0.4", "@vue/cli-plugin-router": "^5.0.4",
"@vue/cli-plugin-typescript": "^5.0.4", "@vue/cli-plugin-typescript": "^5.0.4",
"@vue/cli-plugin-unit-jest": "^5.0.4", "@vue/cli-plugin-unit-jest": "^5.0.4",
"@vue/cli-service": "^5.0.4", "@vue/cli-service": "5.0.4",
"@vue/eslint-config-typescript": "^9.1.0", "@vue/eslint-config-typescript": "^9.1.0",
"@vue/test-utils": "^2.0.0", "@vue/test-utils": "^2.0.0",
"@vue/vue3-jest": "^27.0.0", "@vue/vue3-jest": "^27.0.0",

View File

@ -11,6 +11,10 @@
> >
</ion-loading> </ion-loading>
<items-list :items="tainacanStore.collectionItems"></items-list> <items-list :items="tainacanStore.collectionItems"></items-list>
<ion-infinite-scroll ref="infiniteScroll" threshold="5%" @ionInfinite="loadItemsByCollection">
<ion-infinite-scroll-content>
</ion-infinite-scroll-content>
</ion-infinite-scroll>
<ion-button <ion-button
class="add-items-button" class="add-items-button"
color="primary" color="primary"
@ -27,19 +31,17 @@ import {
} from '../store/storeTainacan'; } from '../store/storeTainacan';
import { ref, defineComponent } from 'vue'; import { ref, defineComponent } from 'vue';
import { add, documentOutline, documentAttachOutline, documentsOutline } from "ionicons/icons"; import { add, documentOutline, documentAttachOutline, documentsOutline } from "ionicons/icons";
import { import {
IonLoading, IonLoading,
IonRefresher, IonRefresher,
IonRefresherContent, IonRefresherContent,
IonIcon, IonIcon,
IonButton, IonButton,
actionSheetController actionSheetController,
IonInfiniteScroll
} from '@ionic/vue'; } from '@ionic/vue';
import BaseLayout from '@/components/base/BaseLayout.vue'; import BaseLayout from '@/components/base/BaseLayout.vue';
import ItemsList from '@/components/lists/ItemsList.vue'; import ItemsList from '@/components/lists/ItemsList.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
BaseLayout, BaseLayout,
@ -48,7 +50,8 @@ export default defineComponent({
IonRefresher, IonRefresher,
IonRefresherContent, IonRefresherContent,
IonIcon, IonIcon,
IonButton IonButton,
IonInfiniteScroll
}, },
props: { props: {
id: String, id: String,
@ -56,14 +59,22 @@ export default defineComponent({
}, },
setup(props) { setup(props) {
const isLoading = ref(false); const isLoading = ref(false);
const infiniteScroll = ref();
const setIsLoading = (state: boolean) => isLoading.value = state; const setIsLoading = (state: boolean) => isLoading.value = state;
const loadItemsByCollection = async () => { const loadItemsByCollection = async (event: any, reset: boolean) => {
await tainacanStore.fetchItemsByCollection(props.id + '', { perPage: '24', orderBy: 'modified'}); let hasMoreCollections = await tainacanStore.fetchItemsByCollection(props.id + '', { perPage: '12', orderBy: 'modified', reset: reset});
}
const doRefresh = async (event: any) => {
await loadItemsByCollection();
if (event && event.target) if (event && event.target)
event.target.complete(); event.target.complete();
if (!hasMoreCollections){
infiniteScroll.value.$el.disabled = true;
}
}
const doRefresh = async (event: any) => {
await loadItemsByCollection({}, true);
if (event && event.target){
event.target.complete();
infiniteScroll.value.$el.disabled = false;
}
} }
const actionSheetLabels = ref({ const actionSheetLabels = ref({
header: '', header: '',
@ -109,15 +120,12 @@ export default defineComponent({
], ],
}); });
await actionSheet.present(); await actionSheet.present();
const { role, data } = await actionSheet.onDidDismiss(); const { role, data } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role and data', role, data); console.log('onDidDismiss resolved with role and data', role, data);
} }
const collectionObject = props.collection ? JSON.parse(props.collection + '') : false; const collectionObject = props.collection ? JSON.parse(props.collection + '') : false;
let tainacanStore = useTainacanStore(); let tainacanStore = useTainacanStore();
return { return {
isLoading, isLoading,
tainacanStore, tainacanStore,
@ -128,7 +136,8 @@ export default defineComponent({
add, add,
actionSheetLabels, actionSheetLabels,
setActionSheetLabels, setActionSheetLabels,
collectionObject collectionObject,
infiniteScroll
} }
}, },
async created() { async created() {
@ -140,9 +149,8 @@ export default defineComponent({
button3: this.$t('label_option_single_item'), button3: this.$t('label_option_single_item'),
cancel: this.$t('label_cancel') cancel: this.$t('label_cancel')
}); });
this.setIsLoading(true); this.setIsLoading(true);
await this.loadItemsByCollection(); await this.loadItemsByCollection({}, true);
this.setIsLoading(false); this.setIsLoading(false);
}, },
}); });

View File

@ -9,6 +9,10 @@
<ion-refresher-content></ion-refresher-content> <ion-refresher-content></ion-refresher-content>
</ion-refresher> </ion-refresher>
<items-list :items="tainacanStore.items"></items-list> <items-list :items="tainacanStore.items"></items-list>
<ion-infinite-scroll ref="infiniteScroll" threshold="5%" @ionInfinite="loadItems">
<ion-infinite-scroll-content>
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</base-layout> </base-layout>
</template> </template>
@ -19,44 +23,50 @@ import {
import { import {
IonLoading, IonLoading,
IonRefresher, IonRefresher,
IonRefresherContent IonRefresherContent,
IonInfiniteScroll
} from '@ionic/vue'; } from '@ionic/vue';
import BaseLayout from '@/components/base/BaseLayout.vue'; import BaseLayout from '@/components/base/BaseLayout.vue';
import { ref } from 'vue'; import { ref } from 'vue';
import ItemsList from '../components/lists/ItemsList.vue'; import ItemsList from '../components/lists/ItemsList.vue';
export default { export default {
components: { components: {
IonLoading, IonLoading,
ItemsList, ItemsList,
BaseLayout, BaseLayout,
IonRefresher, IonRefresher,
IonRefresherContent IonRefresherContent,
IonInfiniteScroll
}, },
setup() { setup() {
const isLoading = ref(false); const isLoading = ref(false);
const setIsLoading = (state: boolean) => isLoading.value = state; const setIsLoading = (state: boolean) => isLoading.value = state;
const infiniteScroll = ref();
const loadItems = async () => { const loadItems = async (event: any, reset: boolean) => {
await tainacanStore.fetchItems({ perPage: '24', orderBy: 'modified'}); let hasMoreItems = await tainacanStore.fetchItems({ perPage: '12', orderBy: 'modified', reset: reset});
}
const doRefresh = async (event: any) => {
await loadItems();
if (event && event.target) if (event && event.target)
event.target.complete(); event.target.complete();
if (!hasMoreItems){
infiniteScroll.value.$el.disabled = true;
}
}
const doRefresh = async (event: any) => {
await loadItems({}, true);
if (event && event.target){
event.target.complete();
infiniteScroll.value.$el.disabled = false;
}
} }
let tainacanStore = useTainacanStore(); let tainacanStore = useTainacanStore();
return { return {
isLoading, isLoading,
setIsLoading, setIsLoading,
tainacanStore, tainacanStore,
doRefresh, doRefresh,
loadItems loadItems,
infiniteScroll
} }
}, },
async created(){ async created(){
this.setIsLoading(true) this.setIsLoading(true)
await this.loadItems(); await this.loadItems();

View File

@ -1,5 +1,5 @@
import { defineStore } from "pinia";
import axios from "axios"; import axios from "axios";
import { defineStore } from "pinia";
import { useWpStore } from "./storeWp"; import { useWpStore } from "./storeWp";
const useTainacanStore = defineStore("tainacan", { const useTainacanStore = defineStore("tainacan", {
@ -13,7 +13,9 @@ const useTainacanStore = defineStore("tainacan", {
totalCollections: 0, totalCollections: 0,
collectionItems: [], collectionItems: [],
totalCollectionItems: 0, totalCollectionItems: 0,
nextItemsByCollectionPage: 1,
items: [], items: [],
nextItemsPage: 1,
totalItems: 0, totalItems: 0,
siteUrl: "", siteUrl: "",
userLogin: "", userLogin: "",
@ -68,30 +70,48 @@ const useTainacanStore = defineStore("tainacan", {
} }
}, },
async fetchItemsByCollection(collectionId: string, params: { perPage: string, orderBy: string }) { async fetchItemsByCollection(collectionId: string, params: { perPage: string, orderBy: string, reset: boolean }) {
try { try {
const wpStore = useWpStore(); const wpStore = useWpStore();
this.collectionItems = [];
let endpoint = `${wpStore.userSiteUrl}/wp-json/tainacan/v2/collection/${collectionId}/items?fetch_only=id,title,thumbnail&perpage=12&orderby=modified`; let endpoint = `${wpStore.userSiteUrl}/wp-json/tainacan/v2/collection/${collectionId}/items?fetch_only=id,title,thumbnail`;
if (params && params.perPage) if (params && params.perPage)
endpoint += '&perpage=' + params.perPage; endpoint += '&perpage=' + params.perPage;
else
endpoint += '&perpage=12';
if (params && params.orderBy) if (params && params.orderBy)
endpoint += '&orderby=' + params.orderBy; endpoint += '&orderby=' + params.orderBy;
else
endpoint += '&orderby=modified';
if (params.reset) {
this.collectionItems = [];
this.nextItemsByCollectionPage = 1;
}
endpoint += '&paged=' + this.nextItemsByCollectionPage;
const response = await axios.get(endpoint); const response = await axios.get(endpoint);
this.collectionItems = response.data.items; this.collectionItems.push(...response.data.items);
this.totalCollectionItems = response.headers['x-wp-total']; this.totalCollectionItems = response.headers['x-wp-total'];
if (!this.totalCollectionItems ||
this.totalCollectionItems === "0") {
return false;
} else {
this.nextItemsByCollectionPage++;
return true;
}
} catch (err) { } catch (err) {
this.collectionItems = []; this.collectionItems = [];
this.totalCollectionItems = 0; this.totalCollectionItems = 0;
this.nextItemsByCollectionPage = 1;
console.error("Erro no carregamento dos items da coleção:", err); console.error("Erro no carregamento dos items da coleção:", err);
return err; return false;
} }
}, },
@ -113,7 +133,7 @@ const useTainacanStore = defineStore("tainacan", {
} }
}, },
async fetchItems(params: { perPage: string, orderBy: string }) { async fetchItems(params: { perPage: string, orderBy: string, reset: boolean }) {
try { try {
const wpStore = useWpStore(); const wpStore = useWpStore();
@ -125,13 +145,29 @@ const useTainacanStore = defineStore("tainacan", {
if (params && params.orderBy) if (params && params.orderBy)
endpoint += '&orderby=' + params.orderBy; endpoint += '&orderby=' + params.orderBy;
if(params.reset){
this.items = [];
this.nextItemsPage = 1;
}
endpoint += '&paged=' + this.nextItemsPage;
const response = await axios.get(endpoint); const response = await axios.get(endpoint);
this.items = response.data.items; this.items.push(...response.data.items);
this.totalItems = response.headers['x-wp-total']; this.totalItems = response.headers['x-wp-total'];
if (!this.totalItems ||
this.totalItems === "0") {
return false;
} else {
this.nextItemsPage++;
return true;
}
} catch (err) { } catch (err) {
this.items = []; this.items = [];
this.totalItems = 0; this.totalItems = 0;
this.nextItemsPage = 1;
console.error("Erro no carregamento dos items:", err); console.error("Erro no carregamento dos items:", err);
return err; return err;
} }