From 5cdea82fb074229c313d039337c1783d4a1a0370 Mon Sep 17 00:00:00 2001 From: Nicholas Ruffing Date: Tue, 7 Nov 2023 22:43:09 -0500 Subject: [PATCH] documentation improvements --- README.md | 6 +- lib/DataGridVue.ts | 37 ++ lib/DataService.ts | 106 +++- lib/Sort.ts | 29 ++ lib/components/ColumnSelectionItem.vue | 9 +- lib/components/DataGridVue.vue | 136 ++++- lib/components/FilterOperatorSelect.vue | 24 +- lib/components/HeaderCell.vue | 19 +- lib/components/HeaderFilter.vue | 12 +- lib/components/PageNavigation.vue | 17 +- package-lock.json | 122 +---- package.json | 3 +- typedoc-vue.ts | 3 +- typedoc.json | 7 +- .../generated/ColumnSelectionItem/README.md | 42 ++ .../docs/generated/DataGridVueGrid/README.md | 490 ++++++++++++++++++ .../generated/FilterOperatorSelect/README.md | 76 +++ vuepress/docs/generated/HeaderCell/README.md | 99 ++++ .../docs/generated/HeaderFilter/README.md | 68 +++ vuepress/docs/generated/Icon/README.md | 49 ++ .../docs/generated/PageNavigation/README.md | 84 +++ vuepress/docs/generated/README.md | 266 ++-------- .../classes/ClientSideDataService.md | 131 +++-- vuepress/docs/generated/classes/Field.md | 53 +- .../generated/classes/LocalStorageService.md | 66 +-- .../classes/ServerSideDataService.md | 71 ++- .../classes/ServerSideStorageService.md | 66 +-- .../classes/SessionStorageService.md | 66 +-- .../docs/generated/enumerations/DataType.md | 59 +++ .../generated/enumerations/FilterOperator.md | 90 ++++ .../enumerations/LocalStorageType.md | 27 + .../docs/generated/enumerations/SortType.md | 32 ++ vuepress/docs/generated/enums/DataType.md | 41 -- .../docs/generated/enums/FilterOperator.md | 69 --- .../docs/generated/enums/LocalStorageType.md | 20 - vuepress/docs/generated/enums/SortType.md | 20 - vuepress/docs/generated/interfaces/Column.md | 114 +++- .../interfaces/ColumnFilterOptions.md | 15 +- .../interfaces/DataGridVueOptions.md | 15 +- .../docs/generated/interfaces/DataService.md | 43 +- vuepress/docs/generated/interfaces/Filter.md | 23 +- .../generated/interfaces/FilterCondition.md | 39 +- .../generated/interfaces/FilterOptions.md | 15 +- .../interfaces/GetGridStateRequest.md | 15 +- .../docs/generated/interfaces/GridState.md | 55 +- .../docs/generated/interfaces/PageData.md | 23 +- .../generated/interfaces/PageDataRequest.md | 68 ++- .../ServerSideDataServiceOptions.md | 55 +- .../ServerSideStorageServiceOptions.md | 63 ++- .../interfaces/SetGridStateRequest.md | 23 +- vuepress/docs/generated/interfaces/Sort.md | 50 +- .../docs/generated/interfaces/SortOptions.md | 35 +- .../generated/interfaces/StorageService.md | 39 +- .../generated/modules/ColumnSelectionItem.md | 20 - .../docs/generated/modules/DataGridVueGrid.md | 229 -------- .../generated/modules/FilterOperatorSelect.md | 38 -- vuepress/docs/generated/modules/HeaderCell.md | 50 -- .../docs/generated/modules/HeaderFilter.md | 35 -- vuepress/docs/generated/modules/Icon.md | 35 -- .../docs/generated/modules/PageNavigation.md | 48 -- .../type-aliases/BeforeGetRequestHandler.md | 20 + .../type-aliases/BeforeRequestHandler.md | 28 + .../type-aliases/BeforeSetRequestHandler.md | 20 + .../type-aliases/FieldValueGetter.md | 9 + .../type-aliases/GetResponseHandler.md | 19 + .../generated/type-aliases/ResponseHandler.md | 27 + .../type-aliases/SetResponseHandler.md | 19 + .../generated/variables/ClientSideFilter.md | 27 + .../generated/variables/ClientSideSort.md | 27 + .../docs/generated/variables/DataGridVue.md | 17 + .../docs/generated/variables/EmptyPageData.md | 9 + .../docs/generated/variables/Formatter.md | 19 + .../generated/variables/StubDataService.md | 13 + .../generated/variables/StubStorageService.md | 9 + .../generated/variables/ValidOperatorsMap.md | 9 + vuepress/docs/shared/changelog.md | 6 +- 76 files changed, 2570 insertions(+), 1368 deletions(-) create mode 100644 vuepress/docs/generated/ColumnSelectionItem/README.md create mode 100644 vuepress/docs/generated/DataGridVueGrid/README.md create mode 100644 vuepress/docs/generated/FilterOperatorSelect/README.md create mode 100644 vuepress/docs/generated/HeaderCell/README.md create mode 100644 vuepress/docs/generated/HeaderFilter/README.md create mode 100644 vuepress/docs/generated/Icon/README.md create mode 100644 vuepress/docs/generated/PageNavigation/README.md create mode 100644 vuepress/docs/generated/enumerations/DataType.md create mode 100644 vuepress/docs/generated/enumerations/FilterOperator.md create mode 100644 vuepress/docs/generated/enumerations/LocalStorageType.md create mode 100644 vuepress/docs/generated/enumerations/SortType.md delete mode 100644 vuepress/docs/generated/enums/DataType.md delete mode 100644 vuepress/docs/generated/enums/FilterOperator.md delete mode 100644 vuepress/docs/generated/enums/LocalStorageType.md delete mode 100644 vuepress/docs/generated/enums/SortType.md delete mode 100644 vuepress/docs/generated/modules/ColumnSelectionItem.md delete mode 100644 vuepress/docs/generated/modules/DataGridVueGrid.md delete mode 100644 vuepress/docs/generated/modules/FilterOperatorSelect.md delete mode 100644 vuepress/docs/generated/modules/HeaderCell.md delete mode 100644 vuepress/docs/generated/modules/HeaderFilter.md delete mode 100644 vuepress/docs/generated/modules/Icon.md delete mode 100644 vuepress/docs/generated/modules/PageNavigation.md create mode 100644 vuepress/docs/generated/type-aliases/BeforeGetRequestHandler.md create mode 100644 vuepress/docs/generated/type-aliases/BeforeRequestHandler.md create mode 100644 vuepress/docs/generated/type-aliases/BeforeSetRequestHandler.md create mode 100644 vuepress/docs/generated/type-aliases/FieldValueGetter.md create mode 100644 vuepress/docs/generated/type-aliases/GetResponseHandler.md create mode 100644 vuepress/docs/generated/type-aliases/ResponseHandler.md create mode 100644 vuepress/docs/generated/type-aliases/SetResponseHandler.md create mode 100644 vuepress/docs/generated/variables/ClientSideFilter.md create mode 100644 vuepress/docs/generated/variables/ClientSideSort.md create mode 100644 vuepress/docs/generated/variables/DataGridVue.md create mode 100644 vuepress/docs/generated/variables/EmptyPageData.md create mode 100644 vuepress/docs/generated/variables/Formatter.md create mode 100644 vuepress/docs/generated/variables/StubDataService.md create mode 100644 vuepress/docs/generated/variables/StubStorageService.md create mode 100644 vuepress/docs/generated/variables/ValidOperatorsMap.md diff --git a/README.md b/README.md index 11ab4a6..00a8b64 100644 --- a/README.md +++ b/README.md @@ -122,4 +122,8 @@ Customizable native Vue3 data grid with very limited dependencies. Leverages a f - Add css variable for input/select font size - v2.1.1 - Readme/documentation improvements - - CSS improvements \ No newline at end of file + - CSS improvements +- v2.1.2 + - Fix for sorting and filtering not working when the data grid is not configured to be paged. + - Fix Icon component import in HeaderCell + - Documentation improvements \ No newline at end of file diff --git a/lib/DataGridVue.ts b/lib/DataGridVue.ts index 42bd898..779d60c 100644 --- a/lib/DataGridVue.ts +++ b/lib/DataGridVue.ts @@ -1,5 +1,8 @@ import type { FilterOperator } from './Filter' +/** + * @description Supported data types for a column. + */ export enum DataType { none = 0, alphanumeric = 1, @@ -8,12 +11,46 @@ export enum DataType { dateTime = 4, } +/** + * @description Column definition + */ export interface Column { + /** + * @description The value to display in the columns header. If not specified {@link Field.fieldName} + * is converted to title casing and displayed as the columns header. + */ title?: string + + /** + * @description The {@link DataType} for the column. + */ dataType: DataType + + /** + * @description The data {@link Field} for the column. The {@link Field} describes how to get the column's value + * from the row's data item. + */ field: Field + + /** + * @description Whether to use this columns value as the key for the data item. It is highly recommended to set this + * on a single column. If more then one column is set as the key column only the first one is used. If no columns are + * set as the key column then the first column is used. + */ isKey?: boolean + + /** + * @description Whether the column should be sortable. This value is ignored if {@link DataGridVueGrid.sortOptions} is + * not set to turn on sorting for the grid. Setting this property to false will then not allow this specific column + * to be sorted. + */ sortable?: boolean + + /** + * @description Whether the column should be filterable. If {@link filterOptions} is not specified then the first + * valid {@link FilterOperator} is used for the columns {@link DataType}. Valid filter operators are defined in + * {@link ValidOperatorsMap}. + */ filterable?: boolean filterOptions?: ColumnFilterOptions width?: string diff --git a/lib/DataService.ts b/lib/DataService.ts index 5b8e51b..23a100a 100644 --- a/lib/DataService.ts +++ b/lib/DataService.ts @@ -2,16 +2,37 @@ import { type PageData, EmptyPageData } from './DataGridVue' import { type Sort, ClientSideSort } from './Sort' import { type Filter, ClientSideFilter } from './Filter' +/** + * @description Interface to implement to define a data service to retrieve grid data. + */ export interface DataService { + /** + * Called to get data for the currently rendered page. + * @param pageNum The page number for the page to load starting with `1` for the first page. + * If the data grid is not set configured to be pageable with the {@link DataGridVueGrid.paged} + * prop then this will always be `-1`. + * @param pageSize The maximum number of data items to display on each page. If the data grid is + * not set configured to be pageable with the {@link DataGridVueGrid.paged} prop then this + * will always be `-1`. + * @param sort The current colomn sort definitions in the order in which they should be applied. + * @param filter The current filter definition or undefined if no filter is set. + * @returns A Promise that returns the {@link PageData} for the current page. + */ getPage: (pageNum: number, pageSize: number, sort: Sort[], filter: Filter | undefined) => Promise } +/** + * @description A stub {@link DataService} that will noop the getPage call and return {@link EmptyPageData}. + */ export const StubDataService = { getPage(pageNum: number, pageSize: number, sort: Sort[], filter: Filter | undefined): Promise { return Promise.resolve(EmptyPageData) }, } as DataService +/** + * @description The client-side {@link DataService} used when {@link DataGridVueGrid.data} is specified. + */ export class ClientSideDataService implements DataService { dataItems: any[] previousSortJson: string @@ -66,10 +87,6 @@ export class ClientSideDataService implements DataService { } getPage(pageNum: number, pageSize: number, sort: Sort[], filter: Filter | undefined): Promise { - if (pageNum <= 0 || pageSize <= 0) { - console.error(`ClientSideDataRepository - getPage - invalid params - pageNum: ${pageNum}, pageSize: ${pageSize}`) - return Promise.reject() - } if (!this.dataItems.length) { return Promise.resolve(EmptyPageData) } @@ -77,36 +94,105 @@ export class ClientSideDataService implements DataService { this.filter(filter) this.sort(sort) - const startIndex = pageSize * (pageNum - 1) - const endIndex = startIndex + pageSize + let paged = this.sorted + if (pageNum > 0 && pageSize > 0) { + const startIndex = pageSize * (pageNum - 1) + const endIndex = startIndex + pageSize - if (startIndex >= this.dataItems.length) { - console.warn(`ClientSideDataRepository - getPage - pageNum exceeds data length`) - return Promise.resolve(EmptyPageData) + if (startIndex >= this.dataItems.length) { + console.warn(`ClientSideDataRepository - getPage - pageNum exceeds data length`) + return Promise.resolve(EmptyPageData) + } + + paged = this.sorted.slice(startIndex, endIndex) } return Promise.resolve({ totalItems: this.filtered.length, - dataItems: this.sorted.slice(startIndex, endIndex), + dataItems: paged, }) } } +/** + * @description Request data interface sent by the {@link ServerSideDataService}. This can be modified before + * the HTTP request is sent using the {@link BeforeRequestHandler} callback on {@link ServerSideDataServiceOptions}. + * @see {@link https://github.com/nruffing/data-grid-vue-dotnet/blob/main/DataGridVueDotnet/PageDataRequest.cs | dotnet model} + */ export interface PageDataRequest { + /** + * @description The page number for the page to load starting with `1` for the first page. + * If the data grid is not set configured to be pageable with the {@link DataGridVueGrid.paged} + * prop then this will always be `-1`. + */ pageNum: number + + /** + * @description The maximum number of data items to display on each page. If the data grid is + * not set configured to be pageable with the {@link DataGridVueGrid.paged} prop then this + * will always be `-1`. + */ pageSize: number + + /** + * @description The current colomn sort definitions in the order in which they should be applied. + */ sort: Sort[] + + /** + * @description The current filter definition or undefined if no filter is set. + */ filter: Filter | undefined } +/** + * Callback type to change the {@link https://developer.mozilla.org/docs/Web/API/Request | Request} + * object before it is sent to the server from the built-in server side data service. This is useful + * when you need to map the {@link PageDataRequest} to a different data contract. + * @see {@link https://www.nuget.org/packages/DataGridVueDotnet/0.0.1-alpha | dotnet IQueryable helpers} + */ export type BeforeRequestHandler = (request: Request, body: PageDataRequest) => Promise + +/** + * Callback type to change the {@link https://developer.mozilla.org/docs/Web/API/Response | Response} + * object before it is handled by the data grid from the built-in server side data service. + * This is useful when you need to map the servers response data back to {@link PageData}. + * @see {@link https://www.nuget.org/packages/DataGridVueDotnet/0.0.1-alpha | dotnet IQueryable helpers} + */ export type ResponseHandler = (response: Response) => Promise + +/** + * @description Options to configure the built-in server-side data service including the POST url and optional + * callbacks to alter the data format of the request and response allowing. This allows the built-in data service + * to handle the data contract of any server. + * @see {@link ServerSideDataService} + * @see {@link https://www.nuget.org/packages/DataGridVueDotnet/0.0.1-alpha | dotnet IQueryable helpers} + */ export interface ServerSideDataServiceOptions { + /** + * @description The full HTTP/HTTPS url to send the POST request. + * Use {@link beforeRequest} callback to alter the HTTP verb or headers. + */ postRoute?: string | URL + + /** + * Optional callback to change the {@link https://developer.mozilla.org/docs/Web/API/Request | Request} + * object before it is sent to the server. This is useful when you need to map the {@link PageDataRequest} + * to a different data contract. + */ beforeRequest?: BeforeRequestHandler + + /** + * Optional callback to change the {@link https://developer.mozilla.org/docs/Web/API/Response | Response} + * object before it is handled by the data grid. This is useful when you need to map the servers response + * data back to {@link PageData}. + */ responseHandler?: ResponseHandler } +/** + * @description The server-side {@link DataService} used when {@link DataGridVueGrid.serverSideOptions} is specified. + */ export class ServerSideDataService implements DataService { options: ServerSideDataServiceOptions diff --git a/lib/Sort.ts b/lib/Sort.ts index 88df994..8615737 100644 --- a/lib/Sort.ts +++ b/lib/Sort.ts @@ -1,18 +1,47 @@ import { DataType } from './DataGridVue' +/** + * @description Grid-level sort options. The grid must be set as sortable for any + * column level sort options to take effect. + */ export interface SortOptions { + /** + * @description Whether the grid should be sortable. + */ sortable: boolean + + /** + * @description Whether more then one column can be sorted at once. + */ multiColumn: boolean } +/** + * @description Whether a sort is ascending or descending. + */ export enum SortType { ascending = 0, descending = 1, } +/** + * @description Column sort definition. + */ export interface Sort { + /** + * @description The {@link Column}.{@link Field.fieldName} that the data is being sorted by. + */ fieldName: string + + /** + * @description The {@link Column.dataType} for the column being sorted. + * @see {@link DataType} + */ dataType: DataType + + /** + * @description The {@link SortType} for the sort (i.e. ascending or descending). + */ type: SortType } diff --git a/lib/components/ColumnSelectionItem.vue b/lib/components/ColumnSelectionItem.vue index 3119217..fd1c32d 100644 --- a/lib/components/ColumnSelectionItem.vue +++ b/lib/components/ColumnSelectionItem.vue @@ -18,10 +18,17 @@ import { type PropType, defineComponent } from 'vue' import type { Column } from '../DataGridVue' import Formatter from '../Formatter' -/**@group Components */ +/** + * @group Components + * @description Column toggle item displayed in the column selected menu. + * @see {@link DataGridVueGrid.showColumnSelection} + */ export default defineComponent({ name: 'ColumnSelectionItem', props: { + /** + * @description The {@link Column} to show or hide. + */ column: { type: Object as PropType, required: true, diff --git a/lib/components/DataGridVue.vue b/lib/components/DataGridVue.vue index abcbe9d..eb37137 100644 --- a/lib/components/DataGridVue.vue +++ b/lib/components/DataGridVue.vue @@ -236,7 +236,10 @@ interface Data { storageService: StorageService } -/** @group Data Grid Component */ +/** + * @group Data Grid Component + * @description Main entrypoint component to render a data grid. + */ export default defineComponent({ name: 'DataGridVue', components: { @@ -247,71 +250,176 @@ export default defineComponent({ ColumnSelectionItem, }, props: { - /** @param data test */ + /** + * @description Array of objects to display in the data grid when using the built-in {@link ClientSideDataService}. + * This prop is required unless serverSideOptions or customDataService is supplied. The order of precedence + * is {@link customDataService}, {@link serverSideOptions}, and then {@link data}. + * The data grid will not react and rerender when this property changes. If that functionaly is needed it is recommended + * to leverage `v-if` to force a new component instance to render. + * @defaultValue undefined + */ data: { - type: Array, + type: Array as PropType, required: false, default: undefined, }, + + /** + * @description Options to configure the built-in server-side data service including the POST url and optional + * callbacks to alter the data format of the request and response allowing. This allows the built-in data service + * to handle the data contract of any server. {@link ServerSideDataService} is used unless {@link customDataService} + * is also specified. + * @see {@link https://www.nuget.org/packages/DataGridVueDotnet/0.0.1-alpha | dotnet IQueryable helpers} + * @defaultValue undefined + */ serverSideOptions: { type: Object as PropType, required: false, default: undefined, }, + + /** + * @description Custom implementation of {@link DataService} to supply the grid's data. When this is specified + * {@link data} and {@link serverSideOptions} are ignored. + * @defaultValue undefined + */ customDataService: { type: Object as PropType, required: false, default: undefined, }, + + /** + * @description {@link Column} definitions to configure data grid columns including header title, column width, custom data getter, + * and column specific filtering and sorting options. It is recommended to supply an array of objects with `v-model:columns` since + * that is required for column reordering and allowing users to show/hide specific columns to rerender the columns. + * {@link Column} objects will not be mutated but a new array will be emitted with the `update:columns` event and that needs to trigger + * this property to get an updated value. The grid will react to any change to this prop which can be leveraged to implement custom + * functionality to do things like allowing users to add/remove columns. + */ columns: { - type: Array, + type: Array as PropType, required: true, }, + + /** + * @description Whether to allow columns to be reordered using drag-and-drop + * powered by {@link https://www.npmjs.com/package/dragon-drop-vue | drag-drop-vue}. + * In order for columns to rerender after dropping {@link columns} should be passed using `v-model:columns`. + * @defaultValue false + */ allowColumnReorder: { type: Boolean, required: false, default: false, }, + + /** + * @description Whether the data grid should be paged. When this is `false` {@link PageDataRequest.pageNum} and + * {@link PageDataRequest.pageSize} will be -1. + * @defaultValue true + */ paged: { type: Boolean, required: false, default: true, }, + + /** + * @description The page size to use when the grid initially loads. + * @defaultValue 15 + */ initialPageSize: { type: Number, required: false, default: 15, }, + + /** + * @description The page sizes to allow the user to select between. The page size select + * will only be displayed if this array contains more then one value. + * @defaultValue [15, 25, 50] + */ pageSizes: { - type: Array, + type: Array as PropType, required: false, default: [15, 25, 50], }, + + /** + * @description Grid-level {@link SortOptions} including whether to allow sorting and if more then + * one column can be sorted at a time. The grid must be set as sortable for any column level sort + * options to take effect. + * @defaultValue undefined + */ sortOptions: { type: Object as PropType, required: false, default: undefined, }, + + /** + * @description Whether to display the `Add/Remove Columns` menu in the options header. Column selection + * can be set externally using the {@link Column.hidden} property. For this functionality to work correctly + * {@link columns} should be passed using `v-model:columns`. + * @defaultValue false + */ showColumnSelection: { type: Boolean, required: false, default: false, }, - localStorageType: { - type: Number, - required: false, - default: LocalStorageType.sessionStorage, - }, + + /** + * @description A key to use to save grid state in {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage | localStorage} + * or {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage | sessionStorage}. + * sessionStorage is used unless {@link localStorageType} is specified. The data + * that is saved as part of the grid state is defined in {@link GridState}. + * This is ignored if {@link serverSideStorageOptions} or {@link customStorageService} is specified. + * @see {@link SessionStorageService} + * @see {@link LocalStorageService} + * @defaultValue '' + */ storageKey: { type: String, required: false, default: '', }, + + /** + * @description Whether grid state is stored in {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage | localStorage} + * or {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage | sessionStorage}. + * To save grid state {@link storageKey} must be specified.The data + * that is saved as part of the grid state is defined in {@link GridState}. + * This is ignored if {@link serverSideStorageOptions} or {@link customStorageService} is specified. + * @see {@link SessionStorageService} + * @see {@link LocalStorageService} + * @defaultValue LocalStorageType.sessionStorage + */ + localStorageType: { + type: Number, + required: false, + default: LocalStorageType.sessionStorage, + }, + + /** + * @description Options to specify to use {@link ServerSideStorageService} to retrieve and store {@link GridState} + * {@link storageKey} and {@link localStorageType} are ignored if this is specified. This is ignored if + * {@link customStorageService} is specified. + * @see {@link ServerSideStorageServiceOptions} + * @defaultValue undefined + */ serverSideStorageOptions: { type: Object as PropType, required: false, default: undefined, }, + + /** + * @description Custom implementation of {@link StorageService} to optionally retrieve/store {@link GridState}. + * When this is specified {@link storageKey}, {@link localStorageType}, and {@link serverSideStorageOptions} are ignored. + * @defaultValue undefined + */ customStorageService: { type: Object as PropType, required: false, @@ -430,11 +538,7 @@ export default defineComponent({ this.setGridState(gridState) } - if (this.paged) { - await this.loadPageData() - } else if (this.data) { - this.displayedData = this.data - } + await this.loadPageData() this.windowResizeDebounce = debounce(this.onWindowResize, 50) window.addEventListener('resize', this.windowResizeDebounce) @@ -460,7 +564,7 @@ export default defineComponent({ }, methods: { async loadPageData() { - const pageData = await this.dataService.getPage(this.currentPage, this.pageSize, this.sort, this.filter) + const pageData = await this.dataService.getPage(this.paged ? this.currentPage : -1, this.paged ? this.pageSize : -1, this.sort, this.filter) this.displayedData = pageData.dataItems this.totalItems = pageData.totalItems }, diff --git a/lib/components/FilterOperatorSelect.vue b/lib/components/FilterOperatorSelect.vue index c59130c..4fa5ece 100644 --- a/lib/components/FilterOperatorSelect.vue +++ b/lib/components/FilterOperatorSelect.vue @@ -20,24 +20,40 @@