From d288410903818e2e9ca62c4268a71febf92af83b Mon Sep 17 00:00:00 2001 From: rdeiser Date: Tue, 8 Sep 2026 08:46:28 -0500 Subject: [PATCH 1/7] feat(tsconfig.json-and-mixpanel.service.ts): adding mixpanel browser sdk Adding Mixpanel Browser SDK so that local Angular components can be tracked events can be sent to Mixpanel. BREAKING CHANGE: --- src/app/services/mixpanel.service.ts | 52 ++++++++++++++++++++++++++++ tsconfig.json | 1 + 2 files changed, 53 insertions(+) create mode 100644 src/app/services/mixpanel.service.ts diff --git a/src/app/services/mixpanel.service.ts b/src/app/services/mixpanel.service.ts new file mode 100644 index 00000000..b4564030 --- /dev/null +++ b/src/app/services/mixpanel.service.ts @@ -0,0 +1,52 @@ +import { Injectable } from '@angular/core'; +import mixpanel from 'mixpanel-browser'; +import { DOCUMENT } from '@angular/common'; +import { Inject } from '@angular/core'; + +@Injectable({ providedIn: 'root' }) +export class MixpanelService { + private initialized = false; + private pageStartTime = Date.now(); + + constructor(@Inject(DOCUMENT) private document: Document) {} + + init(projectToken: string) { + if (!this.initialized) { + mixpanel.init(projectToken, { debug: false, autocapture: false }); + mixpanel.register({ + vid: this.getVid(), + library: 'Kansas State', + user_type: this.getUserType() + }); + this.initialized = true; + } + } + + track(eventName: string, properties: Record = {}) { + const mp = (window as any).mixpanel ?? mixpanel; + if (!mp?.track) return; + + const enriched = { + ...properties, + page: this.document.location.pathname, + page_url: this.document.location.href, + referrer: this.document.referrer, + timestamp: new Date().toISOString(), + time_on_page_ms: Date.now() - this.pageStartTime, + vid: this.getVid(), + user_type: this.getUserType() + }; + + mp.track(eventName, enriched); + } + + private getVid(): string { + const params = new URLSearchParams(this.document.location.search); + return params.get('vid') ?? 'UNKNOWN'; + } + + private getUserType(): string { + // Replace with real check from your store / auth service + return 'anonymous'; + } +} diff --git a/tsconfig.json b/tsconfig.json index 9fa16d63..4520c6dc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", + "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, From eb21d7acdd6b35ca75569db632fde4640f74f337 Mon Sep 17 00:00:00 2001 From: rdeiser Date: Tue, 8 Sep 2026 08:48:57 -0500 Subject: [PATCH 2/7] feat(library-alerts-component-and-libraryh3lp-component): mixpanel events Added Mixpanel Events for LibraryH3lp and Library Alerts components. --- .../library-alerts-pannel.component.ts | 28 +++++++++++++++++-- src/app/libraryh3lp/libraryh3lp.component.ts | 19 +++++++++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/app/library-alerts-pannel/library-alerts-pannel.component.ts b/src/app/library-alerts-pannel/library-alerts-pannel.component.ts index 47350b3f..49085974 100644 --- a/src/app/library-alerts-pannel/library-alerts-pannel.component.ts +++ b/src/app/library-alerts-pannel/library-alerts-pannel.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { HttpClient } from '@angular/common/http'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { MixpanelService } from '../services/mixpanel.service'; @Component({ selector: 'library-alerts-pannel', @@ -19,7 +20,8 @@ export class LibraryAlertsPannelComponent implements OnInit { constructor( private http: HttpClient, - private sanitizer: DomSanitizer + private sanitizer: DomSanitizer, + private mixpanel: MixpanelService ) {} ngOnInit(): void { @@ -34,6 +36,22 @@ export class LibraryAlertsPannelComponent implements OnInit { this.showAlertInfo = data?.informational?.active === true; this.showAlertEmergency = data?.emergency?.active === true; + if (this.showAlertInfo) { + this.mixpanel.track('Library Alert Displayed', { + alert_type: 'informational', + severity: data?.informational?.severity || 'info', + message_length: data?.informational?.message?.length || 0, + }); + } + + if (this.showAlertEmergency) { + this.mixpanel.track('Library Alert Displayed', { + alert_type: 'emergency', + severity: data?.emergency?.severity || 'high', + message_length: data?.emergency?.message?.length || 0, + }); + } + this.infoMessage = this.sanitizer.bypassSecurityTrustHtml( this.decodeHtmlEntitiesDeep(data?.informational?.message) ); @@ -51,10 +69,16 @@ export class LibraryAlertsPannelComponent implements OnInit { closeAlert(type: 'info' | 'emergency'): void { if (type === 'info') { this.showAlertInfo = false; + this.mixpanel.track('Library Alert Dismissed', { + alert_type: 'informational' + }); } if (type === 'emergency') { this.showAlertEmergency = false; + this.mixpanel.track('Library Alert Dismissed', { + alert_type: 'emergency' + }); } } @@ -73,4 +97,4 @@ export class LibraryAlertsPannelComponent implements OnInit { return current; } -} \ No newline at end of file +} diff --git a/src/app/libraryh3lp/libraryh3lp.component.ts b/src/app/libraryh3lp/libraryh3lp.component.ts index fd39137c..833cb7cd 100644 --- a/src/app/libraryh3lp/libraryh3lp.component.ts +++ b/src/app/libraryh3lp/libraryh3lp.component.ts @@ -8,6 +8,7 @@ import { ElementRef, } from '@angular/core'; import { DOCUMENT } from '@angular/common'; +import { MixpanelService } from '../services/mixpanel.service'; @Component({ selector: 'app-libraryh3lp', templateUrl: './libraryh3lp.component.html', @@ -19,7 +20,8 @@ export class Libraryh3lpComponent implements OnInit, OnDestroy, AfterViewInit { constructor( private renderer: Renderer2, private elementRef: ElementRef, - @Inject(DOCUMENT) private document: Document + @Inject(DOCUMENT) private document: Document, + private mixpanel: MixpanelService ) {} ngOnInit() { // No initialization needed here @@ -30,7 +32,6 @@ export class Libraryh3lpComponent implements OnInit, OnDestroy, AfterViewInit { this.showChat = false; this.chatFrameWrap.style.display = 'none'; } - // Load the script (as in your original implementation) this.loadScript(); } toggleChat() { @@ -38,6 +39,15 @@ export class Libraryh3lpComponent implements OnInit, OnDestroy, AfterViewInit { if (this.chatFrameWrap) { this.chatFrameWrap.style.display = this.showChat ? 'block' : 'none'; } + if (this.showChat) { + this.mixpanel.track('Library Chat Opened', { + widget_id: '19250', + }); + } else { + this.mixpanel.track('Library Chat Closed', { + widget_id: '19250', + }); + } } loadScript() { const script = this.renderer.createElement('script'); @@ -49,8 +59,5 @@ export class Libraryh3lpComponent implements OnInit, OnDestroy, AfterViewInit { ); this.renderer.appendChild(this.document.body, script); } - ngOnDestroy() { - // Cleanup if needed (not strictly necessary here) - // For example, if you had any event listeners that need to be removed - } + ngOnDestroy() {} } From 3e7cf66cf1835d295e8b6901189f6cd4bc16a05a Mon Sep 17 00:00:00 2001 From: rdeiser Date: Tue, 8 Sep 2026 09:14:58 -0500 Subject: [PATCH 3/7] ci(zip): update workflow to run on Node 24 Remove force node 24 and updated workflow to be compatible with the new Node.js version --- .github/workflows/zip.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/zip.yml b/.github/workflows/zip.yml index 0560078b..497480eb 100644 --- a/.github/workflows/zip.yml +++ b/.github/workflows/zip.yml @@ -6,17 +6,16 @@ on: branches: [ production ] types: [ closed ] workflow_dispatch: + jobs: build: runs-on: ubuntu-latest - env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true' steps: - name: Check out repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Use Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '24' cache: 'npm' @@ -34,7 +33,7 @@ jobs: mv dist/01KSU_INST-KSU staging/ - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: 01KSU_INST-KSU path: staging/ From 012ef9a11b138abbf901777f42a6d93683622d4f Mon Sep 17 00:00:00 2001 From: rdeiser Date: Tue, 8 Sep 2026 09:29:27 -0500 Subject: [PATCH 4/7] fix(mixpanel-browser-dependenc): add missing mixpanel-browser dependency --- package-lock.json | 115 ++++++++++++++++++++++++++++++++++++++++++++-- package.json | 1 + 2 files changed, 111 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7b349812..1e8d850c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "@ngx-translate/http-loader": "^8.0.0", "@webcomponents/custom-elements": "^1.6.0", "dotenv": "^16.4.5", + "mixpanel-browser": "^2.82.1", "rxjs": "~7.8.0", "tslib": "^2.4.1", "zone.js": "~0.14.10" @@ -4576,6 +4577,62 @@ "win32" ] }, + "node_modules/@mixpanel/rrdom": { + "version": "2.0.0-alpha.18.6", + "resolved": "https://registry.npmjs.org/@mixpanel/rrdom/-/rrdom-2.0.0-alpha.18.6.tgz", + "integrity": "sha512-JY1Kr8c5pPmFBdPMLIEm1e0/hw2xvsS515Qqf+5Lpm0AW+2e/ZvA6P6M+z4fXeuachfZZv06UhTvixiUJv355Q==", + "license": "MIT", + "dependencies": { + "@mixpanel/rrweb-snapshot": "^2.0.0-alpha.18" + } + }, + "node_modules/@mixpanel/rrweb": { + "version": "2.0.0-alpha.18.4", + "resolved": "https://registry.npmjs.org/@mixpanel/rrweb/-/rrweb-2.0.0-alpha.18.4.tgz", + "integrity": "sha512-ICpEYDFEEiCoUuQg+de3VvQCsolF4lNHfEM9DBp5Pwuc7EgXqwWV4wUpiRF/NbhoKk+82X1Qe+oqqlKJb/CGFw==", + "license": "MIT", + "dependencies": { + "@mixpanel/rrdom": "^2.0.0-alpha.18", + "@mixpanel/rrweb-snapshot": "^2.0.0-alpha.18", + "@mixpanel/rrweb-types": "^2.0.0-alpha.18", + "@mixpanel/rrweb-utils": "^2.0.0-alpha.18", + "@types/css-font-loading-module": "0.0.7", + "@xstate/fsm": "^1.4.0", + "base64-arraybuffer": "^1.0.1", + "mitt": "^3.0.0" + } + }, + "node_modules/@mixpanel/rrweb-plugin-console-record": { + "version": "2.0.0-alpha.18.4", + "resolved": "https://registry.npmjs.org/@mixpanel/rrweb-plugin-console-record/-/rrweb-plugin-console-record-2.0.0-alpha.18.4.tgz", + "integrity": "sha512-gGxEnNpfWurQht+fpSJbwPV60ug0LAENlk4Ux3XRmYooNJGPBO1TiQHcM7g0yhrKf4tfbTiKKZ4EXzFlOZs/pw==", + "license": "MIT", + "peerDependencies": { + "@mixpanel/rrweb": "^2.0.0-alpha.18", + "@mixpanel/rrweb-utils": "^2.0.0-alpha.18" + } + }, + "node_modules/@mixpanel/rrweb-snapshot": { + "version": "2.0.0-alpha.18.6", + "resolved": "https://registry.npmjs.org/@mixpanel/rrweb-snapshot/-/rrweb-snapshot-2.0.0-alpha.18.6.tgz", + "integrity": "sha512-8c8TArw8l0mmYPvKc3asq3hIzQ7uVrNVQ4xsVt+ESxHohW8r47ua/YLDpd2jV30FZj4Y3KvGTQl5sXLDI+02Zw==", + "license": "MIT", + "dependencies": { + "postcss": "^8.4.38" + } + }, + "node_modules/@mixpanel/rrweb-types": { + "version": "2.0.0-alpha.18.6", + "resolved": "https://registry.npmjs.org/@mixpanel/rrweb-types/-/rrweb-types-2.0.0-alpha.18.6.tgz", + "integrity": "sha512-KvaTcbZR4mJ3w1b1fEq4AeSg9rUqvQ1gKko9r56ANUw4fqWam23xoXrLJ8Og+hPYTwIDQ99TkZBVXFTGJqYwpQ==", + "license": "MIT" + }, + "node_modules/@mixpanel/rrweb-utils": { + "version": "2.0.0-alpha.18.4", + "resolved": "https://registry.npmjs.org/@mixpanel/rrweb-utils/-/rrweb-utils-2.0.0-alpha.18.4.tgz", + "integrity": "sha512-c3nUbQl19kxHjf8nowFMeXlJw0ZqLesIVBb9t4g1nC4WtaNEPkFotWRdGt5V2cJNQ+aY38/v2uYb8Ren4IcdSQ==", + "license": "MIT" + }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", @@ -5737,6 +5794,12 @@ "@types/node": "*" } }, + "node_modules/@types/css-font-loading-module": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz", + "integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -5789,6 +5852,12 @@ "integrity": "sha512-3N0FpQTeiWjm+Oo1WUYWguUS7E6JLceiGTriFrG8k5PU7zRLJCzLcWURU3wjMbZGS//a2/LgjsnO3QxIlwxt9g==", "dev": true }, + "node_modules/@types/json-logic-js": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/json-logic-js/-/json-logic-js-2.0.5.tgz", + "integrity": "sha512-hu/FTi0zwCjQEFfbPur275cNoZj6NsuOBhhYNzqoSdfmMhuxFr58OZ957lyIOWc9+kO+2tFlBthRjcxuytD4HA==", + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -6111,6 +6180,12 @@ } } }, + "node_modules/@xstate/fsm": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.6.5.tgz", + "integrity": "sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw==", + "license": "MIT" + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -6694,6 +6769,15 @@ "license": "Apache-2.0", "optional": true }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -10715,6 +10799,12 @@ "node": ">=4" } }, + "node_modules/json-logic-js": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/json-logic-js/-/json-logic-js-2.0.5.tgz", + "integrity": "sha512-rTT2+lqcuUmj4DgWfmzupZqQDA64AdmYqizzMPWj3DxGdfFNsxPpcNVSaTj4l8W2tG/+hg7/mQhxjU3aPacO6g==", + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -12065,6 +12155,25 @@ "dev": true, "license": "ISC" }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mixpanel-browser": { + "version": "2.82.1", + "resolved": "https://registry.npmjs.org/mixpanel-browser/-/mixpanel-browser-2.82.1.tgz", + "integrity": "sha512-meJv23+7YYUHs08VlIVUC4x9riKnCLy6THQ264idlonBKzOq4LmmubOjOm71nVRm6osqEbXeXH2fwYrNXHRG1g==", + "license": "Apache-2.0", + "dependencies": { + "@mixpanel/rrweb": "2.0.0-alpha.18.4", + "@mixpanel/rrweb-plugin-console-record": "2.0.0-alpha.18.4", + "@mixpanel/rrweb-utils": "2.0.0-alpha.18.4", + "@types/json-logic-js": "2.0.5", + "json-logic-js": "2.0.5" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -12153,7 +12262,6 @@ "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, "funding": [ { "type": "github", @@ -13120,8 +13228,7 @@ "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -13244,7 +13351,6 @@ "version": "8.4.41", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -14725,7 +14831,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" diff --git a/package.json b/package.json index 40b2799d..b08a2b46 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@ngx-translate/http-loader": "^8.0.0", "@webcomponents/custom-elements": "^1.6.0", "dotenv": "^16.4.5", + "mixpanel-browser": "^2.82.1", "rxjs": "~7.8.0", "tslib": "^2.4.1", "zone.js": "~0.14.10" From e59583865df67d5c5c41d1a65dc0f1b2c09e84a1 Mon Sep 17 00:00:00 2001 From: rdeiser Date: Wed, 9 Sep 2026 13:09:25 -0500 Subject: [PATCH 5/7] feat(nde-view-it-reorder-component): rearranged the subsections of the viewit iframe The subsections of the ViewIt iFrame were rearranged so that the general electronic services are displayed after online access links BREAKING CHANGE: --- .../custom1-module/customComponentMappings.ts | 2 + .../nde-view-it-reorder.component.ts | 82 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/app/nde-view-it-reorder/nde-view-it-reorder.component.ts diff --git a/src/app/custom1-module/customComponentMappings.ts b/src/app/custom1-module/customComponentMappings.ts index a8b27e57..8bba4a33 100644 --- a/src/app/custom1-module/customComponentMappings.ts +++ b/src/app/custom1-module/customComponentMappings.ts @@ -4,6 +4,7 @@ import { NdeProblemReportCustom } from '../nde-problem-report-custom/nde-problem import { PayFinesComponent } from '../pay-fines/pay-fines.component'; import { TrafficResultLimitComponent } from '../traffic-result-limit/traffic-result-limit.component'; import { PickupFilterComponent } from '../pickup-filter/pickup-filter.component'; +import { NdeViewItReorderComponent } from '../nde-view-it-reorder/nde-view-it-reorder.component'; // Define the map export const selectorComponentMap = new Map([ @@ -13,4 +14,5 @@ export const selectorComponentMap = new Map([ ['nde-top-bar-after', LibraryAlertsPannelComponent], ['nde-search-no-results-before', TrafficResultLimitComponent], ['nde-formly-general-wrapper-bottom', PickupFilterComponent], + ['nde-full-display-service-container-before', NdeViewItReorderComponent], ]); diff --git a/src/app/nde-view-it-reorder/nde-view-it-reorder.component.ts b/src/app/nde-view-it-reorder/nde-view-it-reorder.component.ts new file mode 100644 index 00000000..4dc98fda --- /dev/null +++ b/src/app/nde-view-it-reorder/nde-view-it-reorder.component.ts @@ -0,0 +1,82 @@ +import { Component, AfterViewInit, OnDestroy } from '@angular/core'; + +@Component({ + selector: 'nde-view-it-reorder', + template: '', + standalone: true +}) +export class NdeViewItReorderComponent implements AfterViewInit, OnDestroy { + private observers: MutationObserver[] = []; + private scheduled = false; + + ngAfterViewInit(): void { + // Initial pass after render + setTimeout(() => this.reorderViewItSections(), 0); + // Watch only the View It containers, not the whole body + this.attachObservers(); + } + + ngOnDestroy(): void { + this.observers.forEach(o => o.disconnect()); + } + + private attachObservers(): void { + const containers = [ + document.querySelector('[id="nui.getit.service_viewit"]'), + document.querySelector('nde-view-it') + ].filter((c): c is HTMLElement => !!c); + + containers.forEach(container => { + const obs = new MutationObserver(() => this.scheduleReorder()); + obs.observe(container, { childList: true, subtree: false }); + this.observers.push(obs); + }); + } + + private scheduleReorder(): void { + if (this.scheduled) return; + this.scheduled = true; + setTimeout(() => { + this.scheduled = false; + this.reorderViewItSections(); + }, 50); + } + + private reorderViewItSections(): void { + const containers = [ + document.querySelector('[id="nui.getit.service_viewit"]'), + document.querySelector('nde-view-it') + ].filter((c): c is HTMLElement => !!c); + + for (const container of containers) { + const sections = Array.from(container.querySelectorAll('nde-view-it-section')) as HTMLElement[]; + if (sections.length < 2) continue; + + const getTitle = (sec: HTMLElement) => sec.querySelector('.view-it-title span')?.textContent?.trim() ?? ''; + + const isFullText = (sec: HTMLElement) => { + const t = getTitle(sec); + return /viewit\.fulltext/i.test(t) || /full text availability/i.test(t); + }; + const isGES = (sec: HTMLElement) => { + const t = getTitle(sec); + return /c\.uresolver\.GeneralElectronicServices/i.test(t) || /additional services/i.test(t); + }; + + const fullTextSections = sections.filter(isFullText); + const gesSections = sections.filter(isGES); + if (!fullTextSections.length || !gesSections.length) continue; + + const lastFullText = fullTextSections[fullTextSections.length - 1]; + const parent = lastFullText.parentNode as HTMLElement | null; + if (!parent) continue; + + gesSections.forEach(ges => { + if (!parent.contains(ges)) return; + if (ges.previousElementSibling === lastFullText) return; + parent.removeChild(ges); + parent.insertBefore(ges, lastFullText.nextSibling); + }); + } + } +} From 8f6bae823cafe3eead06cf674f561a3ce2ef1c08 Mon Sep 17 00:00:00 2001 From: rdeiser Date: Mon, 14 Sep 2026 09:58:35 -0500 Subject: [PATCH 6/7] refactor(mixpanel.service.ts): remove comments Reviewed code and removed unneeded comments --- src/app/services/mixpanel.service.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/app/services/mixpanel.service.ts b/src/app/services/mixpanel.service.ts index b4564030..56623138 100644 --- a/src/app/services/mixpanel.service.ts +++ b/src/app/services/mixpanel.service.ts @@ -15,8 +15,7 @@ export class MixpanelService { mixpanel.init(projectToken, { debug: false, autocapture: false }); mixpanel.register({ vid: this.getVid(), - library: 'Kansas State', - user_type: this.getUserType() + library: 'Kansas State' }); this.initialized = true; } @@ -33,8 +32,7 @@ export class MixpanelService { referrer: this.document.referrer, timestamp: new Date().toISOString(), time_on_page_ms: Date.now() - this.pageStartTime, - vid: this.getVid(), - user_type: this.getUserType() + vid: this.getVid() }; mp.track(eventName, enriched); @@ -46,7 +44,6 @@ export class MixpanelService { } private getUserType(): string { - // Replace with real check from your store / auth service return 'anonymous'; } } From b843d81ac346219c20699305d092f4b9da603669 Mon Sep 17 00:00:00 2001 From: rdeiser Date: Mon, 14 Sep 2026 10:00:25 -0500 Subject: [PATCH 7/7] feat(library-alerts-pannel-component): information box Added a general information box to accompaniment the informational box within Primo VE --- .../library-alerts-pannel.component.html | 50 ++++++------------- .../library-alerts-pannel.component.scss | 6 +-- 2 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/app/library-alerts-pannel/library-alerts-pannel.component.html b/src/app/library-alerts-pannel/library-alerts-pannel.component.html index deda2b15..9cb908c7 100644 --- a/src/app/library-alerts-pannel/library-alerts-pannel.component.html +++ b/src/app/library-alerts-pannel/library-alerts-pannel.component.html @@ -1,13 +1,6 @@ -
+
- +
@@ -15,27 +8,14 @@
-
- Close Alert Button +
+ Close Alert Button
-
+
- +
@@ -43,13 +23,15 @@
-
- Close Alert Button +
+ Close Alert Button +
+
+ +
+
+

New Search It Interface: The library catalog interface will be updated at the end of the Fall + 2026 Academic Semester. To submit feedback, comments, questions, or concerns, complete this Qualtrics form. +

\ No newline at end of file diff --git a/src/app/library-alerts-pannel/library-alerts-pannel.component.scss b/src/app/library-alerts-pannel/library-alerts-pannel.component.scss index 52bfdd90..417243e3 100644 --- a/src/app/library-alerts-pannel/library-alerts-pannel.component.scss +++ b/src/app/library-alerts-pannel/library-alerts-pannel.component.scss @@ -1,10 +1,10 @@ -.alerts { +.alerts .info-bar { padding-bottom: 0; max-width: 1260px; margin: 0 auto; } -.alert-box { +.alert-box, .info-bar { font-size: 1.25rem; padding: 20px 30px; text-align: left; @@ -28,7 +28,7 @@ background: #ba1623; } -.alert-box__normal { +.alert-box__normal, .info-bar { color: #512888; background: #e6e6e6; border: 1px solid #512888;