@stoker-platform/web-app 0.5.206 → 0.5.208

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.208
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: reduce clear search debounce interval
8
+
9
+ ## 0.5.207
10
+
11
+ ### Patch Changes
12
+
13
+ - fix: fix Cards and Images views search issues
14
+
3
15
  ## 0.5.206
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.206",
3
+ "version": "0.5.208",
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) => {
@@ -1233,12 +1245,15 @@ export function Cards({
1233
1245
  }, [backToStartKey])
1234
1246
 
1235
1247
  useEffect(() => {
1236
- const timer = setTimeout(() => {
1237
- if (isInitialized && fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
1238
- const constraints = removeCardsStatusFilter(filters)
1239
- backToStart(constraints as QueryConstraint[])
1240
- }
1241
- }, 750)
1248
+ const timer = setTimeout(
1249
+ () => {
1250
+ if (isInitialized && fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
1251
+ const constraints = removeCardsStatusFilter(filters)
1252
+ backToStart(constraints as QueryConstraint[])
1253
+ }
1254
+ },
1255
+ search ? 750 : 250,
1256
+ )
1242
1257
  return () => clearTimeout(timer)
1243
1258
  }, [search])
1244
1259
 
@@ -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) {
@@ -539,6 +570,9 @@ function Collection({
539
570
  ? { collection: relationCollection.labels.collection, id: relationParent.id }
540
571
  : undefined
541
572
  const objectIDs = await performFullTextSearch(collection, search, hitsPerPage, constraints, assigning)
573
+ if (!isCurrentData()) {
574
+ return
575
+ }
542
576
  searchResults.current = { ...searchResults.current, [key]: objectIDs }
543
577
  if (
544
578
  objectIDs.length > 0 &&
@@ -567,7 +601,7 @@ function Collection({
567
601
  setServerList((prev) => ({ ...prev, [key]: [] }))
568
602
  setOptimisticList([], key)
569
603
  syncDisplayIsAssigning()
570
- setIsRouteLoading("-", location.pathname)
604
+ releaseRouteLoading()
571
605
  setCursor({})
572
606
  setPages({})
573
607
  setCount({})
@@ -611,6 +645,13 @@ function Collection({
611
645
  let firstLoad = true
612
646
 
613
647
  const load = () => {
648
+ if (!isCurrentData()) {
649
+ if (firstLoad) {
650
+ firstLoad = false
651
+ resolve()
652
+ }
653
+ return
654
+ }
614
655
  if (query.infinite) {
615
656
  setServerList((prev) => {
616
657
  // eslint-disable-next-line security/detect-object-injection
@@ -643,7 +684,14 @@ function Collection({
643
684
  }
644
685
  syncDisplayIsAssigning()
645
686
  if (!query.infinite || firstLoad) {
646
- 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
+ }
647
695
  }
648
696
  if (!isPreloadCacheEnabled || relationList?.loadAll) {
649
697
  if (!isPreloadCacheEnabled) loadedKeys.current.add(key)
@@ -691,6 +739,7 @@ function Collection({
691
739
  const result = await subscribeMany(
692
740
  [labels.collection],
693
741
  (docs: StokerRecord[], cursor?: Cursor) => {
742
+ if (!isCurrentData()) return
694
743
  loadedDocs = docs
695
744
  newCursor = {
696
745
  first: new Map(cursor?.first),
@@ -703,8 +752,8 @@ function Collection({
703
752
  },
704
753
  (error) => {
705
754
  console.error(error)
706
- if (!isPreloadCacheEnabled || relationList?.loadAll) {
707
- setIsRouteLoading("-", location.pathname)
755
+ if (isCurrentData()) {
756
+ releaseRouteLoading()
708
757
  }
709
758
  resolve()
710
759
  if (error instanceof FirestoreError && error.code === "not-found") {
@@ -713,14 +762,19 @@ function Collection({
713
762
  },
714
763
  subscribeOptions,
715
764
  )
765
+ if (!isCurrentData()) {
766
+ result.unsubscribe()
767
+ resolve()
768
+ return
769
+ }
716
770
  const { unsubscribe: newUnsubscribe, count: newCount, pages: newPages } = result
717
771
  promiseLoaded = true
718
772
  if (queryLoaded && startingTab === tabRef.current) {
719
773
  load()
720
774
  }
721
775
  } catch (error) {
722
- if (!isPreloadCacheEnabled || relationList?.loadAll) {
723
- setIsRouteLoading("-", location.pathname)
776
+ if (isCurrentData()) {
777
+ releaseRouteLoading()
724
778
  }
725
779
  reject(error)
726
780
  }
@@ -737,6 +791,10 @@ function Collection({
737
791
  ...(additionalConstraintsRef.current || []),
738
792
  ],
739
793
  })
794
+ if (!isCurrentData()) {
795
+ resolve()
796
+ return
797
+ }
740
798
  setServerList((prev) => ({ ...prev, [key]: data.records }))
741
799
  setOptimisticList(data.records, key)
742
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,11 +509,19 @@ export const Images = memo(
508
509
  }, [order])
509
510
 
510
511
  useEffect(() => {
511
- const timer = setTimeout(() => {
512
- if (isInitialized && fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
513
- backToStart()
514
- }
515
- }, 750)
512
+ if (!isInitialized) return
513
+ if (fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
514
+ setCursor({})
515
+ infiniteLoaderRef.current?.resetloadMoreItemsCache()
516
+ }
517
+ const timer = setTimeout(
518
+ () => {
519
+ if (fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
520
+ backToStart()
521
+ }
522
+ },
523
+ search ? 750 : 250,
524
+ )
516
525
  return () => clearTimeout(timer)
517
526
  }, [search])
518
527
 
@@ -639,10 +648,20 @@ export const Images = memo(
639
648
  if (!list) return []
640
649
  if (typeof orderByField !== "string") return []
641
650
  const removeEmptyRecords: StokerRecord[] = []
642
- const latestFiltered = latestList?.filter((record) => filterRecord(record)) || []
651
+ let latestFiltered = latestList?.filter((record) => filterRecord(record)) || []
652
+ let removedFiltered = removedList
653
+ if (search && !isPreloadCacheEnabled && !isServerReadOnly) {
654
+ const matchingIds = new Set(
655
+ localFullTextSearch(collection, search, latestFiltered.concat(removedFiltered)).map(
656
+ (result) => result.id,
657
+ ),
658
+ )
659
+ latestFiltered = latestFiltered.filter((record) => matchingIds.has(record.id))
660
+ removedFiltered = removedFiltered.filter((record) => matchingIds.has(record.id))
661
+ }
643
662
  defaultList
644
663
  ?.concat(latestFiltered)
645
- .concat(removedList)
664
+ .concat(removedFiltered)
646
665
  .forEach((record) => {
647
666
  if (record !== undefined) {
648
667
  removeEmptyRecords.push(record)
@@ -668,7 +687,7 @@ export const Images = memo(
668
687
  useEffect(() => {
669
688
  setIsFirstLoad(true)
670
689
  setPrevIds(new Set())
671
- }, [filters, orderByField, orderByDirection])
690
+ }, [filters, orderByField, orderByDirection, search])
672
691
 
673
692
  useEffect(() => {
674
693
  if (list && !isFirstLoad && !isPreloadCacheEnabled && !isServerReadOnly) {
@@ -877,6 +896,7 @@ export const Images = memo(
877
896
  (prevProps, nextProps) =>
878
897
  prevProps.list === nextProps.list &&
879
898
  prevProps.search === nextProps.search &&
899
+ prevProps.cursor === nextProps.cursor &&
880
900
  prevProps.isAssigning === nextProps.isAssigning &&
881
901
  prevProps.backToStartKey === nextProps.backToStartKey,
882
902
  )
package/src/List.tsx CHANGED
@@ -867,11 +867,14 @@ export function List({
867
867
  }, [])
868
868
 
869
869
  useEffect(() => {
870
- const timer = setTimeout(() => {
871
- if (isInitialized && fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
872
- backToStart()
873
- }
874
- }, 750)
870
+ const timer = setTimeout(
871
+ () => {
872
+ if (isInitialized && fullTextSearch && !isPreloadCacheEnabled && !isServerReadOnly) {
873
+ backToStart()
874
+ }
875
+ },
876
+ search ? 750 : 250,
877
+ )
875
878
 
876
879
  if (isInitialized && (isPreloadCacheEnabled || isServerReadOnly || isServerFullTextSearch)) {
877
880
  setPageIndex(0)