@stoker-platform/web-app 0.5.96 → 0.5.98

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.98
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: add titles context parameter
8
+ - @stoker-platform/node-client@0.5.55
9
+ - @stoker-platform/utils@0.5.47
10
+ - @stoker-platform/web-client@0.5.56
11
+
12
+ ## 0.5.97
13
+
14
+ ### Patch Changes
15
+
16
+ - feat: add Computed field asRichText option
17
+ - @stoker-platform/node-client@0.5.54
18
+ - @stoker-platform/utils@0.5.46
19
+ - @stoker-platform/web-client@0.5.55
20
+
3
21
  ## 0.5.96
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.96",
3
+ "version": "0.5.98",
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.50.0",
54
- "@stoker-platform/node-client": "0.5.53",
55
- "@stoker-platform/utils": "0.5.45",
56
- "@stoker-platform/web-client": "0.5.54",
54
+ "@stoker-platform/node-client": "0.5.55",
55
+ "@stoker-platform/utils": "0.5.47",
56
+ "@stoker-platform/web-client": "0.5.56",
57
57
  "@tanstack/react-table": "^8.21.3",
58
58
  "@types/react": "18.3.13",
59
59
  "@types/react-dom": "18.3.1",
package/src/Calendar.tsx CHANGED
@@ -394,7 +394,7 @@ export function Calendar({
394
394
  ])) as CalendarConfig
395
395
  setCalendarConfig(calendarConfig)
396
396
  const titles = await getCachedConfigValue(customization, [...collectionAdminPath, "titles"])
397
- setCollectionTitle(titles?.collection)
397
+ setCollectionTitle(titles?.collection || labels.collection)
398
398
  const meta = await getCachedConfigValue(customization, [...collectionAdminPath, "meta"])
399
399
  setMeta(meta)
400
400
  const originalRangeFilter = filters.find((filter) => filter.type === "range")
@@ -1039,9 +1039,9 @@ export function Calendar({
1039
1039
 
1040
1040
  return (
1041
1041
  <>
1042
- {!formList && (
1042
+ {!formList && (meta?.title || collectionTitle) && (
1043
1043
  <Helmet>
1044
- <title>{`${meta?.title || collectionTitle || labels.collection} - Calendar`}</title>
1044
+ <title>{`${meta?.title || collectionTitle || ""} - Calendar`}</title>
1045
1045
  {meta?.description && <meta name="description" content={meta.description} />}
1046
1046
  </Helmet>
1047
1047
  )}
package/src/Cards.tsx CHANGED
@@ -1371,7 +1371,7 @@ export function Cards({
1371
1371
  ])
1372
1372
  setIsOfflineDisabled(offlineDisabled)
1373
1373
  const titles = await getCachedConfigValue(customization, [...collectionAdminPath, "titles"])
1374
- setCollectionTitle(titles?.collection)
1374
+ setCollectionTitle(titles?.collection || labels.collection)
1375
1375
  const meta = await getCachedConfigValue(customization, [...collectionAdminPath, "meta"])
1376
1376
  setMeta(meta)
1377
1377
  const cardsConfig = await getCachedConfigValue(customization, [...collectionAdminPath, "cards"])
@@ -1510,9 +1510,9 @@ export function Cards({
1510
1510
 
1511
1511
  return (
1512
1512
  <>
1513
- {!formList && (
1513
+ {!formList && (meta?.title || collectionTitle) && (
1514
1514
  <Helmet>
1515
- <title>{`${meta?.title || collectionTitle || labels.collection} - Board`}</title>
1515
+ <title>{`${meta?.title || collectionTitle || ""} - Board`}</title>
1516
1516
  {meta?.description && <meta name="description" content={meta.description} />}
1517
1517
  </Helmet>
1518
1518
  )}
package/src/Files.tsx CHANGED
@@ -847,10 +847,12 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
847
847
 
848
848
  return (
849
849
  <>
850
- <Helmet>
851
- <title>{`${meta?.title || collectionTitle || labels.collection} - Files`}</title>
852
- {meta?.description && <meta name="description" content={meta.description} />}
853
- </Helmet>
850
+ {(meta?.title || collectionTitle) && (
851
+ <Helmet>
852
+ <title>{`${meta?.title || collectionTitle || ""} - Files`}</title>
853
+ {meta?.description && <meta name="description" content={meta.description} />}
854
+ </Helmet>
855
+ )}
854
856
 
855
857
  <div className="flex items-center space-x-2 mb-4">
856
858
  {currentPath && (
package/src/Form.tsx CHANGED
@@ -56,7 +56,17 @@ import {
56
56
  getFiles,
57
57
  getTenant,
58
58
  } from "@stoker-platform/web-client"
59
- import { createElement, forwardRef, startTransition, useCallback, useEffect, useMemo, useRef, useState } from "react"
59
+ import {
60
+ createElement,
61
+ forwardRef,
62
+ startTransition,
63
+ useCallback,
64
+ useEffect,
65
+ useLayoutEffect,
66
+ useMemo,
67
+ useRef,
68
+ useState,
69
+ } from "react"
60
70
  import { useNavigate, useParams } from "react-router"
61
71
  import { createPortal } from "react-dom"
62
72
  import isEqual from "lodash/isEqual.js"
@@ -337,7 +347,6 @@ const RecordFormField = (props: FieldProps) => {
337
347
  tryPromise(admin?.icon),
338
348
  ])
339
349
 
340
- setReadOnly(!!readOnly)
341
350
  setLabel(label || field.name)
342
351
  if (!(admin?.description?.condition && !descriptionCondition)) {
343
352
  setDescription(description)
@@ -354,6 +363,8 @@ const RecordFormField = (props: FieldProps) => {
354
363
  setIsButtonGroup(!!isButtonGroup)
355
364
  setIcon(icon)
356
365
  // Prevent button and rich text editor from flickering
366
+ const initialReadOnly = tryFunction(admin?.readOnly, [operation, record])
367
+ setReadOnly(!!initialReadOnly)
357
368
  setTimeout(() => {
358
369
  setIsFormReady((prevState) => prevState + 1)
359
370
  }, 100)
@@ -416,6 +427,18 @@ const RecordFormField = (props: FieldProps) => {
416
427
  isUpdateDisabled))
417
428
 
418
429
  if (isReadOnly && !isRichText) {
430
+ if (field.type === "Computed" && tryFunction(customization.admin?.asRichText)) {
431
+ return (
432
+ <MapField
433
+ {...props}
434
+ label={label}
435
+ description={description}
436
+ isRichText={true}
437
+ readOnly={true}
438
+ icon={icon}
439
+ />
440
+ )
441
+ }
419
442
  return <ComputedField {...props} label={label} description={description} icon={icon} />
420
443
  }
421
444
 
@@ -506,6 +529,18 @@ const RecordFormField = (props: FieldProps) => {
506
529
  />
507
530
  )
508
531
  case "Computed":
532
+ if (field.type === "Computed" && tryFunction(customization.admin?.asRichText)) {
533
+ return (
534
+ <MapField
535
+ {...props}
536
+ label={label}
537
+ description={description}
538
+ isRichText={true}
539
+ readOnly={true}
540
+ icon={icon}
541
+ />
542
+ )
543
+ }
509
544
  return <ComputedField {...props} label={label} description={description} icon={icon} />
510
545
  default:
511
546
  if (isRelationField(field) && schema.collections[field.collection]) {
@@ -1636,7 +1671,7 @@ const RichTextEditor = forwardRef<
1636
1671
  const containerRef = useRef<HTMLDivElement>(null)
1637
1672
  const initializedRef = useRef(false)
1638
1673
 
1639
- useEffect(() => {
1674
+ useLayoutEffect(() => {
1640
1675
  if (!initializedRef.current) return
1641
1676
  if (ref && typeof ref === "object" && ref.current) {
1642
1677
  const quill = ref.current
@@ -1649,7 +1684,7 @@ const RichTextEditor = forwardRef<
1649
1684
  }
1650
1685
  }, [ref, formField.value])
1651
1686
 
1652
- useEffect(() => {
1687
+ useLayoutEffect(() => {
1653
1688
  const container = containerRef.current
1654
1689
  if (!container) return
1655
1690
  initializedRef.current = false
@@ -1712,7 +1747,7 @@ const RichTextEditor = forwardRef<
1712
1747
  }
1713
1748
  }, [ref])
1714
1749
 
1715
- useEffect(() => {
1750
+ useLayoutEffect(() => {
1716
1751
  if (ref && typeof ref === "object" && ref.current) {
1717
1752
  ref.current.enable(!readOnly && !isDisabled)
1718
1753
  const container = containerRef.current
@@ -2407,6 +2442,7 @@ function RecordForm({
2407
2442
  const [hidden, setHidden] = useState(false)
2408
2443
  const [collectionTitle, setCollectionTitle] = useState("")
2409
2444
  const [allTitles, setAllTitles] = useState<Record<StokerCollection, string>>({})
2445
+ const [permissionsTitles, setPermissionsTitles] = useState<Record<StokerCollection, string>>({})
2410
2446
  const [allRecordTitles, setAllRecordTitles] = useState<Record<StokerCollection, string>>({})
2411
2447
  const [recordTitle, setRecordTitle] = useState(undefined)
2412
2448
  const [meta, setMeta] = useState<CollectionMeta | undefined>(undefined)
@@ -3546,8 +3582,15 @@ function RecordForm({
3546
3582
  ])
3547
3583
  return { collection, titles: collectionTitles }
3548
3584
  })
3585
+ const permissionTitlePromises = Object.values(schema.collections).map(async (collection) => {
3586
+ const collectionCustomization = getCollectionConfigModule(collection.labels.collection)
3587
+ const collectionTitles = await tryPromise(collectionCustomization.admin?.titles, ["permissions"])
3588
+ return { collection, titles: collectionTitles }
3589
+ })
3549
3590
 
3550
3591
  const collectionTitleResults = await Promise.all(collectionTitlePromises)
3592
+ const permissionTitleResults = await Promise.all(permissionTitlePromises)
3593
+
3551
3594
  collectionTitleResults.forEach(({ collection, titles: collectionTitles }) => {
3552
3595
  setAllTitles((prev) => ({
3553
3596
  ...prev,
@@ -3564,6 +3607,12 @@ function RecordForm({
3564
3607
  }))
3565
3608
  }
3566
3609
  })
3610
+ permissionTitleResults.forEach(({ collection, titles: collectionTitles }) => {
3611
+ setPermissionsTitles((prev) => ({
3612
+ ...prev,
3613
+ [collection.labels.collection]: collectionTitles?.collection || collection.labels.collection,
3614
+ }))
3615
+ })
3567
3616
 
3568
3617
  if (operation === "create" && offlinePersistenceType && ["ALL", "WRITE"].includes(offlinePersistenceType)) {
3569
3618
  const draft = localStorage.getItem(`stoker-draft-${labels.collection}`)
@@ -4454,10 +4503,12 @@ function RecordForm({
4454
4503
 
4455
4504
  return (
4456
4505
  <>
4457
- <Helmet>
4458
- <title>{`${meta?.title || collectionTitle || labels.collection} - Edit`}</title>
4459
- {meta?.description && <meta name="description" content={meta.description} />}
4460
- </Helmet>
4506
+ {(meta?.title || collectionTitle) && (
4507
+ <Helmet>
4508
+ <title>{`${meta?.title || collectionTitle || ""} - Edit`}</title>
4509
+ {meta?.description && <meta name="description" content={meta.description} />}
4510
+ </Helmet>
4511
+ )}
4461
4512
  {operation === "update" && record && hasBreadcrumbs && (
4462
4513
  <>
4463
4514
  <Breadcrumbs breadcrumbs={breadcrumbs} collection={collection} record={record} />
@@ -4643,7 +4694,7 @@ function RecordForm({
4643
4694
  }
4644
4695
  >
4645
4696
  <FormLabel className="text-primary">
4646
- {allTitles[permissionsCollection.labels.collection]}
4697
+ {permissionsTitles[permissionsCollection.labels.collection]}
4647
4698
  </FormLabel>
4648
4699
  <div className="flex flex-row gap-3 mt-2">
4649
4700
  {permissionsCollection.access.auth?.includes(role) &&
@@ -4820,12 +4871,12 @@ function RecordForm({
4820
4871
  restriction.type ===
4821
4872
  "Record_Owner"
4822
4873
  ) {
4823
- label = `Can only access own ${allTitles[permissionsCollection.labels.collection]}`
4874
+ label = `Can only access own ${permissionsTitles[permissionsCollection.labels.collection]}`
4824
4875
  } else if (
4825
4876
  restriction.type ===
4826
4877
  "Record_User"
4827
4878
  ) {
4828
- label = `Can only access assigned ${allTitles[permissionsCollection.labels.collection]}`
4879
+ label = `Can only access assigned ${permissionsTitles[permissionsCollection.labels.collection]}`
4829
4880
  } else if (
4830
4881
  restriction.type ===
4831
4882
  "Record_Property"
package/src/Images.tsx CHANGED
@@ -522,7 +522,7 @@ export const Images = memo(
522
522
  const imagesConfig = await getCachedConfigValue(customization, [...collectionAdminPath, "images"])
523
523
  setImagesConfig(imagesConfig)
524
524
  const titles = await getCachedConfigValue(customization, [...collectionAdminPath, "titles"])
525
- setCollectionTitle(titles?.collection)
525
+ setCollectionTitle(titles?.collection || labels.collection)
526
526
  const meta = await getCachedConfigValue(customization, [...collectionAdminPath, "meta"])
527
527
  setMeta(meta)
528
528
  setCursor({})
@@ -780,7 +780,7 @@ export const Images = memo(
780
780
 
781
781
  const Meta = () => (
782
782
  <Helmet>
783
- <title>{`${meta?.title || collectionTitle || labels.collection} - Photos`}</title>
783
+ <title>{`${meta?.title || collectionTitle || ""} - Photos`}</title>
784
784
  {meta?.description && <meta name="description" content={meta.description} />}
785
785
  </Helmet>
786
786
  )
@@ -811,7 +811,7 @@ export const Images = memo(
811
811
  : "",
812
812
  )}
813
813
  >
814
- {!formList && <Meta />}
814
+ {!formList && (meta?.title || collectionTitle) && <Meta />}
815
815
  <List
816
816
  height={height}
817
817
  width="100%"
@@ -836,7 +836,7 @@ export const Images = memo(
836
836
  : "",
837
837
  )}
838
838
  >
839
- {!formList && <Meta />}
839
+ {!formList && (meta?.title || collectionTitle) && <Meta />}
840
840
  <InfiniteLoader
841
841
  isItemLoaded={(index) => index < itemCount}
842
842
  itemCount={100000}
package/src/List.tsx CHANGED
@@ -232,7 +232,7 @@ export function List({
232
232
  const metrics = await getCachedConfigValue(customization, [...collectionAdminPath, "metrics"])
233
233
  setMetrics(metrics)
234
234
  const titles = await getCachedConfigValue(customization, [...collectionAdminPath, "titles"])
235
- setCollectionTitle(titles?.collection)
235
+ setCollectionTitle(titles?.collection || labels.collection)
236
236
  const meta = await getCachedConfigValue(customization, [...collectionAdminPath, "meta"])
237
237
  setMeta(meta)
238
238
  const rowHighlight = await getCachedConfigValue(customization, [...collectionAdminPath, "rowHighlight"])
@@ -1319,9 +1319,9 @@ export function List({
1319
1319
 
1320
1320
  return (
1321
1321
  <>
1322
- {!formList && (
1322
+ {!formList && (meta?.title || collectionTitle) && (
1323
1323
  <Helmet>
1324
- <title>{`${meta?.title || collectionTitle || labels.collection} - List`}</title>
1324
+ <title>{`${meta?.title || collectionTitle || ""} - List`}</title>
1325
1325
  {meta?.description && <meta name="description" content={meta.description} />}
1326
1326
  </Helmet>
1327
1327
  )}
@@ -1349,8 +1349,7 @@ export function List({
1349
1349
  metric.type === "count" ||
1350
1350
  metric.type === "custom"
1351
1351
  ) {
1352
- const metricTitle =
1353
- metric.title || `Total ${collectionTitle || labels.collection}`
1352
+ const metricTitle = metric.title || `Total ${collectionTitle}`
1354
1353
  return (
1355
1354
  <div
1356
1355
  key={`metric-${index}`}
@@ -1385,8 +1384,7 @@ export function List({
1385
1384
  )
1386
1385
  }
1387
1386
  if (metric.type === "area") {
1388
- const metricTitle =
1389
- metric.title || `${collectionTitle || labels.collection} Over Time`
1387
+ const metricTitle = metric.title || `${collectionTitle} Over Time`
1390
1388
  const metricField1 = metric.metricField1
1391
1389
  ? getField(fields, metric.metricField1)
1392
1390
  : undefined
@@ -1635,7 +1633,7 @@ export function List({
1635
1633
  <div className="space-y-2">
1636
1634
  <div className="flex justify-between items-center mb-4">
1637
1635
  <h4 id="dialog-title" className="font-medium leading-none">
1638
- Update {collectionTitle || labels.collection}
1636
+ Update {collectionTitle}
1639
1637
  </h4>
1640
1638
  <Button
1641
1639
  type="button"
package/src/Map.tsx CHANGED
@@ -201,7 +201,7 @@ export function Map({
201
201
  const recordTitle = await getCachedConfigValue(customization, [...collectionAdminPath, "titles", "record"])
202
202
  setRecordTitle(recordTitle || labels.record)
203
203
  const titles = await getCachedConfigValue(customization, [...collectionAdminPath, "titles"])
204
- setCollectionTitle(titles?.collection)
204
+ setCollectionTitle(titles?.collection || labels.collection)
205
205
  const mapConfig = await getCachedConfigValue(customization, [...collectionAdminPath, "map"])
206
206
  setMapConfig(mapConfig)
207
207
  const meta = await getCachedConfigValue(customization, [...collectionAdminPath, "meta"])
@@ -559,9 +559,9 @@ export function Map({
559
559
 
560
560
  return (
561
561
  <>
562
- {!formList && (
562
+ {!formList && (meta?.title || collectionTitle) && (
563
563
  <Helmet>
564
- <title>{`${meta?.title || collectionTitle || labels.collection} - Map`}</title>
564
+ <title>{`${meta?.title || collectionTitle || ""} - Map`}</title>
565
565
  {meta?.description && <meta name="description" content={meta.description} />}
566
566
  </Helmet>
567
567
  )}
@@ -75,7 +75,7 @@ export const RecordSidebar = ({
75
75
 
76
76
  const editItem = [
77
77
  {
78
- title: "Edit",
78
+ title: "Details",
79
79
  page: "edit",
80
80
  icon: EditIcon,
81
81
  },