Skip to content
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

[full-ci] refactor pagination into composable, cleanup store, views and tests #6065

Merged
merged 4 commits into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 15 additions & 36 deletions packages/web-app-files/src/components/AppBar/ViewOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
</li>
<li class="files-view-options-list-item">
<oc-page-size
v-model="itemsPerPageModel"
v-model="itemsPerPage"
data-testid="files-pagination-size"
:label="$gettext('Items per page')"
:options="[100, 500, 1000, $gettext('All')]"
Expand All @@ -53,12 +53,24 @@

<script>
import { mapMutations, mapState, mapActions } from 'vuex'
import { watch } from '@vue/composition-api'
import { useRouteQuery, useDefaults } from '../../composables'

export default {
setup() {
const { pagination: paginationDefaults } = useDefaults()
const itemsPerPage = useRouteQuery('items-per-page', paginationDefaults.perPage.value)
watch(itemsPerPage, (v) => {
paginationDefaults.perPage.value = v
})

return {
itemsPerPage
}
},
computed: {
...mapState('Files', ['areHiddenFilesShown']),
...mapState('Files/sidebar', { sidebarClosed: 'closed' }),
...mapState('Files/pagination', ['itemsPerPage']),

viewOptionsButtonLabel() {
return this.$gettext('Display customization options of the files list')
Expand All @@ -81,44 +93,11 @@ export default {
set(value) {
this.SET_HIDDEN_FILES_VISIBILITY(value)
}
},

itemsPerPageModel: {
get() {
return this.itemsPerPage
},

set(value) {
this.updateQuery(value)
}
}
},

watch: {
$route: {
handler(route) {
if (Object.prototype.hasOwnProperty.call(route.query, 'items-per-page')) {
this.SET_ITEMS_PER_PAGE(route.query['items-per-page'])

return
}

this.updateQuery()
},
immediate: true
}
},
methods: {
...mapMutations('Files', ['SET_HIDDEN_FILES_VISIBILITY']),
...mapActions('Files/sidebar', { toggleSidebar: 'toggle' }),
...mapMutations('Files/pagination', ['SET_ITEMS_PER_PAGE']),

updateQuery(limit = this.itemsPerPageModel) {
const query = { ...this.$route.query, 'items-per-page': limit }

this.SET_ITEMS_PER_PAGE(limit)
this.$router.replace({ query }).catch(() => {})
}
...mapActions('Files/sidebar', { toggleSidebar: 'toggle' })
}
}
</script>
Expand Down
14 changes: 9 additions & 5 deletions packages/web-app-files/src/components/FilesList/Pagination.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
</template>

<script>
import { mapState, mapGetters } from 'vuex'

export default {
computed: {
...mapState('Files/pagination', ['currentPage']),
...mapGetters('Files/pagination', ['pages'])
props: {
pages: {
type: Number,
required: true
},
currentPage: {
type: Number,
required: true
}
}
}
</script>
46 changes: 28 additions & 18 deletions packages/web-app-files/src/components/Search/List.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="files-search-result">
<no-content-message v-if="!activeFilesCurrentPage.length" class="files-empty" icon="folder">
<no-content-message v-if="!paginatedResources.length" class="files-empty" icon="folder">
<template #message>
<p class="oc-text-muted">
<span v-if="!!$route.query.term" v-translate>No resource found</span>
Expand All @@ -12,7 +12,7 @@
v-else
class="files-table"
:class="{ 'files-table-squashed': false }"
:resources="activeFilesCurrentPage"
:resources="paginatedResources"
:target-route="{ name: 'files-personal' }"
:are-paths-displayed="true"
:are-thumbnails-displayed="displayThumbnails"
Expand All @@ -22,9 +22,9 @@
@rowMounted="rowMounted"
>
<template #footer>
<pagination />
<pagination :pages="paginationPages" :current-page="paginationPage" />
<list-info
v-if="activeFilesCurrentPage.length > 0"
v-if="paginatedResources.length > 0"
class="uk-width-1-1 oc-my-s"
:files="totalFilesCount.files"
:folders="totalFilesCount.folders"
Expand All @@ -36,28 +36,24 @@
</template>

<script>
import { useStore, useRouteQuery, usePagination, useDefaults } from '../../composables'
import { VisibilityObserver } from 'web-pkg/src/observer'
import { ImageType, ImageDimension } from '../../constants'
import NoContentMessage from '../FilesList/NoContentMessage.vue'
import Pagination from '../../components/FilesList/Pagination.vue'
import debounce from 'lodash-es/debounce'
import { mapMutations, mapGetters, mapActions } from 'vuex'
import { computed } from '@vue/composition-api'
import ListInfo from '../FilesList/ListInfo.vue'
import Pagination from '../FilesList/Pagination.vue'
import MixinFileActions from '../../mixins/fileActions'
import MixinFilesListFilter from '../../mixins/filesListFilter'
import MixinFilesListScrolling from '../../mixins/filesListScrolling'
import MixinFilesListPagination from '../../mixins/filesListPagination'

const visibilityObserver = new VisibilityObserver()

export default {
components: { ListInfo, NoContentMessage, Pagination },
mixins: [
MixinFileActions,
MixinFilesListFilter,
MixinFilesListScrolling,
MixinFilesListPagination
],
components: { ListInfo, Pagination, NoContentMessage },
mixins: [MixinFileActions, MixinFilesListFilter, MixinFilesListScrolling],
props: {
searchResults: {
type: Array,
Expand All @@ -66,18 +62,32 @@ export default {
}
}
},
setup() {
const store = useStore()
const { pagination: paginationDefaults } = useDefaults()
const paginationPageQuery = useRouteQuery('page', '1')
const paginationPage = computed(() => parseInt(String(paginationPageQuery.value)))
const paginationPerPageQuery = useRouteQuery('items-per-page', paginationDefaults.perPage.value)
const { items: paginatedResources, total: paginationPages } = usePagination({
page: paginationPage,
perPage: computed(() => parseInt(String(paginationPerPageQuery.value))),
items: computed(() => store.getters['Files/activeFiles'])
})

return {
paginatedResources,
paginationPages,
paginationPage
}
},
computed: {
...mapGetters(['configuration']),
...mapGetters('Files', ['activeFilesCurrentPage', 'totalFilesCount', 'totalFilesSize']),
...mapGetters('Files', ['totalFilesCount', 'totalFilesSize']),
displayThumbnails() {
return !this.configuration.options.disablePreviews
}
},
watch: {
$route: {
handler: '$_filesListPagination_updateCurrentPage',
immediate: true
},
searchResults: {
handler: function () {
this.CLEAR_CURRENT_FILES_LIST()
Expand Down
5 changes: 4 additions & 1 deletion packages/web-app-files/src/composables/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export * from './useFileListHeaderPosition'
export * from './router'
export * from './store'
export * from './useDefaults'
export * from './useFileListHeaderPosition'
export * from './usePagination'

declare module 'vue/types/vue' {
interface Vue {
Expand Down
2 changes: 2 additions & 0 deletions packages/web-app-files/src/composables/router/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './useRouteQuery'
export * from './useRouter'
25 changes: 25 additions & 0 deletions packages/web-app-files/src/composables/router/useRouteQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { customRef, Ref } from '@vue/composition-api'
import { useRouter } from './useRouter'

type QueryValue = string | (string | null)[]

export const useRouteQuery = (name: string, defaultValue?: QueryValue): Ref<QueryValue> => {
const router = useRouter()

return customRef<QueryValue>((track, trigger) => {
router.afterEach((to, from) => to.query[name] !== from.query[name] && trigger())

return {
get() {
track()
return router.currentRoute.query[name] || defaultValue
},
async set(v) {
await router.replace({
query: { [name]: v }
})
trigger()
}
}
})
}
6 changes: 6 additions & 0 deletions packages/web-app-files/src/composables/router/useRouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { getCurrentInstance } from '@vue/composition-api'
import VueRouter from 'vue-router'

export const useRouter = (): VueRouter => {
return getCurrentInstance().proxy.$router
}
4 changes: 2 additions & 2 deletions packages/web-app-files/src/composables/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './mutationSubscription'
export * from './store'
export * from './useMutationSubscription'
export * from './useStore'
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { onMounted, onBeforeUnmount } from '@vue/composition-api'
import { MutationPayload, SubscribeOptions } from 'vuex'
import { useStore } from './store'
import { useStore } from './useStore'

export const useMutationSubscription = <P extends MutationPayload>(
mutations: string[],
Expand Down
38 changes: 38 additions & 0 deletions packages/web-app-files/src/composables/useDefaults/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { customRef, Ref } from '@vue/composition-api'

interface Defaults {
pagination: {
perPage: Ref
}
}

let defaults: Defaults

/**
* interim solution till options // configuration api is in place
*/
export const useDefaults = (): Defaults => {
if (defaults) {
return defaults
}

defaults = {
pagination: {
perPage: customRef<string>((track, trigger) => {
const defaultValue = '100'
return {
get() {
track()
return window.localStorage.getItem('oc_filesPageLimit') || defaultValue
},
set(v) {
window.localStorage.setItem('oc_filesPageLimit', v)
trigger()
}
}
})
}
}

return defaults
}
34 changes: 34 additions & 0 deletions packages/web-app-files/src/composables/usePagination/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ref, computed, ComputedRef, unref } from '@vue/composition-api'
import { MaybeRef } from '../utils'

interface PaginationOptions<T> {
page: MaybeRef<number>
perPage: MaybeRef<number>
items: MaybeRef<Array<T>>
}

interface PaginationResult<T> {
items: ComputedRef<Array<T>>
total: ComputedRef<number>
}

export function usePagination<T>(options: PaginationOptions<T>): PaginationResult<T> {
const page = ref(options.page)
const perPage = ref(options.perPage)
const total = computed(() => Math.ceil(unref(options.items).length / perPage.value) || 1)
const items = computed(() => {
if (!perPage.value) {
return unref(options.items)
}

const start = (page.value - 1) * perPage.value
const end = start + perPage.value

return unref(options.items).slice(start, end)
})

return {
items,
total
}
}
1 change: 1 addition & 0 deletions packages/web-app-files/src/composables/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './types'
3 changes: 3 additions & 0 deletions packages/web-app-files/src/composables/utils/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Ref } from '@vue/composition-api'

export type MaybeRef<T> = T | Ref<T>
4 changes: 2 additions & 2 deletions packages/web-app-files/src/mixins/actions/emptyTrashBin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { mapActions, mapGetters } from 'vuex'

export default {
computed: {
...mapGetters('Files', ['activeFilesCurrentPage']),
...mapGetters('Files', ['activeFiles']),
$_emptyTrashBin_items() {
return [
{
Expand All @@ -18,7 +18,7 @@ export default {
// empty trash bin is not available for individual resources, but only for the trash bin as a whole
return resources.length === 0
},
isDisabled: () => this.activeFilesCurrentPage.length === 0,
isDisabled: () => this.activeFiles.length === 0,
componentType: 'oc-button',
class: 'oc-files-actions-empty-trash-bin-trigger',
variation: 'danger'
Expand Down
20 changes: 1 addition & 19 deletions packages/web-app-files/src/mixins/filesListFilter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Registry } from '../services'
import { mapMutations, mapGetters } from 'vuex'
import { mapMutations } from 'vuex'

export default {
mounted() {
Expand Down Expand Up @@ -39,27 +39,9 @@ export default {
this.CLEAR_FILES_SEARCHED()
},
immediate: true
},
pages() {
if (!this.$route.query.page) {
return
}

if (this.$route.query.page <= this.pages) {
return
}

this.$router.push({
name: this.$route.name,
query: { ...this.$route.query, page: this.pages },
params: this.$route.params
})
}
},
methods: {
...mapMutations('Files', ['CLEAR_FILES_SEARCHED', 'LOAD_FILES_SEARCHED'])
},
computed: {
...mapGetters('Files/pagination', ['pages'])
}
}
Loading