web-mojo 2.2.65 → 2.2.67
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 +14 -0
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.cjs.js.map +1 -1
- package/dist/admin.es.js +1 -1
- package/dist/admin.es.js.map +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.es.js +1 -1
- package/dist/chunks/ChatView-Cfe0ZGvr.js +2 -0
- package/dist/chunks/ChatView-Cfe0ZGvr.js.map +1 -0
- package/dist/chunks/ChatView-DuQVFrCY.js +2 -0
- package/dist/chunks/ChatView-DuQVFrCY.js.map +1 -0
- package/dist/chunks/{Collection-1sPoIFvQ.js → Collection-BWKmydl5.js} +2 -2
- package/dist/chunks/{Collection-1sPoIFvQ.js.map → Collection-BWKmydl5.js.map} +1 -1
- package/dist/chunks/{Collection-DSBRXpwK.js → Collection-CmjTsmrP.js} +2 -2
- package/dist/chunks/{Collection-DSBRXpwK.js.map → Collection-CmjTsmrP.js.map} +1 -1
- package/dist/chunks/ContextMenu-8vTiZZQV.js +2 -0
- package/dist/chunks/ContextMenu-8vTiZZQV.js.map +1 -0
- package/dist/chunks/ContextMenu-DBw0WMTO.js +2 -0
- package/dist/chunks/ContextMenu-DBw0WMTO.js.map +1 -0
- package/dist/chunks/{DataView--nUWtq6r.js → DataView-BEovBggn.js} +2 -2
- package/dist/chunks/{DataView--nUWtq6r.js.map → DataView-BEovBggn.js.map} +1 -1
- package/dist/chunks/{DataView-CK3Z0TJH.js → DataView-DyJKgOn3.js} +2 -2
- package/dist/chunks/{DataView-CK3Z0TJH.js.map → DataView-DyJKgOn3.js.map} +1 -1
- package/dist/chunks/{Dialog-VoLlToMl.js → Dialog-DW7PHzUc.js} +2 -2
- package/dist/chunks/{Dialog-wBhTkeWg.js.map → Dialog-DW7PHzUc.js.map} +1 -1
- package/dist/chunks/{Dialog-wBhTkeWg.js → Dialog-jfBsXy5X.js} +2 -2
- package/dist/chunks/{Dialog-VoLlToMl.js.map → Dialog-jfBsXy5X.js.map} +1 -1
- package/dist/chunks/Files-C-ChBvr5.js +2 -0
- package/dist/chunks/Files-C-ChBvr5.js.map +1 -0
- package/dist/chunks/Files-DNbHDy43.js +2 -0
- package/dist/chunks/Files-DNbHDy43.js.map +1 -0
- package/dist/chunks/FormView-EoB_ZdIB.js +3 -0
- package/dist/chunks/FormView-EoB_ZdIB.js.map +1 -0
- package/dist/chunks/FormView-Q_lFA0nr.js +3 -0
- package/dist/chunks/FormView-Q_lFA0nr.js.map +1 -0
- package/dist/chunks/{ListView-6JQ6tRXs.js → ListView-BLFFK_Ir.js} +2 -2
- package/dist/chunks/{ListView-6JQ6tRXs.js.map → ListView-BLFFK_Ir.js.map} +1 -1
- package/dist/chunks/{ListView-DVStKiMi.js → ListView-CMZpwyyC.js} +2 -2
- package/dist/chunks/{ListView-DVStKiMi.js.map → ListView-CMZpwyyC.js.map} +1 -1
- package/dist/chunks/{MetricsCountryMapView-CnAEbUw_.js → MetricsCountryMapView-B0kWK-Js.js} +2 -2
- package/dist/chunks/{MetricsCountryMapView-CnAEbUw_.js.map → MetricsCountryMapView-B0kWK-Js.js.map} +1 -1
- package/dist/chunks/{MetricsCountryMapView-J067qrrt.js → MetricsCountryMapView-DuBKO7gz.js} +2 -2
- package/dist/chunks/{MetricsCountryMapView-J067qrrt.js.map → MetricsCountryMapView-DuBKO7gz.js.map} +1 -1
- package/dist/chunks/{MetricsMiniChartWidget-DtWq2_YJ.js → MetricsMiniChartWidget-BkMjI-gz.js} +2 -2
- package/dist/chunks/{MetricsMiniChartWidget-DtWq2_YJ.js.map → MetricsMiniChartWidget-BkMjI-gz.js.map} +1 -1
- package/dist/chunks/{MetricsMiniChartWidget-CtCN1rtt.js → MetricsMiniChartWidget-ChC5GGm6.js} +2 -2
- package/dist/chunks/{MetricsMiniChartWidget-CtCN1rtt.js.map → MetricsMiniChartWidget-ChC5GGm6.js.map} +1 -1
- package/dist/chunks/{PDFViewer-BNCyDElg.js → PDFViewer-iOqYpg-6.js} +2 -2
- package/dist/chunks/{PDFViewer-BNCyDElg.js.map → PDFViewer-iOqYpg-6.js.map} +1 -1
- package/dist/chunks/{PDFViewer-Di4OHAkv.js → PDFViewer-sFoyopz3.js} +2 -2
- package/dist/chunks/{PDFViewer-Di4OHAkv.js.map → PDFViewer-sFoyopz3.js.map} +1 -1
- package/dist/chunks/{Rest-Ds9e8tN8.js → Rest-B1eUyLX5.js} +2 -2
- package/dist/chunks/{Rest-Ds9e8tN8.js.map → Rest-B1eUyLX5.js.map} +1 -1
- package/dist/chunks/{Rest-DHbszkuP.js → Rest-BJ3Mvx1L.js} +2 -2
- package/dist/chunks/{Rest-DHbszkuP.js.map → Rest-BJ3Mvx1L.js.map} +1 -1
- package/dist/chunks/TokenManager-BYMKH_aW.js +2 -0
- package/dist/chunks/{TokenManager-D-9tqubS.js.map → TokenManager-BYMKH_aW.js.map} +1 -1
- package/dist/chunks/TokenManager-DhDUKmaw.js +2 -0
- package/dist/chunks/{TokenManager-8JM2qj_1.js.map → TokenManager-DhDUKmaw.js.map} +1 -1
- package/dist/chunks/User-BnlvMG5J.js +3 -0
- package/dist/chunks/User-BnlvMG5J.js.map +1 -0
- package/dist/chunks/User-DSqcOwPL.js +3 -0
- package/dist/chunks/User-DSqcOwPL.js.map +1 -0
- package/dist/chunks/{WebApp-JJAK0eNM.js → WebApp-B0m6JCjO.js} +2 -2
- package/dist/chunks/{WebApp-JJAK0eNM.js.map → WebApp-B0m6JCjO.js.map} +1 -1
- package/dist/chunks/{WebApp-BdJA4Uup.js → WebApp-Bsic6FPo.js} +2 -2
- package/dist/chunks/{WebApp-BdJA4Uup.js.map → WebApp-Bsic6FPo.js.map} +1 -1
- package/dist/chunks/{WebSocketClient-BoF7TV7i.js → WebSocketClient-Bh0Mmtje.js} +2 -2
- package/dist/chunks/{WebSocketClient-BoF7TV7i.js.map → WebSocketClient-Bh0Mmtje.js.map} +1 -1
- package/dist/chunks/{WebSocketClient-BxL2M7p0.js → WebSocketClient-CLgYPxWX.js} +2 -2
- package/dist/chunks/{WebSocketClient-BxL2M7p0.js.map → WebSocketClient-CLgYPxWX.js.map} +1 -1
- package/dist/chunks/{version-kTtMlfsq.js → version-BY7AsEkb.js} +2 -2
- package/dist/chunks/{version-kTtMlfsq.js.map → version-BY7AsEkb.js.map} +1 -1
- package/dist/chunks/{version-Cn26llLs.js → version-BdfRyQDm.js} +2 -2
- package/dist/chunks/{version-Cn26llLs.js.map → version-BdfRyQDm.js.map} +1 -1
- package/dist/css/web-mojo.css +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.cjs.js.map +1 -1
- package/dist/docit.es.js +1 -1
- package/dist/docit.es.js.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.cjs.js.map +1 -1
- package/dist/lightbox.es.js +1 -1
- package/dist/lightbox.es.js.map +1 -1
- package/dist/map.cjs.js +1 -1
- package/dist/map.es.js +1 -1
- package/dist/timeline.cjs.js +1 -1
- package/dist/timeline.es.js +1 -1
- package/dist/web-mojo.lite.iife.js +1230 -2
- package/dist/web-mojo.lite.iife.js.map +1 -1
- package/dist/web-mojo.lite.iife.min.js +95 -74
- package/dist/web-mojo.lite.iife.min.js.map +1 -1
- package/package.json +8 -7
- package/dist/chunks/ChatView-D1-ev2qA.js +0 -2
- package/dist/chunks/ChatView-D1-ev2qA.js.map +0 -1
- package/dist/chunks/ChatView-DesGp57e.js +0 -2
- package/dist/chunks/ChatView-DesGp57e.js.map +0 -1
- package/dist/chunks/ContextMenu-CsQGpSrv.js +0 -3
- package/dist/chunks/ContextMenu-CsQGpSrv.js.map +0 -1
- package/dist/chunks/ContextMenu-dqFxitXY.js +0 -3
- package/dist/chunks/ContextMenu-dqFxitXY.js.map +0 -1
- package/dist/chunks/FormView-BQnvMheR.js +0 -3
- package/dist/chunks/FormView-BQnvMheR.js.map +0 -1
- package/dist/chunks/FormView-C7FnbmEI.js +0 -3
- package/dist/chunks/FormView-C7FnbmEI.js.map +0 -1
- package/dist/chunks/TokenManager-8JM2qj_1.js +0 -2
- package/dist/chunks/TokenManager-D-9tqubS.js +0 -2
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";const e=require("./Rest-Ds9e8tN8.js"),t=require("./Dialog-VoLlToMl.js"),s=require("./ContextMenu-dqFxitXY.js");class ResultsView extends e.View{constructor(e={}){super({className:"search-results-view flex-grow-1 overflow-auto d-flex flex-column",template:'\n <div id="results-container" class="flex-grow-1 overflow-auto">\n {{#data.loading}}\n <div class="text-center p-4">\n <div class="spinner-border spinner-border-sm text-muted" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n <div class="mt-2 small text-muted">{{data.loadingText}}</div>\n </div>\n {{/data.loading}}\n\n {{^data.loading}}\n {{#data.items}}\n <div class="simple-search-item position-relative"\n data-action="select-item"\n data-item-index="{{index}}">\n {{{itemContent}}}\n\n </div>\n {{/data.items}}\n\n {{#data.showNoResults}}\n <div class="text-center p-4">\n <i class="bi bi-search text-muted mb-2" style="font-size: 1.5rem;"></i>\n <div class="text-muted small">{{data.noResultsText}}</div>\n <button type="button"\n class="btn btn-link btn-sm mt-2 p-0"\n data-action="clear-search">\n Clear search\n </button>\n </div>\n {{/data.showNoResults}}\n\n {{#data.showEmpty}}\n <div class="text-center p-4">\n <i class="{{data.emptyIcon}} text-muted mb-2" style="font-size: 2rem;"></i>\n <div class="text-muted small mb-2">{{data.emptyText}}</div>\n {{#data.emptySubtext}}\n <div class="text-muted" style="font-size: 0.75rem;">\n {{data.emptySubtext}}\n </div>\n {{/data.emptySubtext}}\n </div>\n {{/data.showEmpty}}\n {{/data.loading}}\n </div>\n\n {{#data.showResultsCount}}\n <div class="border-top bg-light p-2 text-center">\n <small class="text-muted">\n {{data.filteredCount}} of {{data.totalCount}}\n </small>\n </div>\n {{/data.showResultsCount}}\n ',...e}),this.parentView=e.parentView}async handleActionSelectItem(e,t){e.preventDefault();const s=parseInt(t.getAttribute("data-item-index"));this.parentView&&this.parentView.handleItemSelection(s)}async handleActionClearSearch(e,t){e.preventDefault(),this.parentView&&this.parentView.clearSearch()}async onAfterRender(){if(this.parentView&&this.parentView.maxHeight){const e=this.element.querySelector("#results-container");e&&(e.style.maxHeight=`${this.parentView.maxHeight}px`)}}}class SimpleSearchView extends e.View{constructor(e={}){super({className:"simple-search-view d-flex flex-column",template:'\n <div class="p-3 border-bottom bg-light">\n {{#data.headerText}}\n <div class="d-flex justify-content-between align-items-start mb-3">\n <h6 class="text-muted fw-semibold mb-0">\n {{#data.headerIcon}}<i class="{{data.headerIcon}} me-2"></i>{{/data.headerIcon}}\n {{{data.headerText}}}\n </h6>\n {{#data.showExitButton}}\n <button class="btn btn-link p-0 text-muted simple-search-exit-btn"\n type="button"\n data-action="exit-view"\n title="Exit"\n aria-label="Exit view">\n <i class="bi bi-x-lg" aria-hidden="true"></i>\n </button>\n {{/data.showExitButton}}\n </div>\n {{/data.headerText}}\n <div class="position-relative">\n <input type="text"\n class="form-control form-control-sm pe-5"\n placeholder="{{data.searchPlaceholder}}"\n value="{{data.searchValue}}"\n data-filter="live-search"\n data-filter-debounce="{{data.debounceMs}}"\n data-change-action="search-items">\n <button class="btn btn-link p-0 position-absolute top-50 end-0 translate-middle-y me-2 text-muted simple-search-clear-btn"\n type="button"\n data-action="clear-search"\n title="Clear search"\n aria-label="Clear search">\n <i class="bi bi-x-circle-fill" aria-hidden="true"></i>\n </button>\n </div>\n </div>\n\n <div data-container="results"></div>\n\n {{#data.showFooter}}\n <div class="p-3 border-top bg-light">\n <small class="text-muted">\n <i class="{{data.footerIcon}} me-1"></i>\n {{{data.footerContent}}}\n </small>\n </div>\n {{/data.showFooter}}\n ',...e}),this.Collection=e.Collection,this.collection=e.collection,this.itemTemplate=e.itemTemplate||this.getDefaultItemTemplate(),this.searchFields=e.searchFields||["name"],this.collectionParams={size:25,...e.collectionParams},void 0===e.headerText&&(this.headerText="Select Item"),this.headerText=e.headerText,this.headerIcon=e.headerIcon||"bi bi-list",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.loadingText=e.loadingText||"Loading items...",this.noResultsText=e.noResultsText||"No items match your search",this.emptyText=e.emptyText||"No items available",this.emptySubtext=e.emptySubtext||null,this.emptyIcon=e.emptyIcon||"bi bi-inbox",this.footerContent=e.footerContent||null,this.footerIcon=e.footerIcon||"bi bi-info-circle",this.showExitButton=e.showExitButton||!1,this.searchValue="",this.filteredItems=[],this.loading=!1,this.hasSearched=!1,this.searchTimer=null,this.debounceMs=e.debounceMs||300,e.maxHeight?this.maxHeight=e.maxHeight:this.addClass("h-100"),this.resultsView=new ResultsView({parentView:this}),!this.collection&&this.Collection&&(this.collection=new this.Collection),this.addChild(this.resultsView)}onInit(){this.collection&&this.setupCollection(),this.collection&&!1!==this.options.autoLoad&&this.loadItems()}setupCollection(){Object.assign(this.collection.params,this.collectionParams),this.collection.on("fetch:success",()=>{this.loading=!1,this.updateFilteredItems()}),this.collection.on("fetch:error",()=>{this.loading=!1})}async loadItems(){if(this.collection){this.loading=!0,this.updateResultsView();try{await this.collection.fetch(),this.updateFilteredItems()}catch(e){console.error("Error loading items:",e);const t=this.getApp();t?.showError?.("Failed to load items. Please try again.")}finally{this.loading=!1,this.updateFilteredItems()}}else console.warn("SimpleSearchView: No collection provided")}updateFilteredItems(){this.collection?(this.filteredItems=this.collection.toJSON(),this.updateResultsView()):this.filteredItems=[]}getNestedValue(e,t){return t.split(".").reduce((e,t)=>e?.[t],e)}async getViewData(){return{searchValue:this.searchValue,showFooter:!!this.footerContent,showExitButton:this.showExitButton,debounceMs:this.debounceMs,headerText:this.headerText,headerIcon:this.headerIcon,searchPlaceholder:this.searchPlaceholder,footerContent:this.footerContent,footerIcon:this.footerIcon}}updateResultsView(){if(!this.resultsView)return;const e=this.collection&&this.collection.length()>0,t=this.filteredItems.length>0,s=this.searchValue.length>0,n=this.filteredItems.map((e,t)=>({...e,index:t,itemContent:this.processItemTemplate(e)}));this.resultsView.data={loading:this.loading,items:n,showEmpty:!this.loading&&!e,showNoResults:!this.loading&&e&&!t&&s,showResultsCount:!this.loading&&e,filteredCount:this.filteredItems.length,totalCount:this.collection?.restEnabled?this.collection?.meta?.count||0:this.collection?.length()||0,loadingText:this.loadingText,noResultsText:this.noResultsText,emptyText:this.emptyText,emptySubtext:this.emptySubtext,emptyIcon:this.emptyIcon},this.resultsView.render()}processItemTemplate(e){let t=this.itemTemplate;return t=t.replace(/\{\{(\w+)\}\}/g,(t,s)=>this.getNestedValue(e,s)||""),t}getDefaultItemTemplate(){return'\n <div class="p-3 border-bottom">\n <div class="fw-semibold text-dark">{{name}}</div>\n <small class="text-muted">{{id}}</small>\n </div>\n '}async onPassThruActionSearchItems(e,t){const s=t.value||"";this.searchValue=s,this.hasSearched=!0,this.searchTimer&&clearTimeout(this.searchTimer),this.performSearch()}async performSearch(){const e={...this.collectionParams};this.searchValue&&this.searchValue.length>1&&(e.search=this.searchValue.trim()),this.collection.setParams(e,!0)}handleItemSelection(e){if(isNaN(e)||e<0||e>=this.filteredItems.length)return void console.error("Invalid item index:",e);const t=this.filteredItems[e];let s=this.collection?this.collection.get(t.id):null;if(!s){s=new this.collection.ModelClass({id:t.id});const n=this.getApp();return n.showLoading(),void s.fetch().then(()=>{n.hideLoading(),this.emit("item:selected",{item:t,model:s,index:e})})}this.emit("item:selected",{item:t,model:s,index:e})}setCollection(e){return this.collection=e,this.setupCollection(),this}setItemTemplate(e){return this.itemTemplate=e,this.updateResultsView(),this}setSearchFields(e){return this.searchFields=Array.isArray(e)?e:[e],this}async refresh(){await this.loadItems()}focusSearch(){const e=this.element?.querySelector('input[data-action="search-items"]');e&&e.focus()}async handleActionExitView(e,t){this.emit("exit",{view:this})}async handleActionClearSearch(e,t){this.clearSearch()}clearSearch(){this.searchValue="",this.hasSearched=!1;const e=this.element?.querySelector('input[data-change-action="search-items"]');e&&(e.value="",e.focus()),this.performSearch()}getItemCount(){return this.collection?this.collection.length():0}getFilteredItemCount(){return this.filteredItems.length}hasItems(){return this.getItemCount()>0}getSearchValue(){return this.searchValue}setSearchValue(e){this.searchValue=e||"",this.hasSearched=!!this.searchValue;const t=this.element?.querySelector('input[data-action="search-items"]');return t&&(t.value=this.searchValue),this.performSearch(),this}async onAfterRender(){if(await super.onAfterRender(),this.resultsView&&!this.resultsView.isMounted()){const e=this.element?.querySelector('[data-container="results"]');e&&await this.resultsView.render(!0,e)}this.updateResultsView()}async onBeforeDestroy(){this.searchTimer&&clearTimeout(this.searchTimer),this.collection&&this.collection.off("update"),await super.onBeforeDestroy()}}class GroupSelectorButton extends e.View{constructor(e={}){super({tagName:"div",className:"nav-item",...e});const t=this.getApp();this.Collection=e.Collection||t?.GroupCollection||s.GroupList,this.collection=e.collection||new this.Collection,this.currentGroup=void 0!==e.currentGroup?e.currentGroup:t?.activeGroup,this.buttonClass=e.buttonClass||"btn btn-link nav-link",this.buttonIcon=e.buttonIcon||"bi-building",this.defaultText=e.defaultText||"Select Group",this.itemTemplate=e.itemTemplate,this.searchFields=e.searchFields||["name"],this.headerText=e.headerText||"Select Group",this.searchPlaceholder=e.searchPlaceholder||"Search groups...",this.autoSetActiveGroup=!1!==e.autoSetActiveGroup,this.onGroupSelected=e.onGroupSelected,this.dialog=null,t?.events&&t.events.on("group:changed",e=>{e.group!==this.currentGroup&&this.setCurrentGroup(e.group)})}async getTemplate(){return'\n <button class="{{buttonClass}}" \n data-action="show-selector"\n type="button"\n style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">\n <i class="{{buttonIcon}} me-1"></i>\n <span class="group-name">{{displayName}}</span>\n </button>\n '}async onBeforeRender(){await super.onBeforeRender(),this.currentGroup?.get?.("name")||this.currentGroup,this.buttonClass=this.buttonClass,this.buttonIcon=this.buttonIcon,this.displayName=this.currentGroup?.get?.("name")||this.currentGroup?.name||this.defaultText}async onActionShowSelector(e){const s=new SimpleSearchView({Collection:this.Collection,collection:this.collection,itemTemplate:this.itemTemplate||this.getDefaultItemTemplate(),searchFields:this.searchFields,headerText:this.headerText,searchPlaceholder:this.searchPlaceholder,headerIcon:this.buttonIcon,showExitButton:!1});return this.dialog=new t.default({title:this.headerText,body:s,size:"md",scrollable:!0,noBodyPadding:!0,buttons:[],closeButton:!0}),s.on("item:selected",e=>{this.handleGroupSelection(e.model||e.item),this.dialog&&this.dialog.hide()}),this.dialog.on("hidden",()=>{this.dialog.destroy(),this.dialog=null}),await this.dialog.render(!0,document.body),this.dialog.show(),!0}handleGroupSelection(e){this.currentGroup=e,this.displayName=e?.get?.("name")||e?.name||this.defaultText,this.render();const t=this.getApp();this.autoSetActiveGroup&&t?.setActiveGroup&&t.setActiveGroup(e),this.onGroupSelected&&this.onGroupSelected({group:e}),this.emit("group-selected",{group:e}),t?.events&&(t.events.emit("group:selected",{group:e}),t.events.emit("group:changed",{group:e}))}getDefaultItemTemplate(){return'\n <div class="d-flex align-items-center p-3 border-bottom">\n <div class="flex-grow-1">\n <div class="fw-semibold text-dark">{{name}}</div>\n <small class="text-muted">#{{id}} {{kind}}</small>\n </div>\n </div>\n '}setCurrentGroup(e){this.currentGroup=e,this.displayName=e?.get?.("name")||e?.name||this.defaultText,this.mounted&&this.render()}getCurrentGroup(){return this.currentGroup}}class TopNav extends e.View{constructor(e={}){const t={light:"navbar navbar-expand-lg navbar-light topnav-light",dark:"navbar navbar-expand-lg navbar-dark topnav-dark",clean:"navbar navbar-expand-lg navbar-light topnav-clean",gradient:"navbar navbar-expand-lg navbar-dark topnav-gradient"};let s=t[e.theme||"light"]||t.light;e.shadow&&(s+=` topnav-shadow-${e.shadow}`),super({tagName:"nav",className:s,enableTooltips:!0,style:"position: relative; z-index: 1030;",...e}),this.displayMode=e.displayMode||"both",this.showPageIcon=!1!==e.showPageIcon,this.showPageDescription=e.showPageDescription||!1,this.showBreadcrumbs=e.showBreadcrumbs||!1,this.groupIcon=e.groupIcon||"bi-building",this.currentPage=null,this.previousPage=null,this.config={brand:e.brand||"MOJO App",brandIcon:e.brandIcon||"bi bi-play-circle",brandRoute:e.brandRoute||"/",navItems:e.navItems||[],rightItems:e.rightItems||[],showSidebarToggle:e.showSidebarToggle||!1,sidebarToggleAction:e.sidebarToggleAction||"toggle-sidebar",...e},this.userMenu=e.userMenu||this.findMenuItem("user"),this.userMenu&&(this.userMenu.id="user"),this.loginMenu=e.loginMenu||this.findMenuItem("login"),this.setupPageListeners(),this.setupGroupListeners(),this.groupSelectorButton=null,this.currentGroup=null}findMenuItem(e){let t=this.config.navItems.find(t=>t.id===e);return t||(t=this.config.rightItems.find(t=>t.id===e)),t||null}replaceMenuItem(e,t){const s=this.config.navItems.findIndex(t=>t.id===e);if(-1!==s)return this.config.navItems[s]=t,!0;const n=this.config.rightItems.findIndex(t=>t.id===e);return-1!==n&&(this.config.rightItems[n]=t,!0)}setBrand(e,t=null){this.config.brand=e,this.config.brandIcon=t||this.config.brandIcon,this.render()}setUser(e){e?(this.userMenu.label=e.get("display_name"),this.replaceMenuItem("login",this.userMenu)):this.replaceMenuItem("user",this.loginMenu),this.setModel(e)}_onModelChange(){this.model&&(this.userMenu.label=this.model.get("display_name")),this.isMounted()&&this.render()}async getTemplate(){return'\n <div class="container-fluid">\n {{#data.showSidebarToggle}}\n <button class="topnav-sidebar-toggle me-2" data-action="{{data.sidebarToggleAction}}" aria-label="Toggle Sidebar">\n <i class="bi bi-chevron-right toggle-chevron"></i>\n </button>\n {{/data.showSidebarToggle}}\n\n {{#data.showGroupInfo}}\n <div class="navbar-brand d-flex align-items-center">\n {{#data.groupIcon}}<i class="{{data.groupIcon}} me-2"></i>{{/data.groupIcon}}\n <div>\n <span class="topnav-group-name"\n role="button"\n tabindex="0"\n data-action="open-group-selector"\n style="cursor: pointer;">\n {{data.currentGroupName}}\n </span>\n {{#data.showPageTitle}}\n <span class="text-muted mx-2">|</span>\n <span>{{data.currentPageName}}</span>\n {{/data.showPageTitle}}\n </div>\n </div>\n {{/data.showGroupInfo}}\n\n {{#data.showPageInfo}}\n <div class="navbar-brand d-flex align-items-center">\n {{#data.currentPageIcon}}<i class="{{data.currentPageIcon}} me-2"></i>{{/data.currentPageIcon}}\n <div>\n <span>{{data.currentPageName}}</span>\n {{#data.currentPageDescription}}\n <small class="d-block" style="font-size: 0.75rem; line-height: 1;">{{data.currentPageDescription}}</small>\n {{/data.currentPageDescription}}\n </div>\n </div>\n {{/data.showPageInfo}}\n\n {{#data.showBrand}}\n <a class="navbar-brand" href="{{data.brandRoute}}">\n {{#data.brandIcon}}<i class="{{data.brandIcon}} me-2"></i>{{/data.brandIcon}}\n {{data.brand}}\n </a>\n {{/data.showBrand}}\n\n <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#{{data.navbarId}}">\n <span class="navbar-toggler-icon"></span>\n </button>\n\n <div class="collapse navbar-collapse" id="{{data.navbarId}}">\n {{#data.showNavItems}}\n <ul class="navbar-nav me-auto mb-2 mb-lg-0">\n {{#data.navItems}}\n <li class="nav-item">\n <a class="nav-link {{#active}}active{{/active}}" href="{{route}}" {{#tooltip}}data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{{tooltip}}"{{/tooltip}}>\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{text}}\n </a>\n </li>\n {{/data.navItems}}\n </ul>\n {{/data.showNavItems}}\n\n {{#data.hasRightItems}}\n <div class="navbar-nav ms-auto">\n {{#data.rightItems}}\n {{#isGroupSelector}}\n <div data-container="group-selector-{{id}}"></div>\n {{/isGroupSelector}}\n {{^isGroupSelector}}\n {{#isDropdown}}\n <div class="nav-item dropdown">\n <a class="nav-link dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false">\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{label}}\n </a>\n <ul class="dropdown-menu dropdown-menu-end">\n {{#items}}\n {{#divider}}\n <li><hr class="dropdown-divider"></li>\n {{/divider}}\n {{#isHeader}}\n <li><h6 class="dropdown-header">{{header}}</h6></li>\n {{/isHeader}}\n {{#isHtml}}\n <li><span class="dropdown-item-text">{{{html}}}</span></li>\n {{/isHtml}}\n {{^divider}}{{^isHeader}}{{^isHtml}}\n <li>\n <a class="dropdown-item" role="button" {{#action}}data-action="{{action}}"{{/action}}>\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{label}}\n </a>\n </li>\n {{/isHtml}}{{/isHeader}}{{/divider}}\n {{/items}}\n </ul>\n </div>\n {{/isDropdown}}\n {{^isDropdown}}\n {{#isButton}}\n <button class="{{buttonClass}}" data-action="{{action}}" data-id="{{id}}" {{#tooltip}}data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{{tooltip}}"{{/tooltip}}>\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{label}}\n </button>\n {{/isButton}}\n {{^isButton}}\n <a class="nav-link" href="{{href}}" {{#action}}data-action="{{action}}"{{/action}} {{#tooltip}}data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{{tooltip}}"{{/tooltip}}>\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{label}}\n </a>\n {{/isButton}}\n {{/isDropdown}}\n {{/isGroupSelector}}\n {{/data.rightItems}}\n </div>\n {{/data.hasRightItems}}\n </div>\n </div>\n '}async onBeforeRender(){await super.onBeforeRender();const e=this.getApp(),t=this.currentGroup||e?.activeGroup,s="group"===this.displayMode||"group_page_titles"===this.displayMode,n="group_page_titles"===this.displayMode,i="page"===this.displayMode||"both"===this.displayMode,a=!s&&!i,o="menu"===this.displayMode||"both"===this.displayMode,r=this.filterItemsByPermissions(this.config.navItems||[]),l=this.processRightItems(this.config.rightItems||[]);this.data={brand:this.config.brand,brandIcon:this.config.brandIcon,brandRoute:this.config.brandRoute,showBrand:a,navbarId:`navbar-${this.id}`,navItems:r,showNavItems:o,rightItems:l,hasRightItems:l.length>0,showGroupInfo:s,showPageTitle:n,currentGroupName:t?.get?.("name")||t?.name||"Select Group",groupIcon:this.groupIcon,showPageInfo:i,currentPageName:this.currentPage?.title||this.currentPage?.name||"",currentPageIcon:this.currentPage?.icon||this.currentPage?.pageIcon||"",currentPageDescription:this.showPageDescription?this.currentPage?.description:"",showSidebarToggle:this.config.showSidebarToggle,sidebarToggleAction:this.config.sidebarToggleAction,displayMode:this.displayMode}}processRightItems(e){return this.filterItemsByPermissions(e).map(e=>{const t={...e};if(e.items&&(t.items=this.filterItemsByPermissions(e.items).map(e=>{const t={...e};return e.divider||(void 0!==e.header?t.isHeader=!0:void 0!==e.text&&(t.isHtml=!0,t.html=e.text)),t})),"group-selector"===e.type){t.isGroupSelector=!0,t.isDropdown=!1,t.isButton=!1;const s={containerId:`group-selector-${e.id||"default"}`};void 0!==e.Collection&&(s.Collection=e.Collection),void 0!==e.collection&&(s.collection=e.collection),void 0!==e.currentGroup&&(s.currentGroup=e.currentGroup),void 0!==e.buttonClass&&(s.buttonClass=e.buttonClass),void 0!==e.buttonIcon&&(s.buttonIcon=e.buttonIcon),void 0!==e.defaultText&&(s.defaultText=e.defaultText),void 0!==e.itemTemplate&&(s.itemTemplate=e.itemTemplate),void 0!==e.searchFields&&(s.searchFields=e.searchFields),void 0!==e.headerText&&(s.headerText=e.headerText),void 0!==e.searchPlaceholder&&(s.searchPlaceholder=e.searchPlaceholder),void 0!==e.autoSetActiveGroup&&(s.autoSetActiveGroup=e.autoSetActiveGroup),void 0!==e.onGroupSelected&&(s.onGroupSelected=e.onGroupSelected);const n=new GroupSelectorButton(s);this.groupSelectorButton=n,this.addChild(n)}else t.items&&t.items.length>0?(t.isDropdown=!0,t.isButton=!1):e.buttonClass?(t.isButton=!0,t.isDropdown=!1):(t.isButton=!1,t.isDropdown=!1);return e.handler&&(this.rightItemHandlers=this.rightItemHandlers||/* @__PURE__ */new Map,this.rightItemHandlers.set(e.id,e.handler)),t})}setupPageListeners(){this.getApp().events.on("page:show",e=>{this.onPageChanged(e)})}setupGroupListeners(){const e=this.getApp();e?.events&&e.events.on(["group:changed","group:loaded"],e=>{e?.group&&(this.currentGroup=e.group),"group"!==this.displayMode&&"group_page_titles"!==this.displayMode||this.mounted&&this.render()})}onPageBeforeChange(e){"page"===this.displayMode||this.displayMode}onPageChanged(e){this.previousPage=this.currentPage,this.currentPage=e.page,"page"!==this.displayMode&&"both"!==this.displayMode||this.updatePageDisplay(),"menu"!==this.displayMode&&"both"!==this.displayMode||this.currentPage&&this.currentPage.route&&this.updateActiveItem(this.currentPage.route)}updatePageDisplay(){this.currentPage&&this.mounted&&this.render()}updateActiveItem(e){const t=e=>e?e.startsWith("/")?e:`/${e}`:"/",s=t(e),n=this.data.navItems.map(e=>{const n=t(e.route);let i=!1;return"/"===n&&"/"===s?i=!0:"/"!==n&&"/"!==s&&(i=s.startsWith(n)||s===n),{...e,active:i}});this.updateData({navItems:n},!0)}onPassThruActionProfile(){this.getApp().events.emit("portal:action",{action:"profile"})}onActionSettings(){this.getApp().events.emit("portal:action",{action:"settings"})}onActionLogout(){this.getApp().events.emit("auth:logout",{action:"logout"})}async onActionOpenGroupSelector(e){if(this.groupSelectorButton)return await this.groupSelectorButton.onActionShowSelector(e),!0;const{GroupList:t}=await Promise.resolve().then(()=>require("./ContextMenu-dqFxitXY.js")).then(e=>e.Group$1),s=new GroupSelectorButton({Collection:t,currentGroup:this.getApp()?.activeGroup});return await s.onActionShowSelector(e),!0}async handleAction(e,t,s){const n=s.getAttribute("data-id");if(n&&this.rightItemHandlers&&this.rightItemHandlers.has(n)){const i=this.rightItemHandlers.get(n);if("function"==typeof i)return await i.call(this,e,t,s)}const i=`onAction${e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,e=>e[1].toUpperCase())}`;if("function"==typeof this[i])return await this[i](t,s);this.emit("action",{action:e,event:t,element:s,topnav:this})}async onActionDefault(e,t,s){if(this.config.navItems)for(const n of this.config.navItems)if(n.action===e&&n.handler)return await n.handler.call(this,e,t,s),!0;if(this.config.rightItems)for(const n of this.config.rightItems){if(n.action===e&&n.handler)return await n.handler.call(this,e,t,s),!0;if(n.items)for(const i of n.items)if(i.action===e&&i.handler)return await i.handler.call(this,e,t,s),!0}return this.getApp().events.emit("portal:action",{action:e,event:t,el:s}),!1}filterItemsByPermissions(e){if(!e)return[];const t=this.getApp(),s=t?.activeUser;return e.filter(e=>!e.permissions||!s||s.hasPermission(e.permissions))}}class Token{constructor(e){this.token=e,this.payload=null,this.uid=null,this.email=null,this.name=null,this.exp=null,this.iat=null,this.isValidToken=!1,this._decode()}_decode(){if(this.token&&"string"==typeof this.token)try{const e=this.token.split(".");if(3!==e.length)return;let t=e[1].replace(/-/g,"+").replace(/_/g,"/");const s=4-t.length%4;4!==s&&(t+="=".repeat(s));const n=atob(t);this.payload=JSON.parse(n),this.uid=this.payload.uid||this.payload.sub||this.payload.user_id||null,this.email=this.payload.email||null,this.name=this.payload.name||this.payload.username||null,this.exp=this.payload.exp?new Date(1e3*this.payload.exp):null,this.iat=this.payload.iat?new Date(1e3*this.payload.iat):null,this.isValidToken=this._checkValidity()}catch(e){this.payload=null}}_checkValidity(){return!(!this.token||!this.payload)&&(!this.payload.exp||Math.floor(Date.now()/1e3)<this.payload.exp)}decode(){return this.payload}getUserId(){return this.uid}isValid(){return this.isValidToken}isExpiringSoon(e=5){if(!this.payload?.exp)return!1;const t=Math.floor(Date.now()/1e3),s=60*e;return this.payload.exp-t<=s}isExpired(){return!!this.payload?.exp&&Math.floor(Date.now()/1e3)>=this.payload.exp}getAgeMinutes(){if(!this.payload?.iat)return null;const e=Math.floor(Date.now()/1e3)-this.payload.iat;return Math.floor(e/60)}getAuthHeader(){return this.token?`Bearer ${this.token}`:null}getUserInfo(){return this.payload?{uid:this.uid,email:this.email,name:this.name,exp:this.exp,iat:this.iat}:null}}exports.SimpleSearchView=SimpleSearchView,exports.TokenManager=class{constructor(){this.tokenKey="access_token",this.refreshTokenKey="refresh_token",this.tokenInstance=null}setTokens(e,t=null,s=!0){const n=s?localStorage:sessionStorage;this.tokenInstance=new Token(e),e&&n.setItem(this.tokenKey,e),t&&n.setItem(this.refreshTokenKey,t)}getToken(){return localStorage.getItem(this.tokenKey)||sessionStorage.getItem(this.tokenKey)}getRefreshToken(){return localStorage.getItem(this.refreshTokenKey)||sessionStorage.getItem(this.refreshTokenKey)}clearTokens(){localStorage.removeItem(this.tokenKey),localStorage.removeItem(this.refreshTokenKey),sessionStorage.removeItem(this.tokenKey),sessionStorage.removeItem(this.refreshTokenKey)}getTokenInstance(){const e=this.getToken();return e?(this.tokenInstance&&this.tokenInstance.token===e||(this.tokenInstance=new Token(e)),this.tokenInstance):(this.tokenInstance=null,null)}getRefreshTokenInstance(){const e=this.getRefreshToken();return e?(this._refreshTokenInstance&&this._refreshTokenInstance.token===e||(this._refreshTokenInstance=new Token(e)),this._refreshTokenInstance):(this._refreshTokenInstance=null,null)}decode(e=null){const t=e||this.getToken();return new Token(t).decode()}getUserId(){const e=this.getTokenInstance();return e?e.getUserId():null}isValid(){const e=this.getTokenInstance();return!!e&&e.isValid()}isExpiringSoon(e=5){const t=this.getTokenInstance();return!!t&&t.isExpiringSoon(e)}getAuthHeader(){const e=this.getTokenInstance();return e?e.getAuthHeader():null}getUserInfo(){const e=this.getTokenInstance();return e?e.getUserInfo():null}checkTokenStatus(){const e=this.getTokenInstance(),t=this.getRefreshTokenInstance();return e&&e.isValid()&&!e.isExpired()?e.isExpiringSoon(10)||e.getAgeMinutes()&&e.getAgeMinutes()>60?t&&t.isValid()&&!t.isExpired()?{action:"refresh",reason:"Access token expiring soon or aged"}:{action:"none",reason:"Access token expiring but refresh token invalid"}:{action:"none",reason:"All tokens valid and not expiring soon"}:t&&t.isValid()&&!t.isExpired()?{action:"refresh",reason:"Access token invalid/expired but refresh token valid"}:{action:"logout",reason:"Both access and refresh tokens are invalid/expired"}}async checkAndRefreshTokens(e){switch(this.checkTokenStatus().action){case"logout":return e.events.emit("auth:unauthorized"),this.stopAutoRefresh(),!0;case"refresh":return await this.refreshToken(e),!0;default:return!1}}startAutoRefresh(e){this.stopAutoRefresh(),this._tokenWatcher=setInterval(()=>{this.checkAndRefreshTokens(e)},6e4)}stopAutoRefresh(){this._tokenWatcher&&(clearInterval(this._tokenWatcher),this._tokenWatcher=null)}async refreshToken(e){const t=this.getRefreshTokenInstance();if(!t||!t.isValid()||t.isExpired())return e.events.emit("auth:unauthorized"),void this.stopAutoRefresh();try{const s=await e.rest.POST("/api/token/refresh",{refresh_token:t.token}),{access_token:n,refresh_token:i}=s.data.data;this.tokenInstance=null,this._refreshTokenInstance=null,this.setTokens(n,i),e.rest.setAuthToken(n),e.events.emit("auth:token:refreshed",{newToken:n,newRefreshToken:i})}catch(s){401===s.status||403===s.status?(e.events.emit("auth:unauthorized"),this.stopAutoRefresh()):e.events.emit("auth:token:refresh:failed",{error:s})}}},exports.TopNav=TopNav;
|
|
2
|
-
//# sourceMappingURL=TokenManager-8JM2qj_1.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{V as e}from"./Rest-DHbszkuP.js";import t from"./Dialog-wBhTkeWg.js";import{G as s}from"./ContextMenu-CsQGpSrv.js";class ResultsView extends e{constructor(e={}){super({className:"search-results-view flex-grow-1 overflow-auto d-flex flex-column",template:'\n <div id="results-container" class="flex-grow-1 overflow-auto">\n {{#data.loading}}\n <div class="text-center p-4">\n <div class="spinner-border spinner-border-sm text-muted" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n <div class="mt-2 small text-muted">{{data.loadingText}}</div>\n </div>\n {{/data.loading}}\n\n {{^data.loading}}\n {{#data.items}}\n <div class="simple-search-item position-relative"\n data-action="select-item"\n data-item-index="{{index}}">\n {{{itemContent}}}\n\n </div>\n {{/data.items}}\n\n {{#data.showNoResults}}\n <div class="text-center p-4">\n <i class="bi bi-search text-muted mb-2" style="font-size: 1.5rem;"></i>\n <div class="text-muted small">{{data.noResultsText}}</div>\n <button type="button"\n class="btn btn-link btn-sm mt-2 p-0"\n data-action="clear-search">\n Clear search\n </button>\n </div>\n {{/data.showNoResults}}\n\n {{#data.showEmpty}}\n <div class="text-center p-4">\n <i class="{{data.emptyIcon}} text-muted mb-2" style="font-size: 2rem;"></i>\n <div class="text-muted small mb-2">{{data.emptyText}}</div>\n {{#data.emptySubtext}}\n <div class="text-muted" style="font-size: 0.75rem;">\n {{data.emptySubtext}}\n </div>\n {{/data.emptySubtext}}\n </div>\n {{/data.showEmpty}}\n {{/data.loading}}\n </div>\n\n {{#data.showResultsCount}}\n <div class="border-top bg-light p-2 text-center">\n <small class="text-muted">\n {{data.filteredCount}} of {{data.totalCount}}\n </small>\n </div>\n {{/data.showResultsCount}}\n ',...e}),this.parentView=e.parentView}async handleActionSelectItem(e,t){e.preventDefault();const s=parseInt(t.getAttribute("data-item-index"));this.parentView&&this.parentView.handleItemSelection(s)}async handleActionClearSearch(e,t){e.preventDefault(),this.parentView&&this.parentView.clearSearch()}async onAfterRender(){if(this.parentView&&this.parentView.maxHeight){const e=this.element.querySelector("#results-container");e&&(e.style.maxHeight=`${this.parentView.maxHeight}px`)}}}class SimpleSearchView extends e{constructor(e={}){super({className:"simple-search-view d-flex flex-column",template:'\n <div class="p-3 border-bottom bg-light">\n {{#data.headerText}}\n <div class="d-flex justify-content-between align-items-start mb-3">\n <h6 class="text-muted fw-semibold mb-0">\n {{#data.headerIcon}}<i class="{{data.headerIcon}} me-2"></i>{{/data.headerIcon}}\n {{{data.headerText}}}\n </h6>\n {{#data.showExitButton}}\n <button class="btn btn-link p-0 text-muted simple-search-exit-btn"\n type="button"\n data-action="exit-view"\n title="Exit"\n aria-label="Exit view">\n <i class="bi bi-x-lg" aria-hidden="true"></i>\n </button>\n {{/data.showExitButton}}\n </div>\n {{/data.headerText}}\n <div class="position-relative">\n <input type="text"\n class="form-control form-control-sm pe-5"\n placeholder="{{data.searchPlaceholder}}"\n value="{{data.searchValue}}"\n data-filter="live-search"\n data-filter-debounce="{{data.debounceMs}}"\n data-change-action="search-items">\n <button class="btn btn-link p-0 position-absolute top-50 end-0 translate-middle-y me-2 text-muted simple-search-clear-btn"\n type="button"\n data-action="clear-search"\n title="Clear search"\n aria-label="Clear search">\n <i class="bi bi-x-circle-fill" aria-hidden="true"></i>\n </button>\n </div>\n </div>\n\n <div data-container="results"></div>\n\n {{#data.showFooter}}\n <div class="p-3 border-top bg-light">\n <small class="text-muted">\n <i class="{{data.footerIcon}} me-1"></i>\n {{{data.footerContent}}}\n </small>\n </div>\n {{/data.showFooter}}\n ',...e}),this.Collection=e.Collection,this.collection=e.collection,this.itemTemplate=e.itemTemplate||this.getDefaultItemTemplate(),this.searchFields=e.searchFields||["name"],this.collectionParams={size:25,...e.collectionParams},void 0===e.headerText&&(this.headerText="Select Item"),this.headerText=e.headerText,this.headerIcon=e.headerIcon||"bi bi-list",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.loadingText=e.loadingText||"Loading items...",this.noResultsText=e.noResultsText||"No items match your search",this.emptyText=e.emptyText||"No items available",this.emptySubtext=e.emptySubtext||null,this.emptyIcon=e.emptyIcon||"bi bi-inbox",this.footerContent=e.footerContent||null,this.footerIcon=e.footerIcon||"bi bi-info-circle",this.showExitButton=e.showExitButton||!1,this.searchValue="",this.filteredItems=[],this.loading=!1,this.hasSearched=!1,this.searchTimer=null,this.debounceMs=e.debounceMs||300,e.maxHeight?this.maxHeight=e.maxHeight:this.addClass("h-100"),this.resultsView=new ResultsView({parentView:this}),!this.collection&&this.Collection&&(this.collection=new this.Collection),this.addChild(this.resultsView)}onInit(){this.collection&&this.setupCollection(),this.collection&&!1!==this.options.autoLoad&&this.loadItems()}setupCollection(){Object.assign(this.collection.params,this.collectionParams),this.collection.on("fetch:success",()=>{this.loading=!1,this.updateFilteredItems()}),this.collection.on("fetch:error",()=>{this.loading=!1})}async loadItems(){if(this.collection){this.loading=!0,this.updateResultsView();try{await this.collection.fetch(),this.updateFilteredItems()}catch(e){console.error("Error loading items:",e);const t=this.getApp();t?.showError?.("Failed to load items. Please try again.")}finally{this.loading=!1,this.updateFilteredItems()}}else console.warn("SimpleSearchView: No collection provided")}updateFilteredItems(){this.collection?(this.filteredItems=this.collection.toJSON(),this.updateResultsView()):this.filteredItems=[]}getNestedValue(e,t){return t.split(".").reduce((e,t)=>e?.[t],e)}async getViewData(){return{searchValue:this.searchValue,showFooter:!!this.footerContent,showExitButton:this.showExitButton,debounceMs:this.debounceMs,headerText:this.headerText,headerIcon:this.headerIcon,searchPlaceholder:this.searchPlaceholder,footerContent:this.footerContent,footerIcon:this.footerIcon}}updateResultsView(){if(!this.resultsView)return;const e=this.collection&&this.collection.length()>0,t=this.filteredItems.length>0,s=this.searchValue.length>0,n=this.filteredItems.map((e,t)=>({...e,index:t,itemContent:this.processItemTemplate(e)}));this.resultsView.data={loading:this.loading,items:n,showEmpty:!this.loading&&!e,showNoResults:!this.loading&&e&&!t&&s,showResultsCount:!this.loading&&e,filteredCount:this.filteredItems.length,totalCount:this.collection?.restEnabled?this.collection?.meta?.count||0:this.collection?.length()||0,loadingText:this.loadingText,noResultsText:this.noResultsText,emptyText:this.emptyText,emptySubtext:this.emptySubtext,emptyIcon:this.emptyIcon},this.resultsView.render()}processItemTemplate(e){let t=this.itemTemplate;return t=t.replace(/\{\{(\w+)\}\}/g,(t,s)=>this.getNestedValue(e,s)||""),t}getDefaultItemTemplate(){return'\n <div class="p-3 border-bottom">\n <div class="fw-semibold text-dark">{{name}}</div>\n <small class="text-muted">{{id}}</small>\n </div>\n '}async onPassThruActionSearchItems(e,t){const s=t.value||"";this.searchValue=s,this.hasSearched=!0,this.searchTimer&&clearTimeout(this.searchTimer),this.performSearch()}async performSearch(){const e={...this.collectionParams};this.searchValue&&this.searchValue.length>1&&(e.search=this.searchValue.trim()),this.collection.setParams(e,!0)}handleItemSelection(e){if(isNaN(e)||e<0||e>=this.filteredItems.length)return void console.error("Invalid item index:",e);const t=this.filteredItems[e];let s=this.collection?this.collection.get(t.id):null;if(!s){s=new this.collection.ModelClass({id:t.id});const n=this.getApp();return n.showLoading(),void s.fetch().then(()=>{n.hideLoading(),this.emit("item:selected",{item:t,model:s,index:e})})}this.emit("item:selected",{item:t,model:s,index:e})}setCollection(e){return this.collection=e,this.setupCollection(),this}setItemTemplate(e){return this.itemTemplate=e,this.updateResultsView(),this}setSearchFields(e){return this.searchFields=Array.isArray(e)?e:[e],this}async refresh(){await this.loadItems()}focusSearch(){const e=this.element?.querySelector('input[data-action="search-items"]');e&&e.focus()}async handleActionExitView(e,t){this.emit("exit",{view:this})}async handleActionClearSearch(e,t){this.clearSearch()}clearSearch(){this.searchValue="",this.hasSearched=!1;const e=this.element?.querySelector('input[data-change-action="search-items"]');e&&(e.value="",e.focus()),this.performSearch()}getItemCount(){return this.collection?this.collection.length():0}getFilteredItemCount(){return this.filteredItems.length}hasItems(){return this.getItemCount()>0}getSearchValue(){return this.searchValue}setSearchValue(e){this.searchValue=e||"",this.hasSearched=!!this.searchValue;const t=this.element?.querySelector('input[data-action="search-items"]');return t&&(t.value=this.searchValue),this.performSearch(),this}async onAfterRender(){if(await super.onAfterRender(),this.resultsView&&!this.resultsView.isMounted()){const e=this.element?.querySelector('[data-container="results"]');e&&await this.resultsView.render(!0,e)}this.updateResultsView()}async onBeforeDestroy(){this.searchTimer&&clearTimeout(this.searchTimer),this.collection&&this.collection.off("update"),await super.onBeforeDestroy()}}class GroupSelectorButton extends e{constructor(e={}){super({tagName:"div",className:"nav-item",...e});const t=this.getApp();this.Collection=e.Collection||t?.GroupCollection||s,this.collection=e.collection||new this.Collection,this.currentGroup=void 0!==e.currentGroup?e.currentGroup:t?.activeGroup,this.buttonClass=e.buttonClass||"btn btn-link nav-link",this.buttonIcon=e.buttonIcon||"bi-building",this.defaultText=e.defaultText||"Select Group",this.itemTemplate=e.itemTemplate,this.searchFields=e.searchFields||["name"],this.headerText=e.headerText||"Select Group",this.searchPlaceholder=e.searchPlaceholder||"Search groups...",this.autoSetActiveGroup=!1!==e.autoSetActiveGroup,this.onGroupSelected=e.onGroupSelected,this.dialog=null,t?.events&&t.events.on("group:changed",e=>{e.group!==this.currentGroup&&this.setCurrentGroup(e.group)})}async getTemplate(){return'\n <button class="{{buttonClass}}" \n data-action="show-selector"\n type="button"\n style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">\n <i class="{{buttonIcon}} me-1"></i>\n <span class="group-name">{{displayName}}</span>\n </button>\n '}async onBeforeRender(){await super.onBeforeRender(),this.currentGroup?.get?.("name")||this.currentGroup,this.buttonClass=this.buttonClass,this.buttonIcon=this.buttonIcon,this.displayName=this.currentGroup?.get?.("name")||this.currentGroup?.name||this.defaultText}async onActionShowSelector(e){const s=new SimpleSearchView({Collection:this.Collection,collection:this.collection,itemTemplate:this.itemTemplate||this.getDefaultItemTemplate(),searchFields:this.searchFields,headerText:this.headerText,searchPlaceholder:this.searchPlaceholder,headerIcon:this.buttonIcon,showExitButton:!1});return this.dialog=new t({title:this.headerText,body:s,size:"md",scrollable:!0,noBodyPadding:!0,buttons:[],closeButton:!0}),s.on("item:selected",e=>{this.handleGroupSelection(e.model||e.item),this.dialog&&this.dialog.hide()}),this.dialog.on("hidden",()=>{this.dialog.destroy(),this.dialog=null}),await this.dialog.render(!0,document.body),this.dialog.show(),!0}handleGroupSelection(e){this.currentGroup=e,this.displayName=e?.get?.("name")||e?.name||this.defaultText,this.render();const t=this.getApp();this.autoSetActiveGroup&&t?.setActiveGroup&&t.setActiveGroup(e),this.onGroupSelected&&this.onGroupSelected({group:e}),this.emit("group-selected",{group:e}),t?.events&&(t.events.emit("group:selected",{group:e}),t.events.emit("group:changed",{group:e}))}getDefaultItemTemplate(){return'\n <div class="d-flex align-items-center p-3 border-bottom">\n <div class="flex-grow-1">\n <div class="fw-semibold text-dark">{{name}}</div>\n <small class="text-muted">#{{id}} {{kind}}</small>\n </div>\n </div>\n '}setCurrentGroup(e){this.currentGroup=e,this.displayName=e?.get?.("name")||e?.name||this.defaultText,this.mounted&&this.render()}getCurrentGroup(){return this.currentGroup}}class TopNav extends e{constructor(e={}){const t={light:"navbar navbar-expand-lg navbar-light topnav-light",dark:"navbar navbar-expand-lg navbar-dark topnav-dark",clean:"navbar navbar-expand-lg navbar-light topnav-clean",gradient:"navbar navbar-expand-lg navbar-dark topnav-gradient"};let s=t[e.theme||"light"]||t.light;e.shadow&&(s+=` topnav-shadow-${e.shadow}`),super({tagName:"nav",className:s,enableTooltips:!0,style:"position: relative; z-index: 1030;",...e}),this.displayMode=e.displayMode||"both",this.showPageIcon=!1!==e.showPageIcon,this.showPageDescription=e.showPageDescription||!1,this.showBreadcrumbs=e.showBreadcrumbs||!1,this.groupIcon=e.groupIcon||"bi-building",this.currentPage=null,this.previousPage=null,this.config={brand:e.brand||"MOJO App",brandIcon:e.brandIcon||"bi bi-play-circle",brandRoute:e.brandRoute||"/",navItems:e.navItems||[],rightItems:e.rightItems||[],showSidebarToggle:e.showSidebarToggle||!1,sidebarToggleAction:e.sidebarToggleAction||"toggle-sidebar",...e},this.userMenu=e.userMenu||this.findMenuItem("user"),this.userMenu&&(this.userMenu.id="user"),this.loginMenu=e.loginMenu||this.findMenuItem("login"),this.setupPageListeners(),this.setupGroupListeners(),this.groupSelectorButton=null,this.currentGroup=null}findMenuItem(e){let t=this.config.navItems.find(t=>t.id===e);return t||(t=this.config.rightItems.find(t=>t.id===e)),t||null}replaceMenuItem(e,t){const s=this.config.navItems.findIndex(t=>t.id===e);if(-1!==s)return this.config.navItems[s]=t,!0;const n=this.config.rightItems.findIndex(t=>t.id===e);return-1!==n&&(this.config.rightItems[n]=t,!0)}setBrand(e,t=null){this.config.brand=e,this.config.brandIcon=t||this.config.brandIcon,this.render()}setUser(e){e?(this.userMenu.label=e.get("display_name"),this.replaceMenuItem("login",this.userMenu)):this.replaceMenuItem("user",this.loginMenu),this.setModel(e)}_onModelChange(){this.model&&(this.userMenu.label=this.model.get("display_name")),this.isMounted()&&this.render()}async getTemplate(){return'\n <div class="container-fluid">\n {{#data.showSidebarToggle}}\n <button class="topnav-sidebar-toggle me-2" data-action="{{data.sidebarToggleAction}}" aria-label="Toggle Sidebar">\n <i class="bi bi-chevron-right toggle-chevron"></i>\n </button>\n {{/data.showSidebarToggle}}\n\n {{#data.showGroupInfo}}\n <div class="navbar-brand d-flex align-items-center">\n {{#data.groupIcon}}<i class="{{data.groupIcon}} me-2"></i>{{/data.groupIcon}}\n <div>\n <span class="topnav-group-name"\n role="button"\n tabindex="0"\n data-action="open-group-selector"\n style="cursor: pointer;">\n {{data.currentGroupName}}\n </span>\n {{#data.showPageTitle}}\n <span class="text-muted mx-2">|</span>\n <span>{{data.currentPageName}}</span>\n {{/data.showPageTitle}}\n </div>\n </div>\n {{/data.showGroupInfo}}\n\n {{#data.showPageInfo}}\n <div class="navbar-brand d-flex align-items-center">\n {{#data.currentPageIcon}}<i class="{{data.currentPageIcon}} me-2"></i>{{/data.currentPageIcon}}\n <div>\n <span>{{data.currentPageName}}</span>\n {{#data.currentPageDescription}}\n <small class="d-block" style="font-size: 0.75rem; line-height: 1;">{{data.currentPageDescription}}</small>\n {{/data.currentPageDescription}}\n </div>\n </div>\n {{/data.showPageInfo}}\n\n {{#data.showBrand}}\n <a class="navbar-brand" href="{{data.brandRoute}}">\n {{#data.brandIcon}}<i class="{{data.brandIcon}} me-2"></i>{{/data.brandIcon}}\n {{data.brand}}\n </a>\n {{/data.showBrand}}\n\n <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#{{data.navbarId}}">\n <span class="navbar-toggler-icon"></span>\n </button>\n\n <div class="collapse navbar-collapse" id="{{data.navbarId}}">\n {{#data.showNavItems}}\n <ul class="navbar-nav me-auto mb-2 mb-lg-0">\n {{#data.navItems}}\n <li class="nav-item">\n <a class="nav-link {{#active}}active{{/active}}" href="{{route}}" {{#tooltip}}data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{{tooltip}}"{{/tooltip}}>\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{text}}\n </a>\n </li>\n {{/data.navItems}}\n </ul>\n {{/data.showNavItems}}\n\n {{#data.hasRightItems}}\n <div class="navbar-nav ms-auto">\n {{#data.rightItems}}\n {{#isGroupSelector}}\n <div data-container="group-selector-{{id}}"></div>\n {{/isGroupSelector}}\n {{^isGroupSelector}}\n {{#isDropdown}}\n <div class="nav-item dropdown">\n <a class="nav-link dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false">\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{label}}\n </a>\n <ul class="dropdown-menu dropdown-menu-end">\n {{#items}}\n {{#divider}}\n <li><hr class="dropdown-divider"></li>\n {{/divider}}\n {{#isHeader}}\n <li><h6 class="dropdown-header">{{header}}</h6></li>\n {{/isHeader}}\n {{#isHtml}}\n <li><span class="dropdown-item-text">{{{html}}}</span></li>\n {{/isHtml}}\n {{^divider}}{{^isHeader}}{{^isHtml}}\n <li>\n <a class="dropdown-item" role="button" {{#action}}data-action="{{action}}"{{/action}}>\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{label}}\n </a>\n </li>\n {{/isHtml}}{{/isHeader}}{{/divider}}\n {{/items}}\n </ul>\n </div>\n {{/isDropdown}}\n {{^isDropdown}}\n {{#isButton}}\n <button class="{{buttonClass}}" data-action="{{action}}" data-id="{{id}}" {{#tooltip}}data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{{tooltip}}"{{/tooltip}}>\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{label}}\n </button>\n {{/isButton}}\n {{^isButton}}\n <a class="nav-link" href="{{href}}" {{#action}}data-action="{{action}}"{{/action}} {{#tooltip}}data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{{tooltip}}"{{/tooltip}}>\n {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}\n {{label}}\n </a>\n {{/isButton}}\n {{/isDropdown}}\n {{/isGroupSelector}}\n {{/data.rightItems}}\n </div>\n {{/data.hasRightItems}}\n </div>\n </div>\n '}async onBeforeRender(){await super.onBeforeRender();const e=this.getApp(),t=this.currentGroup||e?.activeGroup,s="group"===this.displayMode||"group_page_titles"===this.displayMode,n="group_page_titles"===this.displayMode,i="page"===this.displayMode||"both"===this.displayMode,a=!s&&!i,o="menu"===this.displayMode||"both"===this.displayMode,r=this.filterItemsByPermissions(this.config.navItems||[]),l=this.processRightItems(this.config.rightItems||[]);this.data={brand:this.config.brand,brandIcon:this.config.brandIcon,brandRoute:this.config.brandRoute,showBrand:a,navbarId:`navbar-${this.id}`,navItems:r,showNavItems:o,rightItems:l,hasRightItems:l.length>0,showGroupInfo:s,showPageTitle:n,currentGroupName:t?.get?.("name")||t?.name||"Select Group",groupIcon:this.groupIcon,showPageInfo:i,currentPageName:this.currentPage?.title||this.currentPage?.name||"",currentPageIcon:this.currentPage?.icon||this.currentPage?.pageIcon||"",currentPageDescription:this.showPageDescription?this.currentPage?.description:"",showSidebarToggle:this.config.showSidebarToggle,sidebarToggleAction:this.config.sidebarToggleAction,displayMode:this.displayMode}}processRightItems(e){return this.filterItemsByPermissions(e).map(e=>{const t={...e};if(e.items&&(t.items=this.filterItemsByPermissions(e.items).map(e=>{const t={...e};return e.divider||(void 0!==e.header?t.isHeader=!0:void 0!==e.text&&(t.isHtml=!0,t.html=e.text)),t})),"group-selector"===e.type){t.isGroupSelector=!0,t.isDropdown=!1,t.isButton=!1;const s={containerId:`group-selector-${e.id||"default"}`};void 0!==e.Collection&&(s.Collection=e.Collection),void 0!==e.collection&&(s.collection=e.collection),void 0!==e.currentGroup&&(s.currentGroup=e.currentGroup),void 0!==e.buttonClass&&(s.buttonClass=e.buttonClass),void 0!==e.buttonIcon&&(s.buttonIcon=e.buttonIcon),void 0!==e.defaultText&&(s.defaultText=e.defaultText),void 0!==e.itemTemplate&&(s.itemTemplate=e.itemTemplate),void 0!==e.searchFields&&(s.searchFields=e.searchFields),void 0!==e.headerText&&(s.headerText=e.headerText),void 0!==e.searchPlaceholder&&(s.searchPlaceholder=e.searchPlaceholder),void 0!==e.autoSetActiveGroup&&(s.autoSetActiveGroup=e.autoSetActiveGroup),void 0!==e.onGroupSelected&&(s.onGroupSelected=e.onGroupSelected);const n=new GroupSelectorButton(s);this.groupSelectorButton=n,this.addChild(n)}else t.items&&t.items.length>0?(t.isDropdown=!0,t.isButton=!1):e.buttonClass?(t.isButton=!0,t.isDropdown=!1):(t.isButton=!1,t.isDropdown=!1);return e.handler&&(this.rightItemHandlers=this.rightItemHandlers||/* @__PURE__ */new Map,this.rightItemHandlers.set(e.id,e.handler)),t})}setupPageListeners(){this.getApp().events.on("page:show",e=>{this.onPageChanged(e)})}setupGroupListeners(){const e=this.getApp();e?.events&&e.events.on(["group:changed","group:loaded"],e=>{e?.group&&(this.currentGroup=e.group),"group"!==this.displayMode&&"group_page_titles"!==this.displayMode||this.mounted&&this.render()})}onPageBeforeChange(e){"page"===this.displayMode||this.displayMode}onPageChanged(e){this.previousPage=this.currentPage,this.currentPage=e.page,"page"!==this.displayMode&&"both"!==this.displayMode||this.updatePageDisplay(),"menu"!==this.displayMode&&"both"!==this.displayMode||this.currentPage&&this.currentPage.route&&this.updateActiveItem(this.currentPage.route)}updatePageDisplay(){this.currentPage&&this.mounted&&this.render()}updateActiveItem(e){const t=e=>e?e.startsWith("/")?e:`/${e}`:"/",s=t(e),n=this.data.navItems.map(e=>{const n=t(e.route);let i=!1;return"/"===n&&"/"===s?i=!0:"/"!==n&&"/"!==s&&(i=s.startsWith(n)||s===n),{...e,active:i}});this.updateData({navItems:n},!0)}onPassThruActionProfile(){this.getApp().events.emit("portal:action",{action:"profile"})}onActionSettings(){this.getApp().events.emit("portal:action",{action:"settings"})}onActionLogout(){this.getApp().events.emit("auth:logout",{action:"logout"})}async onActionOpenGroupSelector(e){if(this.groupSelectorButton)return await this.groupSelectorButton.onActionShowSelector(e),!0;const{GroupList:t}=await import("./ContextMenu-CsQGpSrv.js").then(e=>e.j),s=new GroupSelectorButton({Collection:t,currentGroup:this.getApp()?.activeGroup});return await s.onActionShowSelector(e),!0}async handleAction(e,t,s){const n=s.getAttribute("data-id");if(n&&this.rightItemHandlers&&this.rightItemHandlers.has(n)){const i=this.rightItemHandlers.get(n);if("function"==typeof i)return await i.call(this,e,t,s)}const i=`onAction${e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,e=>e[1].toUpperCase())}`;if("function"==typeof this[i])return await this[i](t,s);this.emit("action",{action:e,event:t,element:s,topnav:this})}async onActionDefault(e,t,s){if(this.config.navItems)for(const n of this.config.navItems)if(n.action===e&&n.handler)return await n.handler.call(this,e,t,s),!0;if(this.config.rightItems)for(const n of this.config.rightItems){if(n.action===e&&n.handler)return await n.handler.call(this,e,t,s),!0;if(n.items)for(const i of n.items)if(i.action===e&&i.handler)return await i.handler.call(this,e,t,s),!0}return this.getApp().events.emit("portal:action",{action:e,event:t,el:s}),!1}filterItemsByPermissions(e){if(!e)return[];const t=this.getApp(),s=t?.activeUser;return e.filter(e=>!e.permissions||!s||s.hasPermission(e.permissions))}}class Token{constructor(e){this.token=e,this.payload=null,this.uid=null,this.email=null,this.name=null,this.exp=null,this.iat=null,this.isValidToken=!1,this._decode()}_decode(){if(this.token&&"string"==typeof this.token)try{const e=this.token.split(".");if(3!==e.length)return;let t=e[1].replace(/-/g,"+").replace(/_/g,"/");const s=4-t.length%4;4!==s&&(t+="=".repeat(s));const n=atob(t);this.payload=JSON.parse(n),this.uid=this.payload.uid||this.payload.sub||this.payload.user_id||null,this.email=this.payload.email||null,this.name=this.payload.name||this.payload.username||null,this.exp=this.payload.exp?new Date(1e3*this.payload.exp):null,this.iat=this.payload.iat?new Date(1e3*this.payload.iat):null,this.isValidToken=this._checkValidity()}catch(e){this.payload=null}}_checkValidity(){return!(!this.token||!this.payload)&&(!this.payload.exp||Math.floor(Date.now()/1e3)<this.payload.exp)}decode(){return this.payload}getUserId(){return this.uid}isValid(){return this.isValidToken}isExpiringSoon(e=5){if(!this.payload?.exp)return!1;const t=Math.floor(Date.now()/1e3),s=60*e;return this.payload.exp-t<=s}isExpired(){return!!this.payload?.exp&&Math.floor(Date.now()/1e3)>=this.payload.exp}getAgeMinutes(){if(!this.payload?.iat)return null;const e=Math.floor(Date.now()/1e3)-this.payload.iat;return Math.floor(e/60)}getAuthHeader(){return this.token?`Bearer ${this.token}`:null}getUserInfo(){return this.payload?{uid:this.uid,email:this.email,name:this.name,exp:this.exp,iat:this.iat}:null}}class TokenManager{constructor(){this.tokenKey="access_token",this.refreshTokenKey="refresh_token",this.tokenInstance=null}setTokens(e,t=null,s=!0){const n=s?localStorage:sessionStorage;this.tokenInstance=new Token(e),e&&n.setItem(this.tokenKey,e),t&&n.setItem(this.refreshTokenKey,t)}getToken(){return localStorage.getItem(this.tokenKey)||sessionStorage.getItem(this.tokenKey)}getRefreshToken(){return localStorage.getItem(this.refreshTokenKey)||sessionStorage.getItem(this.refreshTokenKey)}clearTokens(){localStorage.removeItem(this.tokenKey),localStorage.removeItem(this.refreshTokenKey),sessionStorage.removeItem(this.tokenKey),sessionStorage.removeItem(this.refreshTokenKey)}getTokenInstance(){const e=this.getToken();return e?(this.tokenInstance&&this.tokenInstance.token===e||(this.tokenInstance=new Token(e)),this.tokenInstance):(this.tokenInstance=null,null)}getRefreshTokenInstance(){const e=this.getRefreshToken();return e?(this._refreshTokenInstance&&this._refreshTokenInstance.token===e||(this._refreshTokenInstance=new Token(e)),this._refreshTokenInstance):(this._refreshTokenInstance=null,null)}decode(e=null){const t=e||this.getToken();return new Token(t).decode()}getUserId(){const e=this.getTokenInstance();return e?e.getUserId():null}isValid(){const e=this.getTokenInstance();return!!e&&e.isValid()}isExpiringSoon(e=5){const t=this.getTokenInstance();return!!t&&t.isExpiringSoon(e)}getAuthHeader(){const e=this.getTokenInstance();return e?e.getAuthHeader():null}getUserInfo(){const e=this.getTokenInstance();return e?e.getUserInfo():null}checkTokenStatus(){const e=this.getTokenInstance(),t=this.getRefreshTokenInstance();return e&&e.isValid()&&!e.isExpired()?e.isExpiringSoon(10)||e.getAgeMinutes()&&e.getAgeMinutes()>60?t&&t.isValid()&&!t.isExpired()?{action:"refresh",reason:"Access token expiring soon or aged"}:{action:"none",reason:"Access token expiring but refresh token invalid"}:{action:"none",reason:"All tokens valid and not expiring soon"}:t&&t.isValid()&&!t.isExpired()?{action:"refresh",reason:"Access token invalid/expired but refresh token valid"}:{action:"logout",reason:"Both access and refresh tokens are invalid/expired"}}async checkAndRefreshTokens(e){switch(this.checkTokenStatus().action){case"logout":return e.events.emit("auth:unauthorized"),this.stopAutoRefresh(),!0;case"refresh":return await this.refreshToken(e),!0;default:return!1}}startAutoRefresh(e){this.stopAutoRefresh(),this._tokenWatcher=setInterval(()=>{this.checkAndRefreshTokens(e)},6e4)}stopAutoRefresh(){this._tokenWatcher&&(clearInterval(this._tokenWatcher),this._tokenWatcher=null)}async refreshToken(e){const t=this.getRefreshTokenInstance();if(!t||!t.isValid()||t.isExpired())return e.events.emit("auth:unauthorized"),void this.stopAutoRefresh();try{const s=await e.rest.POST("/api/token/refresh",{refresh_token:t.token}),{access_token:n,refresh_token:i}=s.data.data;this.tokenInstance=null,this._refreshTokenInstance=null,this.setTokens(n,i),e.rest.setAuthToken(n),e.events.emit("auth:token:refreshed",{newToken:n,newRefreshToken:i})}catch(s){401===s.status||403===s.status?(e.events.emit("auth:unauthorized"),this.stopAutoRefresh()):e.events.emit("auth:token:refresh:failed",{error:s})}}}export{SimpleSearchView as S,TokenManager as T,TopNav as a};
|
|
2
|
-
//# sourceMappingURL=TokenManager-D-9tqubS.js.map
|