From 6322beeb2a75e573cd63d79174b91f46344cca53 Mon Sep 17 00:00:00 2001 From: David Baetge Date: Sat, 4 Jun 2022 02:52:26 +0200 Subject: [PATCH 1/3] Added carbon-data-table-state-manager@0.0.1-alpha.1.0 --- skins/weewx-wdc/src/js/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/skins/weewx-wdc/src/js/index.tsx b/skins/weewx-wdc/src/js/index.tsx index 7a4ca699..41ee8e22 100644 --- a/skins/weewx-wdc/src/js/index.tsx +++ b/skins/weewx-wdc/src/js/index.tsx @@ -3,7 +3,7 @@ import { createRoot } from "react-dom/client"; import { Serie } from "@nivo/line"; import { TABLE_SORT_DIRECTION } from "./data-table/misc"; -import TableBase from "./data-table/table-base"; +import TableBase from "carbon-data-table-state-manager"; import { BarDiagram } from "./diagrams/bar"; import { LineDiagram } from "./diagrams/line"; import { precision, Series } from "./diagrams/types"; @@ -119,6 +119,7 @@ if (table) { root.render( Date: Sat, 4 Jun 2022 02:53:07 +0200 Subject: [PATCH 2/3] Updated package.json --- package.json | 1 + yarn.lock | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2401566d..277b438f 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@react-hook/media-query": "^1.1.1", "carbon-components": "10.25.0", "carbon-components-react": "7.50.0", + "carbon-data-table-state-manager": "^0.0.1-alpha.1.0", "carbon-icons": "7.0.7", "d3-scale": "^4.0.2", "moment": "^2.29.3", diff --git a/yarn.lock b/yarn.lock index 44cd2668..43e76e33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1501,6 +1501,15 @@ carbon-components@10.25.0: lodash.debounce "^4.0.8" warning "^3.0.0" +carbon-data-table-state-manager@^0.0.1-alpha.1.0: + version "0.0.1-alpha.1.0" + resolved "https://registry.yarnpkg.com/carbon-data-table-state-manager/-/carbon-data-table-state-manager-0.0.1-alpha.1.0.tgz#b008c362f2daa06b08c164a2de287d454d033c9e" + integrity sha512-LcdisJn9Q/2klBk5J+qpijbB7KT50mp75VcQ8RNbc8lD0lQbr20WvgFClp+GQduxa78qtwpKZb6NzPgiltVSgQ== + dependencies: + dayjs "^1.11.2" + prop-types "^15.7.0" + use-debounce "^7.0.1" + carbon-icons@7.0.7: version "7.0.7" resolved "https://registry.yarnpkg.com/carbon-icons/-/carbon-icons-7.0.7.tgz#ebafe3e9fa25df973796a8eca06d8a7c501cc610" @@ -1865,6 +1874,11 @@ d3-time@^1.0.10, d3-time@^1.0.11: resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== +dayjs@^1.11.2: + version "1.11.2" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.2.tgz#fa0f5223ef0d6724b3d8327134890cfe3d72fbe5" + integrity sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw== + debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -2969,7 +2983,7 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.7.0, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -3384,6 +3398,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +use-debounce@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-7.0.1.tgz#380e6191cc13ad29f8e2149a12b5c37cc2891190" + integrity sha512-fOrzIw2wstbAJuv8PC9Vg4XgwyTLEOdq4y/Z3IhVl8DAE4svRcgyEUvrEXu+BMNgMoc3YND6qLT61kkgEKXh7Q== + use-debounce@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-8.0.1.tgz#5f3e11b067bdf9f2c554a20b4764e38b48022664" From f65f8522a33add3eb5ea3e406babb91a81014238 Mon Sep 17 00:00:00 2001 From: David Baetge Date: Wed, 8 Jun 2022 01:49:49 +0200 Subject: [PATCH 3/3] Removed table-base component and replaced with CarbonDataTableStateManager. --- bin/user/table_util.py | 8 +- package.json | 2 +- .../js/data-table/components/pagination.tsx | 54 --- .../src/js/data-table/hooks/index.ts | 7 - .../src/js/data-table/hooks/useCollator.ts | 20 - .../js/data-table/hooks/useFilteredRows.ts | 27 -- .../src/js/data-table/hooks/usePageInfo.ts | 33 -- .../js/data-table/hooks/useRowSelection.ts | 33 -- .../src/js/data-table/hooks/useSortInfo.ts | 83 ----- .../src/js/data-table/hooks/useSortedRows.ts | 44 --- .../src/js/data-table/hooks/useUniqueId.ts | 13 - .../misc/doesRowMatchSearchString.ts | 16 - .../weewx-wdc/src/js/data-table/misc/enums.ts | 84 ----- .../weewx-wdc/src/js/data-table/misc/index.ts | 2 - .../src/js/data-table/table-base.tsx | 344 ------------------ skins/weewx-wdc/src/js/index.tsx | 11 +- skins/weewx-wdc/src/scss/index.scss | 5 - yarn.lock | 11 +- 18 files changed, 15 insertions(+), 782 deletions(-) delete mode 100644 skins/weewx-wdc/src/js/data-table/components/pagination.tsx delete mode 100644 skins/weewx-wdc/src/js/data-table/hooks/index.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/hooks/useCollator.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/hooks/useFilteredRows.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/hooks/usePageInfo.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/hooks/useRowSelection.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/hooks/useSortInfo.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/hooks/useSortedRows.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/hooks/useUniqueId.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/misc/doesRowMatchSearchString.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/misc/enums.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/misc/index.ts delete mode 100644 skins/weewx-wdc/src/js/data-table/table-base.tsx diff --git a/bin/user/table_util.py b/bin/user/table_util.py index 8b4ccd2c..a93cf2c4 100644 --- a/bin/user/table_util.py +++ b/bin/user/table_util.py @@ -47,7 +47,7 @@ def get_table_headers(self, obs, unit_labels, obs_labels, period): carbon_headers.append({ "title": "Time", - "id": "timeParsed", + "id": "time", "sortCycle": "tri-states-from-ascending", }) @@ -95,13 +95,13 @@ def get_table_rows(self, obs, period, precision): cs_time = datetime.fromtimestamp(start.raw) # The current series item by time. cs_item = list(filter( - lambda x: (x['timeParsed'] == cs_time.isoformat()), + lambda x: (x['time'] == cs_time.isoformat()), carbon_values )) if len(cs_item) == 0: carbon_values.append({ - "timeParsed": cs_time.isoformat(), + "time": cs_time.isoformat(), observation: data.raw, 'id': start.raw }) @@ -113,7 +113,7 @@ def get_table_rows(self, obs, period, precision): # Sort per time carbon_values.sort( - key=lambda item: datetime.fromisoformat(item['timeParsed']) + key=lambda item: datetime.fromisoformat(item['time']) ) return carbon_values diff --git a/package.json b/package.json index 277b438f..79f43dd6 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@react-hook/media-query": "^1.1.1", "carbon-components": "10.25.0", "carbon-components-react": "7.50.0", - "carbon-data-table-state-manager": "^0.0.1-alpha.1.0", + "carbon-data-table-state-manager": "^1.0.2", "carbon-icons": "7.0.7", "d3-scale": "^4.0.2", "moment": "^2.29.3", diff --git a/skins/weewx-wdc/src/js/data-table/components/pagination.tsx b/skins/weewx-wdc/src/js/data-table/components/pagination.tsx deleted file mode 100644 index 0a5a3335..00000000 --- a/skins/weewx-wdc/src/js/data-table/components/pagination.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { useCallback } from "react"; -import { Pagination as CarbonPagination } from "carbon-components-react"; - -type PaginationProps = { - count: number; - start: number; - pageSize: number; - onChangePageSize: (a: { pageSize: number }) => void; - onChangeStart: (a: { start: number }) => void; - pageSizes: number[]; -}; - -/** - * Wrapped version of Carbon ``, that uses zero-based starting row - * index instead of page number. - */ -const Pagination = (props: PaginationProps): React.ReactElement => { - const handleChangePage = useCallback( - ({ page: newPage, pageSize: newPageSize }) => { - if (props.onChangePageSize && props.pageSize !== newPageSize) { - props.onChangePageSize({ pageSize: newPageSize }); - } - const page = Math.floor(props.start / props.pageSize) + 1; - if (page !== newPage) { - const newStart = Math.min( - Math.max(props.start + (newPage - page) * props.pageSize, 0), - props.count - ); - if (props.onChangeStart && props.start !== newStart) { - props.onChangeStart({ start: newStart }); - } - } - }, - [ - props.start, - props.count, - props.pageSize, - props.onChangeStart, - props.onChangePageSize, - ] - ); - - return ( - - ); -}; - -export default Pagination; diff --git a/skins/weewx-wdc/src/js/data-table/hooks/index.ts b/skins/weewx-wdc/src/js/data-table/hooks/index.ts deleted file mode 100644 index eee74521..00000000 --- a/skins/weewx-wdc/src/js/data-table/hooks/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { default as useCollator } from "./useCollator"; -export { default as useFilteredRows } from "./useFilteredRows"; -export { default as usePageInfo } from "./usePageInfo"; -export { default as useRowSelection } from "./useRowSelection"; -export { default as useSortedRows } from "./useSortedRows"; -export { default as useSortInfo } from "./useSortInfo"; -export { default as useUniqueId } from "./useUniqueId"; diff --git a/skins/weewx-wdc/src/js/data-table/hooks/useCollator.ts b/skins/weewx-wdc/src/js/data-table/hooks/useCollator.ts deleted file mode 100644 index 66622933..00000000 --- a/skins/weewx-wdc/src/js/data-table/hooks/useCollator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { useCallback } from "react"; - -/** - * @param {Intl.Collator} collator The ECMA402 collator. - * @returns {(a: any, b: any) => boolean} The comparator. - */ -const useCollator = ( - collator: Intl.Collator -): ((a: number | string, b: number | string) => number) => - useCallback( - (lhs, rhs) => { - if (typeof lhs === "number" && typeof rhs === "number") { - return lhs - rhs; - } - return collator.compare(lhs.toString(), rhs.toString()); - }, - [collator] - ); - -export default useCollator; diff --git a/skins/weewx-wdc/src/js/data-table/hooks/useFilteredRows.ts b/skins/weewx-wdc/src/js/data-table/hooks/useFilteredRows.ts deleted file mode 100644 index c5b68a9f..00000000 --- a/skins/weewx-wdc/src/js/data-table/hooks/useFilteredRows.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Dispatch, SetStateAction, useMemo, useState } from "react"; -import { useDebounce } from "use-debounce"; -import doesRowMatchSearchString from "../misc/doesRowMatchSearchString"; -import { dataItemDataTable } from "../table-base"; - -/** - * @param {object[]} rows The table rows. - * @returns {Array} The memorized version of filtered rows, search string and the setter for the search string. - */ -const useFilteredRows = ( - rows: dataItemDataTable[] -): [dataItemDataTable[], string, Dispatch>] => { - const [searchString, setSearchString] = useState(""); - const [debouncedSearchString] = useDebounce(searchString, 500); - const filteredRows = useMemo( - () => - !debouncedSearchString - ? rows - : rows.filter((row) => - doesRowMatchSearchString(row, debouncedSearchString) - ), - [debouncedSearchString, rows] - ); - return [filteredRows, searchString, setSearchString]; -}; - -export default useFilteredRows; diff --git a/skins/weewx-wdc/src/js/data-table/hooks/usePageInfo.ts b/skins/weewx-wdc/src/js/data-table/hooks/usePageInfo.ts deleted file mode 100644 index 5eb9add5..00000000 --- a/skins/weewx-wdc/src/js/data-table/hooks/usePageInfo.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Dispatch, SetStateAction, useState } from "react"; - -/** - * @param {number} initialStart The initial start row index, zero-based. - * @param {number} initialPageSize The initial page size. - * @param {number} count The total row count. - * @returns {Array} The start row index, page size, the setter for the start - * row index, the setter for the page size. - */ -const usePageInfo = ( - initialStart: number, - initialPageSize: number, - count: number -): [ - number, - number, - Dispatch>, - Dispatch> -] => { - const [start, setStart] = useState(initialStart); - const [pageSize, setPageSize] = useState(initialPageSize); - // Copes with `start` going beyond the row count - const adjustedStart = - count === 0 || start < count - ? start - : Math.max( - start - (Math.floor((start - count) / pageSize) + 1) * pageSize, - 0 - ); - return [adjustedStart, pageSize, setStart, setPageSize]; -}; - -export default usePageInfo; diff --git a/skins/weewx-wdc/src/js/data-table/hooks/useRowSelection.ts b/skins/weewx-wdc/src/js/data-table/hooks/useRowSelection.ts deleted file mode 100644 index 9b613ef1..00000000 --- a/skins/weewx-wdc/src/js/data-table/hooks/useRowSelection.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { useCallback } from "react"; -import doesRowMatchSearchString from "../misc/doesRowMatchSearchString"; -import { dataItemDataTable } from "../table-base"; - -/** - * @param {object[]} rows The table rows. - * @param {string} searchString The search string. - * @param {Function} setRows The setter for the table rows. - * @returns {Array} The setter for the table row selection. - */ -const useRowSelection = ( - rows: dataItemDataTable[], - searchString: string, - setRows: (a: dataItemDataTable[]) => void -): ((rowId: number, selected: boolean) => void)[] => { - const setRowSelection = useCallback( - (rowId, selected) => { - setRows( - rows.map((row, index) => { - const doChange = - rowId !== undefined - ? rowId === index - : !searchString || doesRowMatchSearchString(row, searchString); - return !doChange ? row : { ...row, selected }; - }) - ); - }, - [rows, searchString, setRows] - ); - return [setRowSelection]; -}; - -export default useRowSelection; diff --git a/skins/weewx-wdc/src/js/data-table/hooks/useSortInfo.ts b/skins/weewx-wdc/src/js/data-table/hooks/useSortInfo.ts deleted file mode 100644 index 7d908b8b..00000000 --- a/skins/weewx-wdc/src/js/data-table/hooks/useSortInfo.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { useCallback, useState } from "react"; -import { - TABLE_SORT_CYCLE, - TABLE_SORT_CYCLES, - TABLE_SORT_DIRECTION, -} from "../misc"; -import { DataTableSortState } from "carbon-components-react/lib/components/DataTable/state/sorting"; - -interface getNextSortProps { - sortCycle: string | undefined; - oldDirection: DataTableSortState; -} - -/** - * @param options The options. - * @param [options.sortCycle=tri-states-from-ascending] The sorting cycle. - * @param options.oldDirection The old sort direction. - * @returns The next sort direction. - */ -const getNextSort = (options: getNextSortProps): DataTableSortState => { - const sortCycle = - options.sortCycle === undefined - ? TABLE_SORT_CYCLE.TRI_STATES_FROM_ASCENDING - : options.sortCycle; - if (!options.oldDirection) { - throw new TypeError( - "Table sort direction is not defined. " + - "Likely that `getNextSort()` is called with non-sorted table column, which should not happen in regular condition." - ); - } - const directions = TABLE_SORT_CYCLES[sortCycle]; - const index = directions.indexOf(options.oldDirection); - if (index < 0) { - if (options.oldDirection === TABLE_SORT_DIRECTION.NONE) { - // If the current sort direction is `none` in bi-state sort cycle, - // returns the first one in the cycle - return directions[0]; - } - throw new RangeError( - `The given sort state (${options.oldDirection}) is not found in the given table sort cycle: ${sortCycle}` - ); - } - return directions[(index + 1) % directions.length]; -}; - -/** - * @param {object} initialSortInfo The initial table sort info. - * @returns {Array} The current table sort info and the setter for the table - * sort info. - */ -const useSortInfo = (initialSortInfo: { - columnId: string; - direction: DataTableSortState; -}): [ - { columnId: string; direction: DataTableSortState }, - ({ - columnId, - sortCycle, - oldDirection, - }: getNextSortProps & { columnId: string }) => void -] => { - const [sortInfo, setSortInfo] = useState(initialSortInfo); - const invokeSetSortInfo = useCallback( - ({ columnId, sortCycle, oldDirection }) => { - const direction = getNextSort({ sortCycle, oldDirection }); - if (direction === TABLE_SORT_DIRECTION.NONE && columnId !== "name") { - // Resets the sorting, given non-primary sorting column has got in - // non-sorting state - setSortInfo(initialSortInfo); - } else { - // Sets the sorting as user desires - setSortInfo({ - columnId, - direction, - }); - } - }, - [initialSortInfo, setSortInfo] - ); - return [sortInfo, invokeSetSortInfo]; -}; - -export default useSortInfo; diff --git a/skins/weewx-wdc/src/js/data-table/hooks/useSortedRows.ts b/skins/weewx-wdc/src/js/data-table/hooks/useSortedRows.ts deleted file mode 100644 index d8ff2a8b..00000000 --- a/skins/weewx-wdc/src/js/data-table/hooks/useSortedRows.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { TABLE_SORT_DIRECTION } from "../misc"; -import useCollator from "./useCollator"; -import { dataItemDataTable } from "../table-base"; - -/** - * The map of how sorting direction affects sorting order. - */ -const collationFactors = { - [TABLE_SORT_DIRECTION.ASC]: 1, - [TABLE_SORT_DIRECTION.DESC]: -1, -}; - -type SortInfo = { - columnId: string; - direction: string; -}; - -/** - * @param {object[]} rows The table rows. - * @param {object} sortInfo The table sort info. - * @param {Intl.Collator} collator The g11n collator. - * @returns {Array} The sorted table rows. - */ -const useSortedRows = ( - rows: dataItemDataTable[], - sortInfo: SortInfo, - collator: Intl.Collator -): [dataItemDataTable[]] => { - const compare = useCollator(collator); - const { columnId: sortColumnId, direction: sortDirection } = sortInfo; - const sortedRows = - sortDirection === TABLE_SORT_DIRECTION.NONE - ? rows - : rows - .slice() - .sort( - (lhs, rhs) => - collationFactors[sortDirection] * - compare(lhs[sortColumnId], rhs[sortColumnId]) - ); - return [sortedRows]; -}; - -export default useSortedRows; diff --git a/skins/weewx-wdc/src/js/data-table/hooks/useUniqueId.ts b/skins/weewx-wdc/src/js/data-table/hooks/useUniqueId.ts deleted file mode 100644 index f2bd0886..00000000 --- a/skins/weewx-wdc/src/js/data-table/hooks/useUniqueId.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useMemo } from "react"; - -/** - * @param {string} id A user-specified unique ID. If present, ID won't be - * auto-generated and the given one will be used. - * @returns {string} The auto-generated unique ID. - */ -const useUniqueId = (id: string): string => { - const uniqueId = useMemo(() => Math.random().toString(36).slice(2), []); - return id || uniqueId; -}; - -export default useUniqueId; diff --git a/skins/weewx-wdc/src/js/data-table/misc/doesRowMatchSearchString.ts b/skins/weewx-wdc/src/js/data-table/misc/doesRowMatchSearchString.ts deleted file mode 100644 index 844f38e9..00000000 --- a/skins/weewx-wdc/src/js/data-table/misc/doesRowMatchSearchString.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { dataItemDataTable } from "../table-base"; - -/** - * @param row A table row. - * @param searchString A search string. - * @returns `true` if the given table row matches the given search string. - */ -const doesRowMatchSearchString = ( - row: dataItemDataTable, - searchString: string -): boolean => - Object.keys(row).some( - (key) => key !== "id" && String(row[key] ?? "").indexOf(searchString) >= 0 - ); - -export default doesRowMatchSearchString; diff --git a/skins/weewx-wdc/src/js/data-table/misc/enums.ts b/skins/weewx-wdc/src/js/data-table/misc/enums.ts deleted file mode 100644 index a1030ef1..00000000 --- a/skins/weewx-wdc/src/js/data-table/misc/enums.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { DataTableSortState } from "carbon-components-react/lib/components/DataTable/state/sorting"; - -/** - * Table size. - */ -export const TABLE_SIZE = { - /** - * Compact size. - */ - COMPACT: "compact", - - /** - * Short size. - */ - SHORT: "short", - - /** - * Regular size. - */ - REGULAR: "normal", - - /** - * Tall size. - */ - TALL: "tall", -}; - -/** - * Table sort state. - */ -export const TABLE_SORT_DIRECTION: { - NONE: DataTableSortState; - ASC: DataTableSortState; - DESC: DataTableSortState; -} = { - /** - * Not sorted. - */ - NONE: "NONE", - - /** - * Sorted in ascending order. - */ - ASC: "ASC", - - /** - * Sorted in descending order. - */ - DESC: "DESC", -}; - -/** - * Table sort cycle. - */ -export const TABLE_SORT_CYCLE = { - BI_STATES_FROM_ASCENDING: "bi-states-from-ascending", - BI_STATES_FROM_DESCENDING: "bi-states-from-descending", - TRI_STATES_FROM_ASCENDING: "tri-states-from-ascending", - TRI_STATES_FROM_DESCENDING: "tri-states-from-descending", -}; - -/** - * Mapping of table sort cycles to table sort states. - */ -export const TABLE_SORT_CYCLES = { - [TABLE_SORT_CYCLE.BI_STATES_FROM_ASCENDING]: [ - TABLE_SORT_DIRECTION.ASC, - TABLE_SORT_DIRECTION.DESC, - ], - [TABLE_SORT_CYCLE.BI_STATES_FROM_DESCENDING]: [ - TABLE_SORT_DIRECTION.DESC, - TABLE_SORT_DIRECTION.ASC, - ], - [TABLE_SORT_CYCLE.TRI_STATES_FROM_ASCENDING]: [ - TABLE_SORT_DIRECTION.NONE, - TABLE_SORT_DIRECTION.ASC, - TABLE_SORT_DIRECTION.DESC, - ], - [TABLE_SORT_CYCLE.TRI_STATES_FROM_DESCENDING]: [ - TABLE_SORT_DIRECTION.NONE, - TABLE_SORT_DIRECTION.DESC, - TABLE_SORT_DIRECTION.ASC, - ], -}; diff --git a/skins/weewx-wdc/src/js/data-table/misc/index.ts b/skins/weewx-wdc/src/js/data-table/misc/index.ts deleted file mode 100644 index 8558e9f1..00000000 --- a/skins/weewx-wdc/src/js/data-table/misc/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./enums"; -export { default as doesRowMatchSearchString } from "./doesRowMatchSearchString"; diff --git a/skins/weewx-wdc/src/js/data-table/table-base.tsx b/skins/weewx-wdc/src/js/data-table/table-base.tsx deleted file mode 100644 index b2c94683..00000000 --- a/skins/weewx-wdc/src/js/data-table/table-base.tsx +++ /dev/null @@ -1,344 +0,0 @@ -import React, { useCallback, useEffect, useState } from "react"; - -import moment from "moment"; - -import { Information16 } from "@carbon/icons-react"; -import { - TableContainer, - Table, - TableHead, - TableHeader, - TableBody, - TableRow, - TableCell, - TableSelectRow, - TableSelectAll, - TooltipIcon, -} from "carbon-components-react"; -import type { DataTableSize } from "carbon-components-react"; -import { DataTableSortState } from "carbon-components-react/lib/components/DataTable/state/sorting"; - -import { - useFilteredRows, - usePageInfo, - useRowSelection, - useSortedRows, - useSortInfo, - useUniqueId, -} from "./hooks"; -import Pagination from "./components/pagination"; -import { TABLE_SORT_DIRECTION } from "./misc"; - -export type dataItemDataTable = { - [key: string]: any; - selected: boolean; - timeParsed: string; - id: number; -}; - -interface TableBaseProps { - collator: Intl.Collator; - columns: { - id: string; - title: string; - sortCycle?: string; - small?: string; - tooltip?: string; - }[]; - hasSelection?: boolean; - id?: string; - pageSize: number; - rows: dataItemDataTable[]; - size?: DataTableSize; - sortInfo: { - columnId: string; - direction: DataTableSortState; - }; - start: number; - zebra?: boolean; - title?: string; - dateFormat?: string; - pageSizes?: number[]; -} - -/** - * An example state manager that an application can start with to achieve - * a fully-customized data table. - * - * There are many different use cases for managing data table state, - * i.e. lazy-loading table row data that are not on the current page. - * - * Carbon has `` component manage table state, - * but one `` supporting every possible use case will make it very complex. - * - * In case Carbon `` doesn't meet the needs of BU/application, - * PALs/applications create a state manager by their own, i.e. starting with - * this example. - * - * Carbon design for table is implemented by ``, ``, - * ``, etc., - * whereas `` is merely a state manager. - * - * Therefore, using a custom component in place of `` does _not_ mean - * going away from Carbon design. - * - * THIS COMPONENT IS FOR DEMONSTRATION PURPOSES ONLY. - * - * @see https://react.carbondesignsystem.com/?path=/docs/components-datatable-batch-actions--usage - * @see https://github.com/carbon-design-system/carbon/issues/6373 - * @see https://github.com/carbon-design-system/carbon/tree/main/packages/react/examples/custom-data-table-state-manager - */ -const TableBase: React.FC = ( - props: TableBaseProps -): React.ReactElement => { - const [rows, setRows] = useState(props.rows); - const [modalOpen, setModalOpen] = useState(false); - const [sortInfo, setSortInfo] = useSortInfo(props.sortInfo); - const [filteredRows, searchString, setSearchString] = useFilteredRows(rows); - const [setRowSelection] = useRowSelection( - filteredRows, - searchString, - setRows - ); - const [sortedRows] = useSortedRows(filteredRows, sortInfo, props.collator); - const [start, pageSize, setStart, setPageSize] = usePageInfo( - props.start, - props.pageSize, - filteredRows.length - ); - - const elementId = useUniqueId(props.id); - const selectedRowsCountInFiltered = filteredRows.filter( - (row) => row.selected - ).length; - const selectedAllInFiltered = - selectedRowsCountInFiltered > 0 && - filteredRows.length === selectedRowsCountInFiltered; - const hasBatchActions = props.hasSelection && selectedRowsCountInFiltered > 0; - const { columnId: sortColumnId, direction: sortDirection } = sortInfo; - const selectionAllName = !props.hasSelection - ? undefined - : `__custom-data-table_select-all_${elementId}`; - - const handleCancelSelection = useCallback(() => { - setRowSelection(undefined, false); - }, [setRowSelection]); - - const handleChangeSearchString = useCallback( - ({ target }) => { - setSearchString(target.value); - }, - [setSearchString] - ); - - const handleChangeSelection = useCallback( - (event) => { - const { currentTarget } = event; - const row = currentTarget.closest("tr"); - if (row) { - setRowSelection(Number(row.dataset.rowId), currentTarget.checked); - } - }, - [setRowSelection] - ); - - const handleChangeSelectionAll = useCallback( - (event) => { - setRowSelection(undefined, event.currentTarget.checked); - }, - [setRowSelection] - ); - - const handleChangeSort = useCallback( - (event) => { - const { currentTarget } = event; - const { - columnId, - sortCycle, - sortDirection: oldDirection, - } = currentTarget.dataset; - setSortInfo({ columnId, sortCycle, oldDirection }); - }, - [setSortInfo] - ); - - const handleChangePageSize = useCallback( - ({ pageSize }) => { - setPageSize(pageSize); - }, - [setPageSize] - ); - - const handleChangeStart = useCallback( - ({ start }) => { - setStart(start); - }, - [setStart] - ); - - const handleDeleteRows = () => { - setModalOpen(true); - }; - - useEffect(() => { - setRows(props.rows); - }, [props.rows]); - - let description = `from ${moment(rows[0].timeParsed).format( - "YYYY/MM/DD HH:mm" - )} till ${moment(rows[rows.length - 1].timeParsed).format( - "YYYY/MM/DD HH:mm" - )}`; - if (props.dateFormat) { - description = `from ${moment(rows[0].timeParsed).format( - props.dateFormat - )} till ${moment(rows[rows.length - 1].timeParsed).format( - props.dateFormat - )}`; - } - - return ( - <> - -
- - - {props.hasSelection && ( - 0 && !selectedAllInFiltered - } - ariaLabel="Select all rows" - name={selectionAllName} - onSelect={handleChangeSelectionAll} - /> - )} - - {props.columns.map( - ({ id: columnId, sortCycle, title, small, tooltip }) => { - const sortDirectionForThisCell = - columnId === sortColumnId - ? sortDirection - : TABLE_SORT_DIRECTION.NONE; - return ( - -
-
- {title}
- {small ? ( - - - - ) : null} -
- - {tooltip && ( - - - - )} -
-
- ); - } - )} -
-
- - {sortedRows.slice(start, start + pageSize).map((row) => { - const { id: rowId, selected } = row; - const selectionName = !props.hasSelection - ? undefined - : `__custom-data-table_${elementId}_${rowId}`; - return ( - - {props.hasSelection && ( - - )} - {props.columns.map(({ id: columnId }) => ( - - {columnId === "timeParsed" ? ( - <> - {props.dateFormat ? ( - <> - {moment(row[columnId]).format(props.dateFormat)} - - ) : ( - <> - {moment(row[columnId]).format("YYYY/MM/DD HH:mm")} - - )} - - ) : ( - <> - {typeof row[columnId] !== "undefined" - ? row[columnId] - : "-"} - - )} - - ))} - - ); - })} - -
- {typeof pageSize !== "undefined" && ( - - )} - - - ); -}; - -TableBase.defaultProps = { - collator: new Intl.Collator(), - hasSelection: false, - pageSize: 5, - size: "normal", - start: 0, -}; - -export default TableBase; diff --git a/skins/weewx-wdc/src/js/index.tsx b/skins/weewx-wdc/src/js/index.tsx index 41ee8e22..0efdee00 100644 --- a/skins/weewx-wdc/src/js/index.tsx +++ b/skins/weewx-wdc/src/js/index.tsx @@ -2,8 +2,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { Serie } from "@nivo/line"; -import { TABLE_SORT_DIRECTION } from "./data-table/misc"; -import TableBase from "carbon-data-table-state-manager"; +import { CarbonDataTableStateManager } from "carbon-data-table-state-manager"; import { BarDiagram } from "./diagrams/bar"; import { LineDiagram } from "./diagrams/line"; import { precision, Series } from "./diagrams/types"; @@ -118,19 +117,19 @@ if (table) { const root = createRoot(table); root.render( - ); } diff --git a/skins/weewx-wdc/src/scss/index.scss b/skins/weewx-wdc/src/scss/index.scss index 941deb15..56ce569a 100644 --- a/skins/weewx-wdc/src/scss/index.scss +++ b/skins/weewx-wdc/src/scss/index.scss @@ -440,11 +440,6 @@ bx-tabs { .data-table-tile { padding: 0; } -.bx--pagination { - .bx--pagination__left { - padding-left: 0; - } -} .bx--data-table--short .bx--table-header-label { white-space: nowrap; } diff --git a/yarn.lock b/yarn.lock index 43e76e33..603975bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1501,13 +1501,12 @@ carbon-components@10.25.0: lodash.debounce "^4.0.8" warning "^3.0.0" -carbon-data-table-state-manager@^0.0.1-alpha.1.0: - version "0.0.1-alpha.1.0" - resolved "https://registry.yarnpkg.com/carbon-data-table-state-manager/-/carbon-data-table-state-manager-0.0.1-alpha.1.0.tgz#b008c362f2daa06b08c164a2de287d454d033c9e" - integrity sha512-LcdisJn9Q/2klBk5J+qpijbB7KT50mp75VcQ8RNbc8lD0lQbr20WvgFClp+GQduxa78qtwpKZb6NzPgiltVSgQ== +carbon-data-table-state-manager@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/carbon-data-table-state-manager/-/carbon-data-table-state-manager-1.0.2.tgz#685c4a6a590663f22e9b7b0de461fb1c8769e6d8" + integrity sha512-DXJH2KFYL8RB9J3wAyHCmmcDVRazyWzdPIWs7rDiiMPnauj5zD3io2lJTjloaC8uhlFQMx5VtGpzoKEmI1j4ew== dependencies: dayjs "^1.11.2" - prop-types "^15.7.0" use-debounce "^7.0.1" carbon-icons@7.0.7: @@ -2983,7 +2982,7 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -prop-types@^15.7.0, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==