@asd20/ui-next 2.21.3 → 2.21.5

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,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.21.5](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.21.4...ui-next-v2.21.5) (2026-08-21)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * fix related page display in ai search results ([dae400e](https://github.com/academydistrict20/asd20-ui-next/commit/dae400e9dedd96c7a2a4afe52ddda8af5aaa1503))
9
+
10
+ ## [2.21.4](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.21.3...ui-next-v2.21.4) (2026-08-13)
11
+
3
12
  ## [2.21.3](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.21.2...ui-next-v2.21.3) (2026-08-12)
4
13
 
5
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asd20/ui-next",
3
- "version": "2.21.3",
3
+ "version": "2.21.5",
4
4
  "private": false,
5
5
  "description": "ASD20 UI component library for Vue 3.",
6
6
  "license": "MIT",
@@ -172,22 +172,24 @@
172
172
  <div
173
173
  v-if="
174
174
  turn.role === 'assistant' &&
175
- turn.id === latestAssistantTurnId
175
+ (getAiTurnRelatedPages(turn).length ||
176
+ turn.relatedPagesStatus === 'pending' ||
177
+ turn.id === latestAssistantTurnId)
176
178
  "
177
179
  class="asd20-site-search__related-pages"
178
180
  >
179
181
  <h2
180
- v-if="aiRelatedPagesPreview.length"
182
+ v-if="getAiTurnRelatedPages(turn).length"
181
183
  class="asd20-site-search__related-pages-title"
182
184
  >
183
185
  Related Pages
184
186
  </h2>
185
187
  <ul
186
- v-if="aiRelatedPagesPreview.length"
188
+ v-if="getAiTurnRelatedPages(turn).length"
187
189
  class="asd20-site-search__related-pages-list"
188
190
  >
189
191
  <li
190
- v-for="page in aiRelatedPagesPreview"
192
+ v-for="page in getAiTurnRelatedPages(turn)"
191
193
  :key="page.id"
192
194
  class="asd20-site-search__related-pages-item"
193
195
  >
@@ -200,15 +202,16 @@
200
202
  </li>
201
203
  </ul>
202
204
  <p
203
- v-if="searchingPages && !aiRelatedPagesPreview.length"
205
+ v-if="turn.relatedPagesStatus === 'pending'"
204
206
  class="asd20-site-search__related-pages-status"
205
207
  >
206
208
  Finding related pages...
207
209
  </p>
208
210
  <asd20-button
211
+ v-if="turn.relatedPagesStatus !== 'pending'"
209
212
  class="asd20-site-search__related-pages-cta"
210
213
  :label="
211
- aiRelatedPagesPreview.length
214
+ getAiTurnRelatedPages(turn).length
212
215
  ? 'View All Pages'
213
216
  : 'Check Pages tab for related results'
214
217
  "
@@ -683,6 +686,7 @@ export default {
683
686
  selectedGroup: null,
684
687
  selectedPerson: null,
685
688
  searchingPages: false,
689
+ pageSearchCompleted: false,
686
690
  searchingFiles: false,
687
691
  searchingPeople: false,
688
692
 
@@ -762,6 +766,8 @@ export default {
762
766
  return (
763
767
  this.hasSubmitted &&
764
768
  !!hasSearchText &&
769
+ this.pageSearchCompleted &&
770
+ !this.searchingAi &&
765
771
  !this.searchingPages &&
766
772
  Array.isArray(this.currentPages) &&
767
773
  this.currentPages.length === 0
@@ -1099,30 +1105,10 @@ export default {
1099
1105
  },
1100
1106
 
1101
1107
  aiRelatedPagesPreview() {
1102
- if (!Array.isArray(this.pageListItems) || !this.pageListItems.length) {
1103
- return []
1104
- }
1105
-
1106
- return this.pageListItems
1107
- .map((item, index) => {
1108
- const page = item && item.page ? item.page : {}
1109
- const title =
1110
- (typeof item.label === 'string' && item.label.trim()) ||
1111
- (typeof page.title === 'string' && page.title.trim()) ||
1112
- `Page ${index + 1}`
1113
- const url =
1114
- (typeof item.link === 'string' && item.link.trim()) ||
1115
- (typeof page.url === 'string' && page.url.trim()) ||
1116
- ''
1117
- const id =
1118
- (typeof page.id === 'string' && page.id.trim()) ||
1119
- (typeof page.slug === 'string' && page.slug.trim()) ||
1120
- `${title}-${index}`
1121
-
1122
- return { id, title, url }
1123
- })
1124
- .filter(page => !!page.url)
1125
- .slice(0, 3)
1108
+ const turn = this.aiTranscript.find(
1109
+ item => item && item.id === this.latestAssistantTurnId
1110
+ )
1111
+ return this.getAiTurnRelatedPages(turn)
1126
1112
  },
1127
1113
  },
1128
1114
 
@@ -1755,6 +1741,7 @@ export default {
1755
1741
  searchMode: this.searchMode || '',
1756
1742
  includeDistrictResults: !!this.resolvedIncludeDistrictResults,
1757
1743
  pages: Array.isArray(this.currentPages) ? this.currentPages : [],
1744
+ pageSearchCompleted: this.pageSearchCompleted,
1758
1745
  files: Array.isArray(this.currentFiles) ? this.currentFiles : [],
1759
1746
  groups: Array.isArray(this.currentGroups) ? this.currentGroups : [],
1760
1747
  people: Array.isArray(this.currentPeople) ? this.currentPeople : [],
@@ -1841,9 +1828,6 @@ export default {
1841
1828
  this.aiConversation = Array.isArray(snapshot.aiConversation)
1842
1829
  ? snapshot.aiConversation
1843
1830
  : []
1844
- this.aiTranscript = Array.isArray(snapshot.aiTranscript)
1845
- ? snapshot.aiTranscript
1846
- : []
1847
1831
  this.aiKeywordsDisplayAnswer = snapshot.aiKeywordsDisplayAnswer || ''
1848
1832
  this.aiKeywordsDisplayPages = snapshot.aiKeywordsDisplayPages || ''
1849
1833
  this.expandedKeywordsTurnId = null
@@ -1860,6 +1844,10 @@ export default {
1860
1844
  ? this.limitWords(targetState.text, 4)
1861
1845
  : ''
1862
1846
  this.keywords = nextKeywords
1847
+ this.pageSearchCompleted =
1848
+ typeof snapshot.pageSearchCompleted === 'boolean'
1849
+ ? snapshot.pageSearchCompleted
1850
+ : !!nextKeywords
1863
1851
 
1864
1852
  this.suppressInputClearReset = true
1865
1853
  this.inputText = ''
@@ -1870,6 +1858,9 @@ export default {
1870
1858
  const groups = Array.isArray(snapshot.groups) ? snapshot.groups : []
1871
1859
  const people = Array.isArray(snapshot.people) ? snapshot.people : []
1872
1860
  this.setSearchResults({ pages, files, groups, people })
1861
+ this.aiTranscript = this.restoreCachedAiTranscript(
1862
+ snapshot.aiTranscript
1863
+ )
1873
1864
 
1874
1865
  if (!skipTabUpdate) {
1875
1866
  const preferredTab = SEARCH_ROUTE_TABS.has(targetState.tab)
@@ -2445,6 +2436,69 @@ export default {
2445
2436
  })
2446
2437
  },
2447
2438
 
2439
+ getAiTurnRelatedPages(turn) {
2440
+ if (!turn || !Array.isArray(turn.relatedPages)) return []
2441
+ return turn.relatedPages
2442
+ },
2443
+
2444
+ buildAiRelatedPagesPreview(items = this.pageListItems) {
2445
+ if (!Array.isArray(items) || !items.length) return []
2446
+
2447
+ return items
2448
+ .map((item, index) => {
2449
+ const page = item && item.page ? item.page : {}
2450
+ if (page.isNoResultsFallback) return null
2451
+ const title =
2452
+ (typeof item.label === 'string' && item.label.trim()) ||
2453
+ (typeof page.title === 'string' && page.title.trim()) ||
2454
+ `Page ${index + 1}`
2455
+ const url =
2456
+ (typeof item.link === 'string' && item.link.trim()) ||
2457
+ (typeof page.url === 'string' && page.url.trim()) ||
2458
+ ''
2459
+ const id =
2460
+ (typeof page.id === 'string' && page.id.trim()) ||
2461
+ (typeof page.slug === 'string' && page.slug.trim()) ||
2462
+ `${title}-${index}`
2463
+
2464
+ return url ? { id, title, url } : null
2465
+ })
2466
+ .filter(Boolean)
2467
+ .slice(0, 3)
2468
+ },
2469
+
2470
+ restoreCachedAiTranscript(transcript) {
2471
+ const turns = Array.isArray(transcript) ? transcript : []
2472
+ let latestAssistantIndex = -1
2473
+ turns.forEach((turn, index) => {
2474
+ if (turn && turn.role === 'assistant') latestAssistantIndex = index
2475
+ })
2476
+ const legacyLatestPreview = this.buildAiRelatedPagesPreview()
2477
+
2478
+ return turns.map((turn, index) => {
2479
+ if (!turn || turn.role !== 'assistant') return turn
2480
+ const hasOwnedPages = Array.isArray(turn.relatedPages)
2481
+ const relatedPages = hasOwnedPages
2482
+ ? turn.relatedPages
2483
+ .filter(page => page && page.url)
2484
+ .slice(0, 3)
2485
+ .map(page => ({ ...page }))
2486
+ : index === latestAssistantIndex
2487
+ ? legacyLatestPreview
2488
+ : []
2489
+ return { ...turn, relatedPages, relatedPagesStatus: 'complete' }
2490
+ })
2491
+ },
2492
+
2493
+ completeAiTurnRelatedPages(turnId, runId) {
2494
+ if (!turnId || !this.isCurrentSearchRun(runId)) return false
2495
+ this.updateAiTranscriptTurn(turnId, {
2496
+ relatedPages: this.buildAiRelatedPagesPreview(),
2497
+ relatedPagesStatus: 'complete',
2498
+ })
2499
+ return true
2500
+ },
2501
+
2448
2502
  setAiTurnSearchLogId(turnId, searchLogId) {
2449
2503
  if (!turnId || !searchLogId) return
2450
2504
  this.updateAiTranscriptTurn(turnId, { searchLogId })
@@ -2577,6 +2631,7 @@ export default {
2577
2631
  this.selectedPerson = null
2578
2632
  this.searchingAi = preserveAiLoading ? this.searchingAi : false
2579
2633
  this.searchingPages = false
2634
+ this.pageSearchCompleted = false
2580
2635
  this.searchingFiles = false
2581
2636
  this.searchingPeople = false
2582
2637
  this.activeAiQuestionKey = preserveAiLoading
@@ -2649,6 +2704,7 @@ export default {
2649
2704
  if (!this.isCurrentSearchRun(runId)) {
2650
2705
  return this.currentPages
2651
2706
  }
2707
+ this.pageSearchCompleted = true
2652
2708
 
2653
2709
  if (this.keywords && this.keywords.trim() && !keepAnswersTab) {
2654
2710
  this.currentTab = 'Pages'
@@ -3046,6 +3102,8 @@ export default {
3046
3102
  searchLogId: null,
3047
3103
  feedbackValue: null,
3048
3104
  feedbackSubmitting: false,
3105
+ relatedPages: [],
3106
+ relatedPagesStatus: keywordsToUse ? 'pending' : 'complete',
3049
3107
  }
3050
3108
  assistantTurnId = assistantTurn.id
3051
3109
  this.aiTranscript = [...this.aiTranscript, assistantTurn]
@@ -3060,6 +3118,7 @@ export default {
3060
3118
  this.keywords = keywordsToUse
3061
3119
  await this.searchPages({ keepAnswersTab: true, runId })
3062
3120
  if (!this.isCurrentSearchRun(runId)) return
3121
+ this.completeAiTurnRelatedPages(assistantTurnId, runId)
3063
3122
  relatedPagesForAnalytics = this.getAnalyticsPages()
3064
3123
  .slice(0, 10)
3065
3124
  .map(p => ({ title: p.title || '', url: p.url || '' }))
@@ -3090,6 +3149,8 @@ export default {
3090
3149
  searchLogId: null,
3091
3150
  feedbackValue: null,
3092
3151
  feedbackSubmitting: false,
3152
+ relatedPages: [],
3153
+ relatedPagesStatus: 'complete',
3093
3154
  },
3094
3155
  ]
3095
3156
  this.currentTab = 'Answers'