@stoker-platform/web-app 0.5.58 → 0.5.60

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,23 @@
1
1
  # @stoker-platform/web-app
2
2
 
3
+ ## 0.5.60
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: add relation list loadAll option
8
+ - Updated dependencies
9
+ - @stoker-platform/web-client@0.5.37
10
+ - @stoker-platform/node-client@0.5.39
11
+ - @stoker-platform/utils@0.5.33
12
+
13
+ ## 0.5.59
14
+
15
+ ### Patch Changes
16
+
17
+ - feat: improve permissions change logic
18
+ - Updated dependencies
19
+ - @stoker-platform/web-client@0.5.36
20
+
3
21
  ## 0.5.58
4
22
 
5
23
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/web-app",
3
- "version": "0.5.58",
3
+ "version": "0.5.60",
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.47.0",
54
- "@stoker-platform/node-client": "0.5.38",
55
- "@stoker-platform/utils": "0.5.32",
56
- "@stoker-platform/web-client": "0.5.35",
54
+ "@stoker-platform/node-client": "0.5.39",
55
+ "@stoker-platform/utils": "0.5.33",
56
+ "@stoker-platform/web-client": "0.5.37",
57
57
  "@tanstack/react-table": "^8.21.3",
58
58
  "@types/react": "18.3.13",
59
59
  "@types/react-dom": "18.3.1",
@@ -14,6 +14,7 @@ import {
14
14
  RelationField,
15
15
  RelationList,
16
16
  StokerCollection,
17
+ StokerPermissions,
17
18
  StokerRecord,
18
19
  StokerRole,
19
20
  } from "@stoker-platform/types"
@@ -30,10 +31,12 @@ import {
30
31
  GetSomeOptions,
31
32
  getTimezone,
32
33
  keepTimezone,
34
+ onStokerPermissionsChange,
33
35
  onStokerSignOut,
34
36
  subscribeMany,
35
37
  SubscribeManyOptions,
36
38
  updateRecord,
39
+ getPreloadListeners,
37
40
  } from "@stoker-platform/web-client"
38
41
  import { createElement, useCallback, useEffect, useMemo, useRef, useState } from "react"
39
42
  import { useLocation, useNavigate } from "react-router"
@@ -153,7 +156,7 @@ function Collection({
153
156
  const schema = getSchema()
154
157
  const customization = getCollectionConfigModule(labels.collection)
155
158
  const timezone = getTimezone()
156
- const permissions = getCurrentUserPermissions()
159
+ const [permissions, setPermissions] = useState<StokerPermissions | null>(() => getCurrentUserPermissions())
157
160
  if (!permissions?.Role) throw new Error("PERMISSION_DENIED")
158
161
  const { toast } = useToast()
159
162
 
@@ -236,6 +239,13 @@ function Collection({
236
239
 
237
240
  const preventChange = isRouteLoadingImmediate.has(location.pathname)
238
241
 
242
+ useEffect(() => {
243
+ const unsubscribe = onStokerPermissionsChange(() => {
244
+ setPermissions(getCurrentUserPermissions())
245
+ })
246
+ return unsubscribe
247
+ }, [])
248
+
239
249
  const onTabChange = useCallback((value: string) => {
240
250
  Object.values(unsubscribe.current).forEach((unsubscribe) => unsubscribe.forEach((unsubscribe) => unsubscribe()))
241
251
  unsubscribe.current = {}
@@ -444,7 +454,7 @@ function Collection({
444
454
  const startingTab = tabRef.current
445
455
  key ||= "default"
446
456
 
447
- if (!isPreloadCacheEnabled) {
457
+ if (!isPreloadCacheEnabled || relationList?.loadAll) {
448
458
  setIsRouteLoading("+", location.pathname)
449
459
  }
450
460
 
@@ -572,8 +582,8 @@ function Collection({
572
582
  if (!query.infinite || firstLoad) {
573
583
  setCursor((prev) => ({ ...prev, [key]: newCursor }))
574
584
  }
575
- if (!isPreloadCacheEnabled) {
576
- loadedKeys.current.add(key)
585
+ if (!isPreloadCacheEnabled || relationList?.loadAll) {
586
+ if (!isPreloadCacheEnabled) loadedKeys.current.add(key)
577
587
  if (loadedKeys.current.size === keysLength.current) {
578
588
  setIsRouteLoading("-", location.pathname)
579
589
  }
@@ -618,7 +628,7 @@ function Collection({
618
628
  },
619
629
  (error) => {
620
630
  console.error(error)
621
- if (!isPreloadCacheEnabled) {
631
+ if (!isPreloadCacheEnabled || relationList?.loadAll) {
622
632
  setIsRouteLoading("-", location.pathname)
623
633
  }
624
634
  resolve()
@@ -628,6 +638,13 @@ function Collection({
628
638
  },
629
639
  {
630
640
  ...currentQuery.options,
641
+ tempCache:
642
+ isPreloadCacheEnabled && relationList?.loadAll
643
+ ? {
644
+ label: `${labels.collection}-${relationList?.field}`,
645
+ constraints: [[`${relationList?.field}.${relationParent?.id}`, ">", {}]],
646
+ }
647
+ : undefined,
631
648
  } as SubscribeManyOptions,
632
649
  )
633
650
  const { unsubscribe: newUnsubscribe, count: newCount, pages: newPages } = result
@@ -636,7 +653,7 @@ function Collection({
636
653
  load()
637
654
  }
638
655
  } catch (error) {
639
- if (!isPreloadCacheEnabled) {
656
+ if (!isPreloadCacheEnabled || relationList?.loadAll) {
640
657
  setIsRouteLoading("-", location.pathname)
641
658
  }
642
659
  reject(error)
@@ -971,51 +988,49 @@ function Collection({
971
988
  if (currentField && (!rangeFilter || isPreloadCacheEnabled)) {
972
989
  let rangeValue = rangeState
973
990
  if (preloadCache?.range) {
974
- if (!rangeValue) {
975
- if (formList) {
991
+ if (formList || relationList?.loadAll) {
992
+ rangeValue = JSON.stringify({
993
+ from: getMinDate(),
994
+ to: getMaxDate(),
995
+ })
996
+ } else if (!rangeValue) {
997
+ const now = convertDateToTimezone(new Date())
998
+ if (rangeSelectorState === "month") {
999
+ rangeValue = JSON.stringify({
1000
+ from: now
1001
+ .startOf("month")
1002
+ .plus({ days: preloadCache.range.startOffsetDays || 0 })
1003
+ .plus({ hours: preloadCache.range.startOffsetHours })
1004
+ .toJSDate()
1005
+ .toISOString(),
1006
+ to: now
1007
+ .endOf("month")
1008
+ .plus({ days: preloadCache.range.endOffsetDays || 0 })
1009
+ .plus({ hours: preloadCache.range.endOffsetHours })
1010
+ .toJSDate()
1011
+ .toISOString(),
1012
+ })
1013
+ } else if (rangeSelectorState === "week") {
976
1014
  rangeValue = JSON.stringify({
977
- from: getMinDate(),
978
- to: getMaxDate(),
1015
+ from: now
1016
+ .startOf("week")
1017
+ .plus({ days: preloadCache.range.startOffsetDays || 0 })
1018
+ .plus({ hours: preloadCache.range.startOffsetHours })
1019
+ .toJSDate()
1020
+ .toISOString(),
1021
+ to: now
1022
+ .endOf("week")
1023
+ .plus({ days: preloadCache.range.endOffsetDays || 0 })
1024
+ .plus({ hours: preloadCache.range.endOffsetHours })
1025
+ .toJSDate()
1026
+ .toISOString(),
979
1027
  })
980
1028
  } else {
981
- const now = convertDateToTimezone(new Date())
982
- if (rangeSelectorState === "month") {
983
- rangeValue = JSON.stringify({
984
- from: now
985
- .startOf("month")
986
- .plus({ days: preloadCache.range.startOffsetDays || 0 })
987
- .plus({ hours: preloadCache.range.startOffsetHours })
988
- .toJSDate()
989
- .toISOString(),
990
- to: now
991
- .endOf("month")
992
- .plus({ days: preloadCache.range.endOffsetDays || 0 })
993
- .plus({ hours: preloadCache.range.endOffsetHours })
994
- .toJSDate()
995
- .toISOString(),
996
- })
997
- } else if (rangeSelectorState === "week") {
998
- rangeValue = JSON.stringify({
999
- from: now
1000
- .startOf("week")
1001
- .plus({ days: preloadCache.range.startOffsetDays || 0 })
1002
- .plus({ hours: preloadCache.range.startOffsetHours })
1003
- .toJSDate()
1004
- .toISOString(),
1005
- to: now
1006
- .endOf("week")
1007
- .plus({ days: preloadCache.range.endOffsetDays || 0 })
1008
- .plus({ hours: preloadCache.range.endOffsetHours })
1009
- .toJSDate()
1010
- .toISOString(),
1011
- })
1012
- } else {
1013
- const preloadCacheRange = getRange(preloadCache.range, timezone)
1014
- rangeValue = JSON.stringify({
1015
- from: preloadCacheRange.start.toISOString(),
1016
- to: preloadCacheRange.end?.toISOString(),
1017
- })
1018
- }
1029
+ const preloadCacheRange = getRange(preloadCache.range, timezone)
1030
+ rangeValue = JSON.stringify({
1031
+ from: preloadCacheRange.start.toISOString(),
1032
+ to: preloadCacheRange.end?.toISOString(),
1033
+ })
1019
1034
  }
1020
1035
  }
1021
1036
  filtersClone.push({
@@ -1144,6 +1159,12 @@ function Collection({
1144
1159
  document.removeEventListener(`stoker:loading:${labels.collection}`, cacheLoading)
1145
1160
  document.removeEventListener(`stoker:loaded:${labels.collection}`, cacheLoaded)
1146
1161
  }
1162
+ if (relationList?.loadAll) {
1163
+ const unsubscribes = getPreloadListeners()[`${labels.collection}-${relationList.field}`]
1164
+ if (unsubscribes) {
1165
+ unsubscribes.forEach((unsubscribe) => unsubscribe())
1166
+ }
1167
+ }
1147
1168
  }
1148
1169
  }, [])
1149
1170
 
@@ -1333,7 +1354,7 @@ function Collection({
1333
1354
  }, [calendarConfig, schema])
1334
1355
 
1335
1356
  const canAddRecords =
1336
- permissions.collections?.[labels.collection].operations.includes("Create") &&
1357
+ permissions.collections?.[labels.collection]?.operations.includes("Create") &&
1337
1358
  !hasEntityRestrictions.some((entityRestriction) => entityRestriction.type === "Individual") &&
1338
1359
  !disableCreate
1339
1360
  const isCreateDisabled = getConnectionStatus() === "Offline" && (isOfflineDisabled || serverWriteOnly)
@@ -1641,6 +1662,8 @@ function Collection({
1641
1662
  [recordTitle],
1642
1663
  )
1643
1664
 
1665
+ if (!permissions.collections?.[labels.collection]) return null
1666
+
1644
1667
  return (
1645
1668
  !collection.singleton && (
1646
1669
  <>
@@ -1664,24 +1687,26 @@ function Collection({
1664
1687
  </Card>
1665
1688
  {(connectionStatus === "online" || isPreloadCacheEnabled) && (
1666
1689
  <>
1667
- {tab !== "calendar" && (hasRangeFilter || currentField) && (
1668
- <div
1669
- className={cn(
1670
- "hidden",
1671
- relationList ? "xl:flex" : "lg:flex",
1672
- "2xl:hidden absolute",
1673
- relationList ? "left-[calc(50%+98px)]" : "left-1/2",
1674
- "transform -translate-x-1/2",
1675
- )}
1676
- >
1677
- <DateRangeSelector
1678
- collection={collection}
1679
- rangeSelector={rangeSelector}
1680
- setRangeSelector={setRangeSelector}
1681
- relationList={!!relationList}
1682
- />
1683
- </div>
1684
- )}
1690
+ {tab !== "calendar" &&
1691
+ !relationList?.loadAll &&
1692
+ (hasRangeFilter || currentField) && (
1693
+ <div
1694
+ className={cn(
1695
+ "hidden",
1696
+ relationList ? "xl:flex" : "lg:flex",
1697
+ "2xl:hidden absolute",
1698
+ relationList ? "left-[calc(50%+98px)]" : "left-1/2",
1699
+ "transform -translate-x-1/2",
1700
+ )}
1701
+ >
1702
+ <DateRangeSelector
1703
+ collection={collection}
1704
+ rangeSelector={rangeSelector}
1705
+ setRangeSelector={setRangeSelector}
1706
+ relationList={!!relationList}
1707
+ />
1708
+ </div>
1709
+ )}
1685
1710
  <div className="relative ml-auto flex-1 md:grow-0 print:hidden flex items-center">
1686
1711
  {tab !== "calendar" &&
1687
1712
  tab !== "map" &&
@@ -1735,7 +1760,7 @@ function Collection({
1735
1760
  )}
1736
1761
  </header>
1737
1762
  )}
1738
- {!(connectionStatus === "online" || isPreloadCacheEnabled) ? (
1763
+ {!(connectionStatus === "online" || (isPreloadCacheEnabled && !relationList?.loadAll)) ? (
1739
1764
  <div
1740
1765
  className={cn(
1741
1766
  "flex justify-center items-center p-5",
@@ -1771,8 +1796,8 @@ function Collection({
1771
1796
  )}
1772
1797
  >
1773
1798
  {formList && (
1774
- <Badge variant="outline" className="py-2 px-4 text-md">
1775
- {formList.label || formList.collection}
1799
+ <Badge variant="outline" className="py-2 px-4 text-md whitespace-nowrap">
1800
+ {formList.label || collectionTitle || formList.collection}
1776
1801
  </Badge>
1777
1802
  )}
1778
1803
  <div className="lg:h-9">
@@ -1800,22 +1825,25 @@ function Collection({
1800
1825
  </TabsList>
1801
1826
  )}
1802
1827
  </div>
1803
- {!formList && tab !== "calendar" && (hasRangeFilter || currentField) && (
1804
- <div
1805
- className={cn(
1806
- relationList
1807
- ? "xl:hidden 2xl:flex xl:absolute xl:left-[calc(50%+128px)] xl:transform xl:-translate-x-[calc(50%+98px)] xl:mt-0 mt-2"
1808
- : "lg:hidden 2xl:flex lg:absolute lg:left-1/2 lg:transform lg:-translate-x-1/2 lg:mt-0 mt-2",
1809
- )}
1810
- >
1811
- <DateRangeSelector
1812
- collection={collection}
1813
- rangeSelector={rangeSelector}
1814
- setRangeSelector={setRangeSelector}
1815
- relationList={!!relationList}
1816
- />
1817
- </div>
1818
- )}
1828
+ {!formList &&
1829
+ !relationList?.loadAll &&
1830
+ tab !== "calendar" &&
1831
+ (hasRangeFilter || currentField) && (
1832
+ <div
1833
+ className={cn(
1834
+ relationList
1835
+ ? "xl:hidden 2xl:flex xl:absolute xl:left-[calc(50%+128px)] xl:transform xl:-translate-x-[calc(50%+98px)] xl:mt-0 mt-2"
1836
+ : "lg:hidden 2xl:flex lg:absolute lg:left-1/2 lg:transform lg:-translate-x-1/2 lg:mt-0 mt-2",
1837
+ )}
1838
+ >
1839
+ <DateRangeSelector
1840
+ collection={collection}
1841
+ rangeSelector={rangeSelector}
1842
+ setRangeSelector={setRangeSelector}
1843
+ relationList={!!relationList}
1844
+ />
1845
+ </div>
1846
+ )}
1819
1847
  <div
1820
1848
  className={cn(
1821
1849
  "ml-auto flex items-center gap-2 justify-center w-full",
package/src/Form.tsx CHANGED
@@ -5247,18 +5247,6 @@ function RecordForm({
5247
5247
  field: formList.sortField || relationCollection.recordTitleField,
5248
5248
  direction: formList.sortDirection,
5249
5249
  }}
5250
- additionalConstraints={(() => {
5251
- if (record) {
5252
- return [
5253
- [
5254
- `${relationList.field}_Array`,
5255
- "array-contains",
5256
- record.id,
5257
- ],
5258
- ]
5259
- }
5260
- return []
5261
- })()}
5262
5250
  />
5263
5251
  </FiltersProvider>
5264
5252
  </div>