@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 +12 -0
- package/package.json +1 -1
- package/src/Cards.tsx +15 -3
- package/src/Collection.tsx +69 -7
- package/src/Images.tsx +21 -4
- package/src/utils/performFullTextSearch.ts +2 -0
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
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
|
-
|
|
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(
|
|
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
|
-
|
|
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) => {
|
package/src/Collection.tsx
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
703
|
-
|
|
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 (
|
|
719
|
-
|
|
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 (
|
|
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
|
-
|
|
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(
|
|
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
|
}
|