@stoker-platform/web-app 0.5.205 → 0.5.207

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,17 @@
1
1
  # @stoker-platform/web-app
2
2
 
3
+ ## 0.5.207
4
+
5
+ ### Patch Changes
6
+
7
+ - fix: fix Cards and Images views search issues
8
+
9
+ ## 0.5.206
10
+
11
+ ### Patch Changes
12
+
13
+ - feat: update Algolia search filters to match web app filters
14
+
3
15
  ## 0.5.205
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/web-app",
3
- "version": "0.5.205",
3
+ "version": "0.5.207",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "scripts": {
package/src/Cards.tsx CHANGED
@@ -812,16 +812,26 @@ function DropZone({
812
812
  if (!statusList) return []
813
813
  if (typeof orderByField !== "string") return []
814
814
  const removeEmptyRecords: StokerRecord[] = []
815
- const latestFiltered =
815
+ let latestFiltered =
816
816
  latestList?.filter(
817
817
  (record) =>
818
818
  record[statusField.name] ===
819
819
  (statusField.type === "Boolean" ? statusValue === statusValues[0] : statusValue) &&
820
820
  filterRecord(record),
821
821
  ) || []
822
+ let removedFiltered = removedList
823
+ if (search && !isPreloadCacheEnabled && !isServerReadOnly) {
824
+ const matchingIds = new Set(
825
+ localFullTextSearch(collection, search, latestFiltered.concat(removedFiltered)).map(
826
+ (result) => result.id,
827
+ ),
828
+ )
829
+ latestFiltered = latestFiltered.filter((record) => matchingIds.has(record.id))
830
+ removedFiltered = removedFiltered.filter((record) => matchingIds.has(record.id))
831
+ }
822
832
  statusList
823
833
  ?.concat(latestFiltered)
824
- .concat(removedList)
834
+ .concat(removedFiltered)
825
835
  .forEach((record) => {
826
836
  if (record !== undefined) {
827
837
  removeEmptyRecords.push(record)
@@ -851,7 +861,8 @@ function DropZone({
851
861
 
852
862
  useEffect(() => {
853
863
  setIsFirstLoad(true)
854
- }, [filters, orderByField, orderByDirection])
864
+ setPrevIds(new Set())
865
+ }, [filters, orderByField, orderByDirection, search])
855
866
 
856
867
  useEffect(() => {
857
868
  if (statusList && !isFirstLoad && !isPreloadCacheEnabled && !isServerReadOnly) {
@@ -1157,6 +1168,7 @@ export function Cards({
1157
1168
  const backToStart = useCallback(
1158
1169
  (latestConstraints?: QueryConstraint[]) => {
1159
1170
  if (!statusField) return
1171
+ setCursor({})
1160
1172
  setList({})
1161
1173
  setServerList({})
1162
1174
  statusValues?.forEach((statusValue) => {
@@ -257,6 +257,7 @@ function Collection({
257
257
  const filtersIsAssigningRef = useRef(isAssigning)
258
258
  const assignQueryGenerationRef = useRef(0)
259
259
  const displayedAssignGenerationRef = useRef(0)
260
+ const dataGenerationRef = useRef<{ [key: string | number]: number }>({})
260
261
 
261
262
  const preventChange = isRouteLoadingImmediate.has(location.pathname)
262
263
 
@@ -474,12 +475,42 @@ function Collection({
474
475
  }
475
476
  }, [search, list])
476
477
 
478
+ const prevSearchRef = useRef<string | undefined>(undefined)
479
+ useEffect(() => {
480
+ if (
481
+ !isPreloadCacheEnabled &&
482
+ !isServerReadOnly &&
483
+ fullTextSearch &&
484
+ tabRef.current !== "map" &&
485
+ tabRef.current !== "calendar"
486
+ ) {
487
+ if (prevSearchRef.current !== undefined && prevSearchRef.current !== search) {
488
+ dataGenerationRef.current.default = (dataGenerationRef.current.default || 0) + 1
489
+ }
490
+ prevSearchRef.current = search
491
+ }
492
+ }, [search])
493
+
477
494
  const getData = useCallback(
478
495
  async (query: Query, key?: string | number) => {
479
496
  const startingTab = tabRef.current
480
497
  key ||= "default"
481
498
 
482
499
  const queryGeneration = ++assignQueryGenerationRef.current
500
+ // eslint-disable-next-line security/detect-object-injection
501
+ if (dataGenerationRef.current[key] === undefined) {
502
+ // eslint-disable-next-line security/detect-object-injection
503
+ dataGenerationRef.current[key] = 0
504
+ }
505
+ // eslint-disable-next-line security/detect-object-injection
506
+ const dataGeneration = ++dataGenerationRef.current[key]
507
+ // eslint-disable-next-line security/detect-object-injection
508
+ const isCurrentData = () => dataGenerationRef.current[key] === dataGeneration
509
+ const releaseRouteLoading = () => {
510
+ if (!isPreloadCacheEnabled || relationList?.loadAll) {
511
+ setIsRouteLoading("-", location.pathname)
512
+ }
513
+ }
483
514
  const queryIsAssigning = filtersIsAssigningRef.current
484
515
  const syncDisplayIsAssigning = () => {
485
516
  if (queryGeneration >= displayedAssignGenerationRef.current) {
@@ -534,7 +565,14 @@ function Collection({
534
565
  hitsPerPage = batchSize
535
566
  }
536
567
  const constraints = getFilterConstraints(latestFilters, false, true) as [string, "==" | "in", unknown][]
537
- const objectIDs = await performFullTextSearch(collection, search, hitsPerPage, constraints)
568
+ const assigning =
569
+ queryIsAssigning && assignable && relationList && relationCollection && relationParent?.id
570
+ ? { collection: relationCollection.labels.collection, id: relationParent.id }
571
+ : undefined
572
+ const objectIDs = await performFullTextSearch(collection, search, hitsPerPage, constraints, assigning)
573
+ if (!isCurrentData()) {
574
+ return
575
+ }
538
576
  searchResults.current = { ...searchResults.current, [key]: objectIDs }
539
577
  if (
540
578
  objectIDs.length > 0 &&
@@ -563,7 +601,7 @@ function Collection({
563
601
  setServerList((prev) => ({ ...prev, [key]: [] }))
564
602
  setOptimisticList([], key)
565
603
  syncDisplayIsAssigning()
566
- setIsRouteLoading("-", location.pathname)
604
+ releaseRouteLoading()
567
605
  setCursor({})
568
606
  setPages({})
569
607
  setCount({})
@@ -607,6 +645,13 @@ function Collection({
607
645
  let firstLoad = true
608
646
 
609
647
  const load = () => {
648
+ if (!isCurrentData()) {
649
+ if (firstLoad) {
650
+ firstLoad = false
651
+ resolve()
652
+ }
653
+ return
654
+ }
610
655
  if (query.infinite) {
611
656
  setServerList((prev) => {
612
657
  // eslint-disable-next-line security/detect-object-injection
@@ -639,7 +684,14 @@ function Collection({
639
684
  }
640
685
  syncDisplayIsAssigning()
641
686
  if (!query.infinite || firstLoad) {
642
- setCursor((prev) => ({ ...prev, [key]: newCursor }))
687
+ if (multipleQueries.length > 0) {
688
+ setCursor((prev) => ({
689
+ ...prev,
690
+ [key]: { first: new Map(), last: new Map() },
691
+ }))
692
+ } else {
693
+ setCursor((prev) => ({ ...prev, [key]: newCursor }))
694
+ }
643
695
  }
644
696
  if (!isPreloadCacheEnabled || relationList?.loadAll) {
645
697
  if (!isPreloadCacheEnabled) loadedKeys.current.add(key)
@@ -687,6 +739,7 @@ function Collection({
687
739
  const result = await subscribeMany(
688
740
  [labels.collection],
689
741
  (docs: StokerRecord[], cursor?: Cursor) => {
742
+ if (!isCurrentData()) return
690
743
  loadedDocs = docs
691
744
  newCursor = {
692
745
  first: new Map(cursor?.first),
@@ -699,8 +752,8 @@ function Collection({
699
752
  },
700
753
  (error) => {
701
754
  console.error(error)
702
- if (!isPreloadCacheEnabled || relationList?.loadAll) {
703
- setIsRouteLoading("-", location.pathname)
755
+ if (isCurrentData()) {
756
+ releaseRouteLoading()
704
757
  }
705
758
  resolve()
706
759
  if (error instanceof FirestoreError && error.code === "not-found") {
@@ -709,14 +762,19 @@ function Collection({
709
762
  },
710
763
  subscribeOptions,
711
764
  )
765
+ if (!isCurrentData()) {
766
+ result.unsubscribe()
767
+ resolve()
768
+ return
769
+ }
712
770
  const { unsubscribe: newUnsubscribe, count: newCount, pages: newPages } = result
713
771
  promiseLoaded = true
714
772
  if (queryLoaded && startingTab === tabRef.current) {
715
773
  load()
716
774
  }
717
775
  } catch (error) {
718
- if (!isPreloadCacheEnabled || relationList?.loadAll) {
719
- setIsRouteLoading("-", location.pathname)
776
+ if (isCurrentData()) {
777
+ releaseRouteLoading()
720
778
  }
721
779
  reject(error)
722
780
  }
@@ -733,6 +791,10 @@ function Collection({
733
791
  ...(additionalConstraintsRef.current || []),
734
792
  ],
735
793
  })
794
+ if (!isCurrentData()) {
795
+ resolve()
796
+ return
797
+ }
736
798
  setServerList((prev) => ({ ...prev, [key]: data.records }))
737
799
  setOptimisticList(data.records, key)
738
800
  syncDisplayIsAssigning()
package/src/Images.tsx CHANGED
@@ -385,6 +385,7 @@ export const Images = memo(
385
385
  ) => {
386
386
  return new Promise<void>((resolve) => {
387
387
  infiniteLoaderRef.current?.resetloadMoreItemsCache()
388
+ setCursor({})
388
389
  setServerList({})
389
390
  setList({})
390
391
  const newQuery = {
@@ -508,8 +509,13 @@ export const Images = memo(
508
509
  }, [order])
509
510
 
510
511
  useEffect(() => {
512
+ if (!isInitialized) return
513
+ if (fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
514
+ setCursor({})
515
+ infiniteLoaderRef.current?.resetloadMoreItemsCache()
516
+ }
511
517
  const timer = setTimeout(() => {
512
- if (isInitialized && fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
518
+ if (fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
513
519
  backToStart()
514
520
  }
515
521
  }, 750)
@@ -639,10 +645,20 @@ export const Images = memo(
639
645
  if (!list) return []
640
646
  if (typeof orderByField !== "string") return []
641
647
  const removeEmptyRecords: StokerRecord[] = []
642
- const latestFiltered = latestList?.filter((record) => filterRecord(record)) || []
648
+ let latestFiltered = latestList?.filter((record) => filterRecord(record)) || []
649
+ let removedFiltered = removedList
650
+ if (search && !isPreloadCacheEnabled && !isServerReadOnly) {
651
+ const matchingIds = new Set(
652
+ localFullTextSearch(collection, search, latestFiltered.concat(removedFiltered)).map(
653
+ (result) => result.id,
654
+ ),
655
+ )
656
+ latestFiltered = latestFiltered.filter((record) => matchingIds.has(record.id))
657
+ removedFiltered = removedFiltered.filter((record) => matchingIds.has(record.id))
658
+ }
643
659
  defaultList
644
660
  ?.concat(latestFiltered)
645
- .concat(removedList)
661
+ .concat(removedFiltered)
646
662
  .forEach((record) => {
647
663
  if (record !== undefined) {
648
664
  removeEmptyRecords.push(record)
@@ -668,7 +684,7 @@ export const Images = memo(
668
684
  useEffect(() => {
669
685
  setIsFirstLoad(true)
670
686
  setPrevIds(new Set())
671
- }, [filters, orderByField, orderByDirection])
687
+ }, [filters, orderByField, orderByDirection, search])
672
688
 
673
689
  useEffect(() => {
674
690
  if (list && !isFirstLoad && !isPreloadCacheEnabled && !isServerReadOnly) {
@@ -877,6 +893,7 @@ export const Images = memo(
877
893
  (prevProps, nextProps) =>
878
894
  prevProps.list === nextProps.list &&
879
895
  prevProps.search === nextProps.search &&
896
+ prevProps.cursor === nextProps.cursor &&
880
897
  prevProps.isAssigning === nextProps.isAssigning &&
881
898
  prevProps.backToStartKey === nextProps.backToStartKey,
882
899
  )
@@ -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
  }