@stoker-platform/web-app 0.5.164 → 0.5.166

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @stoker-platform/web-app
2
2
 
3
+ ## 0.5.166
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: improve secondary sort feature
8
+
9
+ ## 0.5.165
10
+
11
+ ### Patch Changes
12
+
13
+ - feat: add secondary sort feature
14
+ - @stoker-platform/node-client@0.5.66
15
+ - @stoker-platform/utils@0.5.57
16
+ - @stoker-platform/web-client@0.5.67
17
+
3
18
  ## 0.5.164
4
19
 
5
20
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/web-app",
3
- "version": "0.5.164",
3
+ "version": "0.5.166",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "scripts": {
@@ -51,9 +51,9 @@
51
51
  "@radix-ui/react-tooltip": "^1.2.8",
52
52
  "@react-google-maps/api": "^2.20.8",
53
53
  "@sentry/react": "^10.56.0",
54
- "@stoker-platform/node-client": "0.5.65",
55
- "@stoker-platform/utils": "0.5.56",
56
- "@stoker-platform/web-client": "0.5.66",
54
+ "@stoker-platform/node-client": "0.5.66",
55
+ "@stoker-platform/utils": "0.5.57",
56
+ "@stoker-platform/web-client": "0.5.67",
57
57
  "@tanstack/react-table": "^8.21.3",
58
58
  "@types/react": "18.3.13",
59
59
  "@types/react-dom": "18.3.1",
@@ -183,6 +183,13 @@ function Collection({
183
183
  }
184
184
  | undefined
185
185
  >(undefined)
186
+ const [secondarySort, setSecondarySort] = useState<
187
+ | {
188
+ field: string
189
+ direction?: "asc" | "desc"
190
+ }
191
+ | undefined
192
+ >(undefined)
186
193
 
187
194
  const [state, setStokerState] = useStokerState()
188
195
  const setState = useCallback(
@@ -1194,6 +1201,16 @@ function Collection({
1194
1201
  }
1195
1202
  | undefined
1196
1203
  setDefaultSort(defaultSortOverride || defaultSort)
1204
+ const secondarySort = (await getCachedConfigValue(customization, [
1205
+ ...collectionAdminPath,
1206
+ "secondarySort",
1207
+ ])) as
1208
+ | {
1209
+ field: string
1210
+ direction?: "asc" | "desc"
1211
+ }
1212
+ | undefined
1213
+ setSecondarySort(secondarySort)
1197
1214
  const sortState = state[`collection-sort-${labels.collection.toLowerCase()}`]
1198
1215
  if (sortState && !relationList) {
1199
1216
  const newSorting = JSON.parse(sortState)
@@ -2513,6 +2530,7 @@ function Collection({
2513
2530
  setBackToStartKey={setBackToStartKey}
2514
2531
  search={search}
2515
2532
  defaultSort={defaultSort}
2533
+ secondarySort={secondarySort}
2516
2534
  setOptimisticList={setOptimisticList}
2517
2535
  relationList={relationList}
2518
2536
  relationCollection={relationCollection}
package/src/List.tsx CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  getCachedConfigValue,
20
20
  getField,
21
21
  getFieldCustomization,
22
+ getSystemFieldsSchema,
22
23
  isRelationField,
23
24
  isSortingEnabled,
24
25
  tryFunction,
@@ -212,6 +213,12 @@ interface ListProps {
212
213
  direction?: "asc" | "desc"
213
214
  }
214
215
  | undefined
216
+ secondarySort:
217
+ | {
218
+ field: string
219
+ direction?: "asc" | "desc"
220
+ }
221
+ | undefined
215
222
  setOptimisticList: () => void
216
223
  relationList?: RelationList
217
224
  relationCollection?: CollectionSchema
@@ -237,6 +244,7 @@ export function List({
237
244
  setBackToStartKey,
238
245
  search,
239
246
  defaultSort,
247
+ secondarySort,
240
248
  setOptimisticList,
241
249
  relationList,
242
250
  relationCollection,
@@ -246,6 +254,7 @@ export function List({
246
254
  hasBreadcrumbs,
247
255
  }: ListProps) {
248
256
  const { labels, fields, access, recordTitleField, softDelete, fullTextSearch } = collection
257
+ const systemFields = getSystemFieldsSchema()
249
258
  const { serverWriteOnly } = access
250
259
  const softDeleteField = softDelete?.archivedField
251
260
  const softDeleteTimestampField = softDelete?.timestampField
@@ -632,7 +641,31 @@ export function List({
632
641
  })
633
642
  .filter(Boolean) as ColumnDef<StokerRecord>[]
634
643
 
635
- return [selectColumnDef, ...fieldColumns]
644
+ const allColumns = [selectColumnDef, ...fieldColumns]
645
+
646
+ if (secondarySort && !allColumns.some((column) => column.id === secondarySort.field)) {
647
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
648
+ const hiddenColumn: any = {
649
+ id: secondarySort.field,
650
+ accessorKey: secondarySort.field,
651
+ header: () => null,
652
+ cell: () => null,
653
+ enableHiding: true,
654
+ }
655
+ const field = getField(fields.concat(systemFields), secondarySort.field)
656
+ if (field.type === "String") {
657
+ hiddenColumn.sortingFn = "stringSortingFn"
658
+ } else if (isRelationField(field)) {
659
+ hiddenColumn.sortingFn = "relationSortingFn"
660
+ } else if (field.type === "Timestamp") {
661
+ hiddenColumn.sortingFn = "dateSortingFn"
662
+ } else {
663
+ hiddenColumn.sortingFn = "rawSortingFn"
664
+ }
665
+ allColumns.push(hiddenColumn as ColumnDef<StokerRecord>)
666
+ }
667
+
668
+ return allColumns
636
669
  }, [fields, isPreloadCacheEnabled, isServerReadOnly, recordTitleField, connectionStatus])
637
670
 
638
671
  const isSearchRelevanceOrder = !!(search && isPreloadCacheEnabled)
@@ -838,7 +871,10 @@ export function List({
838
871
  } else if (recordTitleField) {
839
872
  setSorting([{ id: recordTitleField, desc: false }])
840
873
  }
841
- }, [table, recordTitleField])
874
+ if ((isPreloadCacheEnabled || isServerReadOnly) && secondarySort) {
875
+ setSorting((prev) => [...prev, { id: secondarySort.field, desc: secondarySort.direction === "desc" }])
876
+ }
877
+ }, [table, recordTitleField, secondarySort, isPreloadCacheEnabled, isServerReadOnly])
842
878
 
843
879
  useEffect(() => {
844
880
  if (isPreloadCacheEnabled || isServerReadOnly) {
@@ -1725,29 +1761,39 @@ export function List({
1725
1761
  {headerGroup.headers.map((header) => {
1726
1762
  let className = ""
1727
1763
  if (header.id !== "select") {
1728
- const field = getField(fields, header.id)
1729
- const fieldCustomization = getFieldCustomization(
1730
- field,
1731
- customization,
1732
- )
1733
- const hidden = tryFunction(fieldCustomization.admin?.hidden)
1734
- if (hidden) {
1735
- switch (hidden) {
1736
- case "sm":
1737
- className = cn(className, "hidden", "sm:table-cell")
1738
- break
1739
- case "md":
1740
- className = cn(className, "hidden", "md:table-cell")
1741
- break
1742
- case "lg":
1743
- className = cn(className, "hidden", "lg:table-cell")
1744
- break
1745
- case "xl":
1746
- className = cn(className, "hidden", "xl:table-cell")
1747
- break
1748
- case "2xl":
1749
- className = cn(className, "hidden", "2xl:table-cell")
1750
- break
1764
+ if (
1765
+ !systemFields.some(
1766
+ (systemField) => systemField.name === header.id,
1767
+ )
1768
+ ) {
1769
+ const field = getField(fields, header.id)
1770
+ const fieldCustomization = getFieldCustomization(
1771
+ field,
1772
+ customization,
1773
+ )
1774
+ const hidden = tryFunction(fieldCustomization.admin?.hidden)
1775
+ if (hidden) {
1776
+ switch (hidden) {
1777
+ case "sm":
1778
+ className = cn(className, "hidden", "sm:table-cell")
1779
+ break
1780
+ case "md":
1781
+ className = cn(className, "hidden", "md:table-cell")
1782
+ break
1783
+ case "lg":
1784
+ className = cn(className, "hidden", "lg:table-cell")
1785
+ break
1786
+ case "xl":
1787
+ className = cn(className, "hidden", "xl:table-cell")
1788
+ break
1789
+ case "2xl":
1790
+ className = cn(
1791
+ className,
1792
+ "hidden",
1793
+ "2xl:table-cell",
1794
+ )
1795
+ break
1796
+ }
1751
1797
  }
1752
1798
  }
1753
1799
  } else {
@@ -1795,50 +1841,58 @@ export function List({
1795
1841
  {row.getVisibleCells().map((cell: Cell<unknown, unknown>) => {
1796
1842
  let className = "p-0"
1797
1843
  const id = cell.column.columnDef.id
1844
+ const field = getField(fields.concat(systemFields), id)
1798
1845
  if (id !== "select") {
1799
- const field = getField(fields, id)
1800
- const fieldCustomization = getFieldCustomization(
1801
- field,
1802
- customization,
1803
- )
1804
- const hidden = tryFunction(fieldCustomization.admin?.hidden)
1805
- if (hidden) {
1806
- switch (hidden) {
1807
- case "sm":
1808
- className = cn(
1809
- className,
1810
- "hidden",
1811
- "sm:table-cell",
1812
- )
1813
- break
1814
- case "md":
1815
- className = cn(
1816
- className,
1817
- "hidden",
1818
- "md:table-cell",
1819
- )
1820
- break
1821
- case "lg":
1822
- className = cn(
1823
- className,
1824
- "hidden",
1825
- "lg:table-cell",
1826
- )
1827
- break
1828
- case "xl":
1829
- className = cn(
1830
- className,
1831
- "hidden",
1832
- "xl:table-cell",
1833
- )
1834
- break
1835
- case "2xl":
1836
- className = cn(
1837
- className,
1838
- "hidden",
1839
- "2xl:table-cell",
1840
- )
1841
- break
1846
+ if (
1847
+ !systemFields.some(
1848
+ (systemField) => systemField.name === id,
1849
+ )
1850
+ ) {
1851
+ const fieldCustomization = getFieldCustomization(
1852
+ field,
1853
+ customization,
1854
+ )
1855
+ const hidden = tryFunction(
1856
+ fieldCustomization.admin?.hidden,
1857
+ )
1858
+ if (hidden) {
1859
+ switch (hidden) {
1860
+ case "sm":
1861
+ className = cn(
1862
+ className,
1863
+ "hidden",
1864
+ "sm:table-cell",
1865
+ )
1866
+ break
1867
+ case "md":
1868
+ className = cn(
1869
+ className,
1870
+ "hidden",
1871
+ "md:table-cell",
1872
+ )
1873
+ break
1874
+ case "lg":
1875
+ className = cn(
1876
+ className,
1877
+ "hidden",
1878
+ "lg:table-cell",
1879
+ )
1880
+ break
1881
+ case "xl":
1882
+ className = cn(
1883
+ className,
1884
+ "hidden",
1885
+ "xl:table-cell",
1886
+ )
1887
+ break
1888
+ case "2xl":
1889
+ className = cn(
1890
+ className,
1891
+ "hidden",
1892
+ "2xl:table-cell",
1893
+ )
1894
+ break
1895
+ }
1842
1896
  }
1843
1897
  }
1844
1898
  if (
@@ -1,4 +1,4 @@
1
- import { getField, getFieldCustomization, tryFunction } from "@stoker-platform/utils"
1
+ import { getField, getFieldCustomization, getSystemFieldsSchema, tryFunction } from "@stoker-platform/utils"
2
2
  import { CollectionCustomization, CollectionSchema, StokerRecord } from "@stoker-platform/types"
3
3
 
4
4
  export const getSortingValue = (
@@ -10,6 +10,11 @@ export const getSortingValue = (
10
10
  parentRecord?: StokerRecord,
11
11
  ) => {
12
12
  const { fields } = collection
13
+ const systemFields = getSystemFieldsSchema()
14
+ if (systemFields.some((systemField) => systemField.name === field)) {
15
+ // eslint-disable-next-line security/detect-object-injection
16
+ return record[field]
17
+ }
13
18
  const fieldSchema = getField(fields, field)
14
19
  const fieldCustomization = getFieldCustomization(fieldSchema, customization)
15
20
  // eslint-disable-next-line security/detect-object-injection