@asd20/ui-next 2.3.7 → 2.4.0
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 +19 -0
- package/package.json +1 -1
- package/src/components/molecules/Asd20StoryItemOld/index.vue +27 -3
- package/src/components/molecules/Asd20Tab/index.vue +22 -1
- package/src/components/organisms/Asd20AiSearch/index.vue +15 -6
- package/src/components/organisms/Asd20SiteSearch/index.vue +234 -80
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
# [2.4.0](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.3.8...ui-next-v2.4.0) (2026-05-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* fix search state routing ([64f10cc](https://github.com/academydistrict20/asd20-ui-next/commit/64f10cc37b2f3d6e2b27b54e4fe96b94054bfb6d))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* improve search persistence and clearing ([6a27f9b](https://github.com/academydistrict20/asd20-ui-next/commit/6a27f9bfe62898ca00618b7fe896b061c44e5532))
|
|
14
|
+
|
|
15
|
+
## [2.3.8](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.3.7...ui-next-v2.3.8) (2026-04-30)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* fix search results not persisting ([041aba0](https://github.com/academydistrict20/asd20-ui-next/commit/041aba02a5dc761ee3c5ca47ab18a364d369c0b5))
|
|
21
|
+
|
|
3
22
|
## [2.3.7](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.3.6...ui-next-v2.3.7) (2026-04-29)
|
|
4
23
|
|
|
5
24
|
|
package/package.json
CHANGED
|
@@ -83,6 +83,27 @@ import Asd20TagGroup from '../../../components/organisms/Asd20TagGroup'
|
|
|
83
83
|
import Asd20TextAvatar from '../../../components/atoms/Asd20TextAvatar'
|
|
84
84
|
import Asd20ThumbnailAvatar from '../../../components/atoms/Asd20ThumbnailAvatar'
|
|
85
85
|
|
|
86
|
+
function resolveRouter(vm) {
|
|
87
|
+
const internal = vm && vm.$
|
|
88
|
+
const context = internal && internal.ctx
|
|
89
|
+
if (context && context.$router) {
|
|
90
|
+
return context.$router
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const parentContext = internal && internal.parent && internal.parent.ctx
|
|
94
|
+
if (parentContext && parentContext.$router) {
|
|
95
|
+
return parentContext.$router
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
internal &&
|
|
100
|
+
internal.appContext &&
|
|
101
|
+
internal.appContext.config &&
|
|
102
|
+
internal.appContext.config.globalProperties &&
|
|
103
|
+
internal.appContext.config.globalProperties.$router
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
86
107
|
export default {
|
|
87
108
|
name: 'Asd20StoryItem',
|
|
88
109
|
|
|
@@ -132,7 +153,8 @@ export default {
|
|
|
132
153
|
return this.link || this.to
|
|
133
154
|
},
|
|
134
155
|
usesRouterNavigation() {
|
|
135
|
-
|
|
156
|
+
const router = resolveRouter(this)
|
|
157
|
+
if (!router || !this.to) return false
|
|
136
158
|
if (typeof this.to === 'string') return this.to.startsWith('/')
|
|
137
159
|
return typeof this.to === 'object'
|
|
138
160
|
},
|
|
@@ -143,9 +165,11 @@ export default {
|
|
|
143
165
|
|
|
144
166
|
methods: {
|
|
145
167
|
onClick(e) {
|
|
146
|
-
|
|
168
|
+
const router = resolveRouter(this)
|
|
169
|
+
|
|
170
|
+
if (this.usesRouterNavigation && router && typeof router.push === 'function') {
|
|
147
171
|
e.preventDefault()
|
|
148
|
-
|
|
172
|
+
router.push(this.to)
|
|
149
173
|
}
|
|
150
174
|
},
|
|
151
175
|
},
|
|
@@ -32,6 +32,27 @@
|
|
|
32
32
|
import Asd20Icon from '../../../components/atoms/Asd20Icon'
|
|
33
33
|
import Asd20Badge from '../../../components/atoms/Asd20Badge'
|
|
34
34
|
|
|
35
|
+
function resolveRouter(vm) {
|
|
36
|
+
const internal = vm && vm.$
|
|
37
|
+
const context = internal && internal.ctx
|
|
38
|
+
if (context && context.$router) {
|
|
39
|
+
return context.$router
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const parentContext = internal && internal.parent && internal.parent.ctx
|
|
43
|
+
if (parentContext && parentContext.$router) {
|
|
44
|
+
return parentContext.$router
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
internal &&
|
|
49
|
+
internal.appContext &&
|
|
50
|
+
internal.appContext.config &&
|
|
51
|
+
internal.appContext.config.globalProperties &&
|
|
52
|
+
internal.appContext.config.globalProperties.$router
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
35
56
|
export default {
|
|
36
57
|
name: 'Asd20Tab',
|
|
37
58
|
|
|
@@ -52,7 +73,7 @@ export default {
|
|
|
52
73
|
|
|
53
74
|
computed: {
|
|
54
75
|
component() {
|
|
55
|
-
if (this
|
|
76
|
+
if (resolveRouter(this) && this.to) return 'router-link'
|
|
56
77
|
return 'button'
|
|
57
78
|
},
|
|
58
79
|
classes() {
|
|
@@ -374,21 +374,30 @@ export default {
|
|
|
374
374
|
hasExistingResults() {
|
|
375
375
|
const siteSearch = this.$refs.siteSearch
|
|
376
376
|
if (!siteSearch) return false
|
|
377
|
+
const pages = Array.isArray(siteSearch.currentPages)
|
|
378
|
+
? siteSearch.currentPages
|
|
379
|
+
: siteSearch.resolvedPages
|
|
380
|
+
const files = Array.isArray(siteSearch.currentFiles)
|
|
381
|
+
? siteSearch.currentFiles
|
|
382
|
+
: siteSearch.resolvedFiles
|
|
383
|
+
const groups = Array.isArray(siteSearch.currentGroups)
|
|
384
|
+
? siteSearch.currentGroups
|
|
385
|
+
: siteSearch.resolvedGroups
|
|
377
386
|
if (
|
|
378
|
-
Array.isArray(
|
|
379
|
-
|
|
387
|
+
Array.isArray(pages) &&
|
|
388
|
+
pages.length
|
|
380
389
|
) {
|
|
381
390
|
return true
|
|
382
391
|
}
|
|
383
392
|
if (
|
|
384
|
-
Array.isArray(
|
|
385
|
-
|
|
393
|
+
Array.isArray(files) &&
|
|
394
|
+
files.length
|
|
386
395
|
) {
|
|
387
396
|
return true
|
|
388
397
|
}
|
|
389
398
|
if (
|
|
390
|
-
Array.isArray(
|
|
391
|
-
|
|
399
|
+
Array.isArray(groups) &&
|
|
400
|
+
groups.length
|
|
392
401
|
) {
|
|
393
402
|
return true
|
|
394
403
|
}
|
|
@@ -327,19 +327,19 @@
|
|
|
327
327
|
v-if="
|
|
328
328
|
hasSubmitted &&
|
|
329
329
|
showContacts &&
|
|
330
|
-
|
|
330
|
+
currentGroups.length === 0 &&
|
|
331
331
|
!searchingFiles
|
|
332
332
|
"
|
|
333
333
|
title="No Contacts Found"
|
|
334
334
|
description="Try using different keywords."
|
|
335
335
|
/>
|
|
336
336
|
<div
|
|
337
|
-
v-if="
|
|
337
|
+
v-if="currentGroups.length > 0 && showContacts"
|
|
338
338
|
class="asd20-site-search__suggested"
|
|
339
339
|
>
|
|
340
340
|
<h3>
|
|
341
341
|
{{
|
|
342
|
-
|
|
342
|
+
currentGroups.length > 1
|
|
343
343
|
? 'Suggested Contacts:'
|
|
344
344
|
: 'Suggested Contact:'
|
|
345
345
|
}}
|
|
@@ -357,7 +357,7 @@
|
|
|
357
357
|
/>
|
|
358
358
|
</div>
|
|
359
359
|
<asd20-loader
|
|
360
|
-
v-if="searchingFiles &&
|
|
360
|
+
v-if="searchingFiles && currentGroups.length === 0"
|
|
361
361
|
size="lg"
|
|
362
362
|
/>
|
|
363
363
|
</asd20-viewport>
|
|
@@ -381,7 +381,7 @@
|
|
|
381
381
|
<hr/>AI can make mistakes. Verify important information."
|
|
382
382
|
/>
|
|
383
383
|
<asd20-notification
|
|
384
|
-
v-if="keywords &&
|
|
384
|
+
v-if="keywords && currentFiles.length === 0 && !searchingFiles"
|
|
385
385
|
title="No Files Found"
|
|
386
386
|
description="Try using different keywords."
|
|
387
387
|
/>
|
|
@@ -707,6 +707,10 @@ export default {
|
|
|
707
707
|
searchingPages: false,
|
|
708
708
|
searchingFiles: false,
|
|
709
709
|
|
|
710
|
+
localSearchPages: null,
|
|
711
|
+
localSearchFiles: null,
|
|
712
|
+
localSearchGroups: null,
|
|
713
|
+
|
|
710
714
|
keywordsFromAi: false,
|
|
711
715
|
aiKeywordsDisplayAnswer: '',
|
|
712
716
|
aiKeywordsDisplayPages: '',
|
|
@@ -725,6 +729,7 @@ export default {
|
|
|
725
729
|
.toString(36)
|
|
726
730
|
.slice(2, 9)}`,
|
|
727
731
|
activeAiQuestionKey: '',
|
|
732
|
+
searchRunId: 0,
|
|
728
733
|
|
|
729
734
|
scrollReflowTimer: null,
|
|
730
735
|
bodyScrollLock: null,
|
|
@@ -738,6 +743,21 @@ export default {
|
|
|
738
743
|
}),
|
|
739
744
|
|
|
740
745
|
computed: {
|
|
746
|
+
currentPages() {
|
|
747
|
+
if (Array.isArray(this.localSearchPages)) return this.localSearchPages
|
|
748
|
+
return Array.isArray(this.resolvedPages) ? this.resolvedPages : []
|
|
749
|
+
},
|
|
750
|
+
|
|
751
|
+
currentFiles() {
|
|
752
|
+
if (Array.isArray(this.localSearchFiles)) return this.localSearchFiles
|
|
753
|
+
return Array.isArray(this.resolvedFiles) ? this.resolvedFiles : []
|
|
754
|
+
},
|
|
755
|
+
|
|
756
|
+
currentGroups() {
|
|
757
|
+
if (Array.isArray(this.localSearchGroups)) return this.localSearchGroups
|
|
758
|
+
return Array.isArray(this.resolvedGroups) ? this.resolvedGroups : []
|
|
759
|
+
},
|
|
760
|
+
|
|
741
761
|
shouldUsePageFallbacks() {
|
|
742
762
|
const hasSearchText =
|
|
743
763
|
typeof this.keywords === 'string' && this.keywords.trim()
|
|
@@ -745,14 +765,14 @@ export default {
|
|
|
745
765
|
this.hasSubmitted &&
|
|
746
766
|
!!hasSearchText &&
|
|
747
767
|
!this.searchingPages &&
|
|
748
|
-
Array.isArray(this.
|
|
749
|
-
this.
|
|
768
|
+
Array.isArray(this.currentPages) &&
|
|
769
|
+
this.currentPages.length === 0
|
|
750
770
|
)
|
|
751
771
|
},
|
|
752
772
|
|
|
753
773
|
displayPages() {
|
|
754
|
-
if (Array.isArray(this.
|
|
755
|
-
return this.
|
|
774
|
+
if (Array.isArray(this.currentPages) && this.currentPages.length) {
|
|
775
|
+
return this.currentPages
|
|
756
776
|
}
|
|
757
777
|
if (!this.shouldUsePageFallbacks) return []
|
|
758
778
|
|
|
@@ -821,8 +841,8 @@ export default {
|
|
|
821
841
|
},
|
|
822
842
|
|
|
823
843
|
fileListItems() {
|
|
824
|
-
return Array.isArray(this.
|
|
825
|
-
? mapFilesToListItems(this.
|
|
844
|
+
return Array.isArray(this.currentFiles)
|
|
845
|
+
? mapFilesToListItems(this.currentFiles)
|
|
826
846
|
: []
|
|
827
847
|
},
|
|
828
848
|
|
|
@@ -843,13 +863,13 @@ export default {
|
|
|
843
863
|
if (this.showContacts) {
|
|
844
864
|
assistantTabs.push({
|
|
845
865
|
label: 'Contacts',
|
|
846
|
-
badge: this.
|
|
866
|
+
badge: this.currentGroups.length,
|
|
847
867
|
active: this.currentTab === 'Contacts',
|
|
848
868
|
})
|
|
849
869
|
}
|
|
850
870
|
assistantTabs.push({
|
|
851
871
|
label: 'Files',
|
|
852
|
-
badge: this.
|
|
872
|
+
badge: this.currentFiles.length,
|
|
853
873
|
active: this.currentTab === 'Files',
|
|
854
874
|
})
|
|
855
875
|
return assistantTabs
|
|
@@ -866,13 +886,13 @@ export default {
|
|
|
866
886
|
if (this.showContacts) {
|
|
867
887
|
keywordTabs.push({
|
|
868
888
|
label: 'Contacts',
|
|
869
|
-
badge: this.
|
|
889
|
+
badge: this.currentGroups.length,
|
|
870
890
|
active: this.currentTab === 'Contacts',
|
|
871
891
|
})
|
|
872
892
|
}
|
|
873
893
|
keywordTabs.push({
|
|
874
894
|
label: 'Files',
|
|
875
|
-
badge: this.
|
|
895
|
+
badge: this.currentFiles.length,
|
|
876
896
|
active: this.currentTab === 'Files',
|
|
877
897
|
})
|
|
878
898
|
return keywordTabs
|
|
@@ -952,7 +972,7 @@ export default {
|
|
|
952
972
|
})
|
|
953
973
|
},
|
|
954
974
|
groupListItems() {
|
|
955
|
-
return (this.
|
|
975
|
+
return (this.currentGroups || []).map(g => {
|
|
956
976
|
const org =
|
|
957
977
|
(Array.isArray(this.organizationOptions) &&
|
|
958
978
|
this.organizationOptions.find(
|
|
@@ -1125,17 +1145,19 @@ export default {
|
|
|
1125
1145
|
return
|
|
1126
1146
|
}
|
|
1127
1147
|
if (newVal !== oldVal) {
|
|
1148
|
+
const runId = this.beginSearchRun()
|
|
1128
1149
|
this.selectedGroup = null
|
|
1129
|
-
this.searchPages()
|
|
1130
|
-
this.searchFilesWithGroupOwners()
|
|
1150
|
+
this.searchPages({ runId })
|
|
1151
|
+
this.searchFilesWithGroupOwners({ runId })
|
|
1131
1152
|
this.syncSearchStateToRoute()
|
|
1132
1153
|
}
|
|
1133
1154
|
}, 400),
|
|
1134
1155
|
|
|
1135
1156
|
resolvedIncludeDistrictResults() {
|
|
1136
1157
|
if (this.routeRestoreInProgress) return
|
|
1137
|
-
this.
|
|
1138
|
-
this.
|
|
1158
|
+
const runId = this.beginSearchRun()
|
|
1159
|
+
this.searchPages({ runId })
|
|
1160
|
+
this.searchFilesWithGroupOwners({ runId })
|
|
1139
1161
|
this.syncSearchStateToRoute()
|
|
1140
1162
|
},
|
|
1141
1163
|
// Clear AI answer if user clears the input
|
|
@@ -1244,9 +1266,44 @@ export default {
|
|
|
1244
1266
|
},
|
|
1245
1267
|
|
|
1246
1268
|
setSearchResults({ pages, files, groups } = {}) {
|
|
1247
|
-
if (pages !== undefined)
|
|
1248
|
-
|
|
1249
|
-
|
|
1269
|
+
if (pages !== undefined) {
|
|
1270
|
+
this.localSearchPages = Array.isArray(pages) ? pages : []
|
|
1271
|
+
}
|
|
1272
|
+
if (files !== undefined) {
|
|
1273
|
+
this.localSearchFiles = Array.isArray(files) ? files : []
|
|
1274
|
+
}
|
|
1275
|
+
if (groups !== undefined) {
|
|
1276
|
+
this.localSearchGroups = Array.isArray(groups) ? groups : []
|
|
1277
|
+
}
|
|
1278
|
+
},
|
|
1279
|
+
|
|
1280
|
+
readSearchResults(target) {
|
|
1281
|
+
if (target === 'pages') return this.currentPages
|
|
1282
|
+
if (target === 'files') return this.currentFiles
|
|
1283
|
+
if (target === 'groups') return this.currentGroups
|
|
1284
|
+
return []
|
|
1285
|
+
},
|
|
1286
|
+
|
|
1287
|
+
readResolvedSearchResults(target) {
|
|
1288
|
+
if (target === 'pages') {
|
|
1289
|
+
return Array.isArray(this.resolvedPages) ? this.resolvedPages : []
|
|
1290
|
+
}
|
|
1291
|
+
if (target === 'files') {
|
|
1292
|
+
return Array.isArray(this.resolvedFiles) ? this.resolvedFiles : []
|
|
1293
|
+
}
|
|
1294
|
+
if (target === 'groups') {
|
|
1295
|
+
return Array.isArray(this.resolvedGroups) ? this.resolvedGroups : []
|
|
1296
|
+
}
|
|
1297
|
+
return []
|
|
1298
|
+
},
|
|
1299
|
+
|
|
1300
|
+
beginSearchRun() {
|
|
1301
|
+
this.searchRunId += 1
|
|
1302
|
+
return this.searchRunId
|
|
1303
|
+
},
|
|
1304
|
+
|
|
1305
|
+
isCurrentSearchRun(runId) {
|
|
1306
|
+
return !runId || this.searchRunId === runId
|
|
1250
1307
|
},
|
|
1251
1308
|
|
|
1252
1309
|
async querySearchCollectionWithFallback({
|
|
@@ -1254,23 +1311,32 @@ export default {
|
|
|
1254
1311
|
storeAction,
|
|
1255
1312
|
payload,
|
|
1256
1313
|
target,
|
|
1314
|
+
runId,
|
|
1257
1315
|
}) {
|
|
1258
1316
|
if (typeof handler === 'function') {
|
|
1259
1317
|
const result = await handler(payload)
|
|
1318
|
+
if (!this.isCurrentSearchRun(runId)) {
|
|
1319
|
+
return this.readSearchResults(target)
|
|
1320
|
+
}
|
|
1260
1321
|
if (Array.isArray(result)) {
|
|
1261
|
-
this[target]
|
|
1322
|
+
this.setSearchResults({ [target]: result })
|
|
1262
1323
|
return result
|
|
1263
1324
|
}
|
|
1264
|
-
return
|
|
1325
|
+
return this.readSearchResults(target)
|
|
1265
1326
|
}
|
|
1266
1327
|
|
|
1267
1328
|
const searchStore = this.getSearchStore()
|
|
1268
1329
|
if (searchStore) {
|
|
1269
1330
|
await searchStore.dispatch(storeAction, payload)
|
|
1270
|
-
|
|
1331
|
+
const result = this.readResolvedSearchResults(target)
|
|
1332
|
+
if (!this.isCurrentSearchRun(runId)) {
|
|
1333
|
+
return this.readSearchResults(target)
|
|
1334
|
+
}
|
|
1335
|
+
this.setSearchResults({ [target]: result })
|
|
1336
|
+
return result
|
|
1271
1337
|
}
|
|
1272
1338
|
|
|
1273
|
-
return
|
|
1339
|
+
return this.readSearchResults(target)
|
|
1274
1340
|
},
|
|
1275
1341
|
|
|
1276
1342
|
async queryAiSiteWithFallback(payload) {
|
|
@@ -1511,9 +1577,9 @@ export default {
|
|
|
1511
1577
|
: 'Pages',
|
|
1512
1578
|
searchMode: this.searchMode || '',
|
|
1513
1579
|
includeDistrictResults: !!this.resolvedIncludeDistrictResults,
|
|
1514
|
-
pages: Array.isArray(this.
|
|
1515
|
-
files: Array.isArray(this.
|
|
1516
|
-
groups: Array.isArray(this.
|
|
1580
|
+
pages: Array.isArray(this.currentPages) ? this.currentPages : [],
|
|
1581
|
+
files: Array.isArray(this.currentFiles) ? this.currentFiles : [],
|
|
1582
|
+
groups: Array.isArray(this.currentGroups) ? this.currentGroups : [],
|
|
1517
1583
|
aiAnswer: this.aiAnswer || null,
|
|
1518
1584
|
aiSources: Array.isArray(this.aiSources) ? this.aiSources : [],
|
|
1519
1585
|
aiErrorMessage: this.aiErrorMessage || '',
|
|
@@ -1791,7 +1857,34 @@ export default {
|
|
|
1791
1857
|
|
|
1792
1858
|
appendSearchContextToUrl(rawUrl) {
|
|
1793
1859
|
if (!rawUrl || typeof rawUrl !== 'string') return rawUrl
|
|
1794
|
-
|
|
1860
|
+
const state = this.getCurrentSearchStateForRoute()
|
|
1861
|
+
if (!state) return rawUrl
|
|
1862
|
+
if (typeof window === 'undefined' || typeof URL === 'undefined') {
|
|
1863
|
+
return rawUrl
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
const trimmedUrl = rawUrl.trim()
|
|
1867
|
+
if (!trimmedUrl) return rawUrl
|
|
1868
|
+
if (/^(#|mailto:|tel:|javascript:)/i.test(trimmedUrl)) return rawUrl
|
|
1869
|
+
|
|
1870
|
+
try {
|
|
1871
|
+
const resolvedUrl = new URL(trimmedUrl, window.location.href)
|
|
1872
|
+
if (resolvedUrl.origin !== window.location.origin) return rawUrl
|
|
1873
|
+
|
|
1874
|
+
const stateQueryValues = this.buildRouteSearchQueryValues(state)
|
|
1875
|
+
Object.entries(stateQueryValues).forEach(([key, value]) => {
|
|
1876
|
+
if (value === undefined || value === null || value === '') {
|
|
1877
|
+
resolvedUrl.searchParams.delete(key)
|
|
1878
|
+
return
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
resolvedUrl.searchParams.set(key, value)
|
|
1882
|
+
})
|
|
1883
|
+
|
|
1884
|
+
return `${resolvedUrl.pathname}${resolvedUrl.search}${resolvedUrl.hash}`
|
|
1885
|
+
} catch (error) {
|
|
1886
|
+
return rawUrl
|
|
1887
|
+
}
|
|
1795
1888
|
},
|
|
1796
1889
|
|
|
1797
1890
|
async restoreSearchStateFromRoute() {
|
|
@@ -1870,18 +1963,21 @@ export default {
|
|
|
1870
1963
|
await this.searchAi(restoredState.text)
|
|
1871
1964
|
} else {
|
|
1872
1965
|
await this.clearSearchState()
|
|
1966
|
+
const runId = this.searchRunId
|
|
1873
1967
|
this.keywordsFromAi = false
|
|
1874
1968
|
this.skipKeywordWatcher = true
|
|
1875
1969
|
this.keywords = this.limitWords(restoredState.text, 4)
|
|
1876
1970
|
this.searchQuestion = restoredState.text
|
|
1877
1971
|
|
|
1878
1972
|
await Promise.all([
|
|
1879
|
-
this.searchPages({ keepAnswersTab: false }),
|
|
1880
|
-
this.searchFilesWithGroupOwners(),
|
|
1973
|
+
this.searchPages({ keepAnswersTab: false, runId }),
|
|
1974
|
+
this.searchFilesWithGroupOwners({ runId }),
|
|
1881
1975
|
])
|
|
1882
1976
|
}
|
|
1883
1977
|
}
|
|
1884
1978
|
|
|
1979
|
+
if (this.lastRestoredSearchKey !== restoreKey) return
|
|
1980
|
+
|
|
1885
1981
|
const hasManualTabOverride =
|
|
1886
1982
|
this.hasRecentManualTabSelection() ||
|
|
1887
1983
|
(this.lastManualTabChangeAt > restoreStartedAt &&
|
|
@@ -2372,7 +2468,18 @@ export default {
|
|
|
2372
2468
|
async clearSearchState(options = {}) {
|
|
2373
2469
|
const resetConversation = options.resetConversation !== false
|
|
2374
2470
|
const resetTranscript = options.resetTranscript !== false
|
|
2471
|
+
const preserveSearchRun = options.preserveSearchRun === true
|
|
2472
|
+
const preserveAiLoading = options.preserveAiLoading === true
|
|
2473
|
+
if (!preserveSearchRun) {
|
|
2474
|
+
this.beginSearchRun()
|
|
2475
|
+
}
|
|
2375
2476
|
this.selectedGroup = null
|
|
2477
|
+
this.searchingAi = preserveAiLoading ? this.searchingAi : false
|
|
2478
|
+
this.searchingPages = false
|
|
2479
|
+
this.searchingFiles = false
|
|
2480
|
+
this.activeAiQuestionKey = preserveAiLoading
|
|
2481
|
+
? this.activeAiQuestionKey
|
|
2482
|
+
: ''
|
|
2376
2483
|
this.aiAnswer = null
|
|
2377
2484
|
this.aiSources = []
|
|
2378
2485
|
this.aiKeywordsDisplayAnswer = ''
|
|
@@ -2422,38 +2529,50 @@ export default {
|
|
|
2422
2529
|
|
|
2423
2530
|
async searchPages(options = {}) {
|
|
2424
2531
|
const keepAnswersTab = options.keepAnswersTab || this.keywordsFromAi
|
|
2532
|
+
const runId = options.runId || this.searchRunId
|
|
2425
2533
|
const searchInput = {
|
|
2426
2534
|
keywords: this.keywords,
|
|
2427
2535
|
question: this.searchQuestion || this.inputText,
|
|
2428
2536
|
}
|
|
2429
2537
|
|
|
2430
2538
|
this.searchingPages = true
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2539
|
+
try {
|
|
2540
|
+
await this.querySearchCollectionWithFallback({
|
|
2541
|
+
handler: this.queryPagesHandler,
|
|
2542
|
+
storeAction: 'search/queryPages',
|
|
2543
|
+
payload: searchInput,
|
|
2544
|
+
target: 'pages',
|
|
2545
|
+
runId,
|
|
2546
|
+
})
|
|
2547
|
+
if (!this.isCurrentSearchRun(runId)) {
|
|
2548
|
+
return this.currentPages
|
|
2549
|
+
}
|
|
2438
2550
|
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2551
|
+
if (this.keywords && this.keywords.trim() && !keepAnswersTab) {
|
|
2552
|
+
this.currentTab = 'Pages'
|
|
2553
|
+
this.scrollResultsToTop()
|
|
2554
|
+
}
|
|
2443
2555
|
|
|
2444
|
-
|
|
2556
|
+
this.keywordsFromAi = false
|
|
2445
2557
|
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2558
|
+
if (!keepAnswersTab) {
|
|
2559
|
+
this.aiAnswer = null
|
|
2560
|
+
this.aiSources = []
|
|
2561
|
+
this.aiKeywordsDisplayAnswer = ''
|
|
2562
|
+
this.aiKeywordsDisplayPages = ''
|
|
2563
|
+
}
|
|
2452
2564
|
|
|
2453
|
-
|
|
2565
|
+
this.persistSearchCacheSnapshot()
|
|
2566
|
+
return this.currentPages
|
|
2567
|
+
} finally {
|
|
2568
|
+
if (this.isCurrentSearchRun(runId)) {
|
|
2569
|
+
this.searchingPages = false
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2454
2572
|
},
|
|
2455
2573
|
|
|
2456
2574
|
async searchFiles(options = {}) {
|
|
2575
|
+
const runId = options.runId || this.searchRunId
|
|
2457
2576
|
const searchInput = {
|
|
2458
2577
|
keywords: this.keywords,
|
|
2459
2578
|
question: this.searchQuestion || this.inputText,
|
|
@@ -2462,26 +2581,41 @@ export default {
|
|
|
2462
2581
|
if (owners.length > 0) searchInput.owners = owners
|
|
2463
2582
|
|
|
2464
2583
|
this.searchingFiles = true
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2584
|
+
try {
|
|
2585
|
+
await this.querySearchCollectionWithFallback({
|
|
2586
|
+
handler: this.queryFilesHandler,
|
|
2587
|
+
storeAction: 'search/queryFiles',
|
|
2588
|
+
payload: searchInput,
|
|
2589
|
+
target: 'files',
|
|
2590
|
+
runId,
|
|
2591
|
+
})
|
|
2592
|
+
if (!this.isCurrentSearchRun(runId)) {
|
|
2593
|
+
return this.currentFiles
|
|
2594
|
+
}
|
|
2595
|
+
this.persistSearchCacheSnapshot()
|
|
2596
|
+
return this.currentFiles
|
|
2597
|
+
} finally {
|
|
2598
|
+
if (this.isCurrentSearchRun(runId)) {
|
|
2599
|
+
this.searchingFiles = false
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2473
2602
|
},
|
|
2474
2603
|
|
|
2475
|
-
async searchFilesWithGroupOwners() {
|
|
2476
|
-
const
|
|
2477
|
-
|
|
2604
|
+
async searchFilesWithGroupOwners(options = {}) {
|
|
2605
|
+
const runId = options.runId || this.searchRunId
|
|
2606
|
+
const groupsPromise = this.searchGroups({ runId })
|
|
2607
|
+
await this.searchFiles({ runId })
|
|
2608
|
+
if (!this.isCurrentSearchRun(runId)) return []
|
|
2478
2609
|
const ownerFilters = await groupsPromise
|
|
2610
|
+
if (!this.isCurrentSearchRun(runId)) return ownerFilters
|
|
2479
2611
|
if (ownerFilters.length > 0) {
|
|
2480
|
-
await this.searchFiles({ owners: ownerFilters })
|
|
2612
|
+
await this.searchFiles({ owners: ownerFilters, runId })
|
|
2481
2613
|
}
|
|
2614
|
+
return ownerFilters
|
|
2482
2615
|
},
|
|
2483
2616
|
|
|
2484
|
-
async searchGroups() {
|
|
2617
|
+
async searchGroups(options = {}) {
|
|
2618
|
+
const runId = options.runId || this.searchRunId
|
|
2485
2619
|
const searchInput = {
|
|
2486
2620
|
keywords: this.keywords,
|
|
2487
2621
|
question: this.searchQuestion || this.inputText,
|
|
@@ -2490,12 +2624,22 @@ export default {
|
|
|
2490
2624
|
handler: this.queryGroupsHandler,
|
|
2491
2625
|
storeAction: 'search/queryGroups',
|
|
2492
2626
|
payload: searchInput,
|
|
2493
|
-
target: '
|
|
2627
|
+
target: 'groups',
|
|
2628
|
+
runId,
|
|
2494
2629
|
})
|
|
2630
|
+
if (!this.isCurrentSearchRun(runId)) {
|
|
2631
|
+
return Array.from(
|
|
2632
|
+
new Set(
|
|
2633
|
+
this.currentGroups
|
|
2634
|
+
.map(group => (group && group.title ? group.title.trim() : ''))
|
|
2635
|
+
.filter(Boolean)
|
|
2636
|
+
)
|
|
2637
|
+
)
|
|
2638
|
+
}
|
|
2495
2639
|
this.persistSearchCacheSnapshot()
|
|
2496
2640
|
return Array.from(
|
|
2497
2641
|
new Set(
|
|
2498
|
-
(this.
|
|
2642
|
+
(this.currentGroups || [])
|
|
2499
2643
|
.map(group => (group && group.title ? group.title.trim() : ''))
|
|
2500
2644
|
.filter(Boolean)
|
|
2501
2645
|
)
|
|
@@ -2530,11 +2674,13 @@ export default {
|
|
|
2530
2674
|
this.searchAi(text)
|
|
2531
2675
|
} else {
|
|
2532
2676
|
await this.clearSearchState()
|
|
2677
|
+
const runId = this.searchRunId
|
|
2533
2678
|
this.keywordsFromAi = false
|
|
2534
2679
|
this.skipKeywordWatcher = true
|
|
2535
2680
|
this.keywords = this.limitWords(text, 4)
|
|
2536
|
-
await this.searchPages({ keepAnswersTab: false })
|
|
2537
|
-
this.searchFilesWithGroupOwners()
|
|
2681
|
+
await this.searchPages({ keepAnswersTab: false, runId })
|
|
2682
|
+
this.searchFilesWithGroupOwners({ runId })
|
|
2683
|
+
if (!this.isCurrentSearchRun(runId)) return
|
|
2538
2684
|
this.currentTab = 'Pages'
|
|
2539
2685
|
this.syncSearchStateToRoute({ text, mode, tab: 'Pages' })
|
|
2540
2686
|
this.$nextTick(() => this.refreshResultsScrollLayer())
|
|
@@ -2621,6 +2767,7 @@ export default {
|
|
|
2621
2767
|
|
|
2622
2768
|
this.activeAiQuestionKey = normalizedQuestion
|
|
2623
2769
|
|
|
2770
|
+
const runId = this.beginSearchRun()
|
|
2624
2771
|
this.searchMode = 'question'
|
|
2625
2772
|
const isFollowUpQuestion = this.hasAssistantTurns
|
|
2626
2773
|
this.currentTab = 'Answers'
|
|
@@ -2642,6 +2789,8 @@ export default {
|
|
|
2642
2789
|
await this.clearSearchState({
|
|
2643
2790
|
resetConversation: false,
|
|
2644
2791
|
resetTranscript: false,
|
|
2792
|
+
preserveSearchRun: true,
|
|
2793
|
+
preserveAiLoading: true,
|
|
2645
2794
|
})
|
|
2646
2795
|
this.searchQuestion = normalizedQuestion
|
|
2647
2796
|
let assistantTurnId = ''
|
|
@@ -2668,6 +2817,7 @@ export default {
|
|
|
2668
2817
|
includeDistrictResults: this.resolvedIncludeDistrictResults,
|
|
2669
2818
|
}
|
|
2670
2819
|
)
|
|
2820
|
+
if (!this.isCurrentSearchRun(runId)) return
|
|
2671
2821
|
|
|
2672
2822
|
const { cleanAnswer, keywords: aiKeywords } =
|
|
2673
2823
|
this.extractKeywordsAndCleanAnswer(answer || '')
|
|
@@ -2732,11 +2882,12 @@ export default {
|
|
|
2732
2882
|
this.keywordsFromAi = true
|
|
2733
2883
|
this.skipKeywordWatcher = true
|
|
2734
2884
|
this.keywords = keywordsToUse
|
|
2735
|
-
await this.searchPages({ keepAnswersTab: true })
|
|
2885
|
+
await this.searchPages({ keepAnswersTab: true, runId })
|
|
2886
|
+
if (!this.isCurrentSearchRun(runId)) return
|
|
2736
2887
|
relatedPagesForAnalytics = this.getAnalyticsPages()
|
|
2737
2888
|
.slice(0, 10)
|
|
2738
2889
|
.map(p => ({ title: p.title || '', url: p.url || '' }))
|
|
2739
|
-
this.searchFilesWithGroupOwners()
|
|
2890
|
+
this.searchFilesWithGroupOwners({ runId })
|
|
2740
2891
|
}
|
|
2741
2892
|
|
|
2742
2893
|
this.currentTab = 'Answers'
|
|
@@ -2747,6 +2898,7 @@ export default {
|
|
|
2747
2898
|
this.refreshResultsScrollLayer()
|
|
2748
2899
|
})
|
|
2749
2900
|
} catch (e) {
|
|
2901
|
+
if (!this.isCurrentSearchRun(runId)) return
|
|
2750
2902
|
console.error('AI search failed', e)
|
|
2751
2903
|
this.aiAnswer = null
|
|
2752
2904
|
this.aiSources = []
|
|
@@ -2769,13 +2921,15 @@ export default {
|
|
|
2769
2921
|
this.scrollTurnToTop(this.anchoredUserTurnId, { defer: true })
|
|
2770
2922
|
}
|
|
2771
2923
|
} finally {
|
|
2772
|
-
this.
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2924
|
+
if (this.isCurrentSearchRun(runId)) {
|
|
2925
|
+
this.searchingAi = false
|
|
2926
|
+
this.activeAiQuestionKey = ''
|
|
2927
|
+
this.persistSearchCacheSnapshot({
|
|
2928
|
+
text: this.searchQuestion || normalizedQuestion,
|
|
2929
|
+
mode: 'question',
|
|
2930
|
+
tab: 'Answers',
|
|
2931
|
+
})
|
|
2932
|
+
}
|
|
2779
2933
|
|
|
2780
2934
|
// Log AI search analytics
|
|
2781
2935
|
const logPagesFromPages =
|
|
@@ -3178,8 +3332,8 @@ export default {
|
|
|
3178
3332
|
},
|
|
3179
3333
|
|
|
3180
3334
|
getAnalyticsPages() {
|
|
3181
|
-
if (!Array.isArray(this.
|
|
3182
|
-
return this.
|
|
3335
|
+
if (!Array.isArray(this.currentPages)) return []
|
|
3336
|
+
return this.currentPages.filter(
|
|
3183
3337
|
page => !this.isNoResultsFallbackPage(page)
|
|
3184
3338
|
)
|
|
3185
3339
|
},
|