@asd20/ui-next 2.11.1 → 2.12.1
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/helpers.js +1 -0
- package/package.json +1 -1
- package/src/components/organisms/Asd20AiSearch/index.vue +2 -0
- package/src/components/organisms/Asd20SiteNavigation/index.vue +4 -0
- package/src/components/organisms/Asd20SiteSearch/index.vue +255 -21
- package/src/components/templates/Asd20DistrictVideoTemplate/index.vue +6 -0
- package/src/components/templates/Asd20SchoolHomeTemplate/index.vue +6 -0
- package/src/components/templates/Asd20SchoolHomeVideoTemplate/index.vue +6 -0
- package/src/helpers/queryPeople.js +122 -0
- package/src/helpers/searchProxyUrl.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.12.1](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.12.0...ui-next-v2.12.1) (2026-05-26)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* add group matches to people searches by keyword ([1edabb4](https://github.com/academydistrict20/asd20-ui-next/commit/1edabb458ead8430e04375cdb00071db345605f3))
|
|
9
|
+
|
|
10
|
+
# [2.12.0](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.11.1...ui-next-v2.12.0) (2026-05-26)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* add querypeople to public api contract ([a1a3141](https://github.com/academydistrict20/asd20-ui-next/commit/a1a3141ec8b3df29da27e947fecba80baf0169e1))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* add people to ai search ([241cf12](https://github.com/academydistrict20/asd20-ui-next/commit/241cf1247633f83a47b6fe3cd3bc91bbff275e80))
|
|
21
|
+
|
|
3
22
|
## [2.11.1](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.11.0...ui-next-v2.11.1) (2026-05-26)
|
|
4
23
|
|
|
5
24
|
|
package/helpers.js
CHANGED
|
@@ -42,6 +42,7 @@ export { default as queryEvents } from './src/helpers/queryEvents.js'
|
|
|
42
42
|
export { default as queryFiles } from './src/helpers/queryFiles.js'
|
|
43
43
|
export { default as queryMessages } from './src/helpers/queryMessages.js'
|
|
44
44
|
export { default as queryPages } from './src/helpers/queryPages.js'
|
|
45
|
+
export { default as queryPeople } from './src/helpers/queryPeople.js'
|
|
45
46
|
export { default as sendAccessibilityIssue } from './src/helpers/sendAccessibilityIssue.js'
|
|
46
47
|
export { default as sendEmail } from './src/helpers/sendEmail.js'
|
|
47
48
|
export { default as sortOrgsByLevel } from './src/helpers/sortOrgsByLevel.js'
|
package/package.json
CHANGED
|
@@ -53,12 +53,14 @@ export default {
|
|
|
53
53
|
pages: { type: Array, default: () => [] },
|
|
54
54
|
files: { type: Array, default: () => [] },
|
|
55
55
|
groups: { type: Array, default: () => [] },
|
|
56
|
+
people: { type: Array, default: () => [] },
|
|
56
57
|
showContacts: { type: Boolean, default: true },
|
|
57
58
|
includeDistrictResults: { type: Boolean, default: true },
|
|
58
59
|
searchLanguageCode: { type: String, default: null },
|
|
59
60
|
queryPagesHandler: { type: Function, default: null },
|
|
60
61
|
queryFilesHandler: { type: Function, default: null },
|
|
61
62
|
queryGroupsHandler: { type: Function, default: null },
|
|
63
|
+
queryPeopleHandler: { type: Function, default: null },
|
|
62
64
|
queryAiSiteHandler: { type: Function, default: null },
|
|
63
65
|
organization: { type: Object, default: () => ({}) },
|
|
64
66
|
organizationOptions: { type: Array, default: () => [] },
|
|
@@ -71,11 +71,13 @@
|
|
|
71
71
|
:pages="pages"
|
|
72
72
|
:files="files"
|
|
73
73
|
:groups="groups"
|
|
74
|
+
:people="people"
|
|
74
75
|
:include-district-results="includeDistrictResults"
|
|
75
76
|
:search-language-code="searchLanguageCode"
|
|
76
77
|
:query-pages-handler="queryPagesHandler"
|
|
77
78
|
:query-files-handler="queryFilesHandler"
|
|
78
79
|
:query-groups-handler="queryGroupsHandler"
|
|
80
|
+
:query-people-handler="queryPeopleHandler"
|
|
79
81
|
:query-ai-site-handler="queryAiSiteHandler"
|
|
80
82
|
:organization="organization"
|
|
81
83
|
:organization-options="organizationOptions"
|
|
@@ -118,12 +120,14 @@ export default {
|
|
|
118
120
|
pages: { type: Array, default: () => [] },
|
|
119
121
|
files: { type: Array, default: () => [] },
|
|
120
122
|
groups: { type: Array, default: () => [] },
|
|
123
|
+
people: { type: Array, default: () => [] },
|
|
121
124
|
showContacts: { type: Boolean, default: true },
|
|
122
125
|
includeDistrictResults: { type: Boolean, default: true },
|
|
123
126
|
searchLanguageCode: { type: String, default: null },
|
|
124
127
|
queryPagesHandler: { type: Function, default: null },
|
|
125
128
|
queryFilesHandler: { type: Function, default: null },
|
|
126
129
|
queryGroupsHandler: { type: Function, default: null },
|
|
130
|
+
queryPeopleHandler: { type: Function, default: null },
|
|
127
131
|
queryAiSiteHandler: { type: Function, default: null },
|
|
128
132
|
organization: { type: Object, default: null },
|
|
129
133
|
organizationOptions: { type: Array, default: () => [] },
|
|
@@ -324,37 +324,35 @@
|
|
|
324
324
|
v-if="
|
|
325
325
|
hasSubmitted &&
|
|
326
326
|
showContacts &&
|
|
327
|
-
|
|
328
|
-
!searchingFiles
|
|
327
|
+
contactResultCount === 0 &&
|
|
328
|
+
!searchingFiles &&
|
|
329
|
+
!searchingPeople
|
|
329
330
|
"
|
|
330
331
|
title="No Contacts Found"
|
|
331
332
|
description="Try using different keywords."
|
|
332
333
|
/>
|
|
333
334
|
<div
|
|
334
|
-
v-if="
|
|
335
|
+
v-if="contactResultCount > 0 && showContacts"
|
|
335
336
|
class="asd20-site-search__suggested"
|
|
336
337
|
>
|
|
337
338
|
<h3>
|
|
338
339
|
{{
|
|
339
|
-
|
|
340
|
+
contactResultCount > 1
|
|
340
341
|
? 'Suggested Contacts:'
|
|
341
342
|
: 'Suggested Contact:'
|
|
342
343
|
}}
|
|
343
344
|
</h3>
|
|
344
345
|
<asd20-list-item
|
|
345
|
-
v-for="item in
|
|
346
|
-
|
|
347
|
-
:
|
|
348
|
-
|
|
349
|
-
:logo-url="item.logoUrl"
|
|
350
|
-
:source-title="item.sourceTitle"
|
|
351
|
-
:attribution="!!item.logoUrl"
|
|
352
|
-
actionable
|
|
353
|
-
@click="selectedGroup = item.group"
|
|
346
|
+
v-for="item in contactListItems"
|
|
347
|
+
v-bind="item"
|
|
348
|
+
:key="item.key"
|
|
349
|
+
@click="onContactClick(item)"
|
|
354
350
|
/>
|
|
355
351
|
</div>
|
|
356
352
|
<asd20-loader
|
|
357
|
-
v-if="
|
|
353
|
+
v-if="
|
|
354
|
+
(searchingFiles || searchingPeople) && contactResultCount === 0
|
|
355
|
+
"
|
|
358
356
|
size="lg"
|
|
359
357
|
/>
|
|
360
358
|
</asd20-viewport>
|
|
@@ -467,6 +465,12 @@
|
|
|
467
465
|
</asd20-viewport>
|
|
468
466
|
</asd20-modal>
|
|
469
467
|
|
|
468
|
+
<asd20-person-modal
|
|
469
|
+
:person="selectedPerson"
|
|
470
|
+
:open="!!selectedPerson"
|
|
471
|
+
@dismiss="selectedPerson = null"
|
|
472
|
+
/>
|
|
473
|
+
|
|
470
474
|
<asd20-modal
|
|
471
475
|
:open="improvementFeedbackModalOpen"
|
|
472
476
|
title="Report Missing or Incorrect Information"
|
|
@@ -539,6 +543,7 @@ import Asd20Notification from '../../molecules/Asd20Notification'
|
|
|
539
543
|
import Asd20Loader from '../../molecules/Asd20Loader'
|
|
540
544
|
import Asd20Modal from '../../molecules/Asd20Modal'
|
|
541
545
|
import Asd20DepartmentContactCard from '../../molecules/Asd20DepartmentContactCard'
|
|
546
|
+
import Asd20PersonModal from '../../organisms/Asd20PersonModal'
|
|
542
547
|
import Asd20Button from '../../atoms/Asd20Button'
|
|
543
548
|
import Asd20Icon from '../../atoms/Asd20Icon'
|
|
544
549
|
import Asd20Spinner from '../../atoms/Asd20Spinner'
|
|
@@ -548,9 +553,11 @@ import Asd20Spinner from '../../atoms/Asd20Spinner'
|
|
|
548
553
|
import debounce from 'lodash/debounce'
|
|
549
554
|
import mapPagesToListItems from '../../../helpers/mapPagesToListItems'
|
|
550
555
|
import mapFilesToListItems from '../../../helpers/mapFilesToListItems'
|
|
556
|
+
import mapPeopleToListItems from '../../../helpers/mapPeopleToListItems'
|
|
551
557
|
import logSearchAnalytics from '../../../helpers/logSearchAnalytics'
|
|
552
558
|
import logSearchFeedback from '../../../helpers/logSearchFeedback'
|
|
553
559
|
import queryAiSite from '../../../helpers/queryAiSite'
|
|
560
|
+
import queryPeople from '../../../helpers/queryPeople'
|
|
554
561
|
import { NO_PAGE_RESULTS_FALLBACKS } from '../../../helpers/queryPages'
|
|
555
562
|
|
|
556
563
|
// Mixins
|
|
@@ -604,6 +611,7 @@ export default {
|
|
|
604
611
|
Asd20Loader,
|
|
605
612
|
Asd20Modal,
|
|
606
613
|
Asd20DepartmentContactCard,
|
|
614
|
+
Asd20PersonModal,
|
|
607
615
|
Asd20Button,
|
|
608
616
|
Asd20Icon,
|
|
609
617
|
Asd20Spinner,
|
|
@@ -625,6 +633,11 @@ export default {
|
|
|
625
633
|
{ type: Array, default: () => [] },
|
|
626
634
|
'search'
|
|
627
635
|
),
|
|
636
|
+
globalPropMixinFactory(
|
|
637
|
+
'people',
|
|
638
|
+
{ type: Array, default: () => [] },
|
|
639
|
+
'search'
|
|
640
|
+
),
|
|
628
641
|
globalPropMixinFactory(
|
|
629
642
|
'includeDistrictResults',
|
|
630
643
|
{ type: Boolean, default: true },
|
|
@@ -642,6 +655,7 @@ export default {
|
|
|
642
655
|
queryPagesHandler: { type: Function, default: null },
|
|
643
656
|
queryFilesHandler: { type: Function, default: null },
|
|
644
657
|
queryGroupsHandler: { type: Function, default: null },
|
|
658
|
+
queryPeopleHandler: { type: Function, default: null },
|
|
645
659
|
queryAiSiteHandler: { type: Function, default: null },
|
|
646
660
|
organization: {
|
|
647
661
|
type: Object,
|
|
@@ -666,12 +680,15 @@ export default {
|
|
|
666
680
|
aiTranscript: [],
|
|
667
681
|
|
|
668
682
|
selectedGroup: null,
|
|
683
|
+
selectedPerson: null,
|
|
669
684
|
searchingPages: false,
|
|
670
685
|
searchingFiles: false,
|
|
686
|
+
searchingPeople: false,
|
|
671
687
|
|
|
672
688
|
localSearchPages: null,
|
|
673
689
|
localSearchFiles: null,
|
|
674
690
|
localSearchGroups: null,
|
|
691
|
+
localSearchPeople: null,
|
|
675
692
|
|
|
676
693
|
keywordsFromAi: false,
|
|
677
694
|
aiKeywordsDisplayAnswer: '',
|
|
@@ -723,6 +740,15 @@ export default {
|
|
|
723
740
|
return Array.isArray(this.resolvedGroups) ? this.resolvedGroups : []
|
|
724
741
|
},
|
|
725
742
|
|
|
743
|
+
currentPeople() {
|
|
744
|
+
if (Array.isArray(this.localSearchPeople)) return this.localSearchPeople
|
|
745
|
+
return Array.isArray(this.resolvedPeople) ? this.resolvedPeople : []
|
|
746
|
+
},
|
|
747
|
+
|
|
748
|
+
contactResultCount() {
|
|
749
|
+
return this.currentGroups.length + this.currentPeople.length
|
|
750
|
+
},
|
|
751
|
+
|
|
726
752
|
shouldUsePageFallbacks() {
|
|
727
753
|
const hasSearchText =
|
|
728
754
|
typeof this.keywords === 'string' && this.keywords.trim()
|
|
@@ -828,7 +854,7 @@ export default {
|
|
|
828
854
|
if (this.showContacts) {
|
|
829
855
|
assistantTabs.push({
|
|
830
856
|
label: 'Contacts',
|
|
831
|
-
badge: this.
|
|
857
|
+
badge: this.contactResultCount,
|
|
832
858
|
active: this.currentTab === 'Contacts',
|
|
833
859
|
})
|
|
834
860
|
}
|
|
@@ -851,7 +877,7 @@ export default {
|
|
|
851
877
|
if (this.showContacts) {
|
|
852
878
|
keywordTabs.push({
|
|
853
879
|
label: 'Contacts',
|
|
854
|
-
badge: this.
|
|
880
|
+
badge: this.contactResultCount,
|
|
855
881
|
active: this.currentTab === 'Contacts',
|
|
856
882
|
})
|
|
857
883
|
}
|
|
@@ -954,6 +980,8 @@ export default {
|
|
|
954
980
|
((g.shortName || g.title || '').match(/\b([A-Z])/g) || []).join('')
|
|
955
981
|
|
|
956
982
|
return {
|
|
983
|
+
key: `group-${g.id || g.title}`,
|
|
984
|
+
contactType: 'group',
|
|
957
985
|
group: g,
|
|
958
986
|
label: `${g.title}`,
|
|
959
987
|
textAvatar,
|
|
@@ -962,6 +990,17 @@ export default {
|
|
|
962
990
|
}
|
|
963
991
|
})
|
|
964
992
|
},
|
|
993
|
+
peopleListItems() {
|
|
994
|
+
return (mapPeopleToListItems(this.currentPeople) || []).map(item => ({
|
|
995
|
+
...item,
|
|
996
|
+
key: `person-${item.id || item.email || item.label}`,
|
|
997
|
+
contactType: 'person',
|
|
998
|
+
}))
|
|
999
|
+
},
|
|
1000
|
+
|
|
1001
|
+
contactListItems() {
|
|
1002
|
+
return [...this.peopleListItems, ...this.groupListItems]
|
|
1003
|
+
},
|
|
965
1004
|
feedbackFormUrlRaw() {
|
|
966
1005
|
if (this.aiSearchFeedbackFormUrl) return this.aiSearchFeedbackFormUrl
|
|
967
1006
|
const runtimeConfig = this.resolveRuntimeConfig()
|
|
@@ -1216,7 +1255,7 @@ export default {
|
|
|
1216
1255
|
: 'en'
|
|
1217
1256
|
},
|
|
1218
1257
|
|
|
1219
|
-
setSearchResults({ pages, files, groups } = {}) {
|
|
1258
|
+
setSearchResults({ pages, files, groups, people } = {}) {
|
|
1220
1259
|
if (pages !== undefined) {
|
|
1221
1260
|
this.localSearchPages = Array.isArray(pages) ? pages : []
|
|
1222
1261
|
}
|
|
@@ -1226,12 +1265,16 @@ export default {
|
|
|
1226
1265
|
if (groups !== undefined) {
|
|
1227
1266
|
this.localSearchGroups = Array.isArray(groups) ? groups : []
|
|
1228
1267
|
}
|
|
1268
|
+
if (people !== undefined) {
|
|
1269
|
+
this.localSearchPeople = Array.isArray(people) ? people : []
|
|
1270
|
+
}
|
|
1229
1271
|
},
|
|
1230
1272
|
|
|
1231
1273
|
readSearchResults(target) {
|
|
1232
1274
|
if (target === 'pages') return this.currentPages
|
|
1233
1275
|
if (target === 'files') return this.currentFiles
|
|
1234
1276
|
if (target === 'groups') return this.currentGroups
|
|
1277
|
+
if (target === 'people') return this.currentPeople
|
|
1235
1278
|
return []
|
|
1236
1279
|
},
|
|
1237
1280
|
|
|
@@ -1245,6 +1288,9 @@ export default {
|
|
|
1245
1288
|
if (target === 'groups') {
|
|
1246
1289
|
return Array.isArray(this.resolvedGroups) ? this.resolvedGroups : []
|
|
1247
1290
|
}
|
|
1291
|
+
if (target === 'people') {
|
|
1292
|
+
return Array.isArray(this.resolvedPeople) ? this.resolvedPeople : []
|
|
1293
|
+
}
|
|
1248
1294
|
return []
|
|
1249
1295
|
},
|
|
1250
1296
|
|
|
@@ -1308,6 +1354,83 @@ export default {
|
|
|
1308
1354
|
}
|
|
1309
1355
|
},
|
|
1310
1356
|
|
|
1357
|
+
async queryPeopleWithFallback(payload) {
|
|
1358
|
+
if (typeof this.queryPeopleHandler === 'function') {
|
|
1359
|
+
const result = await this.queryPeopleHandler(payload)
|
|
1360
|
+
if (Array.isArray(result)) {
|
|
1361
|
+
return { people: result, groups: [] }
|
|
1362
|
+
}
|
|
1363
|
+
return {
|
|
1364
|
+
people: result && Array.isArray(result.people) ? result.people : [],
|
|
1365
|
+
groups: result && Array.isArray(result.groups) ? result.groups : [],
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
const searchStore = this.getSearchStore()
|
|
1370
|
+
if (searchStore) {
|
|
1371
|
+
const result = await searchStore.dispatch('search/queryPeople', payload)
|
|
1372
|
+
return {
|
|
1373
|
+
people:
|
|
1374
|
+
result && Array.isArray(result.people)
|
|
1375
|
+
? result.people
|
|
1376
|
+
: Array.isArray(this.resolvedPeople)
|
|
1377
|
+
? this.resolvedPeople
|
|
1378
|
+
: [],
|
|
1379
|
+
groups: result && Array.isArray(result.groups) ? result.groups : [],
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
const { people } = await queryPeople({
|
|
1384
|
+
...payload,
|
|
1385
|
+
runtimeConfig: this.resolveRuntimeConfig(),
|
|
1386
|
+
})
|
|
1387
|
+
return {
|
|
1388
|
+
people: Array.isArray(people) ? people : [],
|
|
1389
|
+
groups: [],
|
|
1390
|
+
}
|
|
1391
|
+
},
|
|
1392
|
+
|
|
1393
|
+
getContactGroupKey(group = {}) {
|
|
1394
|
+
return String(group.id || group.title || group.contactEmail || '').trim()
|
|
1395
|
+
},
|
|
1396
|
+
|
|
1397
|
+
mergeContactGroups(primaryGroups = [], relatedGroups = []) {
|
|
1398
|
+
const merged = []
|
|
1399
|
+
const keyedIndexes = new Map()
|
|
1400
|
+
const addGroup = group => {
|
|
1401
|
+
if (!group || typeof group !== 'object') return
|
|
1402
|
+
const key = this.getContactGroupKey(group)
|
|
1403
|
+
if (!key) return
|
|
1404
|
+
|
|
1405
|
+
if (keyedIndexes.has(key)) {
|
|
1406
|
+
const existingIndex = keyedIndexes.get(key)
|
|
1407
|
+
const existing = merged[existingIndex]
|
|
1408
|
+
if (
|
|
1409
|
+
existing &&
|
|
1410
|
+
existing.relatedPersonMatch &&
|
|
1411
|
+
!group.relatedPersonMatch
|
|
1412
|
+
) {
|
|
1413
|
+
merged[existingIndex] = group
|
|
1414
|
+
}
|
|
1415
|
+
return
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
keyedIndexes.set(key, merged.length)
|
|
1419
|
+
merged.push(group)
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
primaryGroups.forEach(addGroup)
|
|
1423
|
+
relatedGroups.forEach(addGroup)
|
|
1424
|
+
|
|
1425
|
+
return merged
|
|
1426
|
+
},
|
|
1427
|
+
|
|
1428
|
+
getDirectContactGroups() {
|
|
1429
|
+
return (this.currentGroups || []).filter(
|
|
1430
|
+
group => !(group && group.relatedPersonMatch)
|
|
1431
|
+
)
|
|
1432
|
+
},
|
|
1433
|
+
|
|
1311
1434
|
isLocalDevelopmentHost(hostname = '') {
|
|
1312
1435
|
if (!hostname || typeof hostname !== 'string') return false
|
|
1313
1436
|
const lower = hostname.toLowerCase()
|
|
@@ -1526,6 +1649,7 @@ export default {
|
|
|
1526
1649
|
pages: Array.isArray(this.currentPages) ? this.currentPages : [],
|
|
1527
1650
|
files: Array.isArray(this.currentFiles) ? this.currentFiles : [],
|
|
1528
1651
|
groups: Array.isArray(this.currentGroups) ? this.currentGroups : [],
|
|
1652
|
+
people: Array.isArray(this.currentPeople) ? this.currentPeople : [],
|
|
1529
1653
|
aiAnswer: this.aiAnswer || null,
|
|
1530
1654
|
aiSources: Array.isArray(this.aiSources) ? this.aiSources : [],
|
|
1531
1655
|
aiErrorMessage: this.aiErrorMessage || '',
|
|
@@ -1636,7 +1760,8 @@ export default {
|
|
|
1636
1760
|
const pages = Array.isArray(snapshot.pages) ? snapshot.pages : []
|
|
1637
1761
|
const files = Array.isArray(snapshot.files) ? snapshot.files : []
|
|
1638
1762
|
const groups = Array.isArray(snapshot.groups) ? snapshot.groups : []
|
|
1639
|
-
|
|
1763
|
+
const people = Array.isArray(snapshot.people) ? snapshot.people : []
|
|
1764
|
+
this.setSearchResults({ pages, files, groups, people })
|
|
1640
1765
|
|
|
1641
1766
|
if (!skipTabUpdate) {
|
|
1642
1767
|
const preferredTab = SEARCH_ROUTE_TABS.has(targetState.tab)
|
|
@@ -2177,6 +2302,39 @@ export default {
|
|
|
2177
2302
|
this.$emit('update:active', false)
|
|
2178
2303
|
},
|
|
2179
2304
|
|
|
2305
|
+
onContactClick(item) {
|
|
2306
|
+
if (!item) return
|
|
2307
|
+
if (item.contactType === 'person') {
|
|
2308
|
+
this.selectedPerson = this.normalizePersonForModal(item.person || item)
|
|
2309
|
+
return
|
|
2310
|
+
}
|
|
2311
|
+
if (item.group) {
|
|
2312
|
+
this.selectedGroup = item.group
|
|
2313
|
+
}
|
|
2314
|
+
},
|
|
2315
|
+
|
|
2316
|
+
normalizePersonForModal(person = {}) {
|
|
2317
|
+
const jobTitles = Array.isArray(person.jobTitles)
|
|
2318
|
+
? person.jobTitles
|
|
2319
|
+
: person.jobTitles
|
|
2320
|
+
? [person.jobTitles]
|
|
2321
|
+
: person.jobTypes
|
|
2322
|
+
? Array.isArray(person.jobTypes)
|
|
2323
|
+
? person.jobTypes
|
|
2324
|
+
: [person.jobTypes]
|
|
2325
|
+
: []
|
|
2326
|
+
|
|
2327
|
+
return {
|
|
2328
|
+
...person,
|
|
2329
|
+
id: person.id || person.employeeId || person.profileId || person.userId,
|
|
2330
|
+
displayName: person.displayName || person.name || '',
|
|
2331
|
+
jobTitles,
|
|
2332
|
+
workPhone: person.workPhone || person.phone || '',
|
|
2333
|
+
thumbnailUrl:
|
|
2334
|
+
person.thumbnailUrl || person.thumbnail || person.photoUrl || '',
|
|
2335
|
+
}
|
|
2336
|
+
},
|
|
2337
|
+
|
|
2180
2338
|
resolveRuntimeConfig() {
|
|
2181
2339
|
const runtimeConfig =
|
|
2182
2340
|
this.$config ||
|
|
@@ -2341,9 +2499,11 @@ export default {
|
|
|
2341
2499
|
this.beginSearchRun()
|
|
2342
2500
|
}
|
|
2343
2501
|
this.selectedGroup = null
|
|
2502
|
+
this.selectedPerson = null
|
|
2344
2503
|
this.searchingAi = preserveAiLoading ? this.searchingAi : false
|
|
2345
2504
|
this.searchingPages = false
|
|
2346
2505
|
this.searchingFiles = false
|
|
2506
|
+
this.searchingPeople = false
|
|
2347
2507
|
this.activeAiQuestionKey = preserveAiLoading
|
|
2348
2508
|
? this.activeAiQuestionKey
|
|
2349
2509
|
: ''
|
|
@@ -2366,7 +2526,7 @@ export default {
|
|
|
2366
2526
|
this.aiTranscript = []
|
|
2367
2527
|
this.anchoredUserTurnId = null
|
|
2368
2528
|
}
|
|
2369
|
-
this.setSearchResults({ pages: [], files: [], groups: [] })
|
|
2529
|
+
this.setSearchResults({ pages: [], files: [], groups: [], people: [] })
|
|
2370
2530
|
},
|
|
2371
2531
|
|
|
2372
2532
|
async clearInput() {
|
|
@@ -2471,8 +2631,11 @@ export default {
|
|
|
2471
2631
|
async searchFilesWithGroupOwners(options = {}) {
|
|
2472
2632
|
const runId = options.runId || this.searchRunId
|
|
2473
2633
|
const groupsPromise = this.searchGroups({ runId })
|
|
2634
|
+
const peoplePromise = this.searchPeople({ runId })
|
|
2474
2635
|
await this.searchFiles({ runId })
|
|
2475
2636
|
if (!this.isCurrentSearchRun(runId)) return []
|
|
2637
|
+
await peoplePromise
|
|
2638
|
+
if (!this.isCurrentSearchRun(runId)) return []
|
|
2476
2639
|
const ownerFilters = await groupsPromise
|
|
2477
2640
|
if (!this.isCurrentSearchRun(runId)) return ownerFilters
|
|
2478
2641
|
if (ownerFilters.length > 0) {
|
|
@@ -2481,8 +2644,27 @@ export default {
|
|
|
2481
2644
|
return ownerFilters
|
|
2482
2645
|
},
|
|
2483
2646
|
|
|
2647
|
+
selectBestKeywordTabAfterContactResults({ runId, text } = {}) {
|
|
2648
|
+
if (!this.isCurrentSearchRun(runId)) return
|
|
2649
|
+
if (this.searchMode !== 'keyword') return
|
|
2650
|
+
if (this.currentTab !== 'Pages') return
|
|
2651
|
+
if (this.currentPages.length > 0 || this.contactResultCount === 0)
|
|
2652
|
+
return
|
|
2653
|
+
|
|
2654
|
+
this.currentTab = 'Contacts'
|
|
2655
|
+
this.syncSearchState({
|
|
2656
|
+
text: text || this.searchQuestion || this.inputText,
|
|
2657
|
+
mode: 'keyword',
|
|
2658
|
+
tab: 'Contacts',
|
|
2659
|
+
})
|
|
2660
|
+
this.$nextTick(() => this.refreshResultsScrollLayer())
|
|
2661
|
+
},
|
|
2662
|
+
|
|
2484
2663
|
async searchGroups(options = {}) {
|
|
2485
2664
|
const runId = options.runId || this.searchRunId
|
|
2665
|
+
const existingRelatedGroups = (this.currentGroups || []).filter(
|
|
2666
|
+
group => group && group.relatedPersonMatch
|
|
2667
|
+
)
|
|
2486
2668
|
const searchInput = {
|
|
2487
2669
|
keywords: this.keywords,
|
|
2488
2670
|
question: this.searchQuestion || this.inputText,
|
|
@@ -2497,22 +2679,70 @@ export default {
|
|
|
2497
2679
|
if (!this.isCurrentSearchRun(runId)) {
|
|
2498
2680
|
return Array.from(
|
|
2499
2681
|
new Set(
|
|
2500
|
-
this.
|
|
2682
|
+
this.getDirectContactGroups()
|
|
2501
2683
|
.map(group => (group && group.title ? group.title.trim() : ''))
|
|
2502
2684
|
.filter(Boolean)
|
|
2503
2685
|
)
|
|
2504
2686
|
)
|
|
2505
2687
|
}
|
|
2688
|
+
if (existingRelatedGroups.length > 0) {
|
|
2689
|
+
this.setSearchResults({
|
|
2690
|
+
groups: this.mergeContactGroups(
|
|
2691
|
+
this.currentGroups,
|
|
2692
|
+
existingRelatedGroups
|
|
2693
|
+
),
|
|
2694
|
+
})
|
|
2695
|
+
}
|
|
2506
2696
|
this.persistSearchCacheSnapshot()
|
|
2507
2697
|
return Array.from(
|
|
2508
2698
|
new Set(
|
|
2509
|
-
|
|
2699
|
+
this.getDirectContactGroups()
|
|
2510
2700
|
.map(group => (group && group.title ? group.title.trim() : ''))
|
|
2511
2701
|
.filter(Boolean)
|
|
2512
2702
|
)
|
|
2513
2703
|
)
|
|
2514
2704
|
},
|
|
2515
2705
|
|
|
2706
|
+
async searchPeople(options = {}) {
|
|
2707
|
+
const runId = options.runId || this.searchRunId
|
|
2708
|
+
const searchInput = {
|
|
2709
|
+
keywords: this.keywords,
|
|
2710
|
+
question: this.searchQuestion || this.inputText,
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
this.searchingPeople = true
|
|
2714
|
+
try {
|
|
2715
|
+
let people = []
|
|
2716
|
+
let relatedGroups = []
|
|
2717
|
+
try {
|
|
2718
|
+
const result = await this.queryPeopleWithFallback(searchInput)
|
|
2719
|
+
people = Array.isArray(result)
|
|
2720
|
+
? result
|
|
2721
|
+
: result && Array.isArray(result.people)
|
|
2722
|
+
? result.people
|
|
2723
|
+
: []
|
|
2724
|
+
relatedGroups =
|
|
2725
|
+
result && Array.isArray(result.groups) ? result.groups : []
|
|
2726
|
+
} catch (error) {
|
|
2727
|
+
people = []
|
|
2728
|
+
relatedGroups = []
|
|
2729
|
+
}
|
|
2730
|
+
if (!this.isCurrentSearchRun(runId)) return this.currentPeople
|
|
2731
|
+
this.setSearchResults({ people })
|
|
2732
|
+
if (relatedGroups.length > 0) {
|
|
2733
|
+
this.setSearchResults({
|
|
2734
|
+
groups: this.mergeContactGroups(this.currentGroups, relatedGroups),
|
|
2735
|
+
})
|
|
2736
|
+
}
|
|
2737
|
+
this.persistSearchCacheSnapshot()
|
|
2738
|
+
return this.currentPeople
|
|
2739
|
+
} finally {
|
|
2740
|
+
if (this.isCurrentSearchRun(runId)) {
|
|
2741
|
+
this.searchingPeople = false
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
},
|
|
2745
|
+
|
|
2516
2746
|
async onSubmitInput() {
|
|
2517
2747
|
if (this.searchingAi) return
|
|
2518
2748
|
const text = (this.inputText || '').trim()
|
|
@@ -2547,6 +2777,10 @@ export default {
|
|
|
2547
2777
|
this.keywords = this.limitWords(text, 4)
|
|
2548
2778
|
await this.searchPages({ keepAnswersTab: false, runId })
|
|
2549
2779
|
this.searchFilesWithGroupOwners({ runId })
|
|
2780
|
+
.then(() =>
|
|
2781
|
+
this.selectBestKeywordTabAfterContactResults({ runId, text })
|
|
2782
|
+
)
|
|
2783
|
+
.catch(() => {})
|
|
2550
2784
|
if (!this.isCurrentSearchRun(runId)) return
|
|
2551
2785
|
this.currentTab = 'Pages'
|
|
2552
2786
|
this.syncSearchState({ text, mode, tab: 'Pages' })
|
|
@@ -13,11 +13,13 @@
|
|
|
13
13
|
:pages="searchPages"
|
|
14
14
|
:files="searchFiles"
|
|
15
15
|
:groups="searchGroups"
|
|
16
|
+
:people="searchPeople"
|
|
16
17
|
:include-district-results="includeDistrictResults"
|
|
17
18
|
:search-language-code="searchLanguageCode"
|
|
18
19
|
:query-pages-handler="queryPagesHandler"
|
|
19
20
|
:query-files-handler="queryFilesHandler"
|
|
20
21
|
:query-groups-handler="queryGroupsHandler"
|
|
22
|
+
:query-people-handler="queryPeopleHandler"
|
|
21
23
|
:query-ai-site-handler="queryAiSiteHandler"
|
|
22
24
|
:organization="organization"
|
|
23
25
|
:organization-options="organizationOptions"
|
|
@@ -65,11 +67,13 @@
|
|
|
65
67
|
:pages="searchPages"
|
|
66
68
|
:files="searchFiles"
|
|
67
69
|
:groups="searchGroups"
|
|
70
|
+
:people="searchPeople"
|
|
68
71
|
:include-district-results="includeDistrictResults"
|
|
69
72
|
:search-language-code="searchLanguageCode"
|
|
70
73
|
:query-pages-handler="queryPagesHandler"
|
|
71
74
|
:query-files-handler="queryFilesHandler"
|
|
72
75
|
:query-groups-handler="queryGroupsHandler"
|
|
76
|
+
:query-people-handler="queryPeopleHandler"
|
|
73
77
|
:query-ai-site-handler="queryAiSiteHandler"
|
|
74
78
|
:organization="organization"
|
|
75
79
|
:organization-options="organizationOptions"
|
|
@@ -221,11 +225,13 @@ export default {
|
|
|
221
225
|
searchPages: { type: Array, default: () => [] },
|
|
222
226
|
searchFiles: { type: Array, default: () => [] },
|
|
223
227
|
searchGroups: { type: Array, default: () => [] },
|
|
228
|
+
searchPeople: { type: Array, default: () => [] },
|
|
224
229
|
includeDistrictResults: { type: Boolean, default: true },
|
|
225
230
|
searchLanguageCode: { type: String, default: null },
|
|
226
231
|
queryPagesHandler: { type: Function, default: null },
|
|
227
232
|
queryFilesHandler: { type: Function, default: null },
|
|
228
233
|
queryGroupsHandler: { type: Function, default: null },
|
|
234
|
+
queryPeopleHandler: { type: Function, default: null },
|
|
229
235
|
queryAiSiteHandler: { type: Function, default: null },
|
|
230
236
|
aiSearchFeedbackFormUrl: { type: String, default: '' },
|
|
231
237
|
},
|
|
@@ -13,11 +13,13 @@
|
|
|
13
13
|
:pages="searchPages"
|
|
14
14
|
:files="searchFiles"
|
|
15
15
|
:groups="searchGroups"
|
|
16
|
+
:people="searchPeople"
|
|
16
17
|
:include-district-results="includeDistrictResults"
|
|
17
18
|
:search-language-code="searchLanguageCode"
|
|
18
19
|
:query-pages-handler="queryPagesHandler"
|
|
19
20
|
:query-files-handler="queryFilesHandler"
|
|
20
21
|
:query-groups-handler="queryGroupsHandler"
|
|
22
|
+
:query-people-handler="queryPeopleHandler"
|
|
21
23
|
:query-ai-site-handler="queryAiSiteHandler"
|
|
22
24
|
:organization-options="organizationOptions"
|
|
23
25
|
:organization="organization"
|
|
@@ -109,11 +111,13 @@
|
|
|
109
111
|
:pages="searchPages"
|
|
110
112
|
:files="searchFiles"
|
|
111
113
|
:groups="searchGroups"
|
|
114
|
+
:people="searchPeople"
|
|
112
115
|
:include-district-results="includeDistrictResults"
|
|
113
116
|
:search-language-code="searchLanguageCode"
|
|
114
117
|
:query-pages-handler="queryPagesHandler"
|
|
115
118
|
:query-files-handler="queryFilesHandler"
|
|
116
119
|
:query-groups-handler="queryGroupsHandler"
|
|
120
|
+
:query-people-handler="queryPeopleHandler"
|
|
117
121
|
:query-ai-site-handler="queryAiSiteHandler"
|
|
118
122
|
:organization="organization"
|
|
119
123
|
:organization-options="organizationOptions"
|
|
@@ -234,11 +238,13 @@ export default {
|
|
|
234
238
|
searchPages: { type: Array, default: () => [] },
|
|
235
239
|
searchFiles: { type: Array, default: () => [] },
|
|
236
240
|
searchGroups: { type: Array, default: () => [] },
|
|
241
|
+
searchPeople: { type: Array, default: () => [] },
|
|
237
242
|
includeDistrictResults: { type: Boolean, default: true },
|
|
238
243
|
searchLanguageCode: { type: String, default: null },
|
|
239
244
|
queryPagesHandler: { type: Function, default: null },
|
|
240
245
|
queryFilesHandler: { type: Function, default: null },
|
|
241
246
|
queryGroupsHandler: { type: Function, default: null },
|
|
247
|
+
queryPeopleHandler: { type: Function, default: null },
|
|
242
248
|
queryAiSiteHandler: { type: Function, default: null },
|
|
243
249
|
aiSearchFeedbackFormUrl: { type: String, default: '' },
|
|
244
250
|
},
|
|
@@ -13,11 +13,13 @@
|
|
|
13
13
|
:pages="searchPages"
|
|
14
14
|
:files="searchFiles"
|
|
15
15
|
:groups="searchGroups"
|
|
16
|
+
:people="searchPeople"
|
|
16
17
|
:include-district-results="includeDistrictResults"
|
|
17
18
|
:search-language-code="searchLanguageCode"
|
|
18
19
|
:query-pages-handler="queryPagesHandler"
|
|
19
20
|
:query-files-handler="queryFilesHandler"
|
|
20
21
|
:query-groups-handler="queryGroupsHandler"
|
|
22
|
+
:query-people-handler="queryPeopleHandler"
|
|
21
23
|
:query-ai-site-handler="queryAiSiteHandler"
|
|
22
24
|
:organization="organization"
|
|
23
25
|
:organization-options="organizationOptions"
|
|
@@ -110,11 +112,13 @@
|
|
|
110
112
|
:pages="searchPages"
|
|
111
113
|
:files="searchFiles"
|
|
112
114
|
:groups="searchGroups"
|
|
115
|
+
:people="searchPeople"
|
|
113
116
|
:include-district-results="includeDistrictResults"
|
|
114
117
|
:search-language-code="searchLanguageCode"
|
|
115
118
|
:query-pages-handler="queryPagesHandler"
|
|
116
119
|
:query-files-handler="queryFilesHandler"
|
|
117
120
|
:query-groups-handler="queryGroupsHandler"
|
|
121
|
+
:query-people-handler="queryPeopleHandler"
|
|
118
122
|
:query-ai-site-handler="queryAiSiteHandler"
|
|
119
123
|
:organization="organization"
|
|
120
124
|
:organization-options="organizationOptions"
|
|
@@ -239,11 +243,13 @@ export default {
|
|
|
239
243
|
searchPages: { type: Array, default: () => [] },
|
|
240
244
|
searchFiles: { type: Array, default: () => [] },
|
|
241
245
|
searchGroups: { type: Array, default: () => [] },
|
|
246
|
+
searchPeople: { type: Array, default: () => [] },
|
|
242
247
|
includeDistrictResults: { type: Boolean, default: true },
|
|
243
248
|
searchLanguageCode: { type: String, default: null },
|
|
244
249
|
queryPagesHandler: { type: Function, default: null },
|
|
245
250
|
queryFilesHandler: { type: Function, default: null },
|
|
246
251
|
queryGroupsHandler: { type: Function, default: null },
|
|
252
|
+
queryPeopleHandler: { type: Function, default: null },
|
|
247
253
|
queryAiSiteHandler: { type: Function, default: null },
|
|
248
254
|
aiSearchFeedbackFormUrl: { type: String, default: '' },
|
|
249
255
|
},
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
|
|
3
|
+
import { hasSearchProxyRuntime, resolveSearchProxyUrl } from './searchProxyUrl'
|
|
4
|
+
import { normalizeBaseUrl, resolveRuntimeConfigValue } from './runtimeConfig'
|
|
5
|
+
|
|
6
|
+
function searchPayload({ keywords = '', top = 10 }) {
|
|
7
|
+
const trimmedKeywords = keywords.trim()
|
|
8
|
+
const terms = trimmedKeywords.split(/\s+/).filter(Boolean)
|
|
9
|
+
const expandedTerms = terms
|
|
10
|
+
.map(term => `displayName:${term}* OR email:${term}*`)
|
|
11
|
+
.join(' OR ')
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
count: true,
|
|
15
|
+
queryType: 'full',
|
|
16
|
+
search: trimmedKeywords
|
|
17
|
+
? `"${trimmedKeywords}"${expandedTerms ? ` OR ${expandedTerms}` : ''}`
|
|
18
|
+
: '*',
|
|
19
|
+
top,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default async function queryPeople({
|
|
24
|
+
keywords = '',
|
|
25
|
+
top = 10,
|
|
26
|
+
limit = 0,
|
|
27
|
+
requireKeywords = true,
|
|
28
|
+
indexName = 'people-index',
|
|
29
|
+
requestUrl = '',
|
|
30
|
+
runtimeConfig = null,
|
|
31
|
+
searchKey = '',
|
|
32
|
+
apiVersion = '',
|
|
33
|
+
searchEndpoint = '',
|
|
34
|
+
endpoint = '',
|
|
35
|
+
}) {
|
|
36
|
+
if (!keywords && requireKeywords) {
|
|
37
|
+
return {
|
|
38
|
+
people: [],
|
|
39
|
+
facets: [],
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const resolvedLimit = Number.isFinite(Number(limit)) && Number(limit) > 0
|
|
44
|
+
? Number(limit)
|
|
45
|
+
: top
|
|
46
|
+
const resolvedSearchKey = resolveRuntimeConfigValue({
|
|
47
|
+
explicitValue: searchKey,
|
|
48
|
+
runtimeConfig,
|
|
49
|
+
runtimeConfigKeys: ['azureSearchKey'],
|
|
50
|
+
envKeys: [
|
|
51
|
+
'AZURE_SEARCH_KEY',
|
|
52
|
+
'VUE_APP_AZURE_SEARCH_KEY',
|
|
53
|
+
'GRIDSOME_AZURE_SEARCH_KEY',
|
|
54
|
+
],
|
|
55
|
+
})
|
|
56
|
+
const resolvedApiVersion = resolveRuntimeConfigValue({
|
|
57
|
+
explicitValue: apiVersion,
|
|
58
|
+
runtimeConfig,
|
|
59
|
+
runtimeConfigKeys: ['azureSearchVersion'],
|
|
60
|
+
envKeys: [
|
|
61
|
+
'AZURE_SEARCH_VERSION',
|
|
62
|
+
'VUE_APP_AZURE_SEARCH_API_VERSION',
|
|
63
|
+
'GRIDSOME_AZURE_SEARCH_API_VERSION',
|
|
64
|
+
],
|
|
65
|
+
})
|
|
66
|
+
const resolvedSearchEndpoint = resolveRuntimeConfigValue({
|
|
67
|
+
explicitValue: searchEndpoint || endpoint,
|
|
68
|
+
runtimeConfig,
|
|
69
|
+
runtimeConfigKeys: ['azureSearchEndpoint'],
|
|
70
|
+
envKeys: [
|
|
71
|
+
'AZURE_SEARCH_ENDPOINT',
|
|
72
|
+
'VUE_APP_AZURE_SEARCH_ENDPOINT',
|
|
73
|
+
'GRIDSOME_AZURE_SEARCH_ENDPOINT',
|
|
74
|
+
],
|
|
75
|
+
})
|
|
76
|
+
const resolvedRequestUrl =
|
|
77
|
+
typeof requestUrl === 'string' && requestUrl.trim()
|
|
78
|
+
? requestUrl.trim()
|
|
79
|
+
: !resolvedSearchEndpoint &&
|
|
80
|
+
hasSearchProxyRuntime(runtimeConfig)
|
|
81
|
+
? resolveSearchProxyUrl('people', runtimeConfig)
|
|
82
|
+
: ''
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
!resolvedRequestUrl &&
|
|
86
|
+
(!resolvedSearchEndpoint || !resolvedSearchKey || !resolvedApiVersion)
|
|
87
|
+
) {
|
|
88
|
+
throw new Error('Azure Search or proxy configuration is required for queryPeople.')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const payload = {
|
|
92
|
+
keywords,
|
|
93
|
+
limit: resolvedLimit,
|
|
94
|
+
indexName,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const { data } = resolvedRequestUrl
|
|
98
|
+
? await axios({
|
|
99
|
+
method: 'post',
|
|
100
|
+
url: resolvedRequestUrl,
|
|
101
|
+
data: payload,
|
|
102
|
+
})
|
|
103
|
+
: await axios({
|
|
104
|
+
method: 'post',
|
|
105
|
+
headers: {
|
|
106
|
+
'api-key': resolvedSearchKey,
|
|
107
|
+
},
|
|
108
|
+
params: {
|
|
109
|
+
'api-version': resolvedApiVersion,
|
|
110
|
+
},
|
|
111
|
+
url: `${normalizeBaseUrl(resolvedSearchEndpoint)}/indexes/${indexName}/docs/search`,
|
|
112
|
+
data: searchPayload({
|
|
113
|
+
keywords,
|
|
114
|
+
top: resolvedLimit,
|
|
115
|
+
}),
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
people: Array.isArray(data.value) ? data.value : [],
|
|
120
|
+
facets: data['@search.facets'],
|
|
121
|
+
}
|
|
122
|
+
}
|