@materialui-reactjs/admin 1.0.6 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +322 -0
  2. package/LICENSE +21 -0
  3. package/README.md +587 -453
  4. package/dist/Common-DFahMuQE.cjs +11 -0
  5. package/dist/Common-_PK8HLKN.js +267 -0
  6. package/dist/Env-DoS-iQjs.cjs +1 -0
  7. package/dist/Env-SHztUA3s.js +16 -0
  8. package/dist/HeaderUpdate-Dirxjmxs.cjs +1 -0
  9. package/dist/{chunks/HeaderUpdate-DuS-gHNR.js → HeaderUpdate-drlnuHI8.js} +28 -25
  10. package/dist/SortableItem-C3KzO8Xh.cjs +1 -0
  11. package/dist/SpinnerLoader-BujLjvC3.cjs +1 -0
  12. package/dist/{chunks/SpinnerLoader-h8RDIarB.js → SpinnerLoader-CyhOQC6d.js} +2 -2
  13. package/dist/UDragFile-D8wOZ1Ut.js +96 -0
  14. package/dist/UDragFile-Db0sK4M7.cjs +1 -0
  15. package/dist/{chunks/Validator-CXYkI7vJ.js → Validator-D2zwZeov.js} +83 -52
  16. package/dist/Validator-DBxl8wtE.cjs +1 -0
  17. package/dist/assets/css/form.css +1 -1
  18. package/dist/assets/css/index.css +1 -1
  19. package/dist/ckeditor/ckeditor.d.ts +3 -0
  20. package/dist/ckeditor/plugins/elfinder.d.ts +11 -0
  21. package/dist/ckeditor/plugins/fullscreen.d.ts +15 -0
  22. package/dist/ckeditor/plugins/pdffinder.d.ts +18 -0
  23. package/dist/ckeditor/types.d.ts +37 -0
  24. package/dist/common-CEZp8xpQ.js +30 -0
  25. package/dist/common-ivDX6gGq.cjs +1 -0
  26. package/dist/components/echarts/index.cjs +1 -0
  27. package/dist/components/echarts/index.js +1 -1
  28. package/dist/components/form/AdvancedMultiSelect.d.ts +6 -3
  29. package/dist/components/form/AsxhUImages.d.ts +2 -1
  30. package/dist/components/form/BoxAddRow.d.ts +13 -2
  31. package/dist/components/form/CheckTreeBox.d.ts +12 -3
  32. package/dist/components/form/CusForm.d.ts +19 -6
  33. package/dist/components/form/DateInput.d.ts +2 -1
  34. package/dist/components/form/Editor.d.ts +2 -1
  35. package/dist/components/form/EfFile.d.ts +2 -1
  36. package/dist/components/form/EfImage.d.ts +2 -1
  37. package/dist/components/form/EfImages.d.ts +2 -1
  38. package/dist/components/form/PImage.d.ts +2 -1
  39. package/dist/components/form/SelectAddRowBox.d.ts +9 -5
  40. package/dist/components/form/SelectAddRowBoxAdvanced.d.ts +13 -4
  41. package/dist/components/form/SelectBox.d.ts +20 -7
  42. package/dist/components/form/UDragFile.d.ts +2 -1
  43. package/dist/components/form/UFile.d.ts +2 -1
  44. package/dist/components/form/UFiles.d.ts +9 -2
  45. package/dist/components/form/UImages.d.ts +2 -1
  46. package/dist/components/form/index.cjs +1 -0
  47. package/dist/components/form/index.js +2 -2
  48. package/dist/components/loader/SpinnerLoader.d.ts +5 -1
  49. package/dist/components/loader/index.cjs +1 -0
  50. package/dist/components/loader/index.js +1 -2
  51. package/dist/components/meta/CardTable.d.ts +11 -5
  52. package/dist/components/meta/CardTable.types.d.ts +57 -0
  53. package/dist/components/meta/CusTooltip.d.ts +8 -2
  54. package/dist/components/meta/Head.d.ts +10 -1
  55. package/dist/components/meta/HeaderDetail.d.ts +2 -1
  56. package/dist/components/meta/HeaderUpdate.d.ts +5 -1
  57. package/dist/components/meta/ModalForm.d.ts +41 -11
  58. package/dist/components/meta/Navtabs.d.ts +1 -1
  59. package/dist/components/meta/ScrollTable.d.ts +7 -3
  60. package/dist/components/meta/SearchBox.d.ts +8 -5
  61. package/dist/components/meta/SortableItem.d.ts +11 -1
  62. package/dist/components/meta/index.cjs +1 -0
  63. package/dist/components/meta/index.d.ts +1 -0
  64. package/dist/components/meta/index.js +3 -3
  65. package/dist/components/sidebar/Sidebar.types.d.ts +9 -7
  66. package/dist/components/sidebar/index.cjs +1 -0
  67. package/dist/components/sidebar/index.js +1 -1
  68. package/dist/components/single/Detail.d.ts +8 -3
  69. package/dist/components/single/Fields.d.ts +10 -4
  70. package/dist/components/single/Import.d.ts +8 -3
  71. package/dist/components/single/List.d.ts +33 -7
  72. package/dist/components/single/Update.d.ts +10 -4
  73. package/dist/components/single/UpdateDetail.d.ts +3 -2
  74. package/dist/components/single/UpdateTableDetail.d.ts +4 -3
  75. package/dist/components/single/index.cjs +1 -0
  76. package/dist/components/single/index.js +1 -1
  77. package/dist/components/top-navbar/index.cjs +1 -0
  78. package/dist/components/top-navbar/index.js +78 -2
  79. package/dist/echarts-Bi3uwLbg.cjs +1 -0
  80. package/dist/{chunks/echarts-CRmndsxC.js → echarts-CTzMqeR5.js} +4 -4
  81. package/dist/form-heyswTRq.js +3897 -0
  82. package/dist/form-sgtop6li.cjs +49 -0
  83. package/dist/hook/common.d.ts +87 -0
  84. package/dist/hook/detail.cjs +1 -0
  85. package/dist/hook/detail.d.ts +9 -15
  86. package/dist/hook/detail.js +1 -11
  87. package/dist/hook/fields.cjs +1 -0
  88. package/dist/hook/fields.d.ts +6 -14
  89. package/dist/hook/fields.js +1 -11
  90. package/dist/hook/import.d.ts +6 -11
  91. package/dist/hook/index.cjs +1 -0
  92. package/dist/hook/index.d.ts +29 -20
  93. package/dist/hook/index.js +14 -11
  94. package/dist/hook/update.cjs +1 -0
  95. package/dist/hook/update.d.ts +11 -19
  96. package/dist/hook/update.js +12 -9
  97. package/dist/index.cjs +1 -0
  98. package/dist/index.d.ts +16 -0
  99. package/dist/index.js +14 -11
  100. package/dist/meta-BANk9kHW.cjs +1 -0
  101. package/dist/meta-CheDAmMh.js +745 -0
  102. package/dist/rolldown-runtime-BocRIvOZ.cjs +1 -0
  103. package/dist/sidebar-CfQAYWi-.cjs +1 -0
  104. package/dist/{chunks/sidebar-Dj4Xr9du.js → sidebar-CzRmfvhi.js} +10 -13
  105. package/dist/{chunks/single-CRF61o_U.js → single-BsJ7TYJi.js} +364 -282
  106. package/dist/single-C2WPEjhk.cjs +1 -0
  107. package/dist/style.cjs +0 -0
  108. package/dist/style.d.ts +0 -0
  109. package/dist/style.js +0 -0
  110. package/dist/types/Menu.d.ts +25 -0
  111. package/dist/utils/Common.d.ts +224 -43
  112. package/dist/utils/CusRoute.d.ts +21 -1
  113. package/dist/utils/Env.d.ts +23 -2
  114. package/dist/utils/Group.d.ts +12 -1
  115. package/dist/utils/Validator.d.ts +34 -12
  116. package/dist/utils/index.cjs +11 -0
  117. package/dist/utils/index.d.ts +2 -1
  118. package/dist/utils/index.js +212 -171
  119. package/package.json +190 -163
  120. package/dist/chunks/Common-BURf0rBN.js +0 -222
  121. package/dist/chunks/Env-DRXhvUcb.js +0 -16
  122. package/dist/chunks/UDragFile-BnUR3riq.js +0 -92
  123. package/dist/chunks/form-CPkpL5eA.js +0 -45889
  124. package/dist/chunks/loader-BUiOnhOH.js +0 -1
  125. package/dist/chunks/meta-4qPWijBT.js +0 -758
  126. package/dist/chunks/top-navbar-Bob0gMUh.js +0 -78
  127. package/scripts/postinstall.cjs +0 -80
  128. /package/dist/{chunks/SortableItem-B4-Zsso3.js → SortableItem-B4-Zsso3.js} +0 -0
  129. /package/dist/{components/meta/Pdfviewer.d.ts → hook/import.cjs} +0 -0
@@ -0,0 +1 @@
1
+ const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./Env-DoS-iQjs.cjs"),n=require("./Common-DFahMuQE.cjs"),r=require("./Validator-DBxl8wtE.cjs"),i=require("./UDragFile-Db0sK4M7.cjs"),a=require("./SpinnerLoader-BujLjvC3.cjs"),o=require("./HeaderUpdate-Dirxjmxs.cjs"),s=require("./common-ivDX6gGq.cjs");let c=require("react");c=e.t(c,1);let l=require("react/jsx-runtime"),u=require("react-router-dom"),d=require("react-helmet-async");var f=(e,t,n,r,i,a)=>{if(!a)return!1;if(a===1)return!0;if(!Array.isArray(e))return!1;for(let o of e)if(o){if(o.module===t&&o.controller===n&&o.action===r&&Number(o.code)===Number(i))return o.status!==0&&!!o.isPer;if(Array.isArray(o.subs)&&o.subs.length>0&&f(o.subs,t,n,r,i,a))return!0}return!1},p=class extends c.default.Component{effectRan=!1;module=`admins`;controller=``;state={data:{filter:{}},formValue:{},item:void 0,isDetail:void 0};title=``;cUri=``;_envOverride={};_cLinkOverride;get API_URL(){return this._envOverride.API_URL??t.t().API_URL??``}set API_URL(e){this._envOverride.API_URL=e}get ADMIN_URI(){return this._envOverride.ADMIN_URI??t.t().ADMIN_URI??``}set ADMIN_URI(e){this._envOverride.ADMIN_URI=e}get cLink(){return this._cLinkOverride??this.ADMIN_URI+this.cUri}set cLink(e){this._cLinkOverride=e}getDataUrl=``;ctype=`application/json`;fluid=!1;isBackUri=!0;debug=!1;renderForm=()=>(0,l.jsx)(l.Fragment,{});syncPermissionsAndState=async()=>{let{menuData:e,user:t}=this.props,r={isDetail:f(e,this.module,this.controller,`detail`,0,t.groupId)};this.setState(r,async()=>{let e=n.d();if(e&&r.isDetail){let t=await n.n(this.getDataUrl+`/`+e,{},`GET`,`application/json`,!1),r=t?t.data:void 0;this.setState({item:r||!1,formValue:r?JSON.parse(JSON.stringify(r)):{}},async()=>{await this.componentDidMountAfter()})}})};async initDidMount(){try{if(this.effectRan)return;this.effectRan=!0,this.props.user?.groupId&&await this.syncPermissionsAndState()}catch(e){n.s(e)===`invalid_404`&&this.props.navigate(this.cUri),n.x(n.s(e))}}componentDidMount(){this.initDidMount()}componentDidMountAfter=async()=>{};renderHeaderDetail(){return(0,l.jsx)(o.r,{adminUri:this.ADMIN_URI,title:this.title,cUri:this.cUri})}handleChange=async e=>{e.preventDefault();let t=s.r(e);this.debug&&console.log(`handleChange:`,e.target.name,e.target.value),this.setState(e=>({formValue:{...e.formValue,...t}}))};render(){let{isDetail:e,item:t}=this.state;return e?t===!1?(0,l.jsx)(o.i,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | Chi tiết`}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsx)(`title`,{children:this.title})}),(0,l.jsxs)(`div`,{className:`mb-3 ${this.fluid?`container-fluid`:`container`}`,children:[this.renderHeaderDetail(),(0,l.jsx)(`div`,{className:`position-relative`,children:(0,l.jsx)(a.t,{loading:!t,style:{minHeight:200,marginTop:20},children:this.renderForm()})})]})]}):(0,l.jsx)(o.a,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | Chi tiết`,fluid:this.fluid})}},m=class extends c.default.Component{effectRan=!1;module=`admins`;controller=``;table=``;state={formValue:{},item:void 0,isField:!1,isDetail:!1};title=``;cUri=``;_envOverride={};_cLinkOverride;get API_URL(){return this._envOverride.API_URL??t.t().API_URL??``}set API_URL(e){this._envOverride.API_URL=e}get ADMIN_URI(){return this._envOverride.ADMIN_URI??t.t().ADMIN_URI??``}set ADMIN_URI(e){this._envOverride.ADMIN_URI=e}get cLink(){return this._cLinkOverride??this.ADMIN_URI+this.cUri}set cLink(e){this._cLinkOverride=e}getDataUrl=``;editUrl=``;createUrl=``;ctype=`application/json`;fluid=!1;isBackUri=!1;debug=!1;renderForm=()=>(0,l.jsx)(l.Fragment,{});renderAfterForm=()=>(0,l.jsx)(l.Fragment,{});handleChange=async e=>{e.preventDefault();let t=s.r(e);this.debug&&console.log(`handleChange:`,e.target.name,e.target.value),this.setState(e=>({formValue:{...e.formValue,...t}}))};syncPermissionsAndState=async()=>{let{menuData:e,user:t}=this.props,i={isDetail:f(e,this.module,this.controller,`detail`,0,t.groupId)};this.setState(i,async()=>{try{let e=await n.n(this.getDataUrl,{table:this.table},`GET`,`application/json`,!1),t=e?e.data:void 0;this.setState({item:t||!1,formValue:t?{...t}:{}}),new r.t(`#fieldUpdate`).run()}catch(e){n.s(e)===`invalid_404`&&this.props.navigate(this.cUri),n.x(n.s(e))}})};async initDidMount(){try{if(this.effectRan)return;this.effectRan=!0,this.props.user?.groupId&&(await this.syncPermissionsAndState(),await this.componentDidMountAfter())}catch(e){n.s(e)===`invalid_404`&&this.props.navigate(this.cUri),n.x(n.s(e))}}componentDidMount(){this.initDidMount()}componentDidMountAfter=async()=>{};handleSubmit=async e=>{e.preventDefault();let{formValue:t}=this.state,i=new r.t(`#fieldUpdate`);if(!i.hasErrors()&&!i.isIncomplete()){n.C(`#fieldUpdate`,!0);try{t.table||=this.table;let e=await n.n(this.editUrl,t,`POST`,this.ctype);if(n.S(`Cập nhật thành công`,`top-end`,!0),e.data.id){if(this.isBackUri)return this.props.navigate(this.cUri);this.props.navigate(this.cUri+`/fields`),this.setState({item:{...e.data},formValue:{...e.data}},async()=>{await this.afterSubmit(e.data)})}}catch(e){n.x(n.s(e))}finally{n.C(`#fieldUpdate`,!1)}}};afterSubmit=async e=>{};renderHeaderUpdate(){return(0,l.jsx)(o.t,{adminUri:this.ADMIN_URI,title:this.title,cUri:this.cUri,itemId:r.o(this.state.item)})}render(){let{isDetail:e,item:t}=this.state;return e===!1?(0,l.jsx)(o.a,{cUriTitle:this.title,cUri:this.cUri,title:this.title,fluid:this.fluid}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsxs)(`title`,{children:[this.title,` | Tùy chỉnh dữ liệu`]})}),(0,l.jsx)(`div`,{className:`position-relative mb-3 ${this.fluid?`container-fluid`:`container`}`,children:(0,l.jsx)(u.Form,{id:`fieldUpdate`,className:`position-relative`,method:`post`,encType:`multipart/form-data`,"data-toggle":`validator`,role:`form`,onSubmit:this.handleSubmit,children:(0,l.jsxs)(a.t,{loading:!t,style:{minHeight:200,marginTop:20},children:[this.renderHeaderUpdate(),this.renderForm()]})})}),this.renderAfterForm()]})}},h=class extends c.default.Component{module=`admins`;controller=``;state={formValue:{},error:{},isCre:!1,isEdit:!1};title=``;cUri=``;_envOverride={};_cLinkOverride;get API_URL(){return this._envOverride.API_URL??t.t().API_URL??``}set API_URL(e){this._envOverride.API_URL=e}get ADMIN_URI(){return this._envOverride.ADMIN_URI??t.t().ADMIN_URI??``}set ADMIN_URI(e){this._envOverride.ADMIN_URI=e}get cLink(){return this._cLinkOverride??this.ADMIN_URI+this.cUri}set cLink(e){this._cLinkOverride=e}importUrl=``;importFile=`assetorigin.xlsx`;ctype=`multipart/form-data`;fluid=!1;handleChange=async e=>{e.preventDefault();let{name:t,type:n,value:r}=e.target;if(n===`file`){let n=e.target.files;this.setState(e=>({formValue:{...e.formValue,[t]:n?n[0]:null}}))}else this.setState(e=>({formValue:{...e.formValue,[t]:r}}))};syncPermissionsAndState=()=>{let{menuData:e,user:t}=this.props,n={isCre:f(e,this.module,this.controller,`update`,0,t.groupId),isEdit:f(e,this.module,this.controller,`update`,1,t.groupId)};this.setState(n,async()=>{new r.t(`#itemImport`).run()})};async initDidMount(){try{this.props.user?.groupId&&(this.syncPermissionsAndState(),this.componentDidMountAfter())}catch(e){n.s(e)===`invalid_404`&&this.props.navigate(this.cUri),n.x(n.s(e))}}componentDidMount(){this.initDidMount()}componentDidMountAfter=async()=>{};handleSubmit=async e=>{e.preventDefault();let{formValue:t}=this.state,i=new r.t(`#itemImport`);if(!i.hasErrors()&&!i.isIncomplete()){n.C(`#itemImport`,!0);try{let e=await n.n(this.importUrl,t,`POST`,this.ctype);e.data?.error?.length?Array.isArray(e.data?.error)&&e.data.error.length&&this.setState({error:Object.fromEntries(e.data.error.map((e,t)=>[t,e]))}):(this.props.navigate(this.cUri),n.S(`Import thành công`,`top-end`,!0))}catch(e){n.x(n.s(e))}finally{n.C(`#itemImport`,!1)}}};renderForm=()=>(0,l.jsx)(l.Fragment,{children:(0,l.jsx)(i.t,{onChange:this.handleChange,label:`Import excel`,name:`importfile`,ext:`.xlsx,.xls`})});render(){let{isCre:e,isEdit:t}=this.state;return e===!1&&t===!1?(0,l.jsx)(o.a,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | Import`,fluid:this.fluid}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsxs)(`title`,{children:[this.title,` | `,`Import`]})}),(0,l.jsx)(`div`,{className:`mb-3 ${this.fluid?`container-fluid`:`container`}`,children:(0,l.jsxs)(u.Form,{id:`itemImport`,className:`position-relative`,action:this.importUrl,method:`post`,encType:`multipart/form-data`,"data-toggle":`validator`,role:`form`,onSubmit:this.handleSubmit,children:[(0,l.jsxs)(`div`,{className:`navbar navbar-main navbar-expand-lg px-0 shadow-none border-radius-xl py-3`,children:[(0,l.jsx)(`nav`,{"aria-label":`breadcrumb`,children:(0,l.jsxs)(`ol`,{className:`breadcrumb bg-transparent m-0 p-0`,children:[(0,l.jsx)(`li`,{className:`breadcrumb-item`,children:(0,l.jsx)(u.Link,{className:`text-white`,to:this.ADMIN_URI||`/`,children:(0,l.jsx)(`i`,{className:`fal fa-home`})})}),(0,l.jsx)(`li`,{className:`breadcrumb-item`,children:(0,l.jsx)(u.Link,{className:`text-white`,to:this.cUri,children:this.title})}),(0,l.jsx)(`li`,{className:`breadcrumb-item text-white active`,"aria-current":`page`,children:`Import`})]})}),(0,l.jsxs)(`div`,{className:`ms-auto`,children:[(0,l.jsx)(u.Link,{target:`_blank`,to:this.API_URL+`/importfile/`+this.importFile,className:`btn btn-sm btn-icon btn-info me-2`,title:`Tải xuống biểu mẫu`,children:(0,l.jsx)(`i`,{className:`material-icons text-white position-relative text-lg`,children:`file_download`})}),(0,l.jsx)(u.Link,{to:this.cUri,className:`btn btn-sm btn-icon btn-secondary`,title:`Trở lại`,children:(0,l.jsx)(`i`,{className:`material-icons text-white position-relative text-lg`,children:`reply`})})]})]}),(0,l.jsx)(`div`,{className:`card`,children:(0,l.jsx)(`div`,{className:`card-body pb-0`,children:(0,l.jsx)(`div`,{className:`row justify-content-center`,children:(0,l.jsxs)(`div`,{className:`col-md-8 pt-5 pb-4`,children:[(0,l.jsx)(`div`,{dangerouslySetInnerHTML:{__html:n.y(this.state.error)}}),this.renderForm(),(0,l.jsx)(`div`,{className:`w-100 d-flex`,children:(0,l.jsx)(`button`,{title:`Import`,type:`submit`,className:`btn btn-success mb-4 mx-auto`,children:`Import`})})]})})})})]})})]})}},g=class extends c.default.Component{effectRan=!1;fluid=!1;module=`admins`;controller=``;table=``;hasField=!1;state={loading:!0,data:{items:[],page:1,filter:{},length:10,pageTotal:0,recordTotal:0},isDel:void 0,isCre:void 0,isEdit:void 0,isDelOne:void 0,isDetail:void 0,isIndex:void 0,isImport:void 0,isExport:void 0,isCopy:void 0,selectedIds:[],ftfield:[],tbfield:[]};activeMethod=[`ind`,`det`,`cre`,`edit`,`delone`,`del`];cUri=``;_envOverride={};_cLinkOverride;get API_URL(){return this._envOverride.API_URL??t.t().API_URL??``}set API_URL(e){this._envOverride.API_URL=e}get ADMIN_URI(){return this._envOverride.ADMIN_URI??t.t().ADMIN_URI??``}set ADMIN_URI(e){this._envOverride.ADMIN_URI=e}get cLink(){return this._cLinkOverride??this.ADMIN_URI+this.cUri}set cLink(e){this._cLinkOverride=e}getDataUrl=``;deleteUrl=``;copyUrl=``;exportUrl=``;title=``;handleChange=async e=>{try{e.preventDefault();let{name:t}=e.target,r=await o.l(e,this.state.data.filter||{});if(t===`pageLen`){await this.setFilter(r);let e=r?n.a(r):``;this.props.navigate(`${this.cUri}?${e}`,{replace:!0}),await this.fetchData()}else this.setState(e=>({data:{...e.data,filter:r}}))}catch(e){console.log(e)}};handleSearchForm=async e=>{try{e.preventDefault();let t=await o.c(this.state.data.filter||{},this.cUri,this.props.navigate);await this.setFilter(t),await this.fetchData()}catch(e){console.log(e)}};handleClickPage=async e=>{try{e.preventDefault();let t=await o.s(e,this.state.data.filter||{},this.cUri,this.props.navigate);await this.setFilter(t),await this.fetchData()}catch(e){n.x(n.s(e))}};handleDeleteOne=async e=>{n.b().then(async()=>{try{await n.n(`${this.deleteUrl}/${e}`,{},`DELETE`),n.S(`Xoá thành công!`,`top-end`,!0),await this.fetchData()}catch(e){n.x(n.s(e))}})};handleDelete=async()=>{this.state.selectedIds.length?n.b().then(async()=>{try{await n.n(this.deleteUrl,{selected:this.state.selectedIds},`POST`),n.S(`Xoá thành công!`,`top-end`,!0),await this.fetchData()}catch(e){n.x(n.s(e))}}):n.x(`Vui lòng chọn thông tin`)};handleCopy=async()=>{this.state.selectedIds.length?n.b().then(async()=>{try{await n.n(this.copyUrl,{selected:this.state.selectedIds},`POST`),n.S(`Sao chép thành công!`,`top-end`,!0),await this.fetchData()}catch(e){n.x(n.s(e))}}):n.x(`Vui lòng chọn thông tin`)};handleExport=async()=>{try{let{data:e}=this.state,t=n.a(e.filter||{});this.exportUrl&&(window.location.href=this.exportUrl+`?${t}`)}catch(e){n.x(n.s(e))}};handleSelectOne=(e,t)=>{this.setState(n=>({selectedIds:t?[...new Set([...Array.isArray(n.selectedIds)?n.selectedIds:[],e])]:(n.selectedIds??[]).filter(t=>t!==e)}))};handleSelectAll=(e,t=[])=>{this.setState({selectedIds:e?(this.state.data?.items??[]).map(e=>e.id).filter(e=>typeof e==`number`).filter(e=>!t.includes(e)):[]})};setFilter(e){return new Promise(t=>{this.setState(t=>({data:{...t.data,filter:e}}),t)})}fetchData=async()=>{try{let e=await o.o(this.state.data.filter||{},this.getDataUrl);if(!e||!(`items`in e))return;this.setState({data:{...e,filter:e.filter??this.state.data.filter},selectedIds:[]})}catch(e){console.error(n.s(e))}};syncGetField=async()=>({userfield:{},tablefield:{}});syncPermissionsAndState=async()=>{let{menuData:e,user:t}=this.props,n={isCre:this.activeMethod.includes(`cre`)?f(e,this.module,this.controller,`update`,0,t.groupId):!1,isEdit:this.activeMethod.includes(`edit`)?f(e,this.module,this.controller,`update`,1,t.groupId):!1,isDel:this.activeMethod.includes(`del`)?f(e,this.module,this.controller,`delete`,0,t.groupId):!1,isDelOne:this.activeMethod.includes(`delone`)?f(e,this.module,this.controller,`delete`,1,t.groupId):!1,isIndex:this.activeMethod.includes(`ind`)?f(e,this.module,this.controller,`index`,0,t.groupId):!1,isDetail:this.activeMethod.includes(`det`)?f(e,this.module,this.controller,`detail`,0,t.groupId):!1,isImport:!!this.activeMethod.includes(`imp`),isExport:!!this.activeMethod.includes(`exp`),isCopy:!!this.activeMethod.includes(`cpy`)};this.setState(n,async()=>{if(n.isIndex){if(this.hasField){let{userfield:e,tablefield:t}=await this.syncGetField(),n=e?.data?.ftfield||t?.data?.deft||[],r=e?.data?.tbfield||t?.data?.detb||[];this.setState(e=>({...e,ftfield:n,tbfield:r}))}await this.fetchData(),this.setState({loading:!1}),await this.componentDidMountAfter()}})};async initDidMount(){try{if(this.effectRan)return;this.effectRan=!0;let e=new URLSearchParams(window.location.search),t=Object.fromEntries(e.entries()),n={...this.state.data.filter||{},page:1,...t};await this.setFilter(n),this.props.user?.groupId&&await this.syncPermissionsAndState()}catch(e){n.x(n.s(e))}}componentDidMount(){this.initDidMount()}componentDidMountAfter=async()=>{};renderHeaderIndex(){return(0,l.jsx)(o.n,{adminUri:this.ADMIN_URI,title:this.title,cUri:this.cUri,isExp:this.state.isExport,isImp:this.state.isImport,isCre:this.state.isCre,isDel:this.state.isDel,isCpy:this.state.isCopy,isField:this.hasField,onExport:this.handleExport,onCopy:this.handleCopy,onDelete:this.handleDelete})}renderTable=()=>(0,l.jsx)(l.Fragment,{});renderSearch=()=>(0,l.jsx)(l.Fragment,{});render(){let{isIndex:e,data:t,loading:n}=this.state;return e===!1?(0,l.jsx)(o.a,{cUriTitle:this.title,cUri:this.cUri,title:this.title,fluid:this.fluid}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsx)(`title`,{children:this.title})}),(0,l.jsx)(a.t,{loading:n,children:e&&(0,l.jsxs)(`div`,{className:`mb-3 ${this.fluid?`container-fluid`:`container`}`,children:[this.renderHeaderIndex(),(0,l.jsx)(`div`,{className:`card position-relative`,children:(0,l.jsx)(`div`,{className:`card-body`,style:{minHeight:`200px`},children:(0,l.jsxs)(`div`,{className:`searchForm`,children:[(0,l.jsx)(`form`,{onSubmit:this.handleSearchForm,children:this.renderSearch()}),t?.items?.length?(0,l.jsx)(o.u,{data:t,onChange:this.handleChange,onClickPage:this.handleClickPage}):``,(0,l.jsx)(`div`,{className:`table-responsive mt-2`,children:this.renderTable()}),t?.items?.length?(0,l.jsx)(o.u,{data:t,onChange:this.handleChange,onClickPage:this.handleClickPage}):``]})})})]})})]})}},_=({adminUri:e,cUri:t,title:n,itemId:r,isSave:i=!0,titleAction:a})=>(0,l.jsxs)(`div`,{className:`navbar navbar-main navbar-expand-lg px-0 shadow-none border-radius-xl py-3`,children:[(0,l.jsx)(`nav`,{"aria-label":`breadcrumb`,children:(0,l.jsxs)(`ol`,{className:`breadcrumb bg-transparent m-0 p-0`,children:[(0,l.jsx)(`li`,{className:`breadcrumb-item`,children:(0,l.jsx)(u.Link,{className:`text-white`,to:e||`/`,children:(0,l.jsx)(`i`,{className:`fal fa-home`})})}),(0,l.jsx)(`li`,{className:`breadcrumb-item`,children:(0,l.jsx)(u.Link,{className:`text-white`,to:t,children:n})}),(0,l.jsx)(`li`,{className:`breadcrumb-item text-white active`,"aria-current":`page`,children:a??(r?`Chỉnh sửa`:`Thêm mới`)})]})}),(0,l.jsxs)(`div`,{className:`ms-auto`,children:[i&&(0,l.jsx)(o.d,{title:`Lưu lại`,children:(0,l.jsx)(`button`,{type:`submit`,className:`btn btn-sm btn-icon btn-success me-1`,children:(0,l.jsx)(`i`,{className:`material-icons text-white position-relative text-lg`,children:`save`})})}),(0,l.jsx)(o.d,{title:`Trở lại`,children:(0,l.jsx)(u.Link,{to:t,className:`btn btn-sm btn-icon btn-secondary`,children:(0,l.jsx)(`i`,{className:`material-icons text-white position-relative text-lg`,children:`reply`})})})]})]}),v=({title:e=``,cUri:t=``,fluid:n=!1,cUriTitle:r=``})=>(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsx)(`title`,{children:e||`Truy cập không được phép`})}),(0,l.jsxs)(`div`,{className:`${n?`container-fluid`:`container`}`,children:[(0,l.jsx)(`div`,{className:`navbar navbar-main navbar-expand-lg px-0 shadow-none border-radius-xl py-3`,children:(0,l.jsx)(`nav`,{"aria-label":`breadcrumb`,children:(0,l.jsxs)(`ol`,{className:`breadcrumb bg-transparent m-0 p-0`,children:[(0,l.jsx)(`li`,{className:`breadcrumb-item`,children:(0,l.jsx)(u.Link,{className:`text-white`,to:`/`,children:(0,l.jsx)(`i`,{className:`fal fa-home`})})}),(0,l.jsx)(`li`,{className:`breadcrumb-item`,children:(0,l.jsx)(u.Link,{className:`text-white`,to:t,children:r})})]})})}),(0,l.jsx)(`div`,{style:{minHeight:`50vh`},className:`d-flex align-items-center`,children:(0,l.jsxs)(`div`,{className:`m-auto text-center`,children:[(0,l.jsx)(`h1`,{className:`display-1 text-bolder text-white`,children:`403`}),(0,l.jsx)(`h2`,{className:`text-white`,children:`Truy cập không được phép`}),(0,l.jsx)(`p`,{className:`lead text-white`,children:`Xin lỗi, bạn không có quyền truy cập vào trang này.`}),(0,l.jsx)(u.Link,{to:`/`,className:`btn btn-outline-white mt-4`,children:`trang chủ`})]})})]})]}),y=({title:e=``,cUri:t=``,fluid:n=!1,cUriTitle:r=``})=>(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsx)(`title`,{children:e||`Không tìm thấy dữ liệu`})}),(0,l.jsxs)(`div`,{className:`${n?`container-fluid`:`container`}`,children:[(0,l.jsx)(`div`,{className:`navbar navbar-main navbar-expand-lg px-0 shadow-none border-radius-xl py-3`,children:(0,l.jsx)(`nav`,{"aria-label":`breadcrumb`,children:(0,l.jsxs)(`ol`,{className:`breadcrumb bg-transparent m-0 p-0`,children:[(0,l.jsx)(`li`,{className:`breadcrumb-item`,children:(0,l.jsx)(u.Link,{className:`text-white`,to:`/`,children:(0,l.jsx)(`i`,{className:`fal fa-home`})})}),(0,l.jsx)(`li`,{className:`breadcrumb-item`,children:(0,l.jsx)(u.Link,{className:`text-white`,to:t,children:r})})]})})}),(0,l.jsx)(`div`,{style:{minHeight:`50vh`},className:`d-flex align-items-center`,children:(0,l.jsxs)(`div`,{className:`m-auto text-center`,children:[(0,l.jsx)(`h1`,{className:`display-1 text-bolder text-white`,children:`404`}),(0,l.jsx)(`h2`,{className:`text-white`,children:`Không tìm thấy dữ liệu`}),(0,l.jsx)(`p`,{className:`lead text-white`,children:`Xin lỗi, dữ liệu của bạn không được tìm thấy`}),(0,l.jsx)(u.Link,{to:`/`,className:`btn btn-outline-white mt-4`,children:`trang chủ`})]})})]})]}),b=class extends c.default.Component{effectRan=!1;module=`admins`;controller=``;state={formValue:{},error:{},loading:!0,item:void 0,isCre:void 0,isEdit:void 0,isDetail:void 0};title=``;cUri=``;_envOverride={};_cLinkOverride;get API_URL(){return this._envOverride.API_URL??t.t().API_URL??``}set API_URL(e){this._envOverride.API_URL=e}get ADMIN_URI(){return this._envOverride.ADMIN_URI??t.t().ADMIN_URI??``}set ADMIN_URI(e){this._envOverride.ADMIN_URI=e}get cLink(){return this._cLinkOverride??this.ADMIN_URI+this.cUri}set cLink(e){this._cLinkOverride=e}getDataUrl=``;editUrl=``;createUrl=``;ctype=`application/json`;formRef;fluid=!1;isBackUri=!0;debug=!1;constructor(e){super(e),this.formRef=c.default.createRef()}renderForm=()=>(0,l.jsx)(l.Fragment,{});renderAfterForm=()=>(0,l.jsx)(l.Fragment,{});handleChange=e=>{e.preventDefault();let t=r.r(e);this.setState(e=>({formValue:r.n(e.formValue,t)}))};syncPermissionsAndState=async()=>{let{menuData:e,user:t}=this.props,i={isCre:f(e,this.module,this.controller,`update`,0,t.groupId),isEdit:f(e,this.module,this.controller,`update`,1,t.groupId),isDetail:f(e,this.module,this.controller,`detail`,0,t.groupId)};this.setState(i,async()=>{let e=n.d();if(e&&i.isEdit){let t=await n.n(this.getDataUrl+`/`+e,{},`GET`,`application/json`,!1),i=t?t.data:void 0;this.setState({item:i||!1,formValue:i?JSON.parse(JSON.stringify(i)):{}},async()=>{this.setState({loading:!1}),await this.componentDidMountAfter(),this.formRef.current&&new r.t(this.formRef.current).run()})}else{if(this.setState({loading:!1}),await this.componentDidMountAfter(),!this.formRef.current)return;new r.t(this.formRef.current).run()}})};async initDidMount(){try{if(this.effectRan)return;this.effectRan=!0,this.props.user?.groupId&&await this.syncPermissionsAndState()}catch(e){n.s(e)===`invalid_404`&&this.props.navigate(this.cUri),n.x(n.s(e))}}componentDidMount=()=>{this.initDidMount()};componentDidMountAfter=async()=>{};beforeSubmit=()=>new Promise(e=>{e(!0)});handleSubmit=async e=>{e.preventDefault();let{item:t,formValue:i}=this.state,a=r.o(t),o=new r.t(this.formRef.current);!o.hasErrors()&&!o.isIncomplete()&&this.formRef.current&&this.beforeSubmit().then(async()=>{this.setState({loading:!0});try{let e=a?this.editUrl+`/`+a:this.createUrl,t=await n.n(e,i,`POST`,this.ctype);if(a?n.S(`Cập nhật thành công`,`top-end`,!0):n.S(`Thêm mới thành công`,`top-end`,!0),t?.data?.id){if(this.isBackUri)return this.props.navigate(this.cUri);this.props.navigate(this.cUri+`/edit/`+Number(t.data.id)),this.setState({item:{...t.data},formValue:{...t.data}},async()=>{await this.afterSubmit(t.data)})}}catch(e){n.x(n.s(e))}finally{this.setState({loading:!1})}})};afterSubmit=async e=>{};renderHeaderUpdate(){return(0,l.jsx)(_,{adminUri:this.ADMIN_URI,title:this.title,cUri:this.cUri,itemId:r.o(this.state.item)})}render(){let e=n.d(),{isCre:t,isEdit:i,isDetail:o,item:s}=this.state;return t===!1&&i===!1&&o===!1||t===!1&&e==null||(i===!1||o===!1)&&e?(0,l.jsx)(v,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | `+(e?`Chỉnh sửa`:`Thêm mới`),fluid:this.fluid}):e&&s===!1?(0,l.jsx)(y,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | `+(e?`Chỉnh sửa`:`Thêm mới`)}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsxs)(`title`,{children:[this.title,` | `,r.o(s)?`Chỉnh sửa`:`Thêm mới`]})}),(0,l.jsxs)(`div`,{className:`mb-3 ${this.fluid?`container-fluid`:`container`}`,children:[(0,l.jsx)(`div`,{dangerouslySetInnerHTML:{__html:n.y(this.state.error)}}),(0,l.jsx)(u.Form,{ref:this.formRef,className:`position-relative`,method:`post`,encType:`multipart/form-data`,"data-toggle":`validator`,role:`form`,onSubmit:this.handleSubmit,children:(0,l.jsxs)(a.t,{loading:!!this.state.loading,style:{minHeight:200,marginTop:20},children:[this.renderHeaderUpdate(),this.renderForm()]})}),this.renderAfterForm()]})]})}},x=class extends b{urlUpdateDetail=``;render(){let e=n.d(),{isCre:t,isEdit:i,isDetail:o,item:s}=this.state;if(t===!1&&i===!1&&o===!1||t===!1&&e==null||(i===!1||o===!1)&&e)return(0,l.jsx)(v,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | `+(e?`Chỉnh sửa`:`Thêm mới`),fluid:this.fluid});if(e&&s===!1)return(0,l.jsx)(y,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | `+(e?`Chỉnh sửa`:`Thêm mới`)});let c=r.o(s);return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsxs)(`title`,{children:[this.title,` | `,c?`Chỉnh sửa`:`Thêm mới`]})}),(0,l.jsxs)(`div`,{className:`mb-3 ${this.fluid?`container-fluid`:`container`}`,children:[(0,l.jsx)(_,{adminUri:this.ADMIN_URI,title:this.title,cUri:this.cUri,isSave:!1,itemId:c}),(0,l.jsx)(`div`,{dangerouslySetInnerHTML:{__html:n.y(this.state.error)}}),(0,l.jsx)(`div`,{className:`position-relative`,children:(0,l.jsx)(a.t,{loading:!!this.state.loading,style:{minHeight:200,marginTop:0},children:this.renderForm()})})]})]})}handleDetailSubmit=async(e,t)=>{try{let i=r.o(this.state.item);i&&e?.length&&(n.C(t,!0),await n.n(this.urlUpdateDetail,{itemid:i,details:e}),n.C(t,!1),n.S(`Thêm tài sản thành công`,`top-end`,!0),await this.editDetailAfter(i),this.props.navigate(this.cUri+`/edit/`+i))}catch(e){n.x(n.s(e)),n.C(t,!1)}};editDetailAfter=async e=>{}},S=class extends b{urlGetDeTableList=``;urlGetDeTable=``;urlCreDeTable=``;urlEditDeTable=``;urlDelDeTable=``;modalRef;isBackUri=!1;constructor(e){super(e),this.modalRef=(0,c.createRef)()}async fetchDataDetails(){return{}}render(){let e=n.d(),{isCre:t,isEdit:i,isDetail:a,item:o}=this.state;if(t===!1&&i===!1&&a===!1||t===!1&&e==null||(i===!1||a===!1)&&e)return(0,l.jsx)(v,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | `+(e?`Chỉnh sửa`:`Thêm mới`),fluid:this.fluid});if(e&&o===!1)return(0,l.jsx)(y,{cUriTitle:this.title,cUri:this.cUri,title:this.title+` | `+(e?`Chỉnh sửa`:`Thêm mới`)});let s=r.o(o);return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(d.Helmet,{children:(0,l.jsxs)(`title`,{children:[this.title,` | `,s?`Chỉnh sửa`:`Thêm mới`]})}),(0,l.jsxs)(`div`,{className:`mb-3 ${this.fluid?`container-fluid`:`container`}`,children:[(0,l.jsx)(_,{adminUri:this.ADMIN_URI,title:this.title,cUri:this.cUri,isSave:!1,itemId:s}),o?this.renderDeTable():null,this.renderForm()]})]})}renderDeTable(){return(0,l.jsx)(l.Fragment,{})}renderModalDeBody=(e,t)=>(0,l.jsx)(l.Fragment,{});handleDetailSubmit=async e=>{e.preventDefault()};editDetailAfter=async e=>{}};Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return S}});
package/dist/style.cjs ADDED
File without changes
File without changes
package/dist/style.js ADDED
File without changes
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Hình dạng tối thiểu của một menu mà lớp phân quyền cần để quyết định.
3
+ *
4
+ * Tách ra khỏi `MenuItem` của Sidebar để tránh phụ thuộc vòng:
5
+ * `utils/Group` và `hook` dùng kiểu này, còn `Sidebar.types` mở rộng nó
6
+ * thêm các trường hiển thị (icon, sortOrder, ...).
7
+ *
8
+ * `MenuItem` gán được cho `MenuPermissionItem` một cách cấu trúc (structural),
9
+ * nên `menuData: MenuItem[]` vẫn truyền được vào đây.
10
+ */
11
+ export interface MenuPermissionItem {
12
+ module: string;
13
+ controller: string;
14
+ action: string;
15
+ /**
16
+ * Mã hành động. Cho phép `string` vì API có thể trả về `"0"` thay vì `0` —
17
+ * `checkPermission` so sánh bằng `Number(...)` nên cả hai đều hợp lệ.
18
+ */
19
+ code: number | string;
20
+ /** `0` = đã ẩn/khóa (không tính quyền), khác `0` = đang hoạt động. */
21
+ status: number;
22
+ /** Người dùng hiện tại có quyền với mục này hay không. */
23
+ isPer: boolean;
24
+ subs?: MenuPermissionItem[];
25
+ }
@@ -1,34 +1,105 @@
1
+ import { SweetAlertPosition } from 'sweetalert2';
2
+ import { Modal } from 'bootstrap';
1
3
  import { default as Decimal } from 'decimal.js';
4
+ import { CrudItem, FormValue } from '../hook/common';
2
5
  export declare const loadScript: (src: string) => Promise<void>;
3
6
  export declare const loadScripts: (scripts: string[]) => Promise<void>;
4
7
  export declare const spinnerLoader: (box: string | Element, action?: boolean) => void;
5
- export declare const buildFormData: (data: Record<string, any>) => FormData;
8
+ export declare const buildFormData: (data: Record<string, unknown>) => FormData;
6
9
  export declare class ApiError extends Error {
7
10
  errorCode: string;
8
11
  constructor(message: string, errorCode: string);
9
12
  }
10
- export declare const callFetchApi: (url: string, data?: any, type?: string, ctype?: string) => Promise<any>;
11
- export declare const callFetchApiToken: (url: string, data?: any, type?: string, ctype?: string, isTry?: boolean) => Promise<any>;
13
+ /**
14
+ * Envelope chuẩn của API.
15
+ *
16
+ * @typeParam T kiểu của `data`. Mặc định là `Record<string, unknown>` — chặn
17
+ * ở mức "object có khoá" thay vì `any`, nhưng vẫn cho phép consumer tự chỉ
18
+ * định rõ khi biết trước: `callFetchApiToken<Product[]>("/api/p")`.
19
+ */
20
+ export interface ApiResponse<T = Record<string, unknown>> {
21
+ status: number;
22
+ msg?: string;
23
+ errorCode?: string;
24
+ data: T;
25
+ }
26
+ export declare const callFetchApi: <T = Record<string, unknown>>(url: string, data?: FormValue, type?: string, ctype?: string) => Promise<ApiResponse<T>>;
27
+ /**
28
+ * Gọi API kèm cookie phiên (`credentials: "include"`).
29
+ *
30
+ * `isTry = false` biến mọi lỗi thành `false` thay vì ném — dùng cho các chỗ
31
+ * cần "không có dữ liệu cũng chấp nhận" (ví dụ nạp chi tiết, rỗng -> 404).
32
+ *
33
+ * OVERLOADS: khi `isTry` là `true` (mặc định) hàm luôn ném lỗi, **không bao giờ**
34
+ * trả `false` — nên kiểu trả về là `ApiResponse<T>`. Chỉ khi truyền `isTry: false`
35
+ * mới phải kiểm tra `false` trước khi đọc `.data`.
36
+ */
37
+ export declare function callFetchApiToken<T = Record<string, unknown>>(url: string, data?: FormValue, type?: string, ctype?: string, isTry?: true): Promise<ApiResponse<T>>;
38
+ export declare function callFetchApiToken<T = Record<string, unknown>>(url: string, data: FormValue | undefined, type: string | undefined, ctype: string | undefined, isTry: false): Promise<ApiResponse<T> | false>;
12
39
  export declare const showSweetAlert: (text?: string, confirmText?: string) => Promise<import('sweetalert2').SweetAlertResult<any>>;
13
- export declare const showSweetAlertOk: (title: string, pos?: any, toast?: boolean) => void;
40
+ export declare const showSweetAlertOk: (title: string, pos?: SweetAlertPosition, toast?: boolean) => void;
14
41
  export declare const showSweetAlertWarning: (title: string) => void;
15
42
  export declare const showSweetAlertError: (title: string) => void;
16
- export declare const getName: (id: number, items: any[], keyName?: string) => any;
17
- export declare const getNames: (ids: number[], items: any, keyName?: string) => string;
43
+ /**
44
+ * Tra nhãn hiển thị của một bản ghi theo `id`.
45
+ *
46
+ * @param keyName tên trường chứa nhãn, mặc định `name`.
47
+ * @returns giá trị tương ứng, hoặc `null` nếu không tìm thấy.
48
+ */
49
+ export declare const getName: (id: number, items: CrudItem[], keyName?: string) => string | null;
50
+ /** Nối nhãn của nhiều `id` thành chuỗi, bỏ qua id không tồn tại. */
51
+ export declare const getNames: (ids: number[], items: CrudItem[], keyName?: string) => string;
18
52
  export declare const getLinkFiles: (files: string[]) => string;
19
- export declare const getActiveStatus: (id: string | boolean | number, color?: boolean) => any;
20
- export declare const getPublishStatus: (id: string | boolean | number, color?: boolean) => any;
21
- export declare const getTrueFlaseStatus: (id: string | boolean | number, color?: boolean) => any;
53
+ /** Một mục trong bảng trạng thái (kích hoạt / xuất bản / có-không). */
54
+ export interface StatusOption {
55
+ id: number;
56
+ name: string;
57
+ color: string;
58
+ }
59
+ /**
60
+ * Dựng nhãn trạng thái từ bảng tra cứu.
61
+ *
62
+ * Trả về chính `table` khi `id === false` — đó là quy ước cũ: consumer dùng để
63
+ * lấy luôn danh sách để dựng dropdown, chứ không phải một giá trị hiển thị.
64
+ */
65
+ export declare const getStatus: (id: string | boolean | number, table: StatusOption[], color?: boolean) => string | StatusOption[];
66
+ export declare const getActiveStatus: (id: string | boolean | number, color?: boolean) => string | StatusOption[];
67
+ export declare const getPublishStatus: (id: string | boolean | number, color?: boolean) => string | StatusOption[];
68
+ export declare const getTrueFlaseStatus: (id: string | boolean | number, color?: boolean) => string | StatusOption[];
22
69
  export declare function parseDate(date: string | Date): Date;
23
70
  export declare function strToDate(input?: string | Date): Date;
24
- export declare const formatDateTime: (date: any) => string;
25
- export declare const formatDate: (date: any) => string;
26
- export declare const formatYear: (date: any) => string;
27
- export declare const formatDateSql: (date: any) => string;
28
- export declare const getParams: (name?: string | null) => string | Record<string, string | null> | null;
71
+ /**
72
+ * Kiểu mà các hàm định dạng ngày chấp nhận.
73
+ *
74
+ * `new Date(x)` chỉ nhận `string | number | Date`; trước đây tham số là `any`
75
+ * nên truyền nhầm kiểu (object, mảng...) chỉ lộ ra khi render ra
76
+ * "Invalid Date" ở production.
77
+ */
78
+ export type DateInput = string | number | Date | null | undefined;
79
+ export declare const formatDateTime: (date: DateInput) => string;
80
+ export declare const formatDate: (date: DateInput) => string;
81
+ export declare const formatYear: (date: DateInput) => string;
82
+ export declare const formatDateSql: (date: DateInput) => string;
83
+ /**
84
+ * Đọc query string hiện tại.
85
+ * @param name không truyền -> trả toàn bộ params dạng object;
86
+ * truyền chuỗi -> trá 1 giá trị;
87
+ * truyền mảng chuỗi -> trả object { key: value | null }.
88
+ */
89
+ export declare const getParams: (name?: string | string[] | null) => string | Record<string, string | null> | null;
29
90
  export declare const setParams: (newParams: Record<string, string | null>) => string;
30
- export declare const createQueryString: (params: Record<string, any>) => string;
31
- export declare const getIdParams: () => number | null;
91
+ export declare const createQueryString: (params: Record<string, unknown>) => string;
92
+ /**
93
+ * Lấy `:id` từ URL hiện tại.
94
+ *
95
+ * Route do `CusRoute.addGS()` sinh ra có dạng `.../detail/:id` hoặc `.../edit/:id`,
96
+ * nên `:id` KHÔNG nằm ở cuối pathname. Regex cũ (`/\/(\d+)(\/)?$/`) chỉ khớp khi
97
+ * id nằm cuối -> trả `null` sai, dẫn tới nhánh 403/404 render sai.
98
+ *
99
+ * @param pathname mặc định lấy từ `window.location.pathname` (truyền vào để test hoặc dùng trong router)
100
+ * @param pattern route pattern, mặc định theo convention của `CusRoute`
101
+ */
102
+ export declare const getIdParams: (pathname?: string, pattern?: RegExp) => number | null;
32
103
  export declare const getImage: (image: string, df?: string) => string;
33
104
  export declare const getFile: (file: string) => string;
34
105
  export declare const getPubImage: (image: string, df?: string) => string;
@@ -36,29 +107,124 @@ export declare const getUploadImage: (image: string, df?: string) => string;
36
107
  export declare const getUploadFile: (file: string, df?: string) => string;
37
108
  export declare function randomString(length: number): string;
38
109
  export declare function htmlToText(html: string): string;
39
- export declare const checkUploadFile: (files: any, size?: number, type?: any) => Promise<unknown>;
110
+ /**
111
+ * Dựng RegExp kiểm tra phần mở rộng từ thuộc tính `accept` của `<input type="file">`.
112
+ *
113
+ * ⚠ SỬA LỖI BẢO MẬT: bản cũ lặp ở 7 component dùng
114
+ * new RegExp(`\.(` + acceptAttr.replace(...) + `)$`, 'i')
115
+ * Trong template literal, `\.` là escape KHÔNG hợp lệ nên chuỗi thực tế là
116
+ * `.(pdf|docx)$` — dấu `.` ở regex nghĩa là "ký tự bất kỳ".
117
+ * Hậu quả: file `malwarepdf`, `hongbang.txtpdf`... đều PASS kiểm tra đuôi file.
118
+ * Phải viết `\\.` để regex nhận đúng dấu chấm literal.
119
+ *
120
+ * @param acceptAttr giá trị `accept`, ví dụ `".pdf, .docx"`, `"image/png"` hoặc `".pdf"`
121
+ * @param fallback regex dùng khi `acceptAttr` rỗng (thường là allowlist mặc định)
122
+ */
123
+ export declare const buildAcceptRegExp: (acceptAttr: string | null | undefined, fallback: RegExp) => RegExp;
124
+ /**
125
+ * Kiểm tra danh sách file trước khi upload.
126
+ *
127
+ * Bản cũ có 3 lỗi chuỗi:
128
+ * 1. `type ? type : (regex)` là no-op -> `type` mặc định `false` gây `TypeError: type.test is not a function`;
129
+ * 2. `return false` bên trong Promise executor KHÔNG reject -> promise treo vĩnh viễn,
130
+ * `.then()` ở call-site không bao giờ chạy (form im lặng dù alert đã hiện);
131
+ * 3. `resolve(this)` -> `this` là `undefined` trong arrow function.
132
+ *
133
+ * Nay: reject với `Error` để call-site bắt được, vẫn hiện alert cho UX.
134
+ */
135
+ export declare const checkUploadFile: (files: FileList | File[] | null | undefined, size?: number, type?: RegExp) => Promise<void>;
136
+ /** Escape 5 ký tự HTML nguy hiểm — dùng cho mọi dữ liệu không tin cậy trước khi nhúng vào `__html`. */
137
+ export declare const escapeHtml: (value: unknown) => string;
138
+ /**
139
+ * Render thông báo lỗi thành HTML alert.
140
+ *
141
+ * Đã thêm escape: `errors` đến từ response API (`res.data.error`) — nếu server trả
142
+ * về chuỗi chứa HTML/script thì `dangerouslySetInnerHTML` sẽ thành XSS stored.
143
+ * `type` cũng được kiểm tra theo allowlist để không chèn được class tuỳ ý.
144
+ *
145
+ * Muốn render HTML cố ý thì truyền `{ raw: true }` (chỉ dùng với nội dung do dev sinh).
146
+ */
40
147
  export declare const showMessage: (errors?: {
41
148
  [key: string]: string;
42
- } | string, type?: string) => string;
149
+ } | string, type?: string, options?: {
150
+ raw?: boolean;
151
+ }) => string;
43
152
  export declare const resetForm: (form: HTMLFormElement) => HTMLFormElement;
44
- export declare const mapDataForm: (form: HTMLFormElement, data: Record<string, any>, hidden?: boolean) => Promise<Record<string, any>>;
45
- export declare const elFinderPopup: (el: string, options?: Record<string, any>) => Promise<unknown>;
46
- export declare const createModal: (modalCls: string | HTMLElement) => Promise<unknown>;
47
- export declare const showFinderModal: (btnEl: HTMLDivElement, modalCls: string, fnShow?: ((item: {
48
- data: any;
49
- modalEl?: HTMLElement;
50
- btnEl?: any;
51
- md?: any;
52
- }) => void) | false, fnHide?: (() => void) | false) => void;
53
- export declare const showFinderFileModal: (btnEl: HTMLDivElement, modalCls: string, fnShow?: ((item: {
54
- data: any;
153
+ export declare const mapDataForm: (form: HTMLFormElement, data: Record<string, unknown>, hidden?: boolean) => Promise<Record<string, unknown>>;
154
+ export declare const elFinderPopup: (el: string, options?: Record<string, unknown>) => Promise<unknown>;
155
+ /**
156
+ * Lấy message từ giá trị trong `catch`.
157
+ *
158
+ * `catch` nhận `unknown` (`useUnknownInCatchVariables` bật cùng `strict`) vì
159
+ * JavaScript cho `throw` BẤT KỲ thứ gì — kể cả chuỗi. Trong codebase này
160
+ * `Promise.reject("invalid_404")` là mẫu rất hay dùng, và các call site so sánh
161
+ * `error.message == "invalid_404"`. Nếu ép `catch (error: any)` chỉ để đọc
162
+ * `.message` thì với các giá trị đó runtime sẽ ra `undefined` và so sánh luôn
163
+ * sai — tức là mất luôn cả nhánh xử lý 404.
164
+ *
165
+ * Vì vậy: `Error` thì lấy `.message`, chuỗi thì trả chính nó, còn lại thử
166
+ * `JSON.stringify`. `JSON.stringify` có thể ném với `BigInt`/vòng lặp nên bọc
167
+ * trong `try`.
168
+ */
169
+ export declare const errorMessage: (error: unknown) => string;
170
+ /**
171
+ * Mở modal Bootstrap và trả về instance để điều khiển (`show`/`hide`).
172
+ *
173
+ * Khai báo rõ kiểu của `Promise` vì `new Promise((resolve) => ...)` không có
174
+ * type argument sẽ suy ra là `Promise<unknown>` — mọi call site phải ép `any`
175
+ * mới destructure được `{ md, modalEl }`. `Modal` lấy từ `bootstrap` nên có kiểu
176
+ * đầy đủ (`hide`/`show`/`dispose`), không phải tự định nghĩa.
177
+ */
178
+ export declare const createModal: (modalCls: string | HTMLElement) => Promise<{
179
+ md: Modal;
180
+ modalEl: HTMLElement;
181
+ }>;
182
+ /**
183
+ * Payload mà `showFinderModal`/`showFinderFileModal` đưa cho callback của
184
+ * consumer.
185
+ *
186
+ * `data` là kết quả từ elFinder nên để `unknown` — tuỳ chế độ chọn nó là 1 file
187
+ * hoặc mảng file, và `ElFinderFile` đã mô tả đúng một file. `md` là instance
188
+ * `Modal` của bootstrap, `btnEl` là phần tử đã bấm.
189
+ */
190
+ export interface FinderModalItem {
191
+ data: unknown;
55
192
  modalEl?: HTMLElement;
56
- btnEl?: any;
57
- md?: any;
58
- }) => void) | false, fnHide?: (() => void) | false) => void;
59
- export declare const filterIds: (input: any[] | string) => number[];
60
- export declare function stringToJson(input: any, df?: {}, type?: string): any;
61
- export declare const formatNumber: (number: number, options?: {}, type?: string) => string | 0;
193
+ btnEl?: HTMLDivElement;
194
+ /**
195
+ * Instance modal để điều khiển.
196
+ *
197
+ * Đánh dấu OPTIONAL vì consumer có thể tự dựng object này khi test; nhưng hai
198
+ * hàm `showFinderModal`/`showFinderFileModal` LUÔN truyền kèm `md` nên
199
+ * call site thật dùng callback `FinderModalItem` sẽ không phải kiểm tra lại.
200
+ */
201
+ md?: Modal;
202
+ }
203
+ export declare const showFinderModal: (btnEl: HTMLDivElement, modalCls: string, fnShow?: ((item: FinderModalItem) => void) | false, fnHide?: (() => void) | false) => void;
204
+ export declare const showFinderFileModal: (btnEl: HTMLDivElement, modalCls: string, fnShow?: ((item: FinderModalItem) => void) | false, fnHide?: (() => void) | false) => void;
205
+ /**
206
+ * Giá trị đọc được từ `stringToJson` khi `type` không phải `"ids"`.
207
+ *
208
+ * Hàm xử lý cả mảng lẫn object tuỳ input nên kiểu trả về là `unknown` — bắt
209
+ * buộc call site tự kiểm tra trước khi dùng, thay vì `any` khiến mọi thứ biến
210
+ * thành `any[]` ngay từ đầu.
211
+ */
212
+ export type ParsedJson = unknown;
213
+ /**
214
+ * Ép một mảng bất kỳ thành `number[]`, bỏ `NaN` và trùng lặp.
215
+ *
216
+ * Input đến từ query string / JSON nên có thể là chuỗi số, số, hoặc rỗng.
217
+ */
218
+ export declare const filterIds: (input: ParsedJson | string) => number[];
219
+ /**
220
+ * Đọc JSON từ chuỗi (query string, hidden field...) với giá trị mặc định.
221
+ *
222
+ * Trả về `unknown` vì kết quả có thể là mảng hoặc object tuỳ nội dung JSON —
223
+ * người gọi phải tự kiểm tra. `type = "ids"` thì lọc thành `number[]`.
224
+ */
225
+ export declare function stringToJson(input: unknown, df?: unknown, type?: string): ParsedJson;
226
+ /** Luôn trả về chuỗi đã format (0 -> "0", null -> "0") để không lệch return type. */
227
+ export declare const formatNumber: (number: number, options?: Intl.NumberFormatOptions, type?: string) => string;
62
228
  export declare const decimalNumber: (value: string | number) => Decimal;
63
229
  /**
64
230
  * Lấy ra một mảng giá trị của cùng một field từ mảng object
@@ -79,7 +245,7 @@ export declare const decimalNumber: (value: string | number) => Decimal;
79
245
  * const ids = mapArrFields(data, 'id');
80
246
  * // Kết quả: [1, 2, 3]
81
247
  */
82
- export declare const mapArrFields: (data: any[], field: any) => any[];
248
+ export declare const mapArrFields: (data: readonly CrudItem[], field: string) => unknown[];
83
249
  /**
84
250
  * Gộp (merge) các object trong mảng thành một object duy nhất
85
251
  * Các key trùng nhau sẽ bị ghi đè bởi object xuất hiện sau
@@ -96,10 +262,7 @@ export declare const mapArrFields: (data: any[], field: any) => any[];
96
262
  * const result = mergeArrObject(data);
97
263
  * // Kết quả: { a: 1, b: 3, c: 4, d: 5 }
98
264
  */
99
- export declare const mergeArrObject: (array1: any[], array2: any[], field1: string, field2: string, field2S: string) => {
100
- id: number;
101
- name: string;
102
- }[];
265
+ export declare const mergeArrObject: (array1: readonly unknown[], array2: readonly CrudItem[], field1: string, field2: string, field2S: string) => Record<string, unknown>[];
103
266
  /**
104
267
  * Map lại dữ liệu của mảng object theo rule chỉ định
105
268
  *
@@ -130,11 +293,29 @@ export declare const mergeArrObject: (array1: any[], array2: any[], field1: stri
130
293
  * // { userId: 2, fullName: 'Bình', isAdult: true }
131
294
  * // ]
132
295
  */
133
- export declare const mapArrData: (arr: any[], rule: any) => any[];
296
+ /**
297
+ * Quy tắc ánh xạ cho `mapArrData`: hoặc tên field cần lấy, hoặc hàm tự tính.
298
+ *
299
+ * Về callback: dùng `(...args: never[]) => unknown` chứ không phải
300
+ * `(item: CrudItem) => unknown`. `never` ở vị trí tham số khiến mọi callback có
301
+ * tham số kiểu cụ thể hơn đều gán được (contravariance) — nếu khai báo
302
+ * `(item: CrudItem)` thì consumer viết `(item: { age: number }) => ...` sẽ bị
303
+ * báo lỗi dù hoàn toàn hợp lệ. Thân hàm thì vẫn gọi với `item` thật.
304
+ */
305
+ export type MapArrDataRule = Record<string, string | ((...args: never[]) => unknown)>;
306
+ export declare const mapArrData: (arr: readonly CrudItem[], rule: MapArrDataRule) => CrudItem[];
134
307
  export declare const isStsNum: (status: number, type: string, tryThrow?: boolean) => boolean;
135
308
  export declare function sumArrCol<T extends Record<string, number>>(items: T[], col: keyof T): number;
136
309
  export declare const getFilterType: (type: number) => string;
137
- export declare const getLangs: (key?: any) => string | {
310
+ /** Một ngôn ngữ trong danh sách `getLangs`. */
311
+ export interface Lang {
138
312
  id: number;
139
313
  name: string;
140
- }[];
314
+ }
315
+ /**
316
+ * Danh sách ngôn ngữ, hoặc tên ngôn ngữ khi truyền `key`.
317
+ *
318
+ * Trả về `Lang[] | string` nên call site phải biết mình đang ở nhánh nào —
319
+ * trước đây kiểu `any` khiến `BoxAddRow` phải ép `as Array<{id;name}>`.
320
+ */
321
+ export declare const getLangs: (key?: number | false) => Lang[] | string;
@@ -1,7 +1,27 @@
1
1
  import { RouteObject } from 'react-router-dom';
2
+ import { ReactNode } from 'react';
3
+ /**
4
+ * Một "màn hình" trong route: element của react-router, hoặc `false` để báo
5
+ * "không cài màn hình này".
6
+ *
7
+ * Trước đây tham số này là `any = false` — không rõ ý nghĩa, và sai kiểu vẫn
8
+ * chạy được cho tới lúc runtime.
9
+ */
10
+ export type RouteElement = ReactNode | false;
2
11
  export declare class CusRoute {
3
12
  private routes;
4
- addGS(link: string, layout: any, Index: any, Update?: any, Detail?: any, Import?: any, Fields?: any): Promise<void>;
13
+ /**
14
+ * Thêm một nhóm route CRUD cho một resource.
15
+ *
16
+ * @param link path gốc, ví dụ `/admin/products`
17
+ * @param layout component bọc ngoài
18
+ * @param Index component danh sách
19
+ * @param Update component thêm/sửa — bật cả route `create` và `edit/:id`
20
+ * @param Detail component chi tiết
21
+ * @param Import component import
22
+ * @param Fields component tuỳ chỉnh trường
23
+ */
24
+ addGS(link: string, layout: RouteElement, Index: RouteElement, Update?: RouteElement, Detail?: RouteElement, Import?: RouteElement, Fields?: RouteElement): Promise<void>;
5
25
  addRoute(routeList?: RouteObject[]): void;
6
26
  getRouter(): RouteObject[];
7
27
  }
@@ -1,2 +1,23 @@
1
- export declare function loadEnv(): Promise<any>;
2
- export declare function getEnv(): any;
1
+ export interface EnvType {
2
+ API_URL?: string;
3
+ ADMIN_URI?: string;
4
+ SECRET_KEY?: string;
5
+ STATIC_URL?: string;
6
+ UPLOADS_URL?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ /**
10
+ * Tải cấu hình runtime từ `/env.json`.
11
+ *
12
+ * - KHÔNG BAO GIỜ reject: nếu 404 / network lỗi / parse lỗi thì trả về `{}`.
13
+ * Mục đích: một config thiếu không được làm trắng màn hình toàn bộ app.
14
+ * - Kết quả được cache sau lần gọi đầu tiên; dùng `reloadEnv()` để thử lại.
15
+ */
16
+ export declare function loadEnv(): Promise<EnvType>;
17
+ /**
18
+ * Đọc cấu hình đã tải. Trả `{}` nếu chưa tải xong — cố tình KHÔNG throw để
19
+ * component render được với giá trị rỗng thay vì sập cả cây.
20
+ */
21
+ export declare function getEnv(): EnvType;
22
+ /** Ép tải lại `/env.json` (dùng để retry sau khi lần load đầu thất bại). */
23
+ export declare function reloadEnv(): Promise<EnvType>;
@@ -1 +1,12 @@
1
- export declare const checkPermission: (menuData: any[], moduleText: string, controller: string, action: string, code: number, groupId: number) => any;
1
+ import { MenuPermissionItem } from '../types/Menu';
2
+ /**
3
+ * Kiểm tra quyền của user đối với một hành động.
4
+ *
5
+ * Quy ước `status`: `0` = đã ẩn/khóa (không tính), khác `0` = đang hoạt động.
6
+ * Khớp với bộ lọc ở `Sidebar.tsx` / `SidebarItem.tsx` để menu hiển thị và
7
+ * quyền kiểm tra luôn nhất quán.
8
+ *
9
+ * Fail-closed: không tìm thấy menu tương ứng thì trả `false`
10
+ * (thay vì `true` như bản cũ — fail-open là lỗ hổng phân quyền).
11
+ */
12
+ export declare const checkPermission: (menuData: MenuPermissionItem[], moduleText: string, controller: string, action: string, code: number, groupId: number) => boolean;
@@ -1,3 +1,24 @@
1
+ /**
2
+ * jQuery phải được nạp sẵn (script tag hoặc `import "jquery"` ở app).
3
+ *
4
+ * Resolve LAZY thay vì đọc `window.jQuery` lúc module-eval, để:
5
+ * - import package trong môi trường không có DOM (SSR / test) không crash;
6
+ * - lỗi "chưa nạp jQuery" chỉ nổ ra đúng lúc thực sự validate,
7
+ * kèm thông báo rõ ràng thay vì "x is not a function".
8
+ */
9
+ /**
10
+ * Collection jQuery.
11
+ *
12
+ * CỐ TÌNH không dùng kiểu `JQuery` của `@types/jquery`: bản v4 đã bỏ generic
13
+ * của nó và bỏ luôn `JQuery.Promise`. Nếu những kiểu đó lọt vào `.d.ts` thì mọi
14
+ * consumer chạy `strict` + `skipLibCheck: false` đều **không typecheck được** —
15
+ * đã kiểm chứng bằng cách pack và cài vào một project sạch.
16
+ *
17
+ * Đây là bản port của plugin jQuery Bootstrap Validator, các call site thực sự
18
+ * là động (`$el[0]`, `$el.val()`, `$el.data()`...) nên `any` ở đây là mô tả
19
+ * trung thực, không phải lười.
20
+ */
21
+ type Jq = any;
1
22
  export declare class Validator {
2
23
  options: any;
3
24
  validators: any;
@@ -25,29 +46,30 @@ export declare class Validator {
25
46
  };
26
47
  static VALIDATORS: {
27
48
  native: ($el: any) => any;
28
- match: ($el: JQuery) => string | false | undefined;
29
- minlength: ($el: JQuery) => string | false;
30
- maxlength: ($el: JQuery) => string | false;
31
- filesize: ($el: JQuery<HTMLInputElement>) => boolean;
32
- accept: ($el: JQuery<HTMLInputElement>) => boolean;
33
- pattern: ($el: JQuery) => boolean;
49
+ match: ($el: Jq) => any;
50
+ minlength: ($el: Jq) => string | false;
51
+ maxlength: ($el: Jq) => string | false;
52
+ filesize: ($el: Jq) => boolean;
53
+ accept: ($el: Jq) => boolean;
54
+ pattern: ($el: Jq) => boolean;
34
55
  };
35
56
  constructor(element: any, options?: any);
36
- static getValue($el: JQuery): boolean | number | string | string[];
57
+ static getValue($el: Jq): boolean | number | string | string[];
37
58
  update: () => this;
38
59
  onInput: (e: any) => void;
39
- validateInput: ($el: JQuery, deferErrors: any) => JQuery.Promise<any, any, any> | undefined;
40
- runValidators: ($el: JQuery) => JQuery.Promise<any, any, any>;
60
+ validateInput: ($el: Jq, deferErrors: any) => any;
61
+ runValidators: ($el: Jq) => any;
41
62
  validate: () => this;
42
63
  focusError: () => void;
43
- showErrors: ($el: JQuery) => void;
44
- clearErrors: ($el: JQuery) => void;
64
+ showErrors: ($el: Jq) => void;
65
+ clearErrors: ($el: Jq) => void;
45
66
  hasErrors: () => boolean;
46
67
  isIncomplete: () => boolean;
47
68
  onSubmit: (e: any) => void;
48
69
  toggleSubmit: () => void;
49
- defer: ($el: JQuery, callback: any) => any;
70
+ defer: ($el: Jq, callback: any) => any;
50
71
  reset: () => this;
51
72
  destroy: () => this;
52
73
  run: () => void;
53
74
  }
75
+ export {};
@@ -0,0 +1,11 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../rolldown-runtime-BocRIvOZ.cjs"),t=require("../Env-DoS-iQjs.cjs");let n=require("sweetalert2");n=e.t(n,1);let r=require("sweetalert2-react-content");r=e.t(r,1);let i=require("bootstrap"),a=require("date-fns"),o=require("decimal.js");o=e.t(o,1),t.n();var s=e=>t.t()[e]??``,c=e=>new Promise((t,n)=>{if(document.querySelector(`script[src="${e}"]`)){t();return}let r=document.createElement(`script`);r.src=e,r.onload=()=>t(),r.onerror=()=>n(Error(`Failed to load script ${e}`)),document.body.appendChild(r)}),l=async e=>{for(let t of e)await c(t)},ee=(e,t=!0)=>{let n=typeof e==`string`?document.querySelector(e):e;if(n){if(t)n.querySelector(`.boxSpinner`)||n.insertAdjacentHTML(`afterbegin`,`<div class="boxSpinner rounded">
2
+ <div class="spinner">
3
+ <div class="rect1"></div>
4
+ <div class="rect2"></div>
5
+ <div class="rect3"></div>
6
+ <div class="rect4"></div>
7
+ <div class="rect5"></div>
8
+ <div class="rect6"></div>
9
+ <div class="rect7"></div>
10
+ </div>
11
+ </div>`);else{let e=n.querySelector(`.boxSpinner`);e&&e.remove()}}},u=e=>{let t=new FormData;return Object.entries(e).forEach(([e,n])=>{if(n!=null){if(n instanceof FileList){Array.from(n).forEach(n=>t.append(e,n));return}if(n instanceof File){t.append(e,n);return}if(Array.isArray(n)&&n.every(e=>e instanceof File)){n.forEach(n=>t.append(e,n));return}if(Array.isArray(n)&&n.every(e=>[`string`,`number`,`boolean`].includes(typeof e))){n.forEach(n=>t.append(e,n.toString()));return}if(typeof n==`object`){t.append(e,JSON.stringify(n));return}n!=null&&typeof n!=`function`&&typeof n!=`object`&&t.append(e,String(n))}}),t},d=class extends Error{errorCode;constructor(e,t){super(e),this.name=`ApiError`,this.errorCode=t}},te=async(e,t={},n=`POST`,r=`application/json`)=>{let i={method:n,headers:{"Content-Type":r,"Secret-Key":s(`SECRET_KEY`)},credentials:`include`};n==`POST`&&(i.body=JSON.stringify(t));let a=await(await fetch(e,i)).json();if(a.status==200)return a;throw a.msg?new d(a.msg,a.errorCode??`unknown`):Error(`invalid_response`)};async function f(e,t={},n=`POST`,r=`application/json`,i=!0){let a={"Secret-Key":s(`SECRET_KEY`)};r!==`multipart/form-data`&&(a[`Content-Type`]=r);let o={method:n,headers:a,credentials:`include`};if(n==`POST`&&(o.body=r===`multipart/form-data`?u(t):JSON.stringify(t)),n===`GET`&&Object.keys(t).length>0){let n=new URLSearchParams;Object.entries(t).forEach(([e,t])=>{Array.isArray(t)?t.forEach(t=>n.append(e,String(t))):n.append(e,String(t))});let r=n.toString();e+=(e.includes(`?`)?`&`:`?`)+r}let c=await(await fetch(e,o)).text(),l=null;if(c)try{l=JSON.parse(c)}catch{l=c}if(l&&typeof l!=`string`&&l.status==200)return l;if(l&&typeof l!=`string`&&l.msg&&i)throw new d(l.msg,l.errorCode??`unknown`);if(i)throw Error(`invalid_response`);return!1}var p=(e=`Bạn có chắc muốn thực hiện thao tác này ?`,t=`Đồng ý`)=>(0,r.default)(n.default).fire({title:`Xác nhận`,text:e,icon:`warning`,showCancelButton:!0,confirmButtonColor:`#4CAF50`,cancelButtonColor:`#F44336`,confirmButtonText:t,cancelButtonText:`Hủy`,position:`top`}),m=(e,t=`top`,i=!1)=>{(0,r.default)(n.default).fire({toast:i,icon:`success`,position:t,title:e,showConfirmButton:!1,timer:1500})},ne=e=>{(0,r.default)(n.default).fire({icon:`warning`,title:e,showConfirmButton:!1,timer:1500})},h=e=>{(0,r.default)(n.default).fire({icon:`error`,position:`top`,title:e,showConfirmButton:!1})},re=(e,t,n=`name`)=>{let r=t?.find(t=>t.id===e);return r?r[n]??null:null},ie=(e,t,n=`name`)=>{let r=Array.isArray(e)?e:[],i=Array.isArray(t)?t:[];return r.map(e=>{let t=i.find(t=>t.id===e);return t?t[n]:null}).filter(Boolean).join(`, `)},ae=e=>Array.isArray(e)?e.map((e,t)=>`<p class="mb-0"><a class="text-info" target="_blank" rel="noopener noreferrer" href="${V(F(e,`#`))}">Tập tin ${t+1}</a></p>`).filter(Boolean).join(``):``,g=(e,t,n=!1)=>{if(e===!1)return t;let r=t.find(t=>t.id===Number(e));return r?n?`<span class="badge badge-sm bg-gradient-${r.color}">${r.name}</span>`:r.name:``},oe=[{id:1,name:`Kích hoạt`,color:`success`},{id:0,name:`Khóa`,color:`danger`}],se=[{id:1,name:`Xuất bản`,color:`success`},{id:0,name:`Nháp`,color:`danger`}],ce=[{id:1,name:`Có`,color:`success`},{id:0,name:`Không`,color:`secondary`}],_=(e,t=!1)=>g(e,oe,t),v=(e,t=!1)=>g(e,se,t),y=(e,t=!1)=>g(e,ce,t);function b(e){let t=e instanceof Date?e:new Date(e);if(isNaN(t.getTime()))throw Error(`Ngày không hợp lệ: `+e);return t}function x(e){if(!e)return new Date;if(e instanceof Date)return new Date(e);let t=e.trim().toLowerCase();if(t===`now`)return new Date;let n=new Date,r=t.match(/^([+-]?\d+)\s*(year|years|month|months|week|weeks|day|days|hour|hours|minute|minutes|min|mins|second|seconds|sec|secs)$/);if(r){let e=Number(r[1]);switch(r[2]){case`year`:case`years`:n.setFullYear(n.getFullYear()+e);break;case`month`:case`months`:n.setMonth(n.getMonth()+e);break;case`week`:case`weeks`:n.setDate(n.getDate()+e*7);break;case`day`:case`days`:n.setDate(n.getDate()+e);break;case`hour`:case`hours`:n.setHours(n.getHours()+e);break;case`minute`:case`minutes`:case`min`:case`mins`:n.setMinutes(n.getMinutes()+e);break;case`second`:case`seconds`:case`sec`:case`secs`:n.setSeconds(n.getSeconds()+e)}return n}let i=new Date(t);if(!isNaN(i.getTime()))return i;throw Error(`Invalid date expression: ${e}`)}var S=e=>{if(!e)return null;let t=new Date(e);return isNaN(t.getTime())?null:{dd:String(t.getDate()).padStart(2,`0`),MM:String(t.getMonth()+1).padStart(2,`0`),yyyy:t.getFullYear(),hh:String(t.getHours()).padStart(2,`0`),mm:String(t.getMinutes()).padStart(2,`0`),ss:String(t.getSeconds()).padStart(2,`0`)}},C=e=>{let t=S(e);return t?`${t.dd}/${t.MM}/${t.yyyy} ${t.hh}:${t.mm}:${t.ss}`:e?`Invalid Date`:``},w=e=>{let t=S(e);return t?`${t.dd}/${t.MM}/${t.yyyy}`:e?`Invalid Date`:``},T=e=>{let t=S(e);return t?`${t.yyyy}`:e?`Invalid Date`:``},E=e=>{let t=S(e);return t?`${t.yyyy}-${t.MM}-${t.dd}`:e?`Invalid Date`:``},D=e=>{let t=new URLSearchParams(window.location.search);return e?Array.isArray(e)?e.reduce((e,n)=>(e[n]=t.get(n),e),{}):t.get(e):Object.fromEntries(t.entries())},O=e=>{let t=new URLSearchParams(window.location.search);return Object.entries(e).forEach(([e,n])=>{n===null?t.delete(e):t.set(e,n)}),t.toString()},k=e=>{let t=new URLSearchParams;return Object.entries(e).forEach(([e,n])=>{Array.isArray(n)?n.forEach(n=>{n!=null&&t.append(e,String(n))}):n!=null&&t.set(e,String(n))}),t.toString()},A=(e=typeof window<`u`?window.location.pathname:``,t=/\/(?:edit|detail|update)\/(\d+)(?=\/|$)/i)=>{let n=new RegExp(t.source,t.flags.includes(`g`)?t.flags:t.flags+`g`),r=null,i;for(;(i=n.exec(e))!==null;)r=i;if(!r)return null;let a=Number(r[1]);return Number.isFinite(a)?a:null},j=(e,t=`/styles/default.jpg`)=>e?s(`STATIC_URL`)+(`/`+e).replaceAll(`//`,`/`):t,M=e=>e?s(`STATIC_URL`)+(`/`+e).replaceAll(`//`,`/`):``,N=(e,t=`/styles/default.jpg`)=>e?s(`API_URL`)+(`/`+e).replaceAll(`//`,`/`):t,P=(e,t=`/styles/default.jpg`)=>e?s(`UPLOADS_URL`)+`/`+e:t,F=(e,t=`/styles/default.jpg`)=>e?s(`UPLOADS_URL`)+`/`+e:t;function I(e){let t=``;for(let n=0;n<e;n++){let e=Math.floor(Math.random()*62);t+=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`[e]}return t}function L(e){return new DOMParser().parseFromString(e,`text/html`).body.textContent||``}var R=/\.(jpg|jpeg|png|jfif|doc|docx|xls|xlsx|pdf)$/i,z=(e,t)=>{if(!e)return t;let n=e.split(`,`).map(e=>{let t=e.trim();return(t.includes(`/`)?t.slice(t.indexOf(`/`)+1):t).replace(/^\./,``)}).filter(Boolean);if(n.length===0)return t;let r=n.map(e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`));return RegExp(`\\.(${r.join(`|`)})$`,`i`)},B=(e,t=20,n=R)=>new Promise((r,i)=>{let a=Array.from(e??[]);if(a.length===0)return i(Error(`Tập tin không tồn tại`));for(let e of a){if(!n.test(e.name))return h(`Tập tin không hợp lệ`),i(Error(`Tập tin không hợp lệ`));if(e.size>t*1024*1024)return h(`Tập tin tải lên không quá ${t}M`),i(Error(`Tập tin tải lên không quá ${t}M`))}r()}),le={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`},V=e=>String(e??``).replace(/[&<>"']/g,e=>le[e]),H=new Set([`danger`,`success`,`warning`,`info`,`primary`,`secondary`,`light`,`dark`]),U=(e=``,t=`danger`,n={})=>{let r=H.has(t)?t:`danger`,i=e=>n.raw?e:V(e);return typeof e==`string`?e.trim()===``?``:`<div class="alert alert-${r}">${i(e)}</div>`:!e||typeof e!=`object`?``:Object.values(e).filter(e=>e!=null&&String(e).trim()!==``).map(e=>`<div class="alert alert-${r}">${i(String(e))}</div>`).join(``)},W=e=>(e.querySelectorAll(`input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not(.noReset), textarea`).forEach(e=>{e.value=``,e.dispatchEvent(new Event(`change`,{bubbles:!0}))}),e.querySelectorAll(`select:not(.noReset)`).forEach(e=>{let t=e.querySelector(`option[value=""]`);t?t.selected=!0:e.options.length>0&&(e.selectedIndex=0),e.dispatchEvent(new Event(`change`,{bubbles:!0}))}),e.querySelectorAll(`input[type="checkbox"]:not(.noReset)`).forEach(e=>{e.checked=!1,e.dispatchEvent(new Event(`change`,{bubbles:!0}))}),e.querySelectorAll(`input[type="radio"]:not(.noReset)`).forEach(e=>{e.checked=!1,e.dispatchEvent(new Event(`change`,{bubbles:!0}))}),e),ue=async(e,t,n=!1)=>{try{for(let r in t){let i=`[name="${r}"]:not([type="file"])`,o=e.querySelector(i);if(!o)continue;let s=o.type,c=t[r];if(c&&![`checkbox`,`radio`].includes(s)){let e=String(c),t=(0,a.parse)(e,`yyyy-MM-dd`,new Date),n=(0,a.parse)(e,`yyyy-MM-dd HH:mm:ss`,new Date);o.value=(0,a.isValid)(t)&&e.length===10?(0,a.format)(t,`dd/MM/yyyy`):(0,a.isValid)(n)&&e.length===19?(0,a.format)(n,`dd/MM/yyyy HH:mm`):e,o.dispatchEvent(new Event(`change`,{bubbles:!0}))}else if(s===`checkbox`)o.checked=!!parseInt(String(c)),o.dispatchEvent(new Event(`change`,{bubbles:!0}));else if(s===`radio`){let t=e.querySelectorAll(`input[type="radio"][name="${r}"]`);t.forEach(e=>{e.checked=e.value===String(parseInt(String(c)))}),t.forEach(e=>e.dispatchEvent(new Event(`change`,{bubbles:!0})))}else if(n){let e=o.closest(`.form-group`);e&&e.classList.add(`hidden`)}}return t}catch(e){return Promise.reject(e)}},G=(e,t={})=>new Promise((n,r)=>{try{let r=window.jQuery,i=r(e);if(!i.length)throw Error(`invalid_elfinder`);let a={url:s(`API_URL`)+`/elfinder/connector`,height:500,resizable:!0,baseUrl:`/assets/plugins/elFinder/`,defaultView:`list`,useBrowserHistory:!1,getFileCallback:e=>{n(e)}};i.elfinder(`destroy`).elfinder({...a,...t})}catch(e){r(e)}}),de=e=>{if(e instanceof Error)return e.message;if(typeof e==`string`)return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}},K=e=>new Promise((t,n)=>{try{let n=typeof e==`string`?document.querySelector(e):e;if(!n)throw Error(`invalid_modalEl_btnEl`);n.querySelectorAll(`.btn-md-close`)?.forEach(e=>{e?.addEventListener(`click`,()=>{r.hide()})});let r=i.Modal.getOrCreateInstance(n,{backdrop:`static`,keyboard:!1});t({md:r,modalEl:n})}catch(e){console.log(e),n(e)}}),fe=(e,t,n=!1,r=!1)=>{if(!e)throw Error(`invalid_btnEl`);e.addEventListener(`click`,i=>{i.preventDefault(),K(t).then(({modalEl:t,md:i})=>{G(`#elfinderStatic`).then(t=>{n&&n({data:t,btnEl:e,md:i})}),t.addEventListener(`hidden.bs.modal`,()=>{r&&r()}),i.show()})})},pe=(e,t,n=!1,r=!1)=>{if(!e)throw Error(`invalid_btnEl`);e.addEventListener(`click`,i=>{i.preventDefault(),K(t).then(({modalEl:t,md:i})=>{G(`#elfinderStatic`,{url:s(`API_URL`)+`/elfinder/connectorFiles`}).then(t=>{n&&n({data:t,btnEl:e,md:i})}),t.addEventListener(`hidden.bs.modal`,()=>{r&&r()}),i.show()})})},q=e=>{if(typeof e==`string`&&(e=J(e,[])),!Array.isArray(e))return[];let t=e.map(e=>Number(e)).filter(e=>!Number.isNaN(e));return[...new Set(t)]};function J(e,t={},n=`ids`){let r=t;if(Array.isArray(e)&&(r=e),typeof e==`object`&&e&&(r=e),typeof e==`number`)return t;if(typeof e==`string`)try{let t=JSON.parse(e);Array.isArray(t)&&(r=t),typeof t==`object`&&t&&(r=t)}catch{return t}return n===`ids`&&(r=q(r)),r}var me=(e,t={},n=`vi-VN`)=>e==null||Number.isNaN(e)?`0`:e.toLocaleString(n,t),he=e=>{if(!e)return new o.default(0);let t=String(e).replace(/[^\d.]/g,``);return t?new o.default(t):new o.default(0)},ge=(e,t)=>[...new Set((Array.isArray(e)?e:[]).map(e=>e[t]))],_e=(e,t,n,r,i)=>{let a=e.length,o=[];for(let s=0;s<a;s++){let a=t.find(t=>t[r]===e[s]);a&&o.push({[n]:e[s],[i]:a[i]})}return o},Y=(e,t)=>(Array.isArray(e)?e:[]).map(e=>{let n={};for(let r in t){let i=t[r];typeof i==`string`?n[r]=e[i]:typeof i==`function`&&(n[r]=i(e))}return n}),ve=(e,t,n=!1)=>{if((t??``).split(`-`).map(Number).includes(e))return!0;if(n)throw Error(`invalid_status`);return!1};function ye(e,t){return e?.reduce((e,n)=>e+(n[t]??0),0)||0}var be=e=>{switch(e){case 3:return`tháng `+(new Date().getMonth()+1);case 4:return`năm `+new Date().getFullYear()}return``},xe=(e=!1)=>{let t=[{id:1,name:`Tiếng Việt`}];return e===!1?t:t.find(t=>t.id===e)?.name||``},Se=class{routes=[];async addGS(e,t,n,r=!1,i=!1,a=!1,o=!1){let s={path:e,element:t,children:[{index:!0,element:n},{path:`page/:page`,element:n}]};i&&s.children.push({path:`detail/:id`,element:i}),r&&s.children.push({path:`create`,element:r}),r&&s.children.push({path:`edit/:id`,element:r}),a&&s.children.push({path:`import`,element:a}),o&&s.children.push({path:`fields`,element:o}),this.routes.push(s)}addRoute(e=[]){this.routes=[...this.routes,...e]}getRouter(){return this.routes}},X=(e,t,n,r,i,a)=>{if(!a)return!1;if(a===1)return!0;if(!Array.isArray(e))return!1;for(let o of e)if(o){if(o.module===t&&o.controller===n&&o.action===r&&Number(o.code)===Number(i))return o.status!==0&&!!o.isPer;if(Array.isArray(o.subs)&&o.subs.length>0&&X(o.subs,t,n,r,i,a))return!0}return!1},Z=null,Q=()=>{if(Z)return Z;let e=typeof window<`u`?window.jQuery??window.$:void 0;if(typeof e!=`function`)throw Error(`[@materialui-reactjs/admin] Validator cần jQuery. Hãy thêm "jquery" vào dependencies và nạp nó TRƯỚC khi dùng Validator.`);return Z=e,Z},$=new Proxy((()=>{}),{apply:(e,t,n)=>Q()(...n),get:(e,t)=>Q()[t]}),Ce=class e{options;validators;$element;$btn;$inputs;static VERSION=`0.11.9`;static INPUT_SELECTOR=`:input:not(.nvali,[type="hidden"], [type="submit"], [type="reset"], button)`;static FOCUS_OFFSET=20;static DEFAULTS={delay:500,html:!1,disable:!0,focus:!0,custom:{},errors:{match:`Does not match`,minlength:`Too short`,maxlength:`Too long`},feedback:{success:`glyphicon-ok`,error:`glyphicon-remove`}};static VALIDATORS={native:function(e){let t=e[0];if(t.checkValidity)return!t.checkValidity()&&!t.validity.valid&&(t.validationMessage||`error!`)},match:function(t){let n=t.attr(`data-match`);return n&&t.val()!==$(n).val()&&e.DEFAULTS.errors.match},minlength:function(t){let n=Number(t.attr(`data-minlength`));return String(t.val()??``).length<n&&e.DEFAULTS.errors.minlength},maxlength:function(t){let n=Number(t.attr(`data-maxlength`));return String(t.val()??``).length>n&&e.DEFAULTS.errors.maxlength},filesize:function(e){let t=Number(e.data(`filesize`)),n=e[0];return n?.files?.length?n.files[0].size>t*1024*1024:!1},accept:function(e){let t=e.attr(`data-accept`);if(!t)return!1;let n=e[0];if(!n?.files?.length)return!1;let r=n.files[0];return!new RegExp(t).test(r.name)},pattern:function(e){let t=e.attr(`data-pattern`);return t?!new RegExp(t).test(String(e.val()??``)):!1}};constructor(t,n=!1){this.options=n||e.DEFAULTS,this.validators=$.extend({},e.VALIDATORS),this.$element=$(t),this.$btn=this.$element.find(`button[type="submit"], input[type="submit"], .submitAjax`),this.$inputs=this.$element.find(e.INPUT_SELECTOR).add(this.$element.find(`[data-validate="true"]`)).not(this.$element.find(`[data-validate="false"]`).each((e,t)=>{this.clearErrors($(t))}))}static getValue(e){return e.is(`[type="checkbox"]`)?!!e.prop(`checked`):e.is(`[type="radio"]`)?$(`[name="${e.attr(`name`)}"]:checked`).length>0:e.is(`select[multiple]`)?(e.val()??[]).length:e.val()??``}update=()=>{let t=this;return this.$inputs=this.$element.find(e.INPUT_SELECTOR).add(this.$element.find(`[data-validate="true"]`)).not(this.$element.find(`[data-validate="false"]`).each((e,n)=>{t.clearErrors($(n))})),this.toggleSubmit(),this};onInput=e=>{let t=this,n=$(e.target),r=e.type!==`focusout`;this.$inputs.is(n)&&this.validateInput(n,r)?.done(function(){t.toggleSubmit()})};validateInput=(e,t)=>{let n=e.data(`bs.validator.errors`);e.is(`[type="radio"]`)&&(e=this.$element.find(`input[name="`+e.attr(`name`)+`"]`));let r=$.Event(`validate.bs.validator`,{relatedTarget:e[0]});if(this.$element.trigger(r),r.isDefaultPrevented())return;let i=this;return this.runValidators(e).done(function(a){e.data(`bs.validator.errors`,a),a.length?t?i.defer(e,i.showErrors):i.showErrors(e):i.clearErrors(e),(!n||a.toString()!==n.toString())&&(r=a.length?$.Event(`invalid.bs.validator`,{relatedTarget:e[0],detail:a}):$.Event(`valid.bs.validator`,{relatedTarget:e[0],detail:n}),i.$element.trigger(r)),i.toggleSubmit(),i.$element.trigger($.Event(`validated.bs.validator`,{relatedTarget:e[0]}))})};runValidators=t=>{let n=[],r=$.Deferred(),i=t.data(`bs.validator.deferred`);i&&i.reject(),t.data(`bs.validator.deferred`,r);function a(e){return t.attr(`data-`+e+`-error`)}function o(){let e=t[0];if(!(e instanceof HTMLInputElement)&&!(e instanceof HTMLSelectElement)&&!(e instanceof HTMLTextAreaElement))return null;let n=e.validity;return n.typeMismatch?t.attr(`data-type-error`)??null:n.patternMismatch?t.attr(`data-pattern-error`)??null:n.stepMismatch?t.attr(`data-step-error`)??null:n.rangeOverflow?t.attr(`data-max-error`)??null:n.rangeUnderflow?t.attr(`data-min-error`)??null:n.valueMissing?t.attr(`data-required-error`)??null:null}function s(){return t.attr(`data-error`)}function c(e){return a(e)||o()||s()}return $.each(this.validators,$.proxy(function(r,i){let a;(e.getValue(t)||t.attr(`required`))&&(t.attr(`data-`+r)!==void 0||r==`native`)&&(a=i.call(this,t))&&(a=c(r)||a,n.indexOf(a)===-1&&n.push(a))},this)),r.resolve(n),r.promise()};validate=()=>{let e=this;return $.when(this.$inputs.map((t,n)=>e.validateInput($(n),!1))).then(function(){e.toggleSubmit(),e.focusError()}),this};focusError=()=>{if(!this.options.focus)return;let t=this.$element.find(`.has-error:first :input`);t.length!==0&&($(`html, body`).animate({scrollTop:t.offset().top-e.FOCUS_OFFSET},250),t.focus())};showErrors=e=>{this.options.html;let t=e.data(`bs.validator.errors`),n=e.closest(`.form-group`),r=n.find(`.form-control-feedback`);t.length&&(t=$(`<ul/>`).addClass(`list-unstyled`).append($.map(t,e=>{let t=$(`<li/>`);return this.options.html?t.html(e):t.text(e)})),n.addClass(`has-error has-danger`),n.find(`.invalid-tooltip, .invalid-feedback`).remove(),n.find(`.select2,.form-control`).removeClass(`is-valid`).addClass(`is-invalid`),n.append(`<div class="invalid-feedback"><ul class="list-unstyled">${t.html()}<ul/></div>`),n.removeClass(`has-success`),n.hasClass(`has-feedback`),r.removeClass(this.options.feedback?.success),r.addClass(this.options.feedback?.error))};clearErrors=e=>{let t=e.closest(`.form-group`),n=t.find(`.form-control-feedback`);t.removeClass(`has-error has-danger has-success`),t.find(`.invalid-tooltip, .invalid-feedback`).remove(),t.find(`.select2,.form-control`).addClass(`is-valid`).removeClass(`is-invalid`),t.addClass(`has-success`),t.hasClass(`has-feedback`),n.removeClass(this.options.feedback?.error),n.removeClass(this.options.feedback?.success),n.addClass(this.options.feedback?.success)};hasErrors=()=>!!this.$inputs.filter(function(){return!!($(this).data(`bs.validator.errors`)||[]).length}).length;isIncomplete=()=>!!this.$inputs.filter(`[required]`).filter((t,n)=>{let r=e.getValue($(n));return!(typeof r==`string`?r.trim():r)}).length;onSubmit=e=>{this.validate(),(this.isIncomplete()||this.hasErrors())&&e.preventDefault()};toggleSubmit=()=>{this.options.disable};defer=(e,t)=>{if(t=t.bind(this,e),!this.options.delay)return t();window.clearTimeout(e.data(`bs.validator.timeout`)),e.data(`bs.validator.timeout`,window.setTimeout(t,this.options.delay))};reset=()=>(this.$element.find(`.form-control-feedback`).removeClass(this.options?.feedback.error).removeClass(this.options.feedback.success),this.$inputs.removeData([`bs.validator.errors`,`bs.validator.deferred`]).each(()=>{let e=$(this),t=e.data(`bs.validator.timeout`);window.clearTimeout(t),e.removeData(`bs.validator.timeout`)}),this.$element.find(`.invalid-tooltip, .invalid-feedback`).each(()=>{let e=$(this),t=e.data(`bs.validator.originalContent`);e.removeData(`bs.validator.originalContent`).html(t)}),this.$btn.removeClass(`disabled`),this.$element.find(`.has-error, .has-danger, .has-success, .is-invalid, .is-valid`).removeClass(`has-error has-danger has-success is-invalid is-valid`),this);destroy=()=>(this.reset(),this.$element.removeAttr(`novalidate`).removeData(`bs.validator`).off(`.bs.validator`),this.$inputs.off(`.bs.validator`),this.options=null,this.validators=null,this.$element=null,this.$btn=null,this.$inputs=null,this);run=()=>{this.update(),this.$element.on(`input.bs.validator change.bs.validator focusout.bs.validator`,this.onInput.bind(this)),this.$element.on(`submit.bs.validator`,this.onSubmit.bind(this)),this.$element.on(`reset.bs.validator`,this.reset.bind(this)),this.$element.find(`[data-match]`).each(function(){let t=$(this),n=t.attr(`data-match`);n&&$(n).on(`input.bs.validator`,function(){e.getValue(t)&&t.trigger(`input.bs.validator`)})}),this.$inputs.filter((t,n)=>e.getValue($(n))&&!$(this).closest(`.has-error`).length).trigger(`focusout`),this.$element.attr(`novalidate`,!0)}};exports.ApiError=d,exports.CusRoute=Se,exports.Validator=Ce,exports.buildAcceptRegExp=z,exports.buildFormData=u,exports.callFetchApi=te,exports.callFetchApiToken=f,exports.checkPermission=X,exports.checkUploadFile=B,exports.createModal=K,exports.createQueryString=k,exports.decimalNumber=he,exports.elFinderPopup=G,exports.errorMessage=de,exports.escapeHtml=V,exports.filterIds=q,exports.formatDate=w,exports.formatDateSql=E,exports.formatDateTime=C,exports.formatNumber=me,exports.formatYear=T,exports.getActiveStatus=_,exports.getEnv=t.t,exports.getFile=M,exports.getFilterType=be,exports.getIdParams=A,exports.getImage=j,exports.getLangs=xe,exports.getLinkFiles=ae,exports.getName=re,exports.getNames=ie,exports.getParams=D,exports.getPubImage=N,exports.getPublishStatus=v,exports.getStatus=g,exports.getTrueFlaseStatus=y,exports.getUploadFile=F,exports.getUploadImage=P,exports.htmlToText=L,exports.isStsNum=ve,exports.loadEnv=t.n,exports.loadScript=c,exports.loadScripts=l,exports.mapArrData=Y,exports.mapArrFields=ge,exports.mapDataForm=ue,exports.mergeArrObject=_e,exports.parseDate=b,exports.randomString=I,exports.reloadEnv=t.r,exports.resetForm=W,exports.setParams=O,exports.showFinderFileModal=pe,exports.showFinderModal=fe,exports.showMessage=U,exports.showSweetAlert=p,exports.showSweetAlertError=h,exports.showSweetAlertOk=m,exports.showSweetAlertWarning=ne,exports.spinnerLoader=ee,exports.strToDate=x,exports.stringToJson=J,exports.sumArrCol=ye;