@stoker-platform/web-app 0.5.203 → 0.5.206

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,26 @@
1
1
  # @stoker-platform/web-app
2
2
 
3
+ ## 0.5.206
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: update Algolia search filters to match web app filters
8
+
9
+ ## 0.5.205
10
+
11
+ ### Patch Changes
12
+
13
+ - fix: fix filter clearing issue
14
+
15
+ ## 0.5.204
16
+
17
+ ### Patch Changes
18
+
19
+ - feat: add record sidebar filters
20
+ - @stoker-platform/node-client@0.5.80
21
+ - @stoker-platform/utils@0.5.71
22
+ - @stoker-platform/web-client@0.5.84
23
+
3
24
  ## 0.5.203
4
25
 
5
26
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/web-app",
3
- "version": "0.5.203",
3
+ "version": "0.5.206",
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.79",
55
- "@stoker-platform/utils": "0.5.70",
56
- "@stoker-platform/web-client": "0.5.83",
54
+ "@stoker-platform/node-client": "0.5.80",
55
+ "@stoker-platform/utils": "0.5.71",
56
+ "@stoker-platform/web-client": "0.5.84",
57
57
  "@tanstack/react-table": "^8.21.3",
58
58
  "@types/react": "18.3.13",
59
59
  "@types/react-dom": "18.3.1",
@@ -534,7 +534,11 @@ function Collection({
534
534
  hitsPerPage = batchSize
535
535
  }
536
536
  const constraints = getFilterConstraints(latestFilters, false, true) as [string, "==" | "in", unknown][]
537
- const objectIDs = await performFullTextSearch(collection, search, hitsPerPage, constraints)
537
+ const assigning =
538
+ queryIsAssigning && assignable && relationList && relationCollection && relationParent?.id
539
+ ? { collection: relationCollection.labels.collection, id: relationParent.id }
540
+ : undefined
541
+ const objectIDs = await performFullTextSearch(collection, search, hitsPerPage, constraints, assigning)
538
542
  searchResults.current = { ...searchResults.current, [key]: objectIDs }
539
543
  if (
540
544
  objectIDs.length > 0 &&
@@ -1359,6 +1363,9 @@ function Collection({
1359
1363
  }
1360
1364
  }
1361
1365
  })
1366
+ if (relationList.showFilters) {
1367
+ excluded.push(...relationList.showFilters)
1368
+ }
1362
1369
  }
1363
1370
  return excluded
1364
1371
  }, [isPreloadCacheEnabled, cardsConfig, statusField, tab, filters])
package/src/Filters.tsx CHANGED
@@ -58,6 +58,7 @@ interface FiltersProps {
58
58
  relationParent?: StokerRecord
59
59
  assignable?: Assignable
60
60
  isAssigning?: boolean
61
+ isSidebar?: boolean
61
62
  }
62
63
 
63
64
  export function Filters({
@@ -68,6 +69,7 @@ export function Filters({
68
69
  relationParent,
69
70
  assignable,
70
71
  isAssigning,
72
+ isSidebar,
71
73
  }: FiltersProps) {
72
74
  const { labels, fields } = collection
73
75
  const location = useLocation()
@@ -830,6 +832,13 @@ export function Filters({
830
832
  filters.forEach((filter) => {
831
833
  if (filter.type === "status" || filter.type === "range") return
832
834
  if (relationList && relationList.field === filter.field) return
835
+ if (
836
+ "condition" in filter &&
837
+ filter.condition &&
838
+ !filter.condition(relationCollection, relationParent, isAssigning)
839
+ )
840
+ return
841
+ if (isSidebar && !relationList?.showFilters?.includes(filter.field)) return
833
842
  const field = getField(fields, filter.field)
834
843
  if (!field) return
835
844
  if (filter.type === "select") {
package/src/Record.tsx CHANGED
@@ -30,6 +30,7 @@ import { serverReadOnly } from "./utils/serverReadOnly"
30
30
  import { useRouteLoading } from "./providers/LoadingProvider"
31
31
  import { getRelationFields } from "./utils/getRelationFields"
32
32
  import { FiltersProvider } from "./providers/FiltersProvider"
33
+ import { SidebarFilters } from "./SidebarFilters"
33
34
  import Collection from "./Collection"
34
35
  import { Breadcrumbs } from "./Breadcrumbs"
35
36
  import { Separator } from "./components/ui/separator"
@@ -82,6 +83,7 @@ export const Record = ({ collection }: { collection: CollectionSchema }) => {
82
83
 
83
84
  const [isAssigning, setIsAssigning] = useState<Record<string, boolean>>({})
84
85
  const [assignable, setAssignable] = useState<Assignable[] | undefined>(undefined)
86
+ const [sidebarFiltersContainer, setSidebarFiltersContainer] = useState<HTMLDivElement | null>(null)
85
87
 
86
88
  useEffect(() => {
87
89
  if (id && record && record.id !== id) {
@@ -213,6 +215,7 @@ export const Record = ({ collection }: { collection: CollectionSchema }) => {
213
215
  customRecordPages={customRecordPages}
214
216
  isAssigning={isAssigning}
215
217
  setIsAssigning={setIsAssigning}
218
+ filtersContainerRef={setSidebarFiltersContainer}
216
219
  />
217
220
  <Routes>
218
221
  <Route
@@ -277,6 +280,25 @@ export const Record = ({ collection }: { collection: CollectionSchema }) => {
277
280
  </div>
278
281
  </>
279
282
  )}
283
+ {sidebarFiltersContainer && (
284
+ <SidebarFilters
285
+ key={`${relationList.collection}-sidebar-filters`}
286
+ container={sidebarFiltersContainer}
287
+ collection={relationCollection}
288
+ relationList={relationList}
289
+ relationCollection={collection}
290
+ relationParent={record}
291
+ assignable={assignable?.find(
292
+ (item: Assignable) =>
293
+ item.collection === relationList.collection,
294
+ )}
295
+ isAssigning={
296
+ isAssigning?.[
297
+ relationList.collection.toLowerCase()
298
+ ]
299
+ }
300
+ />
301
+ )}
280
302
  <Collection
281
303
  key={`${relationList.collection}-collection`}
282
304
  collection={relationCollection}
@@ -35,12 +35,14 @@ export const RecordSidebar = ({
35
35
  customRecordPages,
36
36
  isAssigning,
37
37
  setIsAssigning,
38
+ filtersContainerRef,
38
39
  }: {
39
40
  record: StokerRecord
40
41
  collection: CollectionSchema
41
42
  customRecordPages?: CustomRecordPage[]
42
43
  isAssigning: Record<string, boolean>
43
44
  setIsAssigning: (isAssigning: Record<string, boolean>) => void
45
+ filtersContainerRef?: (element: HTMLDivElement | null) => void
44
46
  }) => {
45
47
  const { labels } = collection
46
48
  const { path, id } = useParams()
@@ -308,6 +310,7 @@ export const RecordSidebar = ({
308
310
  )}
309
311
  </div>
310
312
  </SidebarMenu>
313
+ <div ref={filtersContainerRef} />
311
314
  </SidebarGroupContent>
312
315
  </SidebarGroup>
313
316
  </SidebarContent>
@@ -0,0 +1,59 @@
1
+ import { Assignable, CollectionSchema, RelationList, StokerRecord } from "@stoker-platform/types"
2
+ import { useMemo } from "react"
3
+ import { createPortal } from "react-dom"
4
+ import { Filters } from "./Filters"
5
+ import { useFilters } from "./providers/FiltersProvider"
6
+ import { Separator } from "./components/ui/separator"
7
+
8
+ export const SidebarFilters = ({
9
+ container,
10
+ collection,
11
+ relationList,
12
+ relationCollection,
13
+ relationParent,
14
+ assignable,
15
+ isAssigning,
16
+ }: {
17
+ container: HTMLElement
18
+ collection: CollectionSchema
19
+ relationList: RelationList
20
+ relationCollection: CollectionSchema
21
+ relationParent: StokerRecord
22
+ assignable?: Assignable
23
+ isAssigning?: boolean
24
+ }) => {
25
+ const { filters } = useFilters()
26
+ const showFilters = relationList.showFilters
27
+
28
+ const excluded = useMemo(
29
+ () =>
30
+ filters
31
+ .filter((filter) => filter.type !== "status" && filter.type !== "range")
32
+ .map((filter) => filter.field)
33
+ .filter((field) => !showFilters?.includes(field)),
34
+ [filters, showFilters],
35
+ )
36
+
37
+ if (!showFilters?.length) return null
38
+ const hasFiltersToShow = filters.some(
39
+ (filter) => filter.type !== "status" && filter.type !== "range" && showFilters.includes(filter.field),
40
+ )
41
+ if (!hasFiltersToShow) return null
42
+
43
+ return createPortal(
44
+ <div className="flex flex-col gap-4 px-2 pt-2">
45
+ <Separator />
46
+ <Filters
47
+ collection={collection}
48
+ excluded={excluded}
49
+ relationList={relationList}
50
+ relationCollection={relationCollection}
51
+ relationParent={relationParent}
52
+ assignable={assignable}
53
+ isAssigning={isAssigning}
54
+ isSidebar={true}
55
+ />
56
+ </div>,
57
+ container,
58
+ )
59
+ }
@@ -51,5 +51,23 @@ export const getFilterDisjunctions = (collection: CollectionSchema, options?: Fi
51
51
  incrementDisjunctions(2)
52
52
  }
53
53
  }
54
+ if (
55
+ options?.isAssigning &&
56
+ options.relationList &&
57
+ options.relationParent?.id &&
58
+ options.assignable?.includeValueInFilters?.length &&
59
+ options.filters
60
+ ) {
61
+ const activeOrCount = options.filters.filter(
62
+ (filter) =>
63
+ filter.type === "select" &&
64
+ filter.value &&
65
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
66
+ options.assignable!.includeValueInFilters!.some((item) => item.field === filter.field),
67
+ ).length
68
+ for (let i = 0; i < activeOrCount; i++) {
69
+ incrementDisjunctions(2)
70
+ }
71
+ }
54
72
  return disjunctions
55
73
  }
@@ -7,6 +7,7 @@ export const performFullTextSearch = async (
7
7
  search: string,
8
8
  hitsPerPage: number,
9
9
  constraints?: [string, "==" | "in", unknown][],
10
+ assigning?: { collection: string; id: string },
10
11
  ) => {
11
12
  const { labels } = collection
12
13
  const firebaseFunctions = getFunctions(getApp(), import.meta.env.STOKER_FB_FUNCTIONS_REGION)
@@ -16,6 +17,7 @@ export const performFullTextSearch = async (
16
17
  query: search,
17
18
  hitsPerPage,
18
19
  constraints,
20
+ assigning,
19
21
  })) as { data: string[] }
20
22
  return results.data
21
23
  }