diff --git a/packages/pluggableWidgets/gallery-web/CHANGELOG.md b/packages/pluggableWidgets/gallery-web/CHANGELOG.md index 6c1b7c3507..189ecea06d 100644 --- a/packages/pluggableWidgets/gallery-web/CHANGELOG.md +++ b/packages/pluggableWidgets/gallery-web/CHANGELOG.md @@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - We added configurable selection count visibility and clear selection button label template for improved row selection management. +- We added a refresh intervel property, to allow defining an interval (in seconds) for refreshing the content in Gallery + ### Fixed - We fixed an issue where setting the gallery gap to 0 caused an offset, which made the bottom border of items to dissapear. diff --git a/packages/pluggableWidgets/gallery-web/src/Gallery.xml b/packages/pluggableWidgets/gallery-web/src/Gallery.xml index 72e82eb550..a1a0bbae33 100644 --- a/packages/pluggableWidgets/gallery-web/src/Gallery.xml +++ b/packages/pluggableWidgets/gallery-web/src/Gallery.xml @@ -16,6 +16,10 @@ Data source + + Refresh time (in seconds) + + Selection diff --git a/packages/pluggableWidgets/gallery-web/src/controllers/DerivedLoaderController.ts b/packages/pluggableWidgets/gallery-web/src/controllers/DerivedLoaderController.ts index 1b66d88001..e43f422f80 100644 --- a/packages/pluggableWidgets/gallery-web/src/controllers/DerivedLoaderController.ts +++ b/packages/pluggableWidgets/gallery-web/src/controllers/DerivedLoaderController.ts @@ -1,23 +1,50 @@ -import { DatasourceController } from "@mendix/widget-plugin-grid/query/DatasourceController"; import { computed, makeObservable } from "mobx"; +type DerivedLoaderControllerSpec = { + showSilentRefresh: boolean; + refreshIndicator: boolean; + query: { + isFetchingNextBatch: boolean; + isFirstLoad: boolean; + isRefreshing: boolean; + isSilentRefresh: boolean; + }; +}; + export class DerivedLoaderController { - constructor( - private datasourceController: DatasourceController, - private refreshIndicator: boolean - ) { + constructor(private spec: DerivedLoaderControllerSpec) { makeObservable(this, { - isRefreshing: computed, - showRefreshIndicator: computed + isFirstLoad: computed, + isFetchingNextBatch: computed, + isRefreshing: computed }); } + get isFirstLoad(): boolean { + const { query } = this.spec; + + return query.isFirstLoad; + } + + get isFetchingNextBatch(): boolean { + return this.spec.query.isFetchingNextBatch; + } + get isRefreshing(): boolean { - const { isSilentRefresh, isRefreshing } = this.datasourceController; + const { isSilentRefresh, isRefreshing } = this.spec.query; + + if (this.spec.showSilentRefresh) { + return isSilentRefresh || isRefreshing; + } + return !isSilentRefresh && isRefreshing; } get showRefreshIndicator(): boolean { - return this.refreshIndicator && this.isRefreshing; + if (!this.spec.refreshIndicator) { + return false; + } + + return this.isRefreshing; } } diff --git a/packages/pluggableWidgets/gallery-web/src/stores/GalleryStore.ts b/packages/pluggableWidgets/gallery-web/src/stores/GalleryStore.ts index 4c45d00ca0..8024dea4fd 100644 --- a/packages/pluggableWidgets/gallery-web/src/stores/GalleryStore.ts +++ b/packages/pluggableWidgets/gallery-web/src/stores/GalleryStore.ts @@ -37,6 +37,7 @@ interface StaticProps { storeFilters: boolean; storeSort: boolean; refreshIndicator: boolean; + refreshInterval: number; } export type GalleryPropsGate = DerivedPropsGate; @@ -99,10 +100,14 @@ export class GalleryStore extends BaseControllerHost { host: this._sortHost }; - this.loaderCtrl = new DerivedLoaderController(this._query, spec.refreshIndicator); + this.loaderCtrl = new DerivedLoaderController({ + showSilentRefresh: spec.refreshInterval > 1, + refreshIndicator: spec.refreshIndicator, + query: this._query + }); new RefreshController(this, { - delay: 0, + delay: spec.refreshInterval * 1000, query: this._query.derivedQuery }); diff --git a/packages/pluggableWidgets/gallery-web/src/utils/test-utils.tsx b/packages/pluggableWidgets/gallery-web/src/utils/test-utils.tsx index 4fc8a0b41b..0d5ac84aa3 100644 --- a/packages/pluggableWidgets/gallery-web/src/utils/test-utils.tsx +++ b/packages/pluggableWidgets/gallery-web/src/utils/test-utils.tsx @@ -58,7 +58,8 @@ export function createMockGalleryContext(): GalleryRootScope { storeSort: false, refreshIndicator: false, keepSelection: false, - selectionCountPosition: "bottom" + selectionCountPosition: "bottom", + refreshInterval: 0 }; // Create a proper gate provider and gate @@ -76,7 +77,8 @@ export function createMockGalleryContext(): GalleryRootScope { stateStorageType: "localStorage", storeFilters: false, storeSort: false, - refreshIndicator: false + refreshIndicator: false, + refreshInterval: 0 }); const mockSelectHelper = new SelectActionHandler("None", undefined); diff --git a/packages/pluggableWidgets/gallery-web/typings/GalleryProps.d.ts b/packages/pluggableWidgets/gallery-web/typings/GalleryProps.d.ts index b0cfa98317..8f5b2b1f24 100644 --- a/packages/pluggableWidgets/gallery-web/typings/GalleryProps.d.ts +++ b/packages/pluggableWidgets/gallery-web/typings/GalleryProps.d.ts @@ -29,6 +29,7 @@ export interface GalleryContainerProps { tabIndex?: number; filtersPlaceholder?: ReactNode; datasource: ListValue; + refreshInterval: number; itemSelection?: SelectionSingleValue | SelectionMultiValue; itemSelectionMode: ItemSelectionModeEnum; keepSelection: boolean; @@ -76,6 +77,7 @@ export interface GalleryPreviewProps { translate: (text: string) => string; filtersPlaceholder: { widgetCount: number; renderer: ComponentType<{ children: ReactNode; caption?: string }> }; datasource: {} | { caption: string } | { type: string } | null; + refreshInterval: number | null; itemSelection: "None" | "Single" | "Multi"; itemSelectionMode: ItemSelectionModeEnum; keepSelection: boolean;