Skip to content

Commit

Permalink
Server-side pagination for home page clusters list and side bar clusters
Browse files Browse the repository at this point in the history
- Functional Changes
  - SSP now works after vue3 bump
  - Home Page Clusters list now uses server-side pagination
  - Side Bar clusters list now uses server-side pagination
  - Wire in now supported sorting / filtering by id and name used for table columns
  - Allow pagination to be enabled given a specific context
  - Call findPage without persisting to store

- New Pagination Tools
  - PaginatedResourceTable - Convenience Component, wraps ResourceTable with pagination specific props
  - PaginationWrapper - Convenience class to handle requests for resources and updates to them (avoiding store)

- Regressions
  - Side Nav menu ready state was `mgmtCluster.isReady && !pCluster?.hasError`, now ???
  • Loading branch information
richard-cox committed Nov 14, 2024
1 parent 267a31e commit 634996e
Show file tree
Hide file tree
Showing 21 changed files with 1,338 additions and 334 deletions.
125 changes: 125 additions & 0 deletions shell/components/PaginatedResourceTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<script lang="ts">
import { defineComponent } from 'vue';
import ResourceFetch from '@shell/mixins/resource-fetch';
import ResourceTable from '@shell/components/ResourceTable.vue';
import { StorePaginationResult } from 'types/store/pagination.types';
export type FetchSecondaryResourcesOpts = { }
export type FetchSecondaryResources = (opts: FetchSecondaryResourcesOpts) => Promise<any>
export type FetchPageSecondaryResourcesOpts = { canPaginate: boolean, force: boolean, page: any[], pagResult: StorePaginationResult }
export type FetchPageSecondaryResources = (opts: FetchPageSecondaryResourcesOpts) => Promise<any>
/**
* This is meant to enable ResourceList like capabilities outside of List pages / components
*
* Specifically
* - Resource Fetch features, including server-side pagination
* - Some plumbing
*
* This avoids polluting the owning component with mixins
*
*/
export default defineComponent({
name: 'PaginatedResourceTable',
components: { ResourceTable },
mixins: [ResourceFetch],
props: {
schema: {
type: Object,
required: true,
},
headers: {
type: Array,
default: null,
},
paginationHeaders: {
type: Array,
default: null,
},
namespaced: {
type: Boolean,
default: null, // Automatic from schema
},
/**
* Information may be required from resources other than the primary one shown per row
*
* This will fetch them ALL and will be run in a non-server-side pagination world
*/
fetchSecondaryResources: {
type: Function,
default: null,
},
/**
* Information may be required from resources other than the primary one shown per row
*
* This will fetch only those relevent to the current page using server-side pagination based filters
*
* called from shell/mixins/resource-fetch-api-pagination.js
*/
fetchPageSecondaryResources: {
type: Function,
default: null,
}
},
data() {
return { resource: this.schema.id };
},
async fetch() {
await this.$fetchType(this.resource, [], this.inStore);
if (this.canPaginate && this.fetchSecondaryResources) {
await this.fetchSecondaryResources({ });
}
},
computed: {
safeHeaders() {
const customHeaders = this.canPaginate ? this.paginationHeaders : this.headers;
return customHeaders || this.$store.getters['type-map/headersFor'](this.schema, this.canPaginate);
}
}
});
</script>

<template>
<div>
<ResourceTable
v-bind="$attrs"
:schema="schema"
:rows="rows"
:alt-loading="canPaginate"
:loading="loading"

:headers="safeHeaders"
:namespaced="namespaced"

:external-pagination-enabled="canPaginate"
:external-pagination-result="paginationResult"
@pagination-changed="paginationChanged"
>
<!-- Pass down templates provided by the caller -->
<template
v-for="(_, slot) of $slots"
v-slot:[slot]="scope"
>
<slot
:name="slot"
v-bind="scope"
/>
</template>
</ResourceTable>
</div>
</template>
20 changes: 12 additions & 8 deletions shell/components/SortableTable/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,13 @@ export default {
externalPaginationResult: {
type: Object,
default: null
},
manualRefreshButtonSize: {
type: String,
default: ''
}
},
data() {
Expand Down Expand Up @@ -571,9 +577,9 @@ export default {
showHeaderRow() {
return this.search ||
this.tableActions ||
this.$slots['header-left']?.() ||
this.$slots['header-middle']?.() ||
this.$slots['header-right']?.();
this.$slots['header-left'] ||
this.$slots['header-middle'] ||
this.$slots['header-right'];
},
columns() {
Expand Down Expand Up @@ -1109,13 +1115,15 @@ export default {
</template>
</slot>
</div>
<!-- v-if="!hasAdvancedFiltering && $slots['header-middle']" TODO: RC -->
<div
v-if="!hasAdvancedFiltering && $slots['header-middle']"
class="middle"
>
<slot name="header-middle" />
</div>
<!-- v-if="search || hasAdvancedFiltering || isTooManyItemsToAutoUpdate || $slots['header-right']" TODO: RC -->
<div
v-if="search || hasAdvancedFiltering || isTooManyItemsToAutoUpdate || $slots['header-right']"
class="search row"
Expand All @@ -1140,8 +1148,8 @@ export default {
<slot name="header-right" />
<AsyncButton
v-if="isTooManyItemsToAutoUpdate"
class="manual-refresh"
mode="manual-refresh"
:size="manualRefreshButtonSize"
:current-phase="refreshButtonPhase"
@click="debouncedRefreshTableData"
/>
Expand Down Expand Up @@ -1568,10 +1576,6 @@ export default {
opacity: 0.5;
pointer-events: none;
}
.manual-refresh {
height: 40px;
}
.advanced-filter-group {
position: relative;
margin-left: 10px;
Expand Down
4 changes: 2 additions & 2 deletions shell/components/form/ResourceLabeledSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ export enum RESOURCE_LABEL_SELECT_MODE {
}
/**
* Convience wrapper around the LabelSelect component to support pagination
* Convenience wrapper around the LabelSelect component to support pagination
*
* Handles
*
* 1) Conditionally enabling the pagination feature given system settings
* 2) Helper function to fetch the pagination result
*
* A number of ways can be provided to override the convienences (see props)
* A number of ways can be provided to override the conveniences (see props)
*/
export default defineComponent({
name: 'ResourceLabeledSelect',
Expand Down
Loading

0 comments on commit 634996e

Please sign in to comment.