@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.
- package/CHANGELOG.md +322 -0
- package/LICENSE +21 -0
- package/README.md +587 -453
- package/dist/Common-DFahMuQE.cjs +11 -0
- package/dist/Common-_PK8HLKN.js +267 -0
- package/dist/Env-DoS-iQjs.cjs +1 -0
- package/dist/Env-SHztUA3s.js +16 -0
- package/dist/HeaderUpdate-Dirxjmxs.cjs +1 -0
- package/dist/{chunks/HeaderUpdate-DuS-gHNR.js → HeaderUpdate-drlnuHI8.js} +28 -25
- package/dist/SortableItem-C3KzO8Xh.cjs +1 -0
- package/dist/SpinnerLoader-BujLjvC3.cjs +1 -0
- package/dist/{chunks/SpinnerLoader-h8RDIarB.js → SpinnerLoader-CyhOQC6d.js} +2 -2
- package/dist/UDragFile-D8wOZ1Ut.js +96 -0
- package/dist/UDragFile-Db0sK4M7.cjs +1 -0
- package/dist/{chunks/Validator-CXYkI7vJ.js → Validator-D2zwZeov.js} +83 -52
- package/dist/Validator-DBxl8wtE.cjs +1 -0
- package/dist/assets/css/form.css +1 -1
- package/dist/assets/css/index.css +1 -1
- package/dist/ckeditor/ckeditor.d.ts +3 -0
- package/dist/ckeditor/plugins/elfinder.d.ts +11 -0
- package/dist/ckeditor/plugins/fullscreen.d.ts +15 -0
- package/dist/ckeditor/plugins/pdffinder.d.ts +18 -0
- package/dist/ckeditor/types.d.ts +37 -0
- package/dist/common-CEZp8xpQ.js +30 -0
- package/dist/common-ivDX6gGq.cjs +1 -0
- package/dist/components/echarts/index.cjs +1 -0
- package/dist/components/echarts/index.js +1 -1
- package/dist/components/form/AdvancedMultiSelect.d.ts +6 -3
- package/dist/components/form/AsxhUImages.d.ts +2 -1
- package/dist/components/form/BoxAddRow.d.ts +13 -2
- package/dist/components/form/CheckTreeBox.d.ts +12 -3
- package/dist/components/form/CusForm.d.ts +19 -6
- package/dist/components/form/DateInput.d.ts +2 -1
- package/dist/components/form/Editor.d.ts +2 -1
- package/dist/components/form/EfFile.d.ts +2 -1
- package/dist/components/form/EfImage.d.ts +2 -1
- package/dist/components/form/EfImages.d.ts +2 -1
- package/dist/components/form/PImage.d.ts +2 -1
- package/dist/components/form/SelectAddRowBox.d.ts +9 -5
- package/dist/components/form/SelectAddRowBoxAdvanced.d.ts +13 -4
- package/dist/components/form/SelectBox.d.ts +20 -7
- package/dist/components/form/UDragFile.d.ts +2 -1
- package/dist/components/form/UFile.d.ts +2 -1
- package/dist/components/form/UFiles.d.ts +9 -2
- package/dist/components/form/UImages.d.ts +2 -1
- package/dist/components/form/index.cjs +1 -0
- package/dist/components/form/index.js +2 -2
- package/dist/components/loader/SpinnerLoader.d.ts +5 -1
- package/dist/components/loader/index.cjs +1 -0
- package/dist/components/loader/index.js +1 -2
- package/dist/components/meta/CardTable.d.ts +11 -5
- package/dist/components/meta/CardTable.types.d.ts +57 -0
- package/dist/components/meta/CusTooltip.d.ts +8 -2
- package/dist/components/meta/Head.d.ts +10 -1
- package/dist/components/meta/HeaderDetail.d.ts +2 -1
- package/dist/components/meta/HeaderUpdate.d.ts +5 -1
- package/dist/components/meta/ModalForm.d.ts +41 -11
- package/dist/components/meta/Navtabs.d.ts +1 -1
- package/dist/components/meta/ScrollTable.d.ts +7 -3
- package/dist/components/meta/SearchBox.d.ts +8 -5
- package/dist/components/meta/SortableItem.d.ts +11 -1
- package/dist/components/meta/index.cjs +1 -0
- package/dist/components/meta/index.d.ts +1 -0
- package/dist/components/meta/index.js +3 -3
- package/dist/components/sidebar/Sidebar.types.d.ts +9 -7
- package/dist/components/sidebar/index.cjs +1 -0
- package/dist/components/sidebar/index.js +1 -1
- package/dist/components/single/Detail.d.ts +8 -3
- package/dist/components/single/Fields.d.ts +10 -4
- package/dist/components/single/Import.d.ts +8 -3
- package/dist/components/single/List.d.ts +33 -7
- package/dist/components/single/Update.d.ts +10 -4
- package/dist/components/single/UpdateDetail.d.ts +3 -2
- package/dist/components/single/UpdateTableDetail.d.ts +4 -3
- package/dist/components/single/index.cjs +1 -0
- package/dist/components/single/index.js +1 -1
- package/dist/components/top-navbar/index.cjs +1 -0
- package/dist/components/top-navbar/index.js +78 -2
- package/dist/echarts-Bi3uwLbg.cjs +1 -0
- package/dist/{chunks/echarts-CRmndsxC.js → echarts-CTzMqeR5.js} +4 -4
- package/dist/form-heyswTRq.js +3897 -0
- package/dist/form-sgtop6li.cjs +49 -0
- package/dist/hook/common.d.ts +87 -0
- package/dist/hook/detail.cjs +1 -0
- package/dist/hook/detail.d.ts +9 -15
- package/dist/hook/detail.js +1 -11
- package/dist/hook/fields.cjs +1 -0
- package/dist/hook/fields.d.ts +6 -14
- package/dist/hook/fields.js +1 -11
- package/dist/hook/import.d.ts +6 -11
- package/dist/hook/index.cjs +1 -0
- package/dist/hook/index.d.ts +29 -20
- package/dist/hook/index.js +14 -11
- package/dist/hook/update.cjs +1 -0
- package/dist/hook/update.d.ts +11 -19
- package/dist/hook/update.js +12 -9
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +14 -11
- package/dist/meta-BANk9kHW.cjs +1 -0
- package/dist/meta-CheDAmMh.js +745 -0
- package/dist/rolldown-runtime-BocRIvOZ.cjs +1 -0
- package/dist/sidebar-CfQAYWi-.cjs +1 -0
- package/dist/{chunks/sidebar-Dj4Xr9du.js → sidebar-CzRmfvhi.js} +10 -13
- package/dist/{chunks/single-CRF61o_U.js → single-BsJ7TYJi.js} +364 -282
- package/dist/single-C2WPEjhk.cjs +1 -0
- package/dist/style.cjs +0 -0
- package/dist/style.d.ts +0 -0
- package/dist/style.js +0 -0
- package/dist/types/Menu.d.ts +25 -0
- package/dist/utils/Common.d.ts +224 -43
- package/dist/utils/CusRoute.d.ts +21 -1
- package/dist/utils/Env.d.ts +23 -2
- package/dist/utils/Group.d.ts +12 -1
- package/dist/utils/Validator.d.ts +34 -12
- package/dist/utils/index.cjs +11 -0
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +212 -171
- package/package.json +190 -163
- package/dist/chunks/Common-BURf0rBN.js +0 -222
- package/dist/chunks/Env-DRXhvUcb.js +0 -16
- package/dist/chunks/UDragFile-BnUR3riq.js +0 -92
- package/dist/chunks/form-CPkpL5eA.js +0 -45889
- package/dist/chunks/loader-BUiOnhOH.js +0 -1
- package/dist/chunks/meta-4qPWijBT.js +0 -758
- package/dist/chunks/top-navbar-Bob0gMUh.js +0 -78
- package/scripts/postinstall.cjs +0 -80
- /package/dist/{chunks/SortableItem-B4-Zsso3.js → SortableItem-B4-Zsso3.js} +0 -0
- /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
|
package/dist/style.d.ts
ADDED
|
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
|
+
}
|
package/dist/utils/Common.d.ts
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
11
|
-
|
|
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?:
|
|
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
|
-
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
export
|
|
21
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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,
|
|
31
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
45
|
-
export declare const elFinderPopup: (el: string, options?: Record<string,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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?:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
package/dist/utils/CusRoute.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
}
|
package/dist/utils/Env.d.ts
CHANGED
|
@@ -1,2 +1,23 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
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>;
|
package/dist/utils/Group.d.ts
CHANGED
|
@@ -1 +1,12 @@
|
|
|
1
|
-
|
|
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:
|
|
29
|
-
minlength: ($el:
|
|
30
|
-
maxlength: ($el:
|
|
31
|
-
filesize: ($el:
|
|
32
|
-
accept: ($el:
|
|
33
|
-
pattern: ($el:
|
|
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:
|
|
57
|
+
static getValue($el: Jq): boolean | number | string | string[];
|
|
37
58
|
update: () => this;
|
|
38
59
|
onInput: (e: any) => void;
|
|
39
|
-
validateInput: ($el:
|
|
40
|
-
runValidators: ($el:
|
|
60
|
+
validateInput: ($el: Jq, deferErrors: any) => any;
|
|
61
|
+
runValidators: ($el: Jq) => any;
|
|
41
62
|
validate: () => this;
|
|
42
63
|
focusError: () => void;
|
|
43
|
-
showErrors: ($el:
|
|
44
|
-
clearErrors: ($el:
|
|
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:
|
|
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={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},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;
|