diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dea37aa..575b0237 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,9 @@ - Fixed JS error on `file` settings `maxSelect` change ([#7731](https://github.com/pocketbase/pocketbase/issues/7731)). -- Other minor fixes (fixed `number` settings validator to not ignore 0 `max` values, normalized field settings tooltip format, etc.). +- Fixed `number` settings validator to not ignore 0 `max` values. + +- Normalized field settings validation error messages and tooltips. ## v0.39.2 diff --git a/ui/dist/assets/index-B_EjR-cI.js b/ui/dist/assets/index-O9odt_Ys.js similarity index 92% rename from ui/dist/assets/index-B_EjR-cI.js rename to ui/dist/assets/index-O9odt_Ys.js index f4221d23..f24719bb 100644 --- a/ui/dist/assets/index-B_EjR-cI.js +++ b/ui/dist/assets/index-O9odt_Ys.js @@ -50,13 +50,13 @@ This field is disabled if "Only domains" is set.`)})),t.input({type:`text`,id:n+ This field is disabled if "Except domains" is set.`)})),t.input({type:`text`,id:n+`.onlyDomains`,disabled:()=>!app.utils.isEmpty(e.field.exceptDomains),name:()=>`fields.${e.fieldIndex}.onlyDomains`,value:()=>app.utils.joinNonEmpty(e.field.onlyDomains),onchange:n=>e.field.onlyDomains=app.utils.splitNonEmpty(n.target.value,`,`)})),t.div({className:`field-help`},`Use comma as separator.`)),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value to be nonempty string.`)})))]})}function $(e){return t.div({className:`record-field-view field-type-email`},()=>{let n=e.record[e.field.name]||``;return n?e.short?t.span({className:`txt txt-ellipsis`,textContent:app.utils.truncate(n)}):n:t.span({className:`missing-value`})})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.email={icon:`ri-mail-line`,label:`Email`,settings:Fn,input:Pn,view:$,filterModifiers:e=>[`lower`],dummyData:(e,n=!1)=>`test_${app.utils.randomString(3,`123567890`)}@example.com`};function In(e){let n=`url_`+app.utils.randomString();return t.div({className:`record-field-input field-type-url`},t.div({className:`field`},t.label({htmlFor:n},t.i({className:app.fieldTypes.url.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name)),t.input({type:`url`,id:n,spellcheck:!1,name:()=>e.field.name,required:()=>e.field.required,value:()=>e.record[e.field.name]||``,oninput:n=>e.record[e.field.name]=n.target.value})),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function Ln(e){let n=`f_`+app.utils.randomString();return app.components.fieldSettings(e,{content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.exceptDomains`},t.span({className:`txt`},`Except domains`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`List of domains that are NOT allowed. This field is disabled if "Only domains" is set.`)})),t.input({type:`text`,id:n+`.exceptDomains`,disabled:()=>!app.utils.isEmpty(e.field.onlyDomains),name:()=>`fields.${e.fieldIndex}.exceptDomains`,value:()=>app.utils.joinNonEmpty(e.field.exceptDomains),onchange:n=>e.field.exceptDomains=app.utils.splitNonEmpty(n.target.value,`,`)})),t.div({className:`field-help`},`Use comma as separator.`)),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.onlyDomains`},t.span({className:`txt`},`Only domains`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`List of domains that are ONLY allowed. This field is disabled if "Except domains" is set.`)})),t.input({type:`text`,id:n+`.onlyDomains`,disabled:()=>!app.utils.isEmpty(e.field.exceptDomains),name:()=>`fields.${e.fieldIndex}.onlyDomains`,value:()=>app.utils.joinNonEmpty(e.field.onlyDomains),onchange:n=>e.field.onlyDomains=app.utils.splitNonEmpty(n.target.value,`,`)})),t.div({className:`field-help`},`Use comma as separator.`)),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value to be nonempty string.`)})))]})}function Rn(e){return t.div({className:`record-field-view field-type-url`},()=>{let n=e.record[e.field.name]||``;return n?t.a({href:()=>n,className:`txt txt-ellipsis`,rel:`noopener noreferrer`,target:`_blank`,textContent:app.utils.truncate(n),ariaDescription:app.attrs.tooltip(`Open in new tab`),onclick:e=>{e.stopPropagation()}}):t.span({className:`missing-value`})})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.url={icon:`ri-link`,label:`URL`,settings:Ln,input:In,view:Rn,dummyData:(e,n=!1)=>`https://example.com`};var zn=Intl.DateTimeFormat().resolvedOptions().timeZone;function Bn(e){let n=`date_`+app.utils.randomString();return t.div({className:`record-field-input field-type-date`},t.div({className:`field`},t.label({htmlFor:n},t.i({className:app.fieldTypes.date.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name,` (`,zn,`)`)),t.input({id:n,step:1,type:`datetime-local`,name:()=>e.field.name,required:()=>e.field.required,value:()=>app.utils.toDatetimeLocalInputValue(e.record[e.field.name]),onchange:n=>{n.target.value&&(e.record[e.field.name]=app.utils.toRFC3339Datetime(n.target.value))},onblur:n=>{e.record[e.field.name]=null,e.record[e.field.name]=app.utils.toRFC3339Datetime(n.target.value)}})),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function Vn(e){let n=`f_`+app.utils.randomString();return app.components.fieldSettings(e,{content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.min`},t.span({className:`txt`},`Min date (Local)`)),t.input({type:`datetime-local`,id:n+`.min`,step:1,name:()=>`fields.${e.fieldIndex}.min`,value:()=>app.utils.toDatetimeLocalInputValue(e.field.min),onchange:n=>{e.field.min=app.utils.toRFC3339Datetime(n.target.value)}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.max`},t.span({className:`txt`},`Max date (Local)`)),t.input({type:`datetime-local`,id:n+`.max`,step:1,name:()=>`fields.${e.fieldIndex}.max`,value:()=>app.utils.toDatetimeLocalInputValue(e.field.max),onchange:n=>{e.field.max=app.utils.toRFC3339Datetime(n.target.value)}}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value to be nonempty string.`)})))]})}function Hn(e){return t.div({className:`record-field-view field-type-date`},app.components.formattedDate({value:()=>e.record[e.field.name],short:()=>e.short}))}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.date={icon:`ri-calendar-line`,label:`Datetime`,settings:Vn,input:Bn,view:Hn,dummyData:(e,n=!1)=>new Date().toISOString().replaceAll(`T`,` `)};function Un(e){delete e.clone[e.field.name]}function Wn(e){let n=[{label:`Create`,value:1},{label:`Update`,value:2},{label:`Create/Update`,value:3}];function r(e){return e.onCreate&&e.onUpdate?3:e.onUpdate?2:1}function i(n){switch(n){case 1:e.field.onCreate=!0,e.field.onUpdate=!1;break;case 2:e.field.onCreate=!1,e.field.onUpdate=!0;break;case 3:e.field.onCreate=!0,e.field.onUpdate=!0;break}}let a=store({isDropdownOpen:!1});return app.components.fieldSettings(e,{header:t.div({className:`field header-select autodate-select`,ariaDescription:app.attrs.tooltip(`Auto set on`,`left`),onmount:()=>{i(r(e.field))}},app.components.select({required:!0,options:n,disabled:()=>e.originalCollection?.system,value:()=>r(e.field),onchange:e=>i(e?.[0]?.value),ondropdowntoggle:e=>{a.isDropdownOpen=e.newState==`open`}}))})}function Gn(e){return t.div({className:`record-field-view field-type-autodate`},app.components.formattedDate({value:()=>e.record[e.field.name],short:()=>e.short}))}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.autodate={icon:`ri-calendar-check-line`,label:`Autodate`,settings:Wn,view:Gn,onrecordduplicate:Un,dummyData:(e,n=!1)=>{if(!n)return new Date().toISOString().replaceAll(`T`,` `)}};var Kn=`@@filesToDelete`;function qn(e){let n=app.utils.toArray(e.payload[e.field.name]),r=app.utils.toArray(e.record[Kn]?.[e.field.name]);for(let e of r){let r=n.indexOf(e);r>=0&&n.splice(r,1)}e.payload[e.field.name]=n}function Jn(e){let n=`file_`+app.utils.randomString();function r(n){return typeof n==`string`?!!e.record[Kn]?.[e.field.name]?.includes(n):!1}function i(n){if(typeof n==`string`){e.record[Kn]=e.record[`@@filesToDelete`]||{},e.record[Kn][e.field.name]=e.record[`@@filesToDelete`][e.field.name]||[],app.utils.pushUnique(e.record[Kn][e.field.name],n),c();return}let r=app.utils.toArray(e.record[e.field.name]),i=r.indexOf(n);i>=0&&(r.splice(i,1),e.record[e.field.name]=r,c())}function a(n){typeof n==`string`&&(app.utils.removeByValue(e.record[Kn]?.[e.field.name],n),c())}function o(){return e.record[`@@filesToDelete`]?.[e.field.name]?.length||0}function s(){return app.utils.toArray(e.record[e.field.name]).length-o()}function c(){f?.dispatchEvent(new CustomEvent(`change`,{detail:{data:e},bubbles:!0}))}let l=store({get maxReached(){let n=e.field.maxSelect||1;return s()>=n}});function u(n){let r=app.utils.toArray(e.record[e.field.name]);for(let e of n){if(l.maxReached){console.warn(`can't add more files - max allowed files reached`);break}r.push(e)}e.record[e.field.name]=r,c()}let d=t.input({type:`file`,hidden:!0,multiple:()=>e.field.maxSelect>1,accept:()=>e.field.mimeTypes?.join(`,`)||void 0,onchange:e=>{u(e.target.files),e.target.value=null}}),f=t.output({className:`field-content`,name:()=>e.field.name},app.components.sortable({className:`list`,data:()=>{let n=app.utils.toArray(e.record[e.field.name]),r=!1;for(let e=n.length-1;e>=0;e--)typeof n[e]==`string`||n[e]instanceof Blob||(r=!0,n.splice(e,1));return r&&(e.record[e.field.name]=n),n},onchange:n=>{e.record[e.field.name]=n,c()},dataItem:(n,o)=>t.div({rid:n,className:()=>`list-item highlight ${r(n)?`deleted`:``}`},t.div({className:`content gap-10`},()=>typeof n==`string`?[app.components.recordFileThumb({record:e.record,filename:n}),t.button({type:`button`,ariaDescription:app.attrs.tooltip(`Open in new tab`),onclick:async()=>{let r=await app.getFileToken(e.record.collectionId),i=app.pb.files.getURL(e.record,n,{token:r});window.open(i,`_blank`,`noreferrer,noopener`)}},t.span({className:`txt link-primary`},n))]:[app.components.uploadedFileThumb({file:n}),t.span({className:`label success`},`New`),t.span({className:`txt`},n.name)]),t.div({className:`actions`},t.button({type:`button`,className:`btn sm secondary transparent circle`,ariaLabel:app.attrs.tooltip(`Remove file`),hidden:()=>r(n),onclick:()=>i(n)},t.i({className:`ri-close-line`,ariaHidden:!0})),t.button({type:`button`,className:`btn sm warning transparent`,hidden:()=>!r(n),onclick:()=>a(n)},t.span({className:`txt`},`Restore`))))}),t.hr({className:`m-t-5 m-b-0`,hidden:()=>app.utils.toArray(e.record[e.field.name]).length>0}),t.button({type:`button`,className:`btn sm secondary block`,title:()=>l.maxReached?`Max allowed files reached`:void 0,disabled:()=>l.maxReached,onclick:e=>{l.maxReached||d?.click(),document.activeElement?.blur()}},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0}),t.span({className:`txt`},`Upload or drop new file`)));return t.div({className:`record-field-input field-type-file`,ondragover:e=>{e.preventDefault()},ondrop:e=>{let n=e.dataTransfer?.files||[];n.length&&(e.preventDefault(),!l.maxReached&&u(n))}},t.div({className:()=>`field-list ${e.field.required?`required`:``}`},t.label({htmlFor:n},t.i({className:app.fieldTypes.file.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name)),d,f),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function Yn(e){delete e.clone[e.field.name]}function Xn(e){let n=`f_`+app.utils.randomString();return app.components.fieldSettings(e,{header:[t.div({className:`field header-select single-multiple-select`},app.components.select({required:!0,options:[{label:`Single`,value:!1},{label:`Multiple`,value:!0}],value:()=>e.field.maxSelect>1,onchange:n=>{n?.[0]?.value?(!e.field.maxSelect||e.field.maxSelect<2)&&(e.field.maxSelect=10):e.field.maxSelect=1}}))],content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.mimeTypes`},t.span({className:`txt`},`Allowed mime types`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Allow files ONLY with the listed mime types. - Leave empty for no restriction.`)})),app.components.select({max:99,placeholder:`No restriction`,options:app.utils.mimeTypes.map(e=>({value:e.mimeType,label:()=>t.div({className:`inline-flex gap-10`},t.span({className:`txt`},e.ext||`-`),t.small({className:`txt-hint`},e.mimeType))})),name:()=>`fields.${e.fieldIndex}.mimeTypes`,value:()=>app.utils.toArray(e.field.mimeTypes),onchange:n=>e.field.mimeTypes=n.map(e=>e.value)})),t.div({className:`field-help`},t.button({type:`button`,className:`link-hint gap-0`,"html-popovertarget":n+`mimeTypesDropdown`},t.span({className:`txt`},`Choose presets`),t.i({className:`ri-arrow-drop-down-fill`,ariaHidden:!0})),t.div({id:n+`mimeTypesDropdown`,className:`dropdown sm nowrap left p-10`,popover:`auto`},t.button({type:`button`,className:`dropdown-item`,role:`menuitem`,onclick:n=>{e.field.mimeTypes=[`image/jpeg`,`image/png`,`image/svg+xml`,`image/gif`,`image/webp`],n.target.closest(`.dropdown`).hidePopover()},textContent:`Images (jpg, png, svg, gif, webp)`}),t.button({type:`button`,className:`dropdown-item`,role:`menuitem`,onclick:n=>{e.field.mimeTypes=[`application/pdf`,`application/msword`,`application/vnd.openxmlformats-officedocument.wordprocessingml.document`,`application/vnd.ms-excel`,`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`],n.target.closest(`.dropdown`).hidePopover()},textContent:`Documents (pdf, doc/docx, xls/xlsx)`}),t.button({type:`button`,className:`dropdown-item`,role:`menuitem`,onclick:n=>{e.field.mimeTypes=[`video/mp4`,`video/mpeg`,`video/x-msvideo`,`video/quicktime`,`video/3gpp`],n.target.closest(`.dropdown`).hidePopover()},textContent:`Videos (mp4, mpeg, avi, mov, 3gp)`}),t.button({type:`button`,className:`dropdown-item`,role:`menuitem`,onclick:n=>{e.field.mimeTypes=[`application/zip`,`application/x-7z-compressed`,`application/x-rar-compressed`],n.target.closest(`.dropdown`).hidePopover()},textContent:`Archives (zip, 7zip, rar)`})))),t.div({className:()=>e.field.maxSelect>1?`col-sm-6`:`col-sm-9`},t.div({className:`field`},t.label({htmlFor:n+`.thumbs`},t.span({className:`txt`},`Thumb sizes`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`List of additional thumb sizes for image files, along with the default thumb size of 100x100. The thumbs are generated lazily on first access.`)})),t.input({type:`text`,id:n+`.thumbs`,placeholder:`e.g. 50x50, 480x720`,name:()=>`fields.${e.fieldIndex}.thumbs`,value:()=>app.utils.joinNonEmpty(e.field.thumbs),onchange:n=>e.field.thumbs=app.utils.splitNonEmpty(n.target.value,`,`)})),t.div({className:`field-help`},t.span({className:`txt m-r-5`},`Use comma as separator.`),t.button({type:`button`,className:`link-hint gap-0`,"html-popovertarget":n+`thumbFormatsDropdown`},t.span({className:`txt`},`Supported formats`),t.i({className:`ri-arrow-drop-down-fill`,ariaHidden:!0})),t.div({id:n+`thumbFormatsDropdown`,className:`dropdown sm nowrap left p-10`,popover:`auto`},t.ul({className:`m-0 p-l-sm`},t.li(null,t.strong(null,`WxH`),t.span(null,` (e.g. 100x50) - crop to WxH viewbox (from center)`)),t.li(null,t.strong(null,`WxHt`),t.span(null,` (e.g. 100x50t) - crop to WxH viewbox (from top)`)),t.li(null,t.strong(null,`WxHb`),t.span(null,` (e.g. 100x50b) - crop to WxH viewbox (from bottom)`)),t.li(null,t.strong(null,`WxHf`),t.span(null,` (e.g. 100x50f) - fit inside a WxH viewbox (without cropping)`)),t.li(null,t.strong(null,`0xH`),t.span(null,` (e.g. 0x50) - resize to H height preserving the aspect ratio`)),t.li(null,t.strong(null,`Wx0`),t.span(null,` (e.g. 100x0) - resize to W width preserving the aspect ratio`)))))),t.div({className:`col-sm-3`},t.div({className:`field`},t.label({htmlFor:n+`.maxSize`},`Max size`),t.input({type:`number`,id:n+`.maxSize`,step:1,min:0,max:2**53-1,placeholder:`~5MB default`,name:()=>`fields.${e.fieldIndex}.maxSize`,value:()=>e.field.maxSize||``,oninput:n=>e.field.maxSize=parseInt(n.target.value,10)})),t.div({className:`field-help`},`In bytes.`)),()=>{if(e.field.maxSelect>1)return t.div({className:`col-sm-3`},t.div({className:`field`},t.label({htmlFor:n+`.maxSelect`},`Max select`),t.input({type:`number`,id:n+`.maxSelect`,placeholder:`Default to single`,step:1,min:2,required:!0,max:2**53-1,name:()=>`fields.${e.fieldIndex}.maxSelect`,value:()=>e.field.maxSelect||``,onchange:n=>{let r=parseInt(n.target.value,10);r>1?e.field.maxSelect=r:e.field.maxSelect=1}})))},t.div({className:`col-sm-12`},t.div({className:`field m-t-5 m-b-5`},t.input({className:`switch`,type:`checkbox`,id:n+`.protected`,name:()=>`fields.${e.fieldIndex}.protected`,checked:()=>!!e.field.protected,onchange:n=>e.field.protected=n.target.checked}),t.label({htmlFor:n+`.protected`},t.span({className:`txt`},`Protected`),t.small({className:`txt-hint`},`File download requests will need to satisfy the View API rule (`,t.a({href:`https://pocketbase.io/docs/files-handling#protected-files`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Learn more`}),`).`)))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},()=>e.field.maxSelect>1?`(!=[])`:`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(()=>`Requires the field value to be nonempty ${e.field.maxSelect>1?`array`:`string`}.`)})))]})}function Zn(e){return t.div({className:`record-field-view field-type-file`},()=>{let n=app.utils.toArray(e.record[e.field.name]);if(!n.length)return t.span({className:`missing-value`});let r=[],i=e.short?5:100;for(let a=0;a=i){r.push(t.span({className:`thumb sm`},`+`,n.length-i));break}r.push(app.components.recordFileThumb({record:e.record,filename:n[a]}))}return r})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.file={icon:`ri-image-line`,label:`File`,settings:Xn,input:Jn,view:Zn,summaryPriority:-1,onrecordsave:qn,onrecordduplicate:Yn,filterModifiers:e=>e.maxSelect>1?[`each`,`length`]:[],dummyData:(e,n=!1)=>n?e.maxSelect>1?[Qn(`test1.txt`),Qn(`test2.txt`)]:Qn(`test1.txt`):e.maxSelect>1?[`test1_`+app.utils.randomString(10)+`.txt`,`test2_`+app.utils.randomString(10)+`.txt`]:`test_`+app.utils.randomString(10)+`.txt`};function Qn(e){return{toString(){return`new File([...], '${e}')`},toJSON(){return`[[new File([...], '${e}')]]`}}}function $n(e){let n=`rel_`+app.utils.randomString();function r(){l?.dispatchEvent(new CustomEvent(`change`,{detail:{data:e},bubbles:!0}))}let i=store({selected:[],isLoading:!0,get maxReached(){let n=e.field.maxSelect||1;return app.utils.toArray(e.record[e.field.name]).length>=n}});async function a(){i.isLoading=!0;let n=app.utils.toArray(e.record[e.field.name]);if(!n.length){i.selected=[],i.isLoading=!1;return}let r=[],a=[],o=app.utils.toArray(e.record.expand?.[e.field.name]);for(let e of n){let n=o.find(n=>n.id==e);n?r.push(n):a.push(e)}try{if(a.length){let n=app.store.collections.find(n=>n.id==e.field.collectionId),i=[],o=n?.fields?.filter(e=>!e.hidden&&e.presentable&&e.type==`relation`)||[];for(let e of o)i.push(e.name);let s=await app.pb.collection(e.field.collectionId).getFullList({requestKey:null,filter:a.map(e=>app.pb.filter(`id={:id}`,{id:e})).join(`||`),expand:i.join(`,`)||void 0});for(let e of a){let n=s.find(n=>n.id==e);n?r.push(n):console.warn(`missing relation id:`,e)}}i.selected=r,i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}function o(n){let r=app.utils.toArray(e.record[e.field.name]),a=r.indexOf(n);a>=0&&(r.splice(a,1),s(r));let o=i.selected.findIndex(e=>e.id==n);i.selected.splice(o,1)}function s(n=[]){e.record[e.field.name]=e.field.maxSelect>1?n:n?.[0]||``,r()}let c=[watch(()=>e.record[e.field.name],()=>a())],l=t.output({className:`field-content`,name:()=>e.field.name},t.div({hidden:()=>!i.isLoading,className:`list`},()=>app.utils.toArray(e.record[e.field.name]).map(()=>t.div({className:`list-item`},t.span({className:`skeleton-loader`})))),app.components.sortable({className:`list`,hidden:()=>i.isLoading,data:()=>i.selected,onchange:e=>{i.selected=e,s(e.map(e=>e.id))},dataItem:(e,n)=>t.div({rid:e,className:`list-item highlight`},t.div({className:`content`},()=>app.components.recordSummary(e)),t.div({className:`actions`},t.button({type:`button`,className:`btn sm secondary transparent circle`,ariaLabel:app.attrs.tooltip(`Remove`),onclick:()=>o(e.id)},t.i({className:`ri-close-line`,ariaHidden:!0}))))}),t.hr({hidden:()=>!app.utils.isEmpty(e.record[e.field.name]),className:`m-t-5 m-b-0`}),t.button({type:`button`,className:`btn sm secondary block`,disabled:()=>i.isLoading,onclick:n=>{app.modals.openRecordsPicker({collection:e.field.collectionId,selectedIds:app.utils.toArray(e.record[e.field.name]),maxSelect:e.field.maxSelect,onselect:e=>{i.selected=e,s(e.map(e=>e.id))}})}},t.i({className:`ri-magic-line`,ariaHidden:!0}),t.span({className:`txt`},`Open records picker`)));return t.div({className:`record-field-input field-type-relation`,onunmount:()=>{c.forEach(e=>e?.unwatch())}},t.div({className:()=>`field-list ${e.field.required?`required`:``}`},t.label({htmlFor:n},t.i({className:app.fieldTypes.relation.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name)),l),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function er(e){let n=`f_`+app.utils.randomString(),r=[{label:`False`,value:!1},{label:`True`,value:!0}],i=[{label:`Single`,value:!1},{label:`Multiple`,value:!0}],a=[watch(()=>e.field.maxSelect,n=>{n||=1,n<=1&&(e.field.minSelect=0)})];return app.components.fieldSettings(e,{header:[t.div({className:`field header-select collections-select`,onunmount:()=>{a.forEach(e=>e?.unwatch())}},app.components.select({required:!0,className:`inline-error`,placeholder:`Select collection*`,name:()=>`fields.${e.fieldIndex}.collectionId`,disabled:()=>!!e.originalField?.id,options:()=>app.utils.sortedCollections(app.store.collections.filter(e=>e.type!=`view`)).map(e=>({value:e.id,label:e.name})),value:()=>e.field.collectionId,onchange:n=>{e.field.collectionId=n?.[0]?.value||``},after:()=>[t.hr({className:`m-t-5 m-b-5`}),t.button({type:`button`,className:`btn sm outline`,onclick:()=>{app.modals.openCollectionUpsert({},{onsave:n=>{e.field.collectionId=n.id}})}},t.i({className:`ri-add-line`,ariaHidden:!0}),t.span({className:`txt`},`New collection`))]})),t.div({className:`field header-select single-multiple-select`},app.components.select({required:!0,options:i,value:()=>e.field.maxSelect>1,onchange:n=>{n?.[0]?.value?e.field.maxSelect<<0<2&&(e.field.maxSelect=10):e.field.maxSelect=1}}))],content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-6`,hidden:()=>e.field.maxSelect<<0<2},t.div({className:`field`},t.label({htmlFor:n+`.minSelect`},`Min select`),t.input({type:`number`,id:n+`.minSelect`,step:1,min:0,max:2**53-1,placeholder:`No min limit`,name:()=>`fields.${e.fieldIndex}.minSelect`,value:()=>e.field.minSelect||``,onchange:n=>e.field.minSelect=parseInt(n.target.value,10)}))),t.div({className:`col-sm-6`,hidden:()=>e.field.maxSelect<<0<2},t.div({className:`field`},t.label({htmlFor:n+`.maxSelect`},`Max select`),t.input({type:`number`,id:n+`.maxSelect`,step:1,min:()=>e.field.minSelect||2,max:2**53-1,placeholder:`Default to single`,name:()=>`fields.${e.fieldIndex}.maxSelect`,value:()=>e.field.maxSelect||``,onchange:n=>{let r=parseInt(n.target.value,10);r>1?e.field.maxSelect=r:e.field.maxSelect=1}}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.cascadeDelete`},`Cascade delete`),app.components.select({required:!0,id:n+`.cascadeDelete`,name:()=>`fields.${e.fieldIndex}.cascadeDelete`,options:r,value:()=>e.field.cascadeDelete||!1,onchange:n=>{e.field.cascadeDelete=!!n?.[0].value}}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},()=>e.field.maxSelect>1?`(!=[])`:`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(()=>`Requires the field value to be nonempty ${e.field.maxSelect>1?`array`:`string`}.`)})))]})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.relation={icon:`ri-mind-map`,label:`Relation`,settings:er,input:$n,view:dn,filterModifiers:e=>e.maxSelect>1?[`each`,`length`]:[],dummyData:(e,n=!1)=>e.maxSelect>1?[`RECORD_ID1`,`RECORD_ID2`]:`RECORD_ID`};function tr(e){let n=`select_`+app.utils.randomString();return t.div({className:`record-field-input field-type-select`},t.div({className:`field`},t.label({htmlFor:n},t.i({className:app.fieldTypes.select.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name)),app.components.select({id:n,name:()=>e.field.name,max:()=>e.field.maxSelect||1,required:()=>e.field.required,options:()=>e.field.values.map(e=>({value:e})),value:()=>app.utils.toArray(e.record[e.field.name]),onchange:n=>{if(e.field.maxSelect<=1){e.record[e.field.name]=n?.[0]?.value||``;return}e.record[e.field.name]=n.map(e=>e.value)}})),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function nr(e){let n=`f_`+app.utils.randomString(),r=[{label:`Single`,value:!1},{label:`Multiple`,value:!0}],i=t.div({popover:`manual`,className:`dropdown field-select-choices-dropdown`},t.div({className:`field-help m-t-0`,style:`font-size: 0.9em`},`New-line separated choices:`),t.div({className:`field`},t.textarea({className:`autoexpand`,required:!0,value:()=>app.utils.toArray(e.field.values,!1).join(` + Leave empty for no restriction.`)})),app.components.select({max:99,placeholder:`No restriction`,options:app.utils.mimeTypes.map(e=>({value:e.mimeType,label:()=>t.div({className:`inline-flex gap-10`},t.span({className:`txt`},e.ext||`-`),t.small({className:`txt-hint`},e.mimeType))})),name:()=>`fields.${e.fieldIndex}.mimeTypes`,value:()=>app.utils.toArray(e.field.mimeTypes),onchange:n=>e.field.mimeTypes=n.map(e=>e.value)})),t.div({className:`field-help`},t.button({type:`button`,className:`link-hint gap-0`,"html-popovertarget":n+`mimeTypesDropdown`},t.span({className:`txt`},`Choose presets`),t.i({className:`ri-arrow-drop-down-fill`,ariaHidden:!0})),t.div({id:n+`mimeTypesDropdown`,className:`dropdown sm nowrap left p-10`,popover:`auto`},t.button({type:`button`,className:`dropdown-item`,role:`menuitem`,onclick:n=>{e.field.mimeTypes=[`image/jpeg`,`image/png`,`image/svg+xml`,`image/gif`,`image/webp`],n.target.closest(`.dropdown`).hidePopover()},textContent:`Images (jpg, png, svg, gif, webp)`}),t.button({type:`button`,className:`dropdown-item`,role:`menuitem`,onclick:n=>{e.field.mimeTypes=[`application/pdf`,`application/msword`,`application/vnd.openxmlformats-officedocument.wordprocessingml.document`,`application/vnd.ms-excel`,`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`],n.target.closest(`.dropdown`).hidePopover()},textContent:`Documents (pdf, doc/docx, xls/xlsx)`}),t.button({type:`button`,className:`dropdown-item`,role:`menuitem`,onclick:n=>{e.field.mimeTypes=[`video/mp4`,`video/mpeg`,`video/x-msvideo`,`video/quicktime`,`video/3gpp`],n.target.closest(`.dropdown`).hidePopover()},textContent:`Videos (mp4, mpeg, avi, mov, 3gp)`}),t.button({type:`button`,className:`dropdown-item`,role:`menuitem`,onclick:n=>{e.field.mimeTypes=[`application/zip`,`application/x-7z-compressed`,`application/x-rar-compressed`],n.target.closest(`.dropdown`).hidePopover()},textContent:`Archives (zip, 7zip, rar)`})))),t.div({className:()=>e.field.maxSelect>1?`col-sm-6`:`col-sm-9`},t.div({className:`field`},t.label({htmlFor:n+`.thumbs`},t.span({className:`txt`},`Thumb sizes`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`List of additional thumb sizes for image files, along with the default thumb size of 100x100. The thumbs are generated lazily on first access.`)})),t.input({type:`text`,id:n+`.thumbs`,placeholder:`e.g. 50x50, 480x720`,name:()=>`fields.${e.fieldIndex}.thumbs`,value:()=>app.utils.joinNonEmpty(e.field.thumbs),onchange:n=>e.field.thumbs=app.utils.splitNonEmpty(n.target.value,`,`)})),t.div({className:`field-help`},t.span({className:`txt m-r-5`},`Use comma as separator.`),t.button({type:`button`,className:`link-hint gap-0`,"html-popovertarget":n+`thumbFormatsDropdown`},t.span({className:`txt`},`Supported formats`),t.i({className:`ri-arrow-drop-down-fill`,ariaHidden:!0})),t.div({id:n+`thumbFormatsDropdown`,className:`dropdown sm nowrap left p-10`,popover:`auto`},t.ul({className:`m-0 p-l-sm`},t.li(null,t.strong(null,`WxH`),t.span(null,` (e.g. 100x50) - crop to WxH viewbox (from center)`)),t.li(null,t.strong(null,`WxHt`),t.span(null,` (e.g. 100x50t) - crop to WxH viewbox (from top)`)),t.li(null,t.strong(null,`WxHb`),t.span(null,` (e.g. 100x50b) - crop to WxH viewbox (from bottom)`)),t.li(null,t.strong(null,`WxHf`),t.span(null,` (e.g. 100x50f) - fit inside a WxH viewbox (without cropping)`)),t.li(null,t.strong(null,`0xH`),t.span(null,` (e.g. 0x50) - resize to H height preserving the aspect ratio`)),t.li(null,t.strong(null,`Wx0`),t.span(null,` (e.g. 100x0) - resize to W width preserving the aspect ratio`)))))),t.div({className:`col-sm-3`},t.div({className:`field`},t.label({htmlFor:n+`.maxSize`},`Max size`),t.input({type:`number`,id:n+`.maxSize`,step:1,min:0,max:2**53-1,placeholder:`~5MB default`,name:()=>`fields.${e.fieldIndex}.maxSize`,value:()=>e.field.maxSize||``,oninput:n=>e.field.maxSize=parseInt(n.target.value,10)})),t.div({className:`field-help`},`In bytes.`)),t.div({className:`col-sm-3`,hidden:()=>e.field.maxSelect<<0<2},t.div({className:`field`},t.label({htmlFor:n+`.maxSelect`},`Max select`),t.input({type:`number`,id:n+`.maxSelect`,placeholder:`Default to single`,step:1,min:2,required:!0,max:2**53-1,name:()=>`fields.${e.fieldIndex}.maxSelect`,value:()=>e.field.maxSelect||``,onchange:n=>{let r=parseInt(n.target.value,10);r>1?e.field.maxSelect=r:e.field.maxSelect=1}}))),t.div({className:`col-sm-12`},t.div({className:`field m-t-5 m-b-5`},t.input({className:`switch`,type:`checkbox`,id:n+`.protected`,name:()=>`fields.${e.fieldIndex}.protected`,checked:()=>!!e.field.protected,onchange:n=>e.field.protected=n.target.checked}),t.label({htmlFor:n+`.protected`},t.span({className:`txt`},`Protected`),t.small({className:`txt-hint`},`File download requests will need to satisfy the View API rule (`,t.a({href:`https://pocketbase.io/docs/files-handling#protected-files`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Learn more`}),`).`)))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},()=>e.field.maxSelect>1?`(!=[])`:`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(()=>`Requires the field value to be nonempty ${e.field.maxSelect>1?`array`:`string`}.`)})))]})}function Zn(e){return t.div({className:`record-field-view field-type-file`},()=>{let n=app.utils.toArray(e.record[e.field.name]);if(!n.length)return t.span({className:`missing-value`});let r=[],i=e.short?5:100;for(let a=0;a=i){r.push(t.span({className:`thumb sm`},`+`,n.length-i));break}r.push(app.components.recordFileThumb({record:e.record,filename:n[a]}))}return r})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.file={icon:`ri-image-line`,label:`File`,settings:Xn,input:Jn,view:Zn,summaryPriority:-1,onrecordsave:qn,onrecordduplicate:Yn,filterModifiers:e=>e.maxSelect>1?[`each`,`length`]:[],dummyData:(e,n=!1)=>n?e.maxSelect>1?[Qn(`test1.txt`),Qn(`test2.txt`)]:Qn(`test1.txt`):e.maxSelect>1?[`test1_`+app.utils.randomString(10)+`.txt`,`test2_`+app.utils.randomString(10)+`.txt`]:`test_`+app.utils.randomString(10)+`.txt`};function Qn(e){return{toString(){return`new File([...], '${e}')`},toJSON(){return`[[new File([...], '${e}')]]`}}}function $n(e){let n=`rel_`+app.utils.randomString();function r(){l?.dispatchEvent(new CustomEvent(`change`,{detail:{data:e},bubbles:!0}))}let i=store({selected:[],isLoading:!0,get maxReached(){let n=e.field.maxSelect||1;return app.utils.toArray(e.record[e.field.name]).length>=n}});async function a(){i.isLoading=!0;let n=app.utils.toArray(e.record[e.field.name]);if(!n.length){i.selected=[],i.isLoading=!1;return}let r=[],a=[],o=app.utils.toArray(e.record.expand?.[e.field.name]);for(let e of n){let n=o.find(n=>n.id==e);n?r.push(n):a.push(e)}try{if(a.length){let n=app.store.collections.find(n=>n.id==e.field.collectionId),i=[],o=n?.fields?.filter(e=>!e.hidden&&e.presentable&&e.type==`relation`)||[];for(let e of o)i.push(e.name);let s=await app.pb.collection(e.field.collectionId).getFullList({requestKey:null,filter:a.map(e=>app.pb.filter(`id={:id}`,{id:e})).join(`||`),expand:i.join(`,`)||void 0});for(let e of a){let n=s.find(n=>n.id==e);n?r.push(n):console.warn(`missing relation id:`,e)}}i.selected=r,i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}function o(n){let r=app.utils.toArray(e.record[e.field.name]),a=r.indexOf(n);a>=0&&(r.splice(a,1),s(r));let o=i.selected.findIndex(e=>e.id==n);i.selected.splice(o,1)}function s(n=[]){e.record[e.field.name]=e.field.maxSelect>1?n:n?.[0]||``,r()}let c=[watch(()=>e.record[e.field.name],()=>a())],l=t.output({className:`field-content`,name:()=>e.field.name},t.div({hidden:()=>!i.isLoading,className:`list`},()=>app.utils.toArray(e.record[e.field.name]).map(()=>t.div({className:`list-item`},t.span({className:`skeleton-loader`})))),app.components.sortable({className:`list`,hidden:()=>i.isLoading,data:()=>i.selected,onchange:e=>{i.selected=e,s(e.map(e=>e.id))},dataItem:(e,n)=>t.div({rid:e,className:`list-item highlight`},t.div({className:`content`},()=>app.components.recordSummary(e)),t.div({className:`actions`},t.button({type:`button`,className:`btn sm secondary transparent circle`,ariaLabel:app.attrs.tooltip(`Remove`),onclick:()=>o(e.id)},t.i({className:`ri-close-line`,ariaHidden:!0}))))}),t.hr({hidden:()=>!app.utils.isEmpty(e.record[e.field.name]),className:`m-t-5 m-b-0`}),t.button({type:`button`,className:`btn sm secondary block`,disabled:()=>i.isLoading,onclick:n=>{app.modals.openRecordsPicker({collection:e.field.collectionId,selectedIds:app.utils.toArray(e.record[e.field.name]),maxSelect:e.field.maxSelect,onselect:e=>{i.selected=e,s(e.map(e=>e.id))}})}},t.i({className:`ri-magic-line`,ariaHidden:!0}),t.span({className:`txt`},`Open records picker`)));return t.div({className:`record-field-input field-type-relation`,onunmount:()=>{c.forEach(e=>e?.unwatch())}},t.div({className:()=>`field-list ${e.field.required?`required`:``}`},t.label({htmlFor:n},t.i({className:app.fieldTypes.relation.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name)),l),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function er(e){let n=`f_`+app.utils.randomString(),r=[{label:`False`,value:!1},{label:`True`,value:!0}],i=[{label:`Single`,value:!1},{label:`Multiple`,value:!0}],a=[watch(()=>e.field.maxSelect,n=>{n||=1,n<=1&&(e.field.minSelect=0)})];return app.components.fieldSettings(e,{header:[t.div({className:`field header-select collections-select`,onunmount:()=>{a.forEach(e=>e?.unwatch())}},app.components.select({required:!0,className:`inline-error`,placeholder:`Select collection*`,name:()=>`fields.${e.fieldIndex}.collectionId`,disabled:()=>!!e.originalField?.id,options:()=>app.utils.sortedCollections(app.store.collections.filter(e=>e.type!=`view`)).map(e=>({value:e.id,label:e.name})),value:()=>e.field.collectionId,onchange:n=>{e.field.collectionId=n?.[0]?.value||``},after:()=>[t.hr({className:`m-t-5 m-b-5`}),t.button({type:`button`,className:`btn sm outline`,onclick:()=>{app.modals.openCollectionUpsert({},{onsave:n=>{e.field.collectionId=n.id}})}},t.i({className:`ri-add-line`,ariaHidden:!0}),t.span({className:`txt`},`New collection`))]})),t.div({className:`field header-select single-multiple-select`},app.components.select({required:!0,options:i,value:()=>e.field.maxSelect>1,onchange:n=>{n?.[0]?.value?e.field.maxSelect<<0<2&&(e.field.maxSelect=10):e.field.maxSelect=1}}))],content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-6`,hidden:()=>e.field.maxSelect<<0<2},t.div({className:`field`},t.label({htmlFor:n+`.minSelect`},`Min select`),t.input({type:`number`,id:n+`.minSelect`,step:1,min:0,max:2**53-1,placeholder:`No min limit`,name:()=>`fields.${e.fieldIndex}.minSelect`,value:()=>e.field.minSelect||``,onchange:n=>e.field.minSelect=parseInt(n.target.value,10)}))),t.div({className:`col-sm-6`,hidden:()=>e.field.maxSelect<<0<2},t.div({className:`field`},t.label({htmlFor:n+`.maxSelect`},`Max select`),t.input({type:`number`,id:n+`.maxSelect`,step:1,min:()=>e.field.minSelect||2,max:2**53-1,placeholder:`Default to single`,name:()=>`fields.${e.fieldIndex}.maxSelect`,value:()=>e.field.maxSelect||``,onchange:n=>{let r=parseInt(n.target.value,10);r>1?e.field.maxSelect=r:e.field.maxSelect=1}}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.cascadeDelete`},`Cascade delete`),app.components.select({required:!0,id:n+`.cascadeDelete`,name:()=>`fields.${e.fieldIndex}.cascadeDelete`,options:r,value:()=>e.field.cascadeDelete||!1,onchange:n=>{e.field.cascadeDelete=!!n?.[0].value}}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},()=>e.field.maxSelect>1?`(!=[])`:`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(()=>`Requires the field value to be nonempty ${e.field.maxSelect>1?`array`:`string`}.`)})))]})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.relation={icon:`ri-mind-map`,label:`Relation`,settings:er,input:$n,view:dn,filterModifiers:e=>e.maxSelect>1?[`each`,`length`]:[],dummyData:(e,n=!1)=>e.maxSelect>1?[`RECORD_ID1`,`RECORD_ID2`]:`RECORD_ID`};function tr(e){let n=`select_`+app.utils.randomString();return t.div({className:`record-field-input field-type-select`},t.div({className:`field`},t.label({htmlFor:n},t.i({className:app.fieldTypes.select.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name)),app.components.select({id:n,name:()=>e.field.name,max:()=>e.field.maxSelect||1,required:()=>e.field.required,options:()=>e.field.values.map(e=>({value:e})),value:()=>app.utils.toArray(e.record[e.field.name]),onchange:n=>{if(e.field.maxSelect<=1){e.record[e.field.name]=n?.[0]?.value||``;return}e.record[e.field.name]=n.map(e=>e.value)}})),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function nr(e){let n=`f_`+app.utils.randomString(),r=[{label:`Single`,value:!1},{label:`Multiple`,value:!0}],i=t.div({popover:`manual`,className:`dropdown field-select-choices-dropdown`},t.div({className:`field-help m-t-0`,style:`font-size: 0.9em`},`New-line separated choices:`),t.div({className:`field`},t.textarea({className:`autoexpand`,required:!0,value:()=>app.utils.toArray(e.field.values,!1).join(` `),oninput:n=>{let r=n.target.value.trimStart().replaceAll(` `,` `).split(` `);e.field.values=r,app.utils.deleteByPath(app.store.errors,`fields.${e.fieldIndex}.values`)},onchange:n=>{let r=new Set,i=n.target.value.split(` -`);for(let e of i)e!=``&&r.add(e);e.field.values=Array.from(r)},onblur:e=>{(!e.relatedTarget||!i.contains(e.relatedTarget))&&i.hidePopover()}}))),a=[watch(()=>{e.field.values?.length&&e.field.maxSelect>e.field.values.length&&(e.field.maxSelect=e.field.values.length)})];return app.components.fieldSettings(e,{header:[t.div({className:`field header-select field-select-choices-input`,onunmount:()=>{a.forEach(e=>e?.unwatch())}},t.input({type:`text`,placeholder:`Add choices*`,className:`txt-left inline-error`,value:()=>e.field.values?.join(` • `)||``,name:()=>`fields.${e.fieldIndex}.values`,onfocus:e=>(i?.showPopover({source:e.target}),i.querySelector(`textarea`)?.focus(),!1)}),i),t.div({className:`field header-select single-multiple-select`},app.components.select({required:!0,options:r,value:()=>e.field.maxSelect>1,onchange:n=>{n?.[0]?.value?e.field.maxSelect=e.field.values.length||2:e.field.maxSelect=1}}))],content:()=>t.div({className:`grid sm`},()=>{if(e.field.maxSelect>1)return t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.maxSelect`},`Max select`),t.input({type:`number`,id:n+`.maxSelect`,placeholder:`Default to single`,step:1,min:2,max:()=>e.field.values?.length||2,name:()=>`fields.${e.fieldIndex}.maxSelect`,value:()=>e.field.maxSelect||``,onchange:n=>{let r=parseInt(n.target.value,10);r>1?e.field.maxSelect=r:e.field.maxSelect=1}})))},t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},()=>e.field.maxSelect>1?`(!=[])`:`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(()=>`Requires the field value to be nonempty ${e.field.maxSelect>1?`array`:`string`}.`)})))]})}function rr(e){return t.div({className:`record-field-view field-type-select`},()=>{let n=app.utils.toArray(e.record[e.field.name],!1);return n.length?n.map(e=>t.span({className:`label`,title:e,textContent:app.utils.truncate(e,100)})):t.span({className:`missing-value`})})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.select={icon:`ri-list-check`,label:`Select`,settings:nr,input:tr,view:rr,filterModifiers:e=>e.maxSelect>1?[`each`,`length`]:[],dummyData:(e,n=!1)=>e.maxSelect>1?e.values?.slice(0,2)||[]:e.values?.[0]||``};function ir(e){let n=`json_`+app.utils.randomString(),r=store({value:``}),i=[watch(()=>e.record[e.field.name],(n,i)=>{if(!(n!==``&&n===r.value)){if(typeof n==`string`&&!n.startsWith(`"`)&&!n.endsWith(`"`)){r.value=JSON.stringify(n===void 0?null:n),e.record[e.field.name]=r.value;return}typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)?r.value=n:n===null?r.value=`null`:r.value=JSON.stringify(n===void 0?null:n,null,2)}})];function a(){let n=r.value.trim();if(n===``){e.record[e.field.name]=null;return}try{let r=JSON.parse(n);typeof r==`string`?e.record[e.field.name]=JSON.stringify(r):e.record[e.field.name]=r}catch{e.record[e.field.name]=n}}return t.div({className:`record-field-input field-type-json`},t.div({className:`field`,onunmount:()=>{clearTimeout(void 0),i.forEach(e=>e?.unwatch())}},t.label({htmlFor:n},t.i({className:app.fieldTypes.json.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name),t.span({hidden:()=>ar(r.value.trim()),className:`json-state`,ariaDescription:app.attrs.tooltip(`Invalid JSON`,`left`)},t.i({className:`ri-error-warning-fill txt-danger`,ariaHidden:!0})),t.span({hidden:()=>!ar(r.value.trim()),className:`json-state`,ariaDescription:app.attrs.tooltip(`Valid JSON`,`left`)},t.i({className:`ri-checkbox-circle-fill txt-success`,ariaHidden:!0}))),app.components.codeEditor({language:`js`,id:n,name:()=>e.field.name,required:()=>e.field.required,value:()=>r.value,oninput:e=>r.value=e,onblur:()=>a()})),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function ar(e){if(e===``)return!0;try{return JSON.parse(e),!0}catch{return!1}}function or(e){try{let n=e.record[e.field.name];typeof n==`string`&&JSON.parse(n)}catch(n){throw new y({status:400,response:{message:`Invalid JSON data`,data:{[e.field.name]:{code:`invalid_json`,message:n.toString()}}}})}}function sr(e){let n=`f_`+app.utils.randomString(),r=store({showInfo:!1});return app.components.fieldSettings(e,{content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.maxSize`},t.span(null,`Max size `),t.small(null,`(bytes)`)),t.input({type:`number`,id:n+`.maxSize`,name:()=>`fields.${e.fieldIndex}.maxSize`,min:0,step:1,max:2**53-1,placeholder:`Default to max ~1MB`,value:()=>e.field.maxSize||``,oninput:n=>{e.field.maxSize=parseInt(n.target.value,10)}}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value}))),t.div({className:`col-sm-12`},t.button({type:`button`,className:()=>`btn sm secondary ${r.showInfo?``:`transparent`}`,onclick:()=>r.showInfo=!r.showInfo},t.span({className:`txt`},`String value normalizations`),t.i({className:()=>r.showInfo?`ri-arrow-up-s-line`:`ri-arrow-down-s-line`,ariaHidden:!0})),app.components.slide(()=>r.showInfo,t.div({className:`alert m-t-10 info`},t.div({className:`content`},`In order to support seamlessly both `,t.code(null,`application/json`),` and `,t.code(null,`multipart/form-data`),`requests, the following normalization rules are applied if the `,t.code(null,`json`),` field is a plain string:`,t.ul(null,t.li(null,`"true" is converted to the json `,t.code(null,`true`)),t.li(null,`"false" is converted to the json `,t.code(null,`false`)),t.li(null,`"null" is converted to the json `,t.code(null,`null`)),t.li(null,`"[1,2,3]" is converted to the json `,t.code(null,`[1,2,3]`)),t.li(null,`'{"a":1,"b":2}' is converted to the json `,t.code(null,`{"a":1,"b":2}`)),t.li(null,`numeric strings are converted to json number`),t.li(null,`double quoted strings are left as they are (aka. without normalizations)`),t.li(null,`any other string (empty string too) is double quoted`)),`Alternatively, if you want to avoid the string value normalizations, you can wrap your data inside an object, eg. `,t.code(null,`{"data": anything}`),`.`))))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value NOT to be null, '', [], {}.`)})))]})}function cr(e){return t.div({className:`record-field-view field-type-json`},()=>{let n=e.record[e.field.name];return e.short?t.span({className:`txt-code txt-ellipsis`,textContent:app.utils.truncate(app.utils.trimQuotedValue(JSON.stringify(n))||``)}):app.components.codeBlock({value:()=>JSON.stringify(n,null,2)})})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.json={icon:`ri-braces-line`,label:`JSON`,settings:sr,input:ir,view:cr,onrecordsave:or,dummyData:(e,n=!1)=>({example:123})};function lr(e){let n=`geo_`+app.utils.randomString(),r=store({showMap:!1});return t.div({className:`record-field-input field-type-geoPoint`},t.div({className:()=>`field-list ${e.field.required?`required`:``}`},t.label({htmlFor:n},t.i({className:app.fieldTypes.geoPoint.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name)),t.div({className:`field-list-content`},t.div({className:`field-list-item p-0`},t.div({className:`fields`},t.div({className:`field addon`},t.label({htmlFor:n+`.lon`},`Longitude:`)),t.div({className:`field`},t.input({id:n+`.lon`,type:`number`,step:`any`,min:-180,max:180,placeholder:0,name:()=>e.field.name,required:()=>e.field.required,value:()=>e.record[e.field.name]?.lon||``,onchange:n=>{e.record[e.field.name]=e.record[e.field.name]||{},e.record[e.field.name].lon=Number(n.target.value)}})),t.span({className:`delimiter`}),t.div({className:`field addon`},t.label({htmlFor:n+`.lat`},`Latitude:`)),t.div({className:`field`},t.input({id:n+`.lat`,type:`number`,step:`any`,min:-90,max:90,placeholder:0,name:()=>e.field.name,required:()=>e.field.required,value:()=>e.record[e.field.name]?.lat||``,onchange:n=>{e.record[e.field.name]=e.record[e.field.name]||{},e.record[e.field.name].lat=Number(n.target.value)}})),t.span({className:`delimiter`}),t.div({className:`field addon p-5`},t.button({type:`button`,className:()=>`btn sm circle secondary ${r.showMap?``:`transparent`}`,onclick:()=>r.showMap=!r.showMap},t.i({className:`ri-map-2-line`}))))),()=>{if(r.showMap)return t.div({className:`field-list-item p-0`,style:`height: 250px`},app.components.leaflet({point:()=>e.record[e.field.name]||{lat:0,lon:0},onchange:n=>{e.record[e.field.name]=structuredClone(n)}}))})),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function ur(e){let n=`f_`+app.utils.randomString();return app.components.fieldSettings(e,{content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},`(=true)`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value to be true.`)})))]})}function dr(e){return t.div({className:`record-field-view field-type-geoPoint`},t.span({className:`label`},()=>{let n=e.record[e.field.name];return`${n?.lon||0}, ${n?.lat||0}`}))}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.geoPoint={icon:`ri-map-pin-2-line`,label:`Geo Point`,settings:ur,input:lr,view:dr,identifierExtractor:function(e,n=``){return[n+e.name+`.lon`,n+e.name+`.lat`]},dummyData:(e,n=!1)=>({lon:0,lat:0})};function fr(e){let n=`f_`+app.utils.randomString();return app.components.fieldSettings(e,{showHidden:!1,showPresentable:!1,showDuplicate:!1,content:t.div({className:`grid sm`},t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.min`},t.span({className:`txt`},`Min length`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Clear the field or set it to 0 for no limit.`)})),t.input({type:`number`,id:n+`.min`,name:()=>`fields.${e.fieldIndex}.min`,step:1,min:0,max:71,placeholder:`No min limit`,value:()=>e.field.min||``,oninput:n=>{e.field.min=parseInt(n.target.value,10)}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.max`},t.span({className:`txt`},`Max length`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Clear the field or set it to 0 to fallback to the default limit (71).`)})),t.input({type:`number`,id:n+`.max`,name:()=>`fields.${e.fieldIndex}.max`,step:1,min:()=>e.field.min||0,max:71,placeholder:`Up to 71 chars`,value:()=>e.field.max||``,oninput:n=>{e.field.max=parseInt(n.target.value,10)}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.max`},t.span({className:`txt`},`Bcrypt cost`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Clear the field or set it to 0 to fallback to the default (10).`)})),t.input({type:`number`,id:n+`.cost`,name:()=>`fields.${e.fieldIndex}.cost`,step:1,min:4,max:31,placeholder:`Default to 10`,value:()=>e.field.cost||``,oninput:n=>{e.field.cost=parseInt(n.target.value,10)}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.pattern`},t.span({className:`txt`},`Validation pattern`)),t.input({type:`text`,id:n+`.pattern`,placeholder:`ex. ^\\w+$`,name:()=>`fields.${e.fieldIndex}.pattern`,value:()=>e.field.pattern||``,oninput:n=>e.field.pattern=n.target.value}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>{if(!(e.collection?.type==`auth`&&e.field.name==`password`))return[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value to be nonempty string.`)})))]}})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.password={icon:`ri-lock-password-line`,label:`Password`,settings:fr},window.app=window.app||{},window.app.modals=window.app.modals||{},window.app.modals.openIndexUpsert=function(e,n=``,r={onsave:()=>{},ondelete:()=>{}}){let i=pr(e,n,r);i&&(document.body.appendChild(i),app.modals.open(i))};function pr(e,n=``,r={}){if(!e){console.warn(`[indexUpsertModal] missing required collection argument`);return}let i,a=app.utils.randomString(),o=store({originalIndex:``,index:``,get isNew(){return o.originalIndex==``},get indexParts(){return app.utils.parseIndex(o.index)},get lowerCasedIndexColumnNames(){return o.indexParts.columns.map(e=>e.name.toLowerCase())},get canSave(){return o.lowerCasedIndexColumnNames.length>0}}),s=e?.fields?.filter(e=>!e[`@toDelete`]&&e.name!=`id`)?.map(e=>e.name)||[];function c(n){if(o.originalIndex=n||``,!n){let r=app.utils.parseIndex(``);r.tableName=e?.name||``,n=app.utils.buildIndex(r)}o.index=n}function l(){if(!e||!o.canSave){console.warn(`[saveIndex] no collection or invalid save state:`,e,o.canSave);return}e.indexes=e.indexes||[];let n=e.indexes.findIndex(e=>e==o.originalIndex);n>=0?(e.indexes[n]=o.index,app.utils.deleteByPath(app.store.errors,`indexes.`+n)):e.indexes.push(o.index),typeof r?.onsave==`function`&&r.onsave({collection:e,index:o.index,oldIndex:o.originalIndex}),f(),app.modals.close(i)}function u(){if(!e||!o.originalIndex){console.warn(`[deleteIndex] no collection or index:`,e,o.originalIndex);return}let n=e.indexes?.findIndex(e=>e==o.originalIndex);if(n==-1){console.warn(`[deleteIndex] missing index:`,o.originalIndex);return}e.indexes.splice(n,1),app.utils.deleteByPath(app.store.errors,`indexes.`+n),typeof r?.ondelete==`function`&&r.ondelete({collection:e,position:n,index:o.originalIndex}),f(),app.modals.close(i)}function d(n){let r=JSON.parse(JSON.stringify(o.indexParts));r.tableName=e?.name||``;let i=n.toLowerCase(),a=r.columns.findIndex(e=>e.name.toLowerCase()==i);a>=0?r.columns.splice(a,1):app.utils.pushUnique(r.columns,{name:n}),o.index=app.utils.buildIndex(r),f()}function f(){if(app.store.errors?.indexes){let n=e.indexes.findIndex(e=>e==o.originalIndex);app.utils.deleteByPath(app.store.errors,`indexes.`+n)}}return i=t.div({className:`modal popup index-upsert-modal`,onbeforeopen:()=>{c(n)},onafteropen:()=>{app.store.errors?.indexes&&(app.store.errors.indexes=JSON.parse(JSON.stringify(app.store.errors.indexes)))},onafterclose:e=>{e?.remove()}},t.header({className:`modal-header`},t.h6({className:`modal-title`},t.span({className:`txt`},()=>o.isNew?`Create index`:`Update index`))),t.div({className:`modal-content`},t.form({id:a+`form`,className:`grid sm index-upsert-form`,onsubmit:e=>{e.preventDefault(),l()}},t.div({className:`col-12`},t.div({className:`field`},t.input({type:`checkbox`,className:`switch`,id:a+`checkbox_unique`,checked:()=>o.indexParts.unique,onchange:n=>{let r=JSON.parse(JSON.stringify(o.indexParts));r.unique=n.target.checked,r.tableName=r.tableName||e?.name||``,o.index=app.utils.buildIndex(r)}}),t.label({htmlFor:a+`checkbox_unique`},`Unique`))),t.div({className:`col-12`},t.div({className:`field`},app.components.codeEditor({required:!0,className:`collection-index-input pre-wrap`,name:()=>`indexes.`+e.indexes?.findIndex(e=>e==o.originalIndex),placeholder:()=>`e.g. CREATE INDEX idx_test on ${e?.name||`X`} (created)`,value:()=>o.index,oninput:e=>o.index=e})),t.div({hidden:()=>!s.length,className:`field-help m-t-sm`},t.div({className:`flex flex-wrap gap-5`},t.span({className:`txt`,textContent:`Presets:`}),()=>s?.map(e=>{let n=o.lowerCasedIndexColumnNames.includes(e.toLowerCase());return t.button({type:`button`,textContent:e,className:()=>`label handle ${n?`success`:``}`,onclick:()=>d(e)})})))))),t.footer({className:`modal-footer gap-base`},t.button({type:`button`,className:`btn transparent m-r-auto`,onclick:()=>app.modals.close(i)},t.span({className:`txt`},`Close`)),t.button({hidden:()=>o.isNew,type:`button`,className:()=>`btn sm circle transparent secondary`,ariaLabel:app.attrs.tooltip(`Delete index`,`left`),onclick:()=>{app.modals.confirm(`Do you really want to remove the selected index from the collection?`,u)}},t.i({className:`ri-delete-bin-7-line`,ariaHidden:!0})),t.button({type:`submit`,"html-form":a+`form`,disabled:()=>!o.canSave,className:()=>`btn expanded`},t.span({className:`txt`},`Set index`)))),i}function mr(e,n,r={}){let i=`emailTemplate`+app.utils.randomString(),a=store({title:`Email template`,placeholders:[]}),o=app.utils.extendStore(a,r),s=store({get config(){let r=app.utils.getByPath(e,n);return r||(r={subject:``,body:``},app.utils.setByPath(e,n,r)),r},get tokensList(){return[]}}),c=()=>{if(a.placeholders?.length)return t.div({className:`field-help`},t.div({className:`flex flex-wrap gap-5`},t.span({className:`txt`},`Placeholders:`),()=>a.placeholders.map(e=>t.span({className:`label sm`},app.components.copyButton(e,e)))))};return t.details({pbEvent:`emailTemplateAccordion`,className:`accordion email-template-accordion`,name:`email-template`,onunmount:()=>{o.forEach(e=>e?.unwatch())}},t.summary(null,t.i({className:`ri-draft-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:()=>a.title}),()=>{if(app.utils.getByPath(app.store.errors,n))return t.i({ariaHidden:!0,className:`ri-error-warning-fill txt-danger m-l-auto`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.subject`,textContent:`Subject`}),app.components.codeEditor({id:i+`.subject`,name:n+`.subject`,required:!0,singleLine:!0,language:`text`,autocomplete:a.placeholders,value:()=>s.config.subject||``,oninput:e=>s.config.subject=e})),c),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.body`,textContent:`Body (HTML)`}),app.components.codeEditor({id:i+`.body`,name:n+`.body`,required:!0,language:`html`,className:`pre-wrap`,autocomplete:a.placeholders,value:()=>s.config.body||``,oninput:e=>s.config.body=e})),c)))}function hr(e){let n=`mfa_`+app.utils.randomString(),r=store({get config(){return e.mfa||={enabled:!1,duration:600,rule:``},e.mfa},get isSuperusers(){return e.system&&e.name==`_superusers`}});return t.details({pbEvent:`mfaAccordion`,name:`auth-methods`,className:`accordion mfa-accordion`},t.summary(null,t.i({className:`ri-shield-check-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`Multi-factor authentication (MFA)`}),t.span({className:()=>`label m-l-auto ${r.config.enabled?`success`:``}`,textContent:()=>r.config.enabled?`Enabled`:`Disabled`}),()=>{if(app.store.errors?.mfa)return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`alert info`},t.div({className:`content`},t.p(null,`Multi-factor authentication (MFA) requires the user to authenticate with any 2 different auth methods (otp, identity/password, oauth2) before issuing an auth token. `,t.a({href:`https://pocketbase.io/docs/authentication#multi-factor-authentication`,className:`link-hint`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Learn more.`}))))),t.div({className:`col-sm-12`},t.div({className:`field`},t.input({type:`checkbox`,id:n+`.enabled`,name:`mfa.enabled`,className:`switch`,checked:()=>r.config.enabled,onchange:n=>{r.config.enabled=n.target.checked,r.isSuperusers&&(e.otp.enabled=n.target.checked)}}),t.label({htmlFor:n+`.enabled`,textContent:`Enable`}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.duration`,textContent:`Max duration between 2 authentications (in seconds)`}),t.input({type:`number`,id:n+`.duration`,name:`mfa.duration`,min:1,step:1,required:!0,value:()=>r.config.duration||``,oninput:e=>r.config.duration=parseInt(e.target.value,10)}))),t.div({className:`col-sm-12`},app.components.ruleField({label:`MFA rule`,id:n+`.rule`,name:`mfa.rule`,nullable:!1,placeholder:`Leave empty to require MFA for everyone`,autocomplete:n=>app.utils.collectionAutocompleteKeys(e,n),value:()=>r.config.rule||``,oninput:e=>r.config.rule=e}),t.div({className:`field-help`},t.p(null,`This optional rule could be used to enable/disable MFA per account basis.`),t.p(null,`For example, to require MFA only for accounts with non-empty email you can set it to `,t.code(null,`email != ''`),`.`),t.p(null,`Leave the rule empty to require MFA for everyone.`)))))}var gr=[`id`,`email`,`emailVisibility`,`verified`,`tokenKey`,`password`],_r=[`text`,`editor`,`url`,`email`,`json`];function vr(e){let n=`oauth2_`+app.utils.randomString(),r=store({get config(){return e.oauth2||={enabled:!1,mappedFields:{},providers:[]},e.oauth2},get regularFieldOptions(){return e.fields?.filter(e=>_r.includes(e.type)&&!gr.includes(e.name)).map(e=>({value:e.name}))},get regularAndFileFieldOptions(){return e.fields?.filter(e=>(e.type==`file`||_r.includes(e.type))&&!gr.includes(e.name)).map(e=>({value:e.name}))},showMapping:!1});function i(e){app.utils.deleteByPath(app.store.errors,`oauth2.providers.`+e)}return t.details({pbEvent:`oauth2Accordion`,name:`auth-methods`,className:`accordion oauth2-accordion`},t.summary(null,t.i({className:`ri-profile-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`OAuth2`}),t.span({className:()=>`label m-l-auto ${r.config.enabled?`success`:``}`,textContent:()=>r.config.enabled?`Enabled`:`Disabled`}),()=>{if(!app.utils.isEmpty(app.store.errors?.oauth2))return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.input({type:`checkbox`,id:n+`.enabled`,name:`oauth2.enabled`,className:`switch`,checked:()=>r.config.enabled,onchange:e=>r.config.enabled=e.target.checked}),t.label({htmlFor:n+`.enabled`,textContent:`Enable`}))),()=>r.config.providers.map((e,a)=>{let o=n+e.name,s=app.store.oauth2Providers?.find(n=>n.name==e.name)||{};return t.div({className:`col-sm-6`},t.div({className:()=>{let e=`provider-card`;return app.utils.isEmpty(app.store.errors?.oauth2?.providers?.[a])||(e+=` error`),e}},t.figure({className:`provider-logo`},()=>s.logo?t.img({src:`data:image/svg+xml;base64,`+btoa(s.logo),alt:e.name+` logo`}):t.i({className:app.utils.fallbackProviderIcon,ariaHidden:!0})),t.div({className:`content`},t.span({className:`primary-txt`},()=>e.displayName||s.displayName||s.name),t.span({className:`secondary-txt`},()=>e.name||s.name)),t.div({className:`actions`},t.button({type:`button`,title:`Options`,className:`btn secondary transparent sm circle`,"html-popovertarget":o+`dropdown`},t.i({className:`ri-more-2-line`,ariaHidden:!0})),t.div({id:o+`dropdown`,className:`dropdown sm`,popover:`auto`},t.button({type:`button`,className:`dropdown-item`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),app.modals.openProviderSettings(e,{namePrefix:`oauth2.providers.`+a,onsubmit:(e,n)=>{r.config.providers[a]=n,i(a)}})}},t.span({className:`txt`},`Settings`)),t.hr(),t.button({type:`button`,className:`dropdown-item`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),app.modals.confirm(`Do you really want to remove provider "${e.displayName||s.displayName||s.name}"?`,()=>{i(a),r.config.providers.splice(a,1),r.config.providers.length==0&&(r.config.enabled=!1)})}},t.span({className:`txt`},`Remove`))))))}),t.div({className:`col-sm-6`},t.button({type:`button`,className:`btn lg block secondary add-provider-btn`,onclick:()=>{app.modals.openProviderPicker({exclude:r.config.providers.map(e=>e.name),onselect:e=>{app.modals.openProviderSettings({name:e.name},{onsubmit:(e,n)=>{r.config.providers.length==0&&(r.config.enabled=!0),r.config.providers.push(n)}})}})}},t.i({className:`ri-add-line`,ariaHidden:!0}),t.span({className:`txt `},`Add provider`))),t.div({className:`col-sm-12`},t.button({type:`button`,className:()=>`btn secondary sm ${r.showMapping?``:`transparent`}`,onclick:()=>r.showMapping=!r.showMapping},t.span({className:`txt`},`Optional users create fields mapping`),t.i({className:()=>r.showMapping?`ri-arrow-drop-up-line`:`ri-arrow-drop-down-line`,ariaHidden:!0})),app.components.slide(()=>r.showMapping,t.div({className:`grid sm m-t-sm`},t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.mappedFields.name`},`OAuth2 full name`),app.components.select({id:n+`.mappedFields.name`,name:`oauth2.mappedFields.name`,placeholder:`Select field`,options:()=>r.regularFieldOptions,value:()=>e.oauth2.mappedFields.name,onchange:n=>{e.oauth2.mappedFields.name=n?.[0]?.value||``}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.mappedFields.avatarURL`},`OAuth2 avatar`),app.components.select({id:n+`.mappedFields.avatarURL`,name:`oauth2.mappedFields.avatarURL`,placeholder:`Select field`,options:()=>r.regularAndFileFieldOptions,value:()=>e.oauth2.mappedFields.avatarURL,onchange:n=>{e.oauth2.mappedFields.avatarURL=n?.[0]?.value||``}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.mappedFields.id`},`OAuth2 id`),app.components.select({id:n+`.mappedFields.id`,name:`oauth2.mappedFields.id`,placeholder:`Select field`,options:()=>r.regularFieldOptions,value:()=>e.oauth2.mappedFields.id,onchange:n=>{e.oauth2.mappedFields.id=n?.[0]?.value||``}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.mappedFields.username`},`OAuth2 username`),app.components.select({id:n+`.mappedFields.username`,name:`oauth2.mappedFields.username`,placeholder:`Select field`,options:()=>r.regularFieldOptions,value:()=>e.oauth2.mappedFields.username,onchange:n=>{e.oauth2.mappedFields.username=n?.[0]?.value||``}}))))))))}function yr(e){let n=`otp_`+app.utils.randomString(),r=store({get config(){return e.otp||={enabled:!1,duration:300,length:8},e.otp},get isSuperusers(){return e.system&&e.name==`_superusers`}});return t.details({pbEvent:`otpAccordion`,name:`auth-methods`,className:`accordion otp-accordion`},t.summary(null,t.i({className:`ri-time-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`One-time password (OTP)`}),t.span({className:()=>`label m-l-auto ${r.config.enabled?`success`:``}`,textContent:()=>r.config.enabled?`Enabled`:`Disabled`}),()=>{if(app.store.errors?.otp)return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.input({type:`checkbox`,id:n+`.enabled`,name:`otp.enabled`,className:`switch`,checked:()=>r.config.enabled,onchange:n=>{r.config.enabled=n.target.checked,r.isSuperusers&&(e.mfa.enabled=n.target.checked)}}),t.label({htmlFor:n+`.enabled`,textContent:`Enable`}),()=>{if(r.isSuperusers)return t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Superusers can have OTP only as part of Two-factor authentication.`)})})),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.duration`,textContent:`Duration (in seconds)`}),t.input({type:`number`,id:n+`.duration`,name:`otp.duration`,min:1,step:1,required:!0,value:()=>r.config.duration||``,oninput:e=>r.config.duration=parseInt(e.target.value,10)}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.length`,textContent:`Generated password length`}),t.input({type:`number`,id:n+`.length`,name:`otp.length`,min:1,step:1,required:!0,value:()=>r.config.length||``,oninput:e=>r.config.length=parseInt(e.target.value,10)})))))}function br(e){let n=`passwordAuth_`+app.utils.randomString(),r=store({get config(){return e.passwordAuth||={enabled:!0,identityFields:[`email`]},e.passwordAuth},get identityFieldOptions(){let n=[{value:`email`}],r=e?.fields||[],i=e?.indexes||[];for(let e of i){let i=app.utils.parseIndex(e);if(!i.unique||i.columns.length!=1||i.columns[0].name==`email`)continue;let a=r.find(e=>!e.hidden&&e.name.toLowerCase()==i.columns[0].name.toLowerCase());a&&n.push({value:a.name})}return n}});return t.details({pbEvent:`passwordAuthAccordion`,name:`auth-methods`,className:`accordion password-auth-accordion`},t.summary(null,t.i({className:`ri-lock-password-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`Identity/Password`}),t.span({className:()=>`label m-l-auto ${r.config.enabled?`success`:``}`,textContent:()=>r.config.enabled?`Enabled`:`Disabled`}),()=>{if(app.store.errors?.passwordAuth)return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.input({type:`checkbox`,id:n+`.enabled`,name:`passwordAuth.enabled`,className:`switch`,checked:()=>r.config.enabled,onchange:e=>r.config.enabled=e.target.checked}),t.label({htmlFor:n+`.enabled`,textContent:`Enable`}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.identityFields`,textContent:`Identity fields`}),app.components.select({id:n+`.identityFields`,name:`passwordAuth.identityFields`,max:99,required:!0,options:()=>r.identityFieldOptions,value:()=>r.config.identityFields,onchange:e=>{r.config.identityFields=e.map(e=>e.value)}})),t.div({className:`field-help`},`Only non-hidden fields with UNIQUE index constraint can be selected.`))))}function xr(e){let n=`token_`+app.utils.randomString(),r=store({get tokensList(){return e?.name===`_superusers`?[{key:`authToken`,label:`Auth`},{key:`passwordResetToken`,label:`Password reset`},{key:`fileToken`,label:`Protected file`}]:[{key:`authToken`,label:`Auth`},{key:`verificationToken`,label:`Email verification`},{key:`passwordResetToken`,label:`Password reset`},{key:`emailChangeToken`,label:`Email change`},{key:`fileToken`,label:`Protected file`}]}});return t.details({pbEvent:`tokenOptionsAccordion`,name:`other`,className:`accordion token-options-accordion`},t.summary(null,t.i({className:`ri-key-2-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`Token options (invalidate, duration)`})),t.div({className:`grid sm`},()=>r.tokensList.map(r=>{let i=n+r.key;return t.div({className:`col-sm-6`},t.div({className:`field token-field`},t.label({htmlFor:i,textContent:()=>r.label+` duration (in seconds)`}),t.input({id:i,type:`number`,min:1,step:1,required:!0,name:()=>r.key+`.duration`,value:()=>e[r.key].duration,oninput:n=>e[r.key].duration=parseInt(n.target.value,10)})),t.div({className:`field-help m-b-10`},t.button({type:`button`,className:()=>`link-hint ${e[r.key].secret?`txt-success`:``}`,textContent:`Invalidate all previously issued tokens`,onclick:()=>{e[r.key].secret?delete e[r.key].secret:e[r.key].secret=app.utils.randomSecret(50)}})))})))}function Sr(e){let n=`options_`+app.utils.randomString();return t.div({className:`collection-tab-content collection-options-tab-content`},t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`section-heading`},t.strong(null,`Auth methods`),t.div({className:`flex-fill`}),t.div({className:`field`},t.input({id:n+`.authAlert`,name:`authAlert.enabled`,type:`checkbox`,className:`switch sm`,checked:()=>!!e.collection.authAlert?.enabled,onchange:n=>{e.collection.authAlert=e.collection.authAlert||{},e.collection.authAlert.enabled=n.target.checked}}),t.label({htmlFor:n+`.authAlert`},`Send email alert for new logins`))),br(e.collection),()=>{if(e.originalCollection?.name!=`_superusers`)return vr(e.collection)},yr(e.collection),hr(e.collection)),t.div({className:`col-12`},t.div({className:`section-heading`},t.strong(null,`Mail templates`),t.button({tabIndex:-1,type:`buttton`,className:`m-l-auto label handle txt-bold`,textContent:`Send test email`,onclick:()=>app.modals.openMailTest(e.collection?.name)})),mr(e.collection,`verificationTemplate`,{title:`Default Verification email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{TOKEN}`]}),mr(e.collection,`resetPasswordTemplate`,{title:`Default Password reset email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{TOKEN}`]}),mr(e.collection,`confirmEmailChangeTemplate`,{title:`Default Confirm email change email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{TOKEN}`]}),mr(e.collection,`otp.emailTemplate`,{title:`Default OTP email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{OTP}`,`{OTP_ID}`]}),mr(e.collection,`authAlert.emailTemplate`,{title:`Default Login alert email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{ALERT_INFO}`]})),t.div({className:`col-12`},t.div({className:`section-heading`},t.strong(null,`Other`)),xr(e.collection))))}function Cr(e){return t.div({className:`collection-tab-content collection-fields-tab-content`},t.div({className:`collection-fields-list`},app.components.sortable({handle:`.sort-handle`,data:()=>(e.collection?.fields||[])?.filter(e=>!!app.fieldTypes[e.type]?.settings),dataItem:(n,r)=>app.fieldTypes[n.type].settings({field:n,get originalCollection(){return e.originalCollection},get collection(){return e.collection},get originalField(){return e.originalCollection?.fields?.find(e=>n.id&&e.id==n.id)},get fieldIndex(){return e.collection.fields?.findIndex(e=>n.id?e.id==n.id:e==n)}}),onchange:(n,r,i)=>{e.collection.fields=n}})),()=>app.components.addCollectionFieldButton(e.collection),t.hr(),t.p({className:`txt-bold`},`Unique constraints and indexes (`,()=>e.collection.indexes?.length,`)`),app.components.sortable({className:`indexes-list`,data:()=>e.collection.indexes||[],onchange:function(n){e.collection.indexes=n},dataItem:(n,r)=>{let i=app.utils.parseIndex(n);return t.button({type:`button`,className:()=>`label handle ${app.store.errors?.indexes?.[r]?.message?`danger error`:`success`}`,ariaDescription:app.attrs.tooltip(()=>app.store.errors?.indexes?.[r]?.message||``),onclick:()=>app.modals.openIndexUpsert(e.collection,n)},()=>{if(i.unique)return t.strong(null,`Unique:`)},t.span({className:`txt`},()=>i.columns?.map(e=>e.name).join(`, `)))},after:()=>t.button({type:`button`,className:`label handle`,onclick:()=>app.modals.openIndexUpsert(e.collection)},t.i({className:`ri-add-line`,ariaHidden:!0}),t.span({className:`txt`},`New index`))}))}function wr(e){let n=store({showRulesInfo:!1,showAuthRules:!1}),r=()=>app.attrs.tooltip(e.originalCollection?.system?`System collection rule cannot be changed.`:null,`top-left`);function i(n){return app.utils.collectionAutocompleteKeys(e.collection,n)}return t.div({className:`collection-tab-content collection-rules-tab-content`},t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`flex txt-hint txt-sm`},t.span({className:`txt`},`All rules follow the `,t.a({target:`_blank`,rel:`noopener noreferrer`,href:`https://pocketbase.io/docs/api-rules-and-filters`,textContent:`PocketBase filter syntax and operators`}),`.`),t.strong({tabIndex:-1,className:`m-l-auto link-hint`,textContent:()=>n.showRulesInfo?`Hide available fields`:`Show available fields`,onclick:()=>n.showRulesInfo=!n.showRulesInfo})),app.components.slide(()=>n.showRulesInfo,t.div({className:`alert warning m-t-sm`},t.div({className:`content`},t.p(null,`The following record fields are available:`),t.div({className:`flex flex-wrap gap-5`},()=>app.utils.getAllCollectionIdentifiers(e.collection).map(e=>t.code(null,e))),t.hr({className:`m-t-10 m-b-10`}),t.p(null,`The request fields could be accessed with the special `,t.strong(null,`@request`),` fields:`),t.div({className:`flex flex-wrap gap-5`},t.code(null,`@request.headers.*`),t.code(null,`@request.query.*`),t.code(null,`@request.body.*`),t.code(null,`@request.auth.*`)),t.hr({className:`m-t-10 m-b-10`}),t.p(null,`You could also add constraints and query other collections using the `,t.strong(null,`@collection`),` field:`),t.div({className:`flex flex-wrap gap-5`},t.code(null,`@collection.ANY_COLLECTION_NAME.*`)),t.hr({className:`m-t-10 m-b-10`}),t.p(null,`Example rule:`),()=>{let n=e.collection.fields?.find(e=>e.type==`date`||e.type==`autodate`);return n?t.code(null,`@request.auth.id != "" && ${n.name} > "2022-01-01 00:00:00.000Z"`):t.code(null,`@request.auth.id != ""`)})))),t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:`List/Search rule`,name:`listRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.listRule,oninput:n=>e.collection.listRule=n})),t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:`View rule`,name:`viewRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.viewRule,oninput:n=>e.collection.viewRule=n})),()=>{if(e.collection.type!=`view`)return[t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:[t.span({className:`txt`,textContent:`Create rule`}),t.i({hidden:()=>e.collection.createRule==null,className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`The main record fields hold the values that are going to be inserted in the database.`)})],name:`createRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.createRule,oninput:n=>e.collection.createRule=n})),t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:[t.span({className:`txt`,textContent:`Update rule`}),t.i({hidden:()=>e.collection.updateRule==null,className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`The main record fields hold the old/existing record field values. +`);for(let e of i)e!=``&&r.add(e);e.field.values=Array.from(r)},onblur:e=>{(!e.relatedTarget||!i.contains(e.relatedTarget))&&i.hidePopover()}}))),a=[watch(()=>{e.field.values?.length&&e.field.maxSelect>e.field.values.length&&(e.field.maxSelect=e.field.values.length)})];return app.components.fieldSettings(e,{header:[t.div({className:`field header-select field-select-choices-input`,onunmount:()=>{a.forEach(e=>e?.unwatch())}},t.input({type:`text`,placeholder:`Add choices*`,className:`txt-left inline-error`,value:()=>e.field.values?.join(` • `)||``,name:()=>`fields.${e.fieldIndex}.values`,onfocus:e=>(i?.showPopover({source:e.target}),i.querySelector(`textarea`)?.focus(),!1)}),i),t.div({className:`field header-select single-multiple-select`},app.components.select({required:!0,options:r,value:()=>e.field.maxSelect>1,onchange:n=>{n?.[0]?.value?e.field.maxSelect=e.field.values.length||2:e.field.maxSelect=1}}))],content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-12`,hidden:()=>e.field.maxSelect<<0<2},t.div({className:`field`},t.label({htmlFor:n+`.maxSelect`},`Max select`),t.input({type:`number`,id:n+`.maxSelect`,placeholder:`Default to single`,step:1,min:2,max:()=>e.field.values?.length||2,name:()=>`fields.${e.fieldIndex}.maxSelect`,value:()=>e.field.maxSelect||``,onchange:n=>{let r=parseInt(n.target.value,10);r>1?e.field.maxSelect=r:e.field.maxSelect=1}}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},()=>e.field.maxSelect>1?`(!=[])`:`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(()=>`Requires the field value to be nonempty ${e.field.maxSelect>1?`array`:`string`}.`)})))]})}function rr(e){return t.div({className:`record-field-view field-type-select`},()=>{let n=app.utils.toArray(e.record[e.field.name],!1);return n.length?n.map(e=>t.span({className:`label`,title:e,textContent:app.utils.truncate(e,100)})):t.span({className:`missing-value`})})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.select={icon:`ri-list-check`,label:`Select`,settings:nr,input:tr,view:rr,filterModifiers:e=>e.maxSelect>1?[`each`,`length`]:[],dummyData:(e,n=!1)=>e.maxSelect>1?e.values?.slice(0,2)||[]:e.values?.[0]||``};function ir(e){let n=`json_`+app.utils.randomString(),r=store({value:``}),i=[watch(()=>e.record[e.field.name],(n,i)=>{if(!(n!==``&&n===r.value)){if(typeof n==`string`&&!n.startsWith(`"`)&&!n.endsWith(`"`)){r.value=JSON.stringify(n===void 0?null:n),e.record[e.field.name]=r.value;return}typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)?r.value=n:n===null?r.value=`null`:r.value=JSON.stringify(n===void 0?null:n,null,2)}})];function a(){let n=r.value.trim();if(n===``){e.record[e.field.name]=null;return}try{let r=JSON.parse(n);typeof r==`string`?e.record[e.field.name]=JSON.stringify(r):e.record[e.field.name]=r}catch{e.record[e.field.name]=n}}return t.div({className:`record-field-input field-type-json`},t.div({className:`field`,onunmount:()=>{clearTimeout(void 0),i.forEach(e=>e?.unwatch())}},t.label({htmlFor:n},t.i({className:app.fieldTypes.json.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name),t.span({hidden:()=>ar(r.value.trim()),className:`json-state`,ariaDescription:app.attrs.tooltip(`Invalid JSON`,`left`)},t.i({className:`ri-error-warning-fill txt-danger`,ariaHidden:!0})),t.span({hidden:()=>!ar(r.value.trim()),className:`json-state`,ariaDescription:app.attrs.tooltip(`Valid JSON`,`left`)},t.i({className:`ri-checkbox-circle-fill txt-success`,ariaHidden:!0}))),app.components.codeEditor({language:`js`,id:n,name:()=>e.field.name,required:()=>e.field.required,value:()=>r.value,oninput:e=>r.value=e,onblur:()=>a()})),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function ar(e){if(e===``)return!0;try{return JSON.parse(e),!0}catch{return!1}}function or(e){try{let n=e.record[e.field.name];typeof n==`string`&&JSON.parse(n)}catch(n){throw new y({status:400,response:{message:`Invalid JSON data`,data:{[e.field.name]:{code:`invalid_json`,message:n.toString()}}}})}}function sr(e){let n=`f_`+app.utils.randomString(),r=store({showInfo:!1});return app.components.fieldSettings(e,{content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.maxSize`},t.span(null,`Max size `),t.small(null,`(bytes)`)),t.input({type:`number`,id:n+`.maxSize`,name:()=>`fields.${e.fieldIndex}.maxSize`,min:0,step:1,max:2**53-1,placeholder:`Default to max ~1MB`,value:()=>e.field.maxSize||``,oninput:n=>{e.field.maxSize=parseInt(n.target.value,10)}}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value}))),t.div({className:`col-sm-12`},t.button({type:`button`,className:()=>`btn sm secondary ${r.showInfo?``:`transparent`}`,onclick:()=>r.showInfo=!r.showInfo},t.span({className:`txt`},`String value normalizations`),t.i({className:()=>r.showInfo?`ri-arrow-up-s-line`:`ri-arrow-down-s-line`,ariaHidden:!0})),app.components.slide(()=>r.showInfo,t.div({className:`alert m-t-10 info`},t.div({className:`content`},`In order to support seamlessly both `,t.code(null,`application/json`),` and `,t.code(null,`multipart/form-data`),`requests, the following normalization rules are applied if the `,t.code(null,`json`),` field is a plain string:`,t.ul(null,t.li(null,`"true" is converted to the json `,t.code(null,`true`)),t.li(null,`"false" is converted to the json `,t.code(null,`false`)),t.li(null,`"null" is converted to the json `,t.code(null,`null`)),t.li(null,`"[1,2,3]" is converted to the json `,t.code(null,`[1,2,3]`)),t.li(null,`'{"a":1,"b":2}' is converted to the json `,t.code(null,`{"a":1,"b":2}`)),t.li(null,`numeric strings are converted to json number`),t.li(null,`double quoted strings are left as they are (aka. without normalizations)`),t.li(null,`any other string (empty string too) is double quoted`)),`Alternatively, if you want to avoid the string value normalizations, you can wrap your data inside an object, eg. `,t.code(null,`{"data": anything}`),`.`))))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value NOT to be null, '', [], {}.`)})))]})}function cr(e){return t.div({className:`record-field-view field-type-json`},()=>{let n=e.record[e.field.name];return e.short?t.span({className:`txt-code txt-ellipsis`,textContent:app.utils.truncate(app.utils.trimQuotedValue(JSON.stringify(n))||``)}):app.components.codeBlock({value:()=>JSON.stringify(n,null,2)})})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.json={icon:`ri-braces-line`,label:`JSON`,settings:sr,input:ir,view:cr,onrecordsave:or,dummyData:(e,n=!1)=>({example:123})};function lr(e){let n=`geo_`+app.utils.randomString(),r=store({showMap:!1});return t.div({className:`record-field-input field-type-geoPoint`},t.div({className:()=>`field-list ${e.field.required?`required`:``}`},t.label({htmlFor:n},t.i({className:app.fieldTypes.geoPoint.icon,ariaHidden:!0}),t.span({className:`txt`},()=>e.field.name)),t.div({className:`field-list-content`},t.div({className:`field-list-item p-0`},t.div({className:`fields`},t.div({className:`field addon`},t.label({htmlFor:n+`.lon`},`Longitude:`)),t.div({className:`field`},t.input({id:n+`.lon`,type:`number`,step:`any`,min:-180,max:180,placeholder:0,name:()=>e.field.name,required:()=>e.field.required,value:()=>e.record[e.field.name]?.lon||``,onchange:n=>{e.record[e.field.name]=e.record[e.field.name]||{},e.record[e.field.name].lon=Number(n.target.value)}})),t.span({className:`delimiter`}),t.div({className:`field addon`},t.label({htmlFor:n+`.lat`},`Latitude:`)),t.div({className:`field`},t.input({id:n+`.lat`,type:`number`,step:`any`,min:-90,max:90,placeholder:0,name:()=>e.field.name,required:()=>e.field.required,value:()=>e.record[e.field.name]?.lat||``,onchange:n=>{e.record[e.field.name]=e.record[e.field.name]||{},e.record[e.field.name].lat=Number(n.target.value)}})),t.span({className:`delimiter`}),t.div({className:`field addon p-5`},t.button({type:`button`,className:()=>`btn sm circle secondary ${r.showMap?``:`transparent`}`,onclick:()=>r.showMap=!r.showMap},t.i({className:`ri-map-2-line`}))))),()=>{if(r.showMap)return t.div({className:`field-list-item p-0`,style:`height: 250px`},app.components.leaflet({point:()=>e.record[e.field.name]||{lat:0,lon:0},onchange:n=>{e.record[e.field.name]=structuredClone(n)}}))})),()=>{if(e.field.help)return t.div({className:`field-help`},e.field.help)})}function ur(e){let n=`f_`+app.utils.randomString();return app.components.fieldSettings(e,{content:()=>t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},`(=true)`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value to be true.`)})))]})}function dr(e){return t.div({className:`record-field-view field-type-geoPoint`},t.span({className:`label`},()=>{let n=e.record[e.field.name];return`${n?.lon||0}, ${n?.lat||0}`}))}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.geoPoint={icon:`ri-map-pin-2-line`,label:`Geo Point`,settings:ur,input:lr,view:dr,identifierExtractor:function(e,n=``){return[n+e.name+`.lon`,n+e.name+`.lat`]},dummyData:(e,n=!1)=>({lon:0,lat:0})};function fr(e){let n=`f_`+app.utils.randomString();return app.components.fieldSettings(e,{showHidden:!1,showPresentable:!1,showDuplicate:!1,content:t.div({className:`grid sm`},t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.min`},t.span({className:`txt`},`Min length`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Clear the field or set it to 0 for no limit.`)})),t.input({type:`number`,id:n+`.min`,name:()=>`fields.${e.fieldIndex}.min`,step:1,min:0,max:71,placeholder:`No min limit`,value:()=>e.field.min||``,oninput:n=>{e.field.min=parseInt(n.target.value,10)}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.max`},t.span({className:`txt`},`Max length`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Clear the field or set it to 0 to fallback to the default limit (71).`)})),t.input({type:`number`,id:n+`.max`,name:()=>`fields.${e.fieldIndex}.max`,step:1,min:()=>e.field.min||0,max:71,placeholder:`Up to 71 chars`,value:()=>e.field.max||``,oninput:n=>{e.field.max=parseInt(n.target.value,10)}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.max`},t.span({className:`txt`},`Bcrypt cost`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Clear the field or set it to 0 to fallback to the default (10).`)})),t.input({type:`number`,id:n+`.cost`,name:()=>`fields.${e.fieldIndex}.cost`,step:1,min:4,max:31,placeholder:`Default to 10`,value:()=>e.field.cost||``,oninput:n=>{e.field.cost=parseInt(n.target.value,10)}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.pattern`},t.span({className:`txt`},`Validation pattern`)),t.input({type:`text`,id:n+`.pattern`,placeholder:`ex. ^\\w+$`,name:()=>`fields.${e.fieldIndex}.pattern`,value:()=>e.field.pattern||``,oninput:n=>e.field.pattern=n.target.value}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.help`},`Help text`),t.input({type:`text`,id:n+`.help`,name:()=>`fields.${e.fieldIndex}.help`,value:()=>e.field.help||``,oninput:n=>e.field.help=n.target.value})))),footer:()=>{if(!(e.collection?.type==`auth`&&e.field.name==`password`))return[t.div({className:`field`},t.input({className:`sm`,type:`checkbox`,id:n+`.required`,name:()=>`fields.${e.fieldIndex}.required`,checked:()=>!!e.field.required,onchange:n=>e.field.required=n.target.checked}),t.label({htmlFor:n+`.required`},t.span({className:`txt`},`Required`),t.small({className:`txt-hint`},`(!='')`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Requires the field value to be nonempty string.`)})))]}})}window.app=window.app||{},window.app.fieldTypes=window.app.fieldTypes||{},window.app.fieldTypes.password={icon:`ri-lock-password-line`,label:`Password`,settings:fr},window.app=window.app||{},window.app.modals=window.app.modals||{},window.app.modals.openIndexUpsert=function(e,n=``,r={onsave:()=>{},ondelete:()=>{}}){let i=pr(e,n,r);i&&(document.body.appendChild(i),app.modals.open(i))};function pr(e,n=``,r={}){if(!e){console.warn(`[indexUpsertModal] missing required collection argument`);return}let i,a=app.utils.randomString(),o=store({originalIndex:``,index:``,get isNew(){return o.originalIndex==``},get indexParts(){return app.utils.parseIndex(o.index)},get lowerCasedIndexColumnNames(){return o.indexParts.columns.map(e=>e.name.toLowerCase())},get canSave(){return o.lowerCasedIndexColumnNames.length>0}}),s=e?.fields?.filter(e=>!e[`@toDelete`]&&e.name!=`id`)?.map(e=>e.name)||[];function c(n){if(o.originalIndex=n||``,!n){let r=app.utils.parseIndex(``);r.tableName=e?.name||``,n=app.utils.buildIndex(r)}o.index=n}function l(){if(!e||!o.canSave){console.warn(`[saveIndex] no collection or invalid save state:`,e,o.canSave);return}e.indexes=e.indexes||[];let n=e.indexes.findIndex(e=>e==o.originalIndex);n>=0?(e.indexes[n]=o.index,app.utils.deleteByPath(app.store.errors,`indexes.`+n)):e.indexes.push(o.index),typeof r?.onsave==`function`&&r.onsave({collection:e,index:o.index,oldIndex:o.originalIndex}),f(),app.modals.close(i)}function u(){if(!e||!o.originalIndex){console.warn(`[deleteIndex] no collection or index:`,e,o.originalIndex);return}let n=e.indexes?.findIndex(e=>e==o.originalIndex);if(n==-1){console.warn(`[deleteIndex] missing index:`,o.originalIndex);return}e.indexes.splice(n,1),app.utils.deleteByPath(app.store.errors,`indexes.`+n),typeof r?.ondelete==`function`&&r.ondelete({collection:e,position:n,index:o.originalIndex}),f(),app.modals.close(i)}function d(n){let r=JSON.parse(JSON.stringify(o.indexParts));r.tableName=e?.name||``;let i=n.toLowerCase(),a=r.columns.findIndex(e=>e.name.toLowerCase()==i);a>=0?r.columns.splice(a,1):app.utils.pushUnique(r.columns,{name:n}),o.index=app.utils.buildIndex(r),f()}function f(){if(app.store.errors?.indexes){let n=e.indexes.findIndex(e=>e==o.originalIndex);app.utils.deleteByPath(app.store.errors,`indexes.`+n)}}return i=t.div({className:`modal popup index-upsert-modal`,onbeforeopen:()=>{c(n)},onafteropen:()=>{app.store.errors?.indexes&&(app.store.errors.indexes=JSON.parse(JSON.stringify(app.store.errors.indexes)))},onafterclose:e=>{e?.remove()}},t.header({className:`modal-header`},t.h6({className:`modal-title`},t.span({className:`txt`},()=>o.isNew?`Create index`:`Update index`))),t.div({className:`modal-content`},t.form({id:a+`form`,className:`grid sm index-upsert-form`,onsubmit:e=>{e.preventDefault(),l()}},t.div({className:`col-12`},t.div({className:`field`},t.input({type:`checkbox`,className:`switch`,id:a+`checkbox_unique`,checked:()=>o.indexParts.unique,onchange:n=>{let r=JSON.parse(JSON.stringify(o.indexParts));r.unique=n.target.checked,r.tableName=r.tableName||e?.name||``,o.index=app.utils.buildIndex(r)}}),t.label({htmlFor:a+`checkbox_unique`},`Unique`))),t.div({className:`col-12`},t.div({className:`field`},app.components.codeEditor({required:!0,className:`collection-index-input pre-wrap`,name:()=>`indexes.`+e.indexes?.findIndex(e=>e==o.originalIndex),placeholder:()=>`e.g. CREATE INDEX idx_test on ${e?.name||`X`} (created)`,value:()=>o.index,oninput:e=>o.index=e})),t.div({hidden:()=>!s.length,className:`field-help m-t-sm`},t.div({className:`flex flex-wrap gap-5`},t.span({className:`txt`,textContent:`Presets:`}),()=>s?.map(e=>{let n=o.lowerCasedIndexColumnNames.includes(e.toLowerCase());return t.button({type:`button`,textContent:e,className:()=>`label handle ${n?`success`:``}`,onclick:()=>d(e)})})))))),t.footer({className:`modal-footer gap-base`},t.button({type:`button`,className:`btn transparent m-r-auto`,onclick:()=>app.modals.close(i)},t.span({className:`txt`},`Close`)),t.button({hidden:()=>o.isNew,type:`button`,className:()=>`btn sm circle transparent secondary`,ariaLabel:app.attrs.tooltip(`Delete index`,`left`),onclick:()=>{app.modals.confirm(`Do you really want to remove the selected index from the collection?`,u)}},t.i({className:`ri-delete-bin-7-line`,ariaHidden:!0})),t.button({type:`submit`,"html-form":a+`form`,disabled:()=>!o.canSave,className:()=>`btn expanded`},t.span({className:`txt`},`Set index`)))),i}function mr(e,n,r={}){let i=`emailTemplate`+app.utils.randomString(),a=store({title:`Email template`,placeholders:[]}),o=app.utils.extendStore(a,r),s=store({get config(){let r=app.utils.getByPath(e,n);return r||(r={subject:``,body:``},app.utils.setByPath(e,n,r)),r},get tokensList(){return[]}}),c=()=>{if(a.placeholders?.length)return t.div({className:`field-help`},t.div({className:`flex flex-wrap gap-5`},t.span({className:`txt`},`Placeholders:`),()=>a.placeholders.map(e=>t.span({className:`label sm`},app.components.copyButton(e,e)))))};return t.details({pbEvent:`emailTemplateAccordion`,className:`accordion email-template-accordion`,name:`email-template`,onunmount:()=>{o.forEach(e=>e?.unwatch())}},t.summary(null,t.i({className:`ri-draft-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:()=>a.title}),()=>{if(app.utils.getByPath(app.store.errors,n))return t.i({ariaHidden:!0,className:`ri-error-warning-fill txt-danger m-l-auto`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.subject`,textContent:`Subject`}),app.components.codeEditor({id:i+`.subject`,name:n+`.subject`,required:!0,singleLine:!0,language:`text`,autocomplete:a.placeholders,value:()=>s.config.subject||``,oninput:e=>s.config.subject=e})),c),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.body`,textContent:`Body (HTML)`}),app.components.codeEditor({id:i+`.body`,name:n+`.body`,required:!0,language:`html`,className:`pre-wrap`,autocomplete:a.placeholders,value:()=>s.config.body||``,oninput:e=>s.config.body=e})),c)))}function hr(e){let n=`mfa_`+app.utils.randomString(),r=store({get config(){return e.mfa||={enabled:!1,duration:600,rule:``},e.mfa},get isSuperusers(){return e.system&&e.name==`_superusers`}});return t.details({pbEvent:`mfaAccordion`,name:`auth-methods`,className:`accordion mfa-accordion`},t.summary(null,t.i({className:`ri-shield-check-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`Multi-factor authentication (MFA)`}),t.span({className:()=>`label m-l-auto ${r.config.enabled?`success`:``}`,textContent:()=>r.config.enabled?`Enabled`:`Disabled`}),()=>{if(app.store.errors?.mfa)return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`alert info`},t.div({className:`content`},t.p(null,`Multi-factor authentication (MFA) requires the user to authenticate with any 2 different auth methods (otp, identity/password, oauth2) before issuing an auth token. `,t.a({href:`https://pocketbase.io/docs/authentication#multi-factor-authentication`,className:`link-hint`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Learn more.`}))))),t.div({className:`col-sm-12`},t.div({className:`field`},t.input({type:`checkbox`,id:n+`.enabled`,name:`mfa.enabled`,className:`switch`,checked:()=>r.config.enabled,onchange:n=>{r.config.enabled=n.target.checked,r.isSuperusers&&(e.otp.enabled=n.target.checked)}}),t.label({htmlFor:n+`.enabled`,textContent:`Enable`}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.duration`,textContent:`Max duration between 2 authentications (in seconds)`}),t.input({type:`number`,id:n+`.duration`,name:`mfa.duration`,min:1,step:1,required:!0,value:()=>r.config.duration||``,oninput:e=>r.config.duration=parseInt(e.target.value,10)}))),t.div({className:`col-sm-12`},app.components.ruleField({label:`MFA rule`,id:n+`.rule`,name:`mfa.rule`,nullable:!1,placeholder:`Leave empty to require MFA for everyone`,autocomplete:n=>app.utils.collectionAutocompleteKeys(e,n),value:()=>r.config.rule||``,oninput:e=>r.config.rule=e}),t.div({className:`field-help`},t.p(null,`This optional rule could be used to enable/disable MFA per account basis.`),t.p(null,`For example, to require MFA only for accounts with non-empty email you can set it to `,t.code(null,`email != ''`),`.`),t.p(null,`Leave the rule empty to require MFA for everyone.`)))))}var gr=[`id`,`email`,`emailVisibility`,`verified`,`tokenKey`,`password`],_r=[`text`,`editor`,`url`,`email`,`json`];function vr(e){let n=`oauth2_`+app.utils.randomString(),r=store({get config(){return e.oauth2||={enabled:!1,mappedFields:{},providers:[]},e.oauth2},get regularFieldOptions(){return e.fields?.filter(e=>_r.includes(e.type)&&!gr.includes(e.name)).map(e=>({value:e.name}))},get regularAndFileFieldOptions(){return e.fields?.filter(e=>(e.type==`file`||_r.includes(e.type))&&!gr.includes(e.name)).map(e=>({value:e.name}))},showMapping:!1});function i(e){app.utils.deleteByPath(app.store.errors,`oauth2.providers.`+e)}return t.details({pbEvent:`oauth2Accordion`,name:`auth-methods`,className:`accordion oauth2-accordion`},t.summary(null,t.i({className:`ri-profile-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`OAuth2`}),t.span({className:()=>`label m-l-auto ${r.config.enabled?`success`:``}`,textContent:()=>r.config.enabled?`Enabled`:`Disabled`}),()=>{if(!app.utils.isEmpty(app.store.errors?.oauth2))return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.input({type:`checkbox`,id:n+`.enabled`,name:`oauth2.enabled`,className:`switch`,checked:()=>r.config.enabled,onchange:e=>r.config.enabled=e.target.checked}),t.label({htmlFor:n+`.enabled`,textContent:`Enable`}))),()=>r.config.providers.map((e,a)=>{let o=n+e.name,s=app.store.oauth2Providers?.find(n=>n.name==e.name)||{};return t.div({className:`col-sm-6`},t.div({className:()=>{let e=`provider-card`;return app.utils.isEmpty(app.store.errors?.oauth2?.providers?.[a])||(e+=` error`),e}},t.figure({className:`provider-logo`},()=>s.logo?t.img({src:`data:image/svg+xml;base64,`+btoa(s.logo),alt:e.name+` logo`}):t.i({className:app.utils.fallbackProviderIcon,ariaHidden:!0})),t.div({className:`content`},t.span({className:`primary-txt`},()=>e.displayName||s.displayName||s.name),t.span({className:`secondary-txt`},()=>e.name||s.name)),t.div({className:`actions`},t.button({type:`button`,title:`Options`,className:`btn secondary transparent sm circle`,"html-popovertarget":o+`dropdown`},t.i({className:`ri-more-2-line`,ariaHidden:!0})),t.div({id:o+`dropdown`,className:`dropdown sm`,popover:`auto`},t.button({type:`button`,className:`dropdown-item`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),app.modals.openProviderSettings(e,{namePrefix:`oauth2.providers.`+a,onsubmit:(e,n)=>{r.config.providers[a]=n,i(a)}})}},t.span({className:`txt`},`Settings`)),t.hr(),t.button({type:`button`,className:`dropdown-item`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),app.modals.confirm(`Do you really want to remove provider "${e.displayName||s.displayName||s.name}"?`,()=>{i(a),r.config.providers.splice(a,1),r.config.providers.length==0&&(r.config.enabled=!1)})}},t.span({className:`txt`},`Remove`))))))}),t.div({className:`col-sm-6`},t.button({type:`button`,className:`btn lg block secondary add-provider-btn`,onclick:()=>{app.modals.openProviderPicker({exclude:r.config.providers.map(e=>e.name),onselect:e=>{app.modals.openProviderSettings({name:e.name},{onsubmit:(e,n)=>{r.config.providers.length==0&&(r.config.enabled=!0),r.config.providers.push(n)}})}})}},t.i({className:`ri-add-line`,ariaHidden:!0}),t.span({className:`txt `},`Add provider`))),t.div({className:`col-sm-12`},t.button({type:`button`,className:()=>`btn secondary sm ${r.showMapping?``:`transparent`}`,onclick:()=>r.showMapping=!r.showMapping},t.span({className:`txt`},`Optional users create fields mapping`),t.i({className:()=>r.showMapping?`ri-arrow-drop-up-line`:`ri-arrow-drop-down-line`,ariaHidden:!0})),app.components.slide(()=>r.showMapping,t.div({className:`grid sm m-t-sm`},t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.mappedFields.name`},`OAuth2 full name`),app.components.select({id:n+`.mappedFields.name`,name:`oauth2.mappedFields.name`,placeholder:`Select field`,options:()=>r.regularFieldOptions,value:()=>e.oauth2.mappedFields.name,onchange:n=>{e.oauth2.mappedFields.name=n?.[0]?.value||``}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.mappedFields.avatarURL`},`OAuth2 avatar`),app.components.select({id:n+`.mappedFields.avatarURL`,name:`oauth2.mappedFields.avatarURL`,placeholder:`Select field`,options:()=>r.regularAndFileFieldOptions,value:()=>e.oauth2.mappedFields.avatarURL,onchange:n=>{e.oauth2.mappedFields.avatarURL=n?.[0]?.value||``}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.mappedFields.id`},`OAuth2 id`),app.components.select({id:n+`.mappedFields.id`,name:`oauth2.mappedFields.id`,placeholder:`Select field`,options:()=>r.regularFieldOptions,value:()=>e.oauth2.mappedFields.id,onchange:n=>{e.oauth2.mappedFields.id=n?.[0]?.value||``}}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.mappedFields.username`},`OAuth2 username`),app.components.select({id:n+`.mappedFields.username`,name:`oauth2.mappedFields.username`,placeholder:`Select field`,options:()=>r.regularFieldOptions,value:()=>e.oauth2.mappedFields.username,onchange:n=>{e.oauth2.mappedFields.username=n?.[0]?.value||``}}))))))))}function yr(e){let n=`otp_`+app.utils.randomString(),r=store({get config(){return e.otp||={enabled:!1,duration:300,length:8},e.otp},get isSuperusers(){return e.system&&e.name==`_superusers`}});return t.details({pbEvent:`otpAccordion`,name:`auth-methods`,className:`accordion otp-accordion`},t.summary(null,t.i({className:`ri-time-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`One-time password (OTP)`}),t.span({className:()=>`label m-l-auto ${r.config.enabled?`success`:``}`,textContent:()=>r.config.enabled?`Enabled`:`Disabled`}),()=>{if(app.store.errors?.otp)return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.input({type:`checkbox`,id:n+`.enabled`,name:`otp.enabled`,className:`switch`,checked:()=>r.config.enabled,onchange:n=>{r.config.enabled=n.target.checked,r.isSuperusers&&(e.mfa.enabled=n.target.checked)}}),t.label({htmlFor:n+`.enabled`,textContent:`Enable`}),()=>{if(r.isSuperusers)return t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Superusers can have OTP only as part of Two-factor authentication.`)})})),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.duration`,textContent:`Duration (in seconds)`}),t.input({type:`number`,id:n+`.duration`,name:`otp.duration`,min:1,step:1,required:!0,value:()=>r.config.duration||``,oninput:e=>r.config.duration=parseInt(e.target.value,10)}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:n+`.length`,textContent:`Generated password length`}),t.input({type:`number`,id:n+`.length`,name:`otp.length`,min:1,step:1,required:!0,value:()=>r.config.length||``,oninput:e=>r.config.length=parseInt(e.target.value,10)})))))}function br(e){let n=`passwordAuth_`+app.utils.randomString(),r=store({get config(){return e.passwordAuth||={enabled:!0,identityFields:[`email`]},e.passwordAuth},get identityFieldOptions(){let n=[{value:`email`}],r=e?.fields||[],i=e?.indexes||[];for(let e of i){let i=app.utils.parseIndex(e);if(!i.unique||i.columns.length!=1||i.columns[0].name==`email`)continue;let a=r.find(e=>!e.hidden&&e.name.toLowerCase()==i.columns[0].name.toLowerCase());a&&n.push({value:a.name})}return n}});return t.details({pbEvent:`passwordAuthAccordion`,name:`auth-methods`,className:`accordion password-auth-accordion`},t.summary(null,t.i({className:`ri-lock-password-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`Identity/Password`}),t.span({className:()=>`label m-l-auto ${r.config.enabled?`success`:``}`,textContent:()=>r.config.enabled?`Enabled`:`Disabled`}),()=>{if(app.store.errors?.passwordAuth)return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.div({className:`grid sm`},t.div({className:`col-sm-12`},t.div({className:`field`},t.input({type:`checkbox`,id:n+`.enabled`,name:`passwordAuth.enabled`,className:`switch`,checked:()=>r.config.enabled,onchange:e=>r.config.enabled=e.target.checked}),t.label({htmlFor:n+`.enabled`,textContent:`Enable`}))),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:n+`.identityFields`,textContent:`Identity fields`}),app.components.select({id:n+`.identityFields`,name:`passwordAuth.identityFields`,max:99,required:!0,options:()=>r.identityFieldOptions,value:()=>r.config.identityFields,onchange:e=>{r.config.identityFields=e.map(e=>e.value)}})),t.div({className:`field-help`},`Only non-hidden fields with UNIQUE index constraint can be selected.`))))}function xr(e){let n=`token_`+app.utils.randomString(),r=store({get tokensList(){return e?.name===`_superusers`?[{key:`authToken`,label:`Auth`},{key:`passwordResetToken`,label:`Password reset`},{key:`fileToken`,label:`Protected file`}]:[{key:`authToken`,label:`Auth`},{key:`verificationToken`,label:`Email verification`},{key:`passwordResetToken`,label:`Password reset`},{key:`emailChangeToken`,label:`Email change`},{key:`fileToken`,label:`Protected file`}]}});return t.details({pbEvent:`tokenOptionsAccordion`,name:`other`,className:`accordion token-options-accordion`},t.summary(null,t.i({className:`ri-key-2-line`,ariaHidden:!0}),t.span({className:`txt`,textContent:`Token options (invalidate, duration)`})),t.div({className:`grid sm`},()=>r.tokensList.map(r=>{let i=n+r.key;return t.div({className:`col-sm-6`},t.div({className:`field token-field`},t.label({htmlFor:i,textContent:()=>r.label+` duration (in seconds)`}),t.input({id:i,type:`number`,min:1,step:1,required:!0,name:()=>r.key+`.duration`,value:()=>e[r.key].duration,oninput:n=>e[r.key].duration=parseInt(n.target.value,10)})),t.div({className:`field-help m-b-10`},t.button({type:`button`,className:()=>`link-hint ${e[r.key].secret?`txt-success`:``}`,textContent:`Invalidate all previously issued tokens`,onclick:()=>{e[r.key].secret?delete e[r.key].secret:e[r.key].secret=app.utils.randomSecret(50)}})))})))}function Sr(e){let n=`options_`+app.utils.randomString();return t.div({className:`collection-tab-content collection-options-tab-content`},t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`section-heading`},t.strong(null,`Auth methods`),t.div({className:`flex-fill`}),t.div({className:`field`},t.input({id:n+`.authAlert`,name:`authAlert.enabled`,type:`checkbox`,className:`switch sm`,checked:()=>!!e.collection.authAlert?.enabled,onchange:n=>{e.collection.authAlert=e.collection.authAlert||{},e.collection.authAlert.enabled=n.target.checked}}),t.label({htmlFor:n+`.authAlert`},`Send email alert for new logins`))),br(e.collection),()=>{if(e.originalCollection?.name!=`_superusers`)return vr(e.collection)},yr(e.collection),hr(e.collection)),t.div({className:`col-12`},t.div({className:`section-heading`},t.strong(null,`Mail templates`),t.button({tabIndex:-1,type:`buttton`,className:`m-l-auto label handle txt-bold`,textContent:`Send test email`,onclick:()=>app.modals.openMailTest(e.collection?.name)})),mr(e.collection,`verificationTemplate`,{title:`Default Verification email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{TOKEN}`]}),mr(e.collection,`resetPasswordTemplate`,{title:`Default Password reset email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{TOKEN}`]}),mr(e.collection,`confirmEmailChangeTemplate`,{title:`Default Confirm email change email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{TOKEN}`]}),mr(e.collection,`otp.emailTemplate`,{title:`Default OTP email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{OTP}`,`{OTP_ID}`]}),mr(e.collection,`authAlert.emailTemplate`,{title:`Default Login alert email template`,placeholders:[`{APP_NAME}`,`{APP_URL}`,`{RECORD:*}`,`{ALERT_INFO}`]})),t.div({className:`col-12`},t.div({className:`section-heading`},t.strong(null,`Other`)),xr(e.collection))))}function Cr(e){return t.div({className:`collection-tab-content collection-fields-tab-content`},t.div({className:`collection-fields-list`},app.components.sortable({handle:`.sort-handle`,data:()=>(e.collection?.fields||[])?.filter(e=>!!app.fieldTypes[e.type]?.settings),dataItem:(n,r)=>app.fieldTypes[n.type].settings({field:n,get originalCollection(){return e.originalCollection},get collection(){return e.collection},get originalField(){return e.originalCollection?.fields?.find(e=>n.id&&e.id==n.id)},get fieldIndex(){return e.collection.fields?.findIndex(e=>n.id?e.id==n.id:e==n)}}),onchange:(n,r,i)=>{e.collection.fields=n}})),()=>app.components.addCollectionFieldButton(e.collection),t.hr(),t.p({className:`txt-bold`},`Unique constraints and indexes (`,()=>e.collection.indexes?.length,`)`),app.components.sortable({className:`indexes-list`,data:()=>e.collection.indexes||[],onchange:function(n){e.collection.indexes=n},dataItem:(n,r)=>{let i=app.utils.parseIndex(n);return t.button({type:`button`,className:()=>`label handle ${app.store.errors?.indexes?.[r]?.message?`danger error`:`success`}`,ariaDescription:app.attrs.tooltip(()=>app.store.errors?.indexes?.[r]?.message||``),onclick:()=>app.modals.openIndexUpsert(e.collection,n)},()=>{if(i.unique)return t.strong(null,`Unique:`)},t.span({className:`txt`},()=>i.columns?.map(e=>e.name).join(`, `)))},after:()=>t.button({type:`button`,className:`label handle`,onclick:()=>app.modals.openIndexUpsert(e.collection)},t.i({className:`ri-add-line`,ariaHidden:!0}),t.span({className:`txt`},`New index`))}))}function wr(e){let n=store({showRulesInfo:!1,showAuthRules:!1}),r=()=>app.attrs.tooltip(e.originalCollection?.system?`System collection rule cannot be changed.`:null,`top-left`);function i(n){return app.utils.collectionAutocompleteKeys(e.collection,n)}return t.div({className:`collection-tab-content collection-rules-tab-content`},t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`flex txt-hint txt-sm`},t.span({className:`txt`},`All rules follow the `,t.a({target:`_blank`,rel:`noopener noreferrer`,href:`https://pocketbase.io/docs/api-rules-and-filters`,textContent:`PocketBase filter syntax and operators`}),`.`),t.strong({tabIndex:-1,className:`m-l-auto link-hint`,textContent:()=>n.showRulesInfo?`Hide available fields`:`Show available fields`,onclick:()=>n.showRulesInfo=!n.showRulesInfo})),app.components.slide(()=>n.showRulesInfo,t.div({className:`alert warning m-t-sm`},t.div({className:`content`},t.p(null,`The following record fields are available:`),t.div({className:`flex flex-wrap gap-5`},()=>app.utils.getAllCollectionIdentifiers(e.collection).map(e=>t.code(null,e))),t.hr({className:`m-t-10 m-b-10`}),t.p(null,`The request fields could be accessed with the special `,t.strong(null,`@request`),` fields:`),t.div({className:`flex flex-wrap gap-5`},t.code(null,`@request.headers.*`),t.code(null,`@request.query.*`),t.code(null,`@request.body.*`),t.code(null,`@request.auth.*`)),t.hr({className:`m-t-10 m-b-10`}),t.p(null,`You could also add constraints and query other collections using the `,t.strong(null,`@collection`),` field:`),t.div({className:`flex flex-wrap gap-5`},t.code(null,`@collection.ANY_COLLECTION_NAME.*`)),t.hr({className:`m-t-10 m-b-10`}),t.p(null,`Example rule:`),()=>{let n=e.collection.fields?.find(e=>e.type==`date`||e.type==`autodate`);return n?t.code(null,`@request.auth.id != "" && ${n.name} > "2022-01-01 00:00:00.000Z"`):t.code(null,`@request.auth.id != ""`)})))),t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:`List/Search rule`,name:`listRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.listRule,oninput:n=>e.collection.listRule=n})),t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:`View rule`,name:`viewRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.viewRule,oninput:n=>e.collection.viewRule=n})),()=>{if(e.collection.type!=`view`)return[t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:[t.span({className:`txt`,textContent:`Create rule`}),t.i({hidden:()=>e.collection.createRule==null,className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`The main record fields hold the values that are going to be inserted in the database.`)})],name:`createRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.createRule,oninput:n=>e.collection.createRule=n})),t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:[t.span({className:`txt`,textContent:`Update rule`}),t.i({hidden:()=>e.collection.updateRule==null,className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`The main record fields hold the old/existing record field values. To target the newly submitted ones you can use @request.body.*.`)})],name:`updateRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.updateRule,oninput:n=>e.collection.updateRule=n})),t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:`Delete rule`,name:`deleteRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.deleteRule,oninput:n=>e.collection.deleteRule=n}))]}),()=>{if(e.collection.type==`auth`)return[t.hr({className:`m-t-base m-b-base`}),t.button({type:`button`,onmount:()=>{n.showAuthRules=e.collection.manageRule!==null||e.collection.authRule!==``},className:()=>`btn secondary sm ${n.showAuthRules?``:`transparent`}`,onclick:()=>{n.showAuthRules=!n.showAuthRules}},t.span({className:`txt`},`Additional auth collection rules`),t.i({ariaHidden:!0,className:()=>n.showAuthRules?`ri-arrow-drop-up-line`:`ri-arrow-drop-down-line`})),app.components.slide(()=>n.showAuthRules,t.div({className:`grid sm m-t-sm`},t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:`Authentication rule`,name:`authRule`,placeholder:``,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.authRule,oninput:n=>e.collection.authRule=n}),t.div({className:`field-help`},t.p(null,`This rule is executed every time `,t.strong(null,`before authentication`),` allowing you to restrict who can authenticate.`),t.p(null,`For example, to allow only verified users you can set it to `,t.code(null,`verified = true`),`.`),t.p(null,`Leave it empty to allow anyone with an account to authenticate.`),t.p(null,`To disable authentication entirely you can change it to "Set superusers only".`))),t.div({className:`col-12`,ariaDescription:r()},app.components.ruleField({label:`Manage rule`,name:`manageRule`,autocomplete:i,disabled:()=>e.originalCollection?.system,value:()=>e.collection.manageRule,oninput:n=>e.collection.manageRule=n}),t.div({className:`field-help`},t.p(null,`This rule is executed in addition to the `,t.strong(null,`create`),` and `,t.strong(null,`update`),` API rules.`),t.p(null,`It enables superuser-like permissions to allow fully managing the auth record(s), eg. changing the password without requiring to enter the old one, directly updating the verified state or email, etc.`)))))]})}var Tr=`test_view_query`;function Er(e){let n=`query_`+app.utils.randomString(),r=`SELECT.FROM.WHERE.LEFT JOIN.INNER JOIN.ON.AS.GROUP BY.HAVING.ORDER BY.ASC.DESC.LIMIT.OFFSET.WITH.NOT.IN.AND.OR.EXISTS.LIKE.CAST.REAL.DECIMAL.NUMERIC.INT.TEXT.BOOL`.split(`.`),i=store({testRecords:[],testError:``,isTesting:!1});async function a(n){if(i.isTesting=!0,i.testRecords=[],(app.store.errors?.viewQuery||app.store.errors?.fields)&&(delete app.store.errors.viewQuery,delete app.store.errors.fields),!n){i.testError=``,i.isTesting=!1;return}try{let r=await app.pb.collections.dryRunViewQuery(n,{requestKey:Tr});e.collection?.id?i.testRecords=r.sample.map(n=>(n.collectionId=e.collection?.id,n.collectionName=e.collection?.name,n)):i.testRecords=r.sample,i.testError=``,i.isTesting=!1}catch(e){e.isAbort||(i.testError=e.message||`Invalid query.`,i.isTesting=!1)}}let o,s=[watch(()=>e.collection?.viewQuery,e=>{clearTimeout(o),o=setTimeout(()=>a(e),200)})];return t.div({pbEvent:`collectionViewQueryTabContent`,className:`collection-tab-content collection-view-query-tab-content`,onunmount:()=>{clearTimeout(o),app.pb.cancelRequest(Tr),s.forEach(e=>e?.unwatch())}},t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`txt-right txt-sm m-b-10`},t.button({type:`button`,className:`txt-bold link-hint`,"html-popovertarget":n+`caveats_dropdown`},()=>`Query caveats`)),t.div({id:n+`caveats_dropdown`,className:`dropdown sm query-caveats-dropdown`,popover:`auto`},t.ul(null,t.li(null,`Wildcard columns (*) are not supported.`),t.li(null,`The query must have a unique `,t.code(null,`id`),` column.`,t.br(),`If your query doesn't have a suitable one, you can use the universal `,t.code(null,`(ROW_NUMBER() OVER()) as id`),`.`),t.li(null,`Expressions must be aliased with a valid formatted field name, e.g. `,t.code(null,`MAX(balance) as maxBalance`),`.`),t.li(null,`Combined/multi-spaced expressions must be wrapped in parenthesis, e.g. `,t.code(null,`(MAX(balance) + 1) as maxBalance`),`.`),t.li(null,`UNION expressions are supported but the entire query must be wrapped in parenthesis.`))),t.div({className:`field`},t.label({htmlFor:n+`.viewQuery`},t.span({className:`txt`},`Select query`),t.span({hidden:()=>!i.testError,className:`query-state`,ariaDescription:app.attrs.tooltip(`Invalid query`,`left`)},t.i({className:`ri-error-warning-fill txt-danger`,ariaHidden:!0})),t.span({hidden:()=>!!i.testError,className:`query-state`,ariaDescription:app.attrs.tooltip(`Valid query`,`left`)},t.i({className:`ri-checkbox-circle-fill txt-success`,ariaHidden:!0}))),app.components.codeEditor({id:n+`.viewQuery`,name:`viewQuery`,language:`sql`,required:!0,autocomplete:r,className:`inline-error`,value:()=>e.collection.viewQuery||``,oninput:n=>{e.collection.viewQuery=n}}))),t.div({className:`col-12`},t.p({className:`txt-sm txt-bold`},`Sample output:`),t.div({className:`view-query-sample-wrapper`},t.span({hidden:()=>!i.isTesting,className:`loader sm`}),app.components.codeBlock({language:()=>i.testError?`plain`:`js`,className:()=>`view-query-sample ${i.testError?`txt-danger`:``}`,value:()=>i.testRecords?.length?JSON.stringify(i.testRecords,null,2):i.testError||`N/A`})))))}window.app=window.app||{},window.app.modals=window.app.modals||{},window.app.modals.openCollectionUpsert=function(e={},n={onbeforeopen:null,onafteropen:null,onbeforeclose:null,onafterclose:null,onsave:null,ondelete:null,onduplicate:null,ontruncate:null}){app.store.errors=null;let r=Dr(e||{},n||{});document.body.appendChild(r),app.modals.open(r)},window.app.collectionTypes={base:{icon:`ri-folder-2-line`,tabs:{Fields:Cr,"API rules":wr}},view:{icon:`ri-table-line`,tabs:{Query:Er,"API rules":wr}},auth:{icon:`ri-group-line`,tabs:{Fields:Cr,"API rules":wr,Options:Sr}}};function Dr(e,n){let r,i=`collection_upsert_`+app.utils.randomString(),a=store({isSaving:!1,originalCollection:{},collection:{},selectedTab:``,errorTabs:{},get activeTab(){return app.collectionTypes[a.collection.type]?.tabs&&(!a.selectedTab||!app.collectionTypes[a.collection.type].tabs?.[a.selectedTab])?Object.keys(app.collectionTypes[a.collection.type].tabs)?.[0]||``:a.selectedTab},get isNew(){return app.utils.isEmpty(a.originalCollection?.id)},get collectionTypeOptions(){return Object.keys(app.collectionTypes).map(e=>({value:e,label:app.utils.sentenize(e,!1)+` collection`}))},get collectionHash(){return Object.keys(a.collection).length,JSON.stringify(a.collection)},get originalCollectionHash(){return JSON.stringify(a.originalCollection)},get hasChanges(){return a.originalCollectionHash!=a.collectionHash},get canSave(){return!a.isSaving&&(a.isNew||a.hasChanges)}});async function o(e){app.utils.isEmpty(e)&&(e=JSON.parse(JSON.stringify(app.store.collectionScaffolds.base))||{type:`base`,fields:[]},e.fields.push({type:`autodate`,name:`created`,onCreate:!0}),e.fields.push({type:`autodate`,name:`updated`,onCreate:!0,onUpdate:!0})),a.originalCollection=JSON.parse(JSON.stringify(e)),a.collection=JSON.parse(JSON.stringify(e))}async function s(e=!0){a.canSave&&(a.isSaving=!0,app.modals.openCollectionChangesConfirmation(a.originalCollection,a.collection,()=>l(e),()=>{a.isSaving=!1}))}function c(){let e=JSON.parse(JSON.stringify(a.collection));e.fields=e.fields||[];for(let n=e.fields.length-1;n>=0;n--)if(e.fields[n][`@toDelete`]){e.fields.splice(n,1);continue}return e}async function l(e=!0){a.isSaving=!0;try{let i=c(),o=app.utils.isEmpty(a.originalCollection?.id),s;s=o?app.pb.collections.create(i):app.pb.collections.update(a.originalCollection.id,i);let l=JSON.stringify(await s);app.store.collectionScaffolds=await app.pb.collections.getScaffolds({requestKey:`save.reloadScaffolds`}),a.originalCollection=JSON.parse(l),a.collection=JSON.parse(l),app.store.addOrUpdateCollection(JSON.parse(l)),n?.onsave?.(JSON.parse(l),o),a.isSaving=!1,app.toasts.success(o?`Successfully created collection "${a.collection.name}".`:`Successfully updated collection "${a.collection.name}".`,{key:`collectionSave`}),app.store.errors=null,e&&app.modals.close(r,!0)}catch(e){e?.isAbort||(a.isSaving=!1,app.checkApiError(e,!1),app.toasts.error(e.message||`Failed to save collection.`,{key:`collectionSave`}))}}function u(){a.collection=JSON.parse(JSON.stringify(a.originalCollection)),app.store.errors=null}async function d(){let e=a.originalCollection?JSON.parse(JSON.stringify(a.originalCollection)):{};return e.id=``,e.system=!1,e.name+=`_duplicate`,e.created=``,e.updated=``,e.indexes=e.indexes?.map(n=>app.utils.replaceIndexFields(n,n=>({indexName:n.indexName+app.utils.randomString(3),tableName:e.name})))||[],await n.onduplicate?.(e),o(e)}async function f(e){a.selectedTab=e,await new Promise(e=>setTimeout(e,0)),app.store.errors&&(app.store.errors=JSON.parse(JSON.stringify(app.store.errors)))}return r=t.div({pbEvent:`collectionUpsertModal`,"html-data-collectionId":()=>a.originalCollection?.id,"html-data-collectionName":()=>a.originalCollection?.name,className:`modal collection-upsert-modal`,inert:()=>a.isSaving,onkeydown:e=>{if((e.ctrlKey||e.metaKey)&&e.code==`KeyS`){e.preventDefault();let n=document.activeElement;n?.blur(),s(!1),n?.focus()}},onbeforeopen:()=>(o(e),n.onbeforeopen?.(el)),onafteropen:e=>{n.onafteropen?.(e)},onbeforeclose:(e,r)=>r?n.onbeforeclose?.(e):a.isSaving?!1:a.hasChanges?new Promise(r=>{app.modals.confirm(`You have unsaved changes. Do you really want to discard them?`,()=>r(n.onbeforeclose?.(e)),()=>r(!1))}):n.onbeforeclose?.(e),onafterclose:e=>{n.onafterclose?.(e),e?.remove()},onmount:e=>{e._watchers?.forEach(e=>e?.unwatch()),e._watchers=[watch(()=>a.collection.type,(e,n)=>{if(!n||e==n||!app.store.collectionScaffolds[e])return;app.utils.deleteByPath(app.store.errors,`fields`);let r=JSON.parse(JSON.stringify(app.store.collectionScaffolds[e]));a.collection=Object.assign(structuredClone(r),JSON.parse(JSON.stringify(a.collection))),a.originalCollection=r,Or(a.collection)}),watch(()=>a.collection.name,(n,r)=>{n=app.utils.slugify(n),a.collection.name=n,!(r===void 0||!n||n==r)&&(clearTimeout(e.__collectionRenameTimeoutId),e.__collectionRenameTimeoutId=setTimeout(()=>{a.collection.indexes=a.collection.indexes?.map(e=>app.utils.replaceIndexFields(e,{tableName:a.collection.name}))},150))}),watch(()=>JSON.stringify(app.store.errors),async e=>{if(!e){a.errorTabs={};return}await new Promise(e=>setTimeout(e,0)),a.errorTabs={};let n=r?.querySelectorAll(`.modal-content [data-tab] .error`);for(let e of n){let n=e.closest(`[data-tab]`)?.dataset?.tab;n&&(a.errorTabs[n]=!0)}})]},onunmount:e=>{clearTimeout(e?.__collectionRenameTimeoutId),e?._watchers?.forEach(e=>e?.unwatch())}},t.header({className:`modal-header isolated`},t.div({className:`grid sm`},t.div({className:`col-12 flex`},t.h6({className:`modal-title`},t.span(null,()=>a.isNew?`Create `:`Edit `),t.strong({hidden:()=>a.isNew,className:`txt-ellipsis collection-name`},()=>a.originalCollection?.name),t.span(null,` collection`)),t.div({className:`flex-fill`}),()=>{if(!app.utils.isEmpty(a.originalCollection?.id))return[t.button({type:`button`,className:`btn sm circle transparent`,title:`More options`,"html-popovertarget":i+`modal-header-dropdown`},t.i({className:`ri-more-line`,ariaHidden:!0})),t.div({id:i+`modal-header-dropdown`,className:`dropdown nowrap modal-header-dropdown`,popover:`auto`},t.button({type:`button`,className:`dropdown-item`,onclick:e=>{e.target.closest(`.dropdown`).hidePopover(),app.utils.copyToClipboard(JSON.stringify(a.originalCollection,null,2)),app.toasts.success(`Collection copied to clipboard!`)}},t.i({className:`ri-braces-line`,ariaHidden:!0}),t.span({className:`txt`},`Copy JSON`)),t.button({type:`button`,className:`dropdown-item`,onclick:e=>{e.target.closest(`.dropdown`).hidePopover(),a.hasChanges?app.modals.confirm(`You have unsaved changes. Do you really want to discard them?`,d,null,{yesButton:`Yes, discard`}):d()}},t.i({className:`ri-file-copy-line`,ariaHidden:!0}),t.span({className:`txt`},`Duplicate`)),t.hr(),()=>{if(a.collection.type!=`view`)return kr(a,n)},()=>{if(!a.collection.system)return Ar(a,n)})]}),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:i+`col_name`,textContent:()=>`Name${a.collection?.system?` (system)`:``}`}),t.input({id:i+`col_name`,type:`text`,name:`name`,required:!0,spellcheck:!1,placeholder:`e.g. posts`,autofocus:()=>a.isNew,disabled:()=>!a.isNew&&a.collection?.system,value:()=>a.collection.name||``,onmount:e=>{e.addEventListener(`compositionend`,e=>{a.collection.name=e.target.value})},oninput:e=>{e.isComposing||(a.collection.name=e.target.value)}})),t.div({className:`field addon`},t.button({type:`button`,disabled:()=>!a.isNew,className:()=>`btn sm collection-type-select ${a.isNew?`outline`:`transparent`}`,"html-popovertarget":i+`col_type_dropdown`},t.span({className:`txt`},`Type: `,()=>app.utils.sentenize(a.collection.type,!1)||`N/A`),t.i({hidden:()=>!a.isNew,ariaHidden:!0,className:`ri-arrow-drop-down-line m-l-auto`})),t.div({id:i+`col_type_dropdown`,className:`dropdown nowrap collection-type-dropdown`,popover:`auto`},()=>{let e=[];for(let n of a.collectionTypeOptions)e.push(t.button({type:`button`,className:()=>`dropdown-item ${n.value==a.collection.type?`active`:``}`,onclick:e=>{e.target.closest(`.dropdown`).hidePopover(),a.collection.type=n.value}},t.i({ariaHidden:!0,className:app.collectionTypes[n.value]?.icon||app.utils.fallbackCollectionIcon}),t.span({className:`txt`},n.label||n.value)));return e})))),t.div({className:`col-12`},t.nav({className:`tabs-header equal-width`},()=>{let e=[],n=app.collectionTypes[a.collection.type]?.tabs||{};for(let r in n)e.push(t.button({type:`button`,"html-data-tab":r,disabled:()=>a.isSaving,className:()=>`tab-item ${a.activeTab==r?`active`:``}`,onclick:()=>f(r)},t.span({className:`txt`},r),()=>{if(a.errorTabs[r])return t.i({className:`ri-error-warning-fill txt-danger txt-base`,ariaDescription:app.attrs.tooltip(`Has errors`)})}));return e})))),t.div({className:`modal-content`},()=>{let e=[],n=app.collectionTypes[a.collection.type]?.tabs||{};for(let r in n)e.push(t.div({"html-data-tab":r,hidden:()=>a.activeTab!=r,className:`tab-content-wrapper block`},()=>app.collectionTypes[a.collection.type]?.tabs?.[r]?.(a)));return e}),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,disabled:()=>a.isSaving,onclick:()=>app.modals.close(r)},t.span({className:`txt`},`Close`)),()=>{let e=JSON.stringify(app.store.errors,null,2);if(!(e==``||e==`null`||e==`{}`||e==`[]`))return t.i({className:`ri-error-warning-line txt-danger`,ariaDescription:app.attrs.tooltip(()=>`Raw errors: `+e,`top`,`code`)})},t.div({className:`btns`},t.button({type:`button`,className:()=>`btn expanded-lg ${a.isSaving?`loading`:``}`,disabled:()=>!a.canSave,onclick:()=>s(!0)},t.span({className:`txt`},()=>a.isNew?`Create`:`Save changes`)),t.button({type:`button`,title:`Save options`,className:()=>`btn p-5`,disabled:()=>!a.canSave,"html-popovertarget":i+`save_options`},t.i({className:`ri-arrow-up-s-line`,ariaHidden:!0})),t.div({id:i+`save_options`,className:`dropdown nowrap`,popover:`auto`},t.button({type:`button`,className:`dropdown-item`,onclick:e=>{e.target.closest(`.dropdown`).hidePopover(),s(!1)}},t.span({className:`txt`},`Save and continue`),t.small({className:`txt-hint`},`(Ctrl+S)`)),t.hr(),t.button({type:`button`,className:`dropdown-item`,onclick:e=>{e.target.closest(`.dropdown`).hidePopover(),u()}},t.span({className:`txt`},`Reset form`)))))),r}function Or(e){let n=JSON.parse(JSON.stringify(app.store.collectionScaffolds[e.type])),r=JSON.parse(JSON.stringify(e.fields))||[],i=r.filter(e=>!e.system);e.fields=n.fields||[];for(let n of r){if(!n.system)continue;let r=e.fields.find(e=>e.name==n.name);r&&Object.assign(r,n)}for(let n of i)e.fields.push(n);if(e.indexes=e.indexes||[],e.indexes.length){let r=n?.indexes||[];indexesLoop:for(let n=e.indexes.length-1;n>=0;n--){let i=app.utils.parseIndex(e.indexes[n]),a=i.indexName.toLowerCase();for(let i of r)if(a==app.utils.parseIndex(i).indexName.toLowerCase()){e.indexes.splice(n,1);continue indexesLoop}for(let r of i.columns)if(!e.fields.find(e=>e.name.toLowerCase()==r.name.toLowerCase())){e.indexes.splice(n,1);continue indexesLoop}}}app.utils.mergeUnique(e.indexes,n.indexes),e.indexes=e.indexes?.map(n=>app.utils.replaceIndexFields(n,{tableName:e.name||``}))}function kr(e,n){let r=`truncate_`+app.utils.randomString(),i=store({isSubmitting:!1,nameConfirm:``});async function a(){if(i.isSubmitting||!e.originalCollection?.name||e.originalCollection.name!=i.nameConfirm)return!1;i.isSubmitting=!0;try{return await app.pb.collections.truncate(e.originalCollection.name),n.ontruncate?.(JSON.parse(JSON.stringify(e.originalCollection))),app.toasts.success(`Successfully truncated collection "${e.originalCollection.name}".`),i.isSubmitting=!1,!0}catch(e){i.isSubmitting=!1,app.checkApiError(e)}return!1}return t.button({type:`button`,className:`dropdown-item txt-danger`,disabled:()=>i.isSubmitting,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),app.modals.confirm(t.div(null,t.h6({className:`block txt-center`},`Do you really want to delete all records of the collection?`),t.div({className:`confirm-collection-label txt-bold m-t-sm m-b-sm`},`Type the collection name `,t.div({className:`label`},()=>e.originalCollection.name,app.components.copyButton(()=>e.originalCollection?.name)),` to confirm:`),t.div({className:`field`},t.label({htmlFor:r+`.confirm_name`},`Collection name`),t.input({id:r+`.confirm_name`,type:`text`,required:!0,pattern:()=>RegExp.escape(e.originalCollection.name),value:()=>i.nameConfirm,oninput:e=>i.nameConfirm=e.target.value}))),async()=>{if(document.getElementById(r+`.confirm_name`)?.reportValidity(),!await a())return!1;app.modals.close(n.target.closest(`.modal`))},()=>{i.nameConfirm=``})}},t.i({className:`ri-eraser-line`,ariaHidden:!0}),t.span({className:`txt`},`Truncate`))}function Ar(e,n){let r=`delete_`+app.utils.randomString(),i=store({isSubmitting:!1,nameConfirm:``});async function a(){if(i.isSubmitting||!e.originalCollection?.name||e.originalCollection.name!=i.nameConfirm)return!1;i.isSubmitting=!0;try{return await app.pb.collections.delete(e.originalCollection.name),n?.ondelete?.(JSON.parse(JSON.stringify(e.originalCollection))),app.utils.removeByKey(app.store.collections,`id`,e.originalCollection.id),app.toasts.success(`Successfully deleted collection "${e.originalCollection.name}".`),i.isSubmitting=!1,!0}catch(e){i.isSubmitting=!1,app.checkApiError(e)}return!1}return t.button({type:`button`,className:`dropdown-item txt-danger`,disabled:()=>i.isSubmitting,onclick:n=>{n.target.closest(`.dropdown`).hidePopover();let o=n.target.closest(`.modal`);app.modals.confirm(t.div({className:`block`},t.h6({className:`block txt-center`},()=>e.originalCollection.type==`view`?`Do you really want to delete the selected collection?`:`Do you really want to delete the selected collection and all its records`),t.div({className:`confirm-collection-label txt-bold m-t-sm m-b-sm`},`Type the collection name `,t.div({className:`label`},()=>e.originalCollection.name,app.components.copyButton(()=>e.originalCollection?.name)),` to confirm:`),t.div({className:`field`},t.label({htmlFor:r+`.confirm_name`},`Collection name`),t.input({id:r+`.confirm_name`,type:`text`,required:!0,pattern:()=>RegExp.escape(e.originalCollection.name),value:()=>i.nameConfirm,oninput:e=>i.nameConfirm=e.target.value}))),async()=>{if(document.getElementById(r+`.confirm_name`)?.reportValidity(),!await a())return!1;app.modals.close(o)},()=>{i.nameConfirm=``})}},t.i({className:`ri-delete-bin-7-line`,ariaHidden:!0}),t.span({className:`txt`},`Delete`))}window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.addCollectionFieldButton=function(e){let n=`new_field_`+app.utils.randomString();function r(n){let r={id:``,name:i(n),type:n,system:!1,hidden:!1,presentable:!1,required:!1,__focus:!0};e.fields=e.fields||[];let a=e.fields.findLastIndex(e=>e.type!=`autodate`);r.type!=`autodate`&&a>=0?e.fields.splice(a+1,0,r):e.fields.push(r)}function i(e=``){let n=e,r=2,i=e.match(/\d+$/)?.[0]||``,o=i?e.substring(0,e.length-i.length):e;for(;a(n);)n=o+((i<<0)+r),r++;return n}function a(n){return!!e.fields?.find(e=>e.name.toLowerCase()===n.toLowerCase())}return t.div({className:`new-collection-field-btn-wrapper`},t.button({type:`button`,className:`btn block outline`,"html-popovertarget":n+`_dropdown`},t.i({className:`ri-add-line`,ariaHidden:!0}),t.span({className:`txt`},`New field`)),t.div({id:n+`_dropdown`,className:`dropdown field-types-dropdown`,popover:`auto`},()=>{let e=[];for(let n in app.fieldTypes){if(n==`password`)continue;let i=app.fieldTypes[n];i.settings&&e.push(t.button({type:`button`,className:`dropdown-item`,onclick:e=>{e.target.closest(`.dropdown`)?.hidePopover(),r(n)}},t.i({className:i.icon||app.utils.fallbackFieldIcon,ariaHidden:!0}),t.span({className:`txt`},i.label||n)))}return e}))},window.app=window.app||{},window.app.utils=window.app.utils||{};var jr={maxKeys:30,requestKeys:!0,collectionJoinKeys:!0};window.app.utils.collectionAutocompleteKeys=function(e,n,r={}){if(!e||!n||!app.store.collections?.length)return[];r=Object.assign({},jr,r);let i=Nr(n,app.store.collections,e).sort(Mr);if(r.requestKeys){let r=Pr(n,app.store.collections,e).sort(Mr);for(let e of r)i.push(e)}if(r.collectionJoinKeys){let e=Fr(n,app.store.collections).sort(Mr);for(let n of e)i.push(n)}return i.length>r.maxKeys?i.slice(0,r.maxKeys):i};function Mr(e,n){return e.length-n.length}function Nr(e,n,r,i=``,a=0){if(!e||a>=4||(typeof r==`string`&&(r=n.find(e=>e.name==r||e.id==r)),!r))return[];e=e.toLowerCase();let o=r.type==`auth`,s=app.utils.getAllCollectionIdentifiers(r,i).filter(n=>n.toLowerCase().includes(e)),c=r.fields||[];for(let r of c){if(r.type==`password`||o&&r.name==`tokenKey`)continue;let c=[];if(i==`@request.body.`&&(c.push(i+r.name+`:changed`),c.push(i+r.name+`:isset`)),typeof app.fieldTypes[r.type]?.filterModifiers==`function`){let e=app.fieldTypes[r.type]?.filterModifiers(r)||[];for(let n of e)c.push(i+r.name+`:`+n)}for(let n of c)n.toLowerCase().includes(e)&&s.push(n);if(r.type==`relation`&&r.collectionId){let o=Nr(e,n,r.collectionId,i+r.name+`.`,a+1);for(let e of o)s.push(e)}}for(let o of n){let c=o.fields||[];for(let l of c){if(l.type!=`relation`||l.collectionId!=r.id)continue;let c=i+o.name+`_via_`+l.name,u=Nr(e,n,o,c+`.`,a+2);for(let e of u)s.push(e)}}return s}function Pr(e,n,r){if(!e)return[];e=e.toLowerCase();let i=[];for(let n of[`@request.context`,`@request.method`,`@request.query.`,`@request.body.`,`@request.headers.`,`@request.auth.collectionId`,`@request.auth.collectionName`])n.toLowerCase().includes(e)&&i.push(n);let a=n.filter(e=>e.type===`auth`);for(let r of a){if(r.system)continue;let a=Nr(e,n,r,`@request.auth.`);for(let e of a)app.utils.pushUnique(i,e)}if(typeof r==`string`&&(r=n.find(e=>e.name==r||e.id==r)),!r)return i;let o=Nr(e,n,r,`@request.body.`);for(let e of o)i.push(e);return i}function Fr(e,n){let r=[],i=`@collection.`,a,o;if(12!e.exclude?.includes(r.name)&&(r.name+r.displayName).toLowerCase().replaceAll(` `,``).includes(n))}});function i(){r.searchTerm=``}return n=t.div({pbEvent:`providerPickerModal`,className:`modal provider-picker-modal`,onbeforeopen:n=>e.onbeforeopen?.(n),onafteropen:n=>{e.onafteropen?.(n)},onbeforeclose:n=>e.onbeforeclose?.(n),onafterclose:n=>{e.onafterclose?.(n),n?.remove()}},t.header({className:`modal-header`},t.h6({className:`modal-title`},t.span({className:`txt`},`Select OAuth2 provider`))),t.div({className:`modal-content`},t.div({className:`grid sm`},t.div({className:`col-12`},t.div({className:`fields searchbar`},t.div({className:`field`},t.input({placeholder:`Search...`,className:`p-l-20`,value:()=>r.searchTerm,oninput:e=>r.searchTerm=e.target.value})),()=>{if(r.searchTerm)return t.div({rid:`search-ctrls`,className:`field addon p-r-5`},t.button({type:`button`,className:`btn sm pill secondary transparent`,onclick:()=>i()},`Clear`))})),()=>{if(!(app.store.isLoadingOAuth2Providers||r.filteredProviders.length))return t.div({rid:`notfound`,className:`block txt-center txt-hint`},t.p(null,`No providers found.`),t.button({type:`button`,className:`btn sm secondary`,textContent:`Clear search`,onclick:()=>i()}))},()=>app.store.isLoadingOAuth2Providers?t.div({className:`col-12 txt-center`},t.span({className:`loader active`})):r.filteredProviders.map(r=>t.div({className:`col-sm-6`},t.button({type:`button`,className:`provider-card handle`,onclick:()=>{app.modals.close(n),e.onselect?.(r)}},t.figure({className:`provider-logo`},()=>r.logo?t.img({src:`data:image/svg+xml;base64,`+btoa(r.logo),alt:r.name+` logo`}):t.i({className:app.utils.fallbackProviderIcon,ariaHidden:!0})),t.div({className:`content`},t.span({className:`primadry-txt`},r.displayName||r.name),t.span({className:`secondary-txt`},r.name))))))),t.footer({className:`modal-footer gap-base`},t.button({type:`button`,className:`btn transparent m-r-auto`,onclick:()=>app.modals.close(n)},t.span({className:`txt`},`Close`)))),n}window.app=window.app||{},window.app.modals=window.app.modals||{},window.app.modals.openProviderSettings=function(e={},n={namePrefix:``,onbeforeopen:null,onafteropen:null,onbeforeclose:null,onafterclose:null,onsubmit:null}){let r=Lr(e,n);r&&(document.body.appendChild(r),app.modals.open(r))};function Lr(e,n){let r,i=`provider_`+app.utils.randomString();e||={};let a=!e.clientId,o=JSON.stringify(e),s=app.store.oauth2Providers?.find(n=>n.name==e.name);if(!s){console.warn(`missing provider for config`,e);return}let c=store({config:JSON.parse(o),get hasChanges(){return o!=JSON.stringify(c.config)},onsubmit:(e,n)=>{}});function l(){c.hasChanges&&(n.onsubmit?.(s,JSON.parse(JSON.stringify(c.config))),app.modals.close(r))}return r=t.div({pbEvent:`providerSettingsModal`,className:`modal provider-settings-modal`,onbeforeopen:e=>n.onbeforeopen?.(e),onafteropen:e=>{n.onafteropen?.(e),setTimeout(()=>{app.store.errors?.oauth2&&(app.store.errors.oauth2=JSON.parse(JSON.stringify(app.store.errors.oauth2)))},0)},onbeforeclose:e=>n.onbeforeclose?.(e),onafterclose:e=>{n.onafterclose?.(e),e?.remove()}},t.header({className:`modal-header`},t.figure({className:`provider-logo`},()=>s.logo?t.img({src:`data:image/svg+xml;base64,`+btoa(s.logo),alt:s.name+` logo`}):t.i({className:app.utils.fallbackProviderIcon,ariaHidden:!0})),t.h6({className:`modal-title`},e.displayName||s.displayName||s.name,t.small({className:`txt-hint`},` (`,e.name,`)`))),t.form({pbEvent:`providerSettingsForm`,id:i+`form`,className:`modal-content`,onsubmit:e=>{e.preventDefault(),l()}},t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.clientId`,textContent:`Client ID`}),t.input({type:`text`,required:!0,id:i+`.clientId`,autocomplete:`off`,name:()=>n.namePrefix+`.clientId`,value:()=>c.config.clientId||``,oninput:e=>c.config.clientId=e.target.value.trim()}))),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.clientSecret`,textContent:`Client secret`}),t.input({type:`password`,id:i+`.clientSecret`,autocomplete:`new-password`,required:()=>a||c.config.clientSecret!==void 0,name:()=>n.namePrefix+`.clientSecret`,value:()=>c.config.clientSecret||``,oninput:e=>c.config.clientSecret=e.target.value.trim(),onkeyup:e=>{e.key==`Backspace`&&c.config.clientSecret===void 0&&(c.config.clientSecret=``)},placeholder:()=>a||c.config.clientSecret!==void 0?``:`* * * * * *`}))),()=>{if(typeof app.oauth2?.[s.name]==`function`)return t.div({className:`col-12`},app.oauth2[s.name](s,n.namePrefix,c))})),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,onclick:()=>app.modals.close(r)},t.span({className:`txt`},`Close`)),t.button({"html-form":i+`form`,type:`submit`,className:`btn`,disabled:()=>!c.hasChanges},t.span({className:`txt`},`Set provider config`)))),r}window.app=window.app||{},window.app.modals=window.app.modals||{},window.app.modals.openCollectionChangesConfirmation=async function(e,n,r,i){let a=store({isLoadingConflictingOIDCProviders:!1,conflictingOIDCProviders:[],get isCollectionRenamed(){return e?.name!=n?.name},get isNewCollectionAuth(){return n?.type===`auth`},get isNewCollectionView(){return n?.type===`view`},get renamedFields(){return a.isNewCollectionView?[]:n?.fields?.filter?.(n=>{let r;return n.id&&!n[`@toDelete`]&&(r=e.fields?.find?.(e=>e.id==n.id)),r&&r.name!=n.name})||[]},get deletedFields(){return a.isNewCollectionView?[]:n?.fields?.filter?.(e=>e.id&&e[`@toDelete`])||[]},get multipleToSingleFields(){return a.isNewCollectionView?[]:n?.fields?.filter?.(n=>{let r=e?.fields?.find?.(e=>e.id==n.id);if(!r||r.maxSelect===void 0)return!1;let i=r.maxSelect||1,a=n.maxSelect||1;return i>1&&a==1})||[]},get changedRules(){if(window.location.protocol!=`https:`)return[];let r=[],i=[`listRule`,`viewRule`];a.isNewCollectionView||i.push(`createRule`,`updateRule`,`deleteRule`),a.isNewCollectionAuth&&i.push(`manageRule`,`authRule`);let o,s;for(let a of i)o=e?.[a],s=n?.[a],o!==s&&r.push({prop:a,oldRule:o,newRule:s});return r},get needConfirmation(){return!app.utils.isEmpty(e?.id)&&(a.isCollectionRenamed||a.renamedFields.length||a.deletedFields.length||a.multipleToSingleFields.length||a.changedRules.length||a.conflictingOIDCProviders.length)}}),o=[`oidc`,`oidc2`,`oidc3`];async function s(){if(!(app.utils.isEmpty(e?.id)||!a.isNewCollectionAuth)){a.isLoadingConflictingOIDCProviders=!0;try{a.conflictingOIDCProviders=[];for(let r of o){let i=e?.oauth2?.providers?.find?.(e=>e.name==r),o=n?.oauth2?.providers?.find?.(e=>e.name==r);if(!i||!o)continue;let s=new URL(i.authURL).host,c=new URL(o.authURL).host;s!=c&&await app.pb.collection(`_externalAuths`).getFirstListItem(app.pb.filter(`collectionRef={:collectionId} && provider={:provider}`,{collectionId:n?.id,provider:r}),{requestKey:null})&&a.conflictingOIDCProviders.push({name:r,oldHost:s,newHost:c})}a.isLoadingConflictingOIDCProviders=!1}catch(e){e.isAbort&&(a.isLoadingConflictingOIDCProviders=!1,app.checkApiError(e))}}}if(await s(),!a.needConfirmation)return r();app.modals.confirm(t.div({className:`dangerous-collection-changes-list`},t.h5({className:`block txt-center m-b-base`},`Do you really want to save the collection changes?`),()=>{if(!(!a.isCollectionRenamed&&!a.deletedFields.length&&!a.renamedFields.length))return t.div({className:`alert warning m-b-base`},t.p(null,`If the collection participate in another collection rule, filter or view query, you'll have to update it manually!`),()=>{if(a.deletedFields.length)return t.p(null,`All data associated with the removed fields will be permanently deleted!`)})},()=>{if(a.isCollectionRenamed)return t.ul({className:`collection-changes-list changes-renamed-collection`},t.li({className:`list-item`},`Renamed collection `,t.strong({className:`label warning`},e?.name),t.i({className:`ri-arrow-right-line txt-sm`,ariaHidden:!0}),t.strong({className:`label success`},n?.name||`N/A`)))},()=>{if(a.renamedFields.length)return t.ul({className:`collection-changes-list changes-renamed-fields`},()=>a.renamedFields.map(n=>{let r=e?.fields?.find?.(e=>e.id==n.id);return t.li({className:`list-item`},`Renamed field `,t.strong({className:`label warning`},r?.name),t.i({className:`ri-arrow-right-line txt-sm`,ariaHidden:!0}),t.strong({className:`label success`},n.name||`N/A`))}))},()=>{if(a.deletedFields.length)return t.ul({className:`collection-changes-list changes-deleted-fields`},()=>a.deletedFields.map(e=>t.li({className:`list-item`},`Deleted field `,t.strong({className:`label danger`},e.name||`N/A`))))},()=>{if(a.multipleToSingleFields.length)return t.ul({className:`collection-changes-list changes-multiple-to-single-fields`},()=>a.multipleToSingleFields.map(e=>t.li({className:`list-item`},`Multiple to single value conversion of field `,t.strong({className:`label warning`},e.name||e.id),t.em({className:`txt-sm`},` (will keep only the last array item)`))))},()=>{if(a.changedRules.length)return t.ul({className:`collection-changes-list changes-api-rules`},()=>a.changedRules.map(e=>t.li({className:`list-item`},t.div({className:`content`},t.span({className:`txt`},`Changed API rule for `),t.code(null,e.prop)),t.small({className:`txt-bold`},`Old:`),t.div({className:`rule-content old-rule`},e.oldRule===null?`null (superusers only)`:e.oldRule||`""`),t.small({className:`txt-bold`},`New:`),t.div({className:`rule-content new-rule`},e.newRule===null?`null (superusers only)`:e.newRule||`""`))))},()=>{if(a.conflictingOIDCProviders.length)return t.ul({className:`collection-changes-list changes-api-rules`},()=>a.conflictingOIDCProviders.map(e=>t.li({className:`list-item`},`Changed OIDC `,e.name,` host `,t.strong({className:`label warning`},e.oldHost),t.i({className:`ri-arrow-right-line txt-sm`,ariaHidden:!0}),t.strong({className:`label success`},e.newHost),t.br(),t.span({className:`txt-hint`},`If the old and new OIDC configuration is not for the same provider consider deleting`,` all old _externalAuths records associated to the current collection and provider,`,` otherwise it may result in account linking errors.`),` `,t.a({rel:`noopenener noreferrer`,target:`_blank`,href:()=>`#/collections?collection=_externalAuths&filter=collectionRef%3D%22${n?.id}%22+%26%26+provider%3D%22${e.name}%22`,textContent:`Review existing _externalAuths records`}))))}),r,i,{className:`collection-changes-confirm-modal`,yesButton:`Yes, save changes`})},window.app=window.app||{},window.app.modals=window.app.modals||{},window.app.modals.openCollectionsOverview=function(e={onbeforeopen:null,onafteropen:null,onbeforeclose:null,onafterclose:null}){let n=Rr(e);n&&(document.body.appendChild(n),app.modals.open(n))};function Rr(e={}){let n=`overview_modal_`+app.utils.randomString(),r={"Fields and relations":zr,Rules:Br},i=store({showSystemCollections:!1,activeTab:Object.keys(r)[0],get collections(){return i.showSystemCollections?app.store.collections:app.store.collections.filter(e=>!e.system)}}),a=t.div({pbEvent:`collectionsOverviewModal`,className:`modal popup collections-overview-modal`,onbeforeopen:n=>e.onbeforeopen?.(n),onafteropen:n=>{e.onafteropen?.(n)},onbeforeclose:n=>e.onbeforeclose?.(n),onafterclose:n=>{e.onafterclose?.(n),n?.remove()}},t.header({className:`modal-header isolated`},t.div({className:`grid sm`},t.div({className:`col-12`},t.div({className:`flex`},t.h6({className:`modal-title`},`Collections overview`),t.div({className:`flex-fill`}),t.div({className:`field`},t.input({id:n+`.showSystemCollections`,type:`checkbox`,className:`sm switch`,checked:()=>i.showSystemCollections,onchange:e=>i.showSystemCollections=e.target.checked}),t.label({htmlFor:n+`.showSystemCollections`},`System collections`)),t.button({type:`button`,className:`btn sm secondary transparent circle modal-close-btn`,title:`Close`,onclick:()=>app.modals.close(a)},t.i({className:`ri-close-line`,ariaHidden:!0})))),t.div({className:`col-12`},t.div({className:`tabs-header equal-width`},()=>{let e=[];for(let n in r)e.push(t.button({type:`button`,className:()=>`tab-item ${i.activeTab==n?`active`:``}`,onclick:()=>i.activeTab=n,textContent:n}));return e})))),()=>r[i.activeTab]?.(i));return a}function zr(e){return t.div({className:`modal-content erd-tab`},app.components.erd({collections:()=>{let n,r;function i(e,i){return n=e.name.startsWith(`_`),r=i.name.startsWith(`_`),e.system&&!i.system||n&&!r?1:!e.system&&i.system||!n&&r?-1:0}return e.collections.slice().sort(i)}}))}function Br(e){let n=[{value:`listRule`,label:`List/Search rule`},{value:`viewRule`,label:`View rule`},{value:`createRule`,label:`Create rule`,filter:e=>e.type!=`view`},{value:`updateRule`,label:`Update rule`,filter:e=>e.type!=`view`},{value:`deleteRule`,label:`Delete rule`,filter:e=>e.type!=`view`},{value:`authRule`,label:`Auth rule`,filter:e=>e.type==`auth`},{value:`manageRule`,label:`Manage rule`,filter:e=>e.type==`auth`},{value:`mfaRule`,label:`MFA rule`,emptyLabel:t.span({className:`label info`},`Enabled for everyone`),rule:e=>e.mfa?.rule,filter:e=>e.mfa?.enabled&&e.type==`auth`}],r=store({activeRuleOption:n[0],get activeCollections(){return r.activeRuleOption.filter?e.collections.filter(e=>r.activeRuleOption.filter(e)):e.collections}});return t.div({className:`modal-content rules-tab`},t.table({className:`rules-table`},t.thead({className:`sticky`},t.tr(null,t.td({colSpan:99,className:`col-rule-btns`},t.div({className:`rule-btns`},()=>n.map(e=>t.button({type:`button`,className:()=>`btn sm ${r.activeRuleOption?.value==e.value?`outline`:`transparent secondary`}`,textContent:()=>e.label,onclick:()=>r.activeRuleOption=e})))))),t.tbody(null,()=>r.activeCollections.length?r.activeCollections.map(e=>t.tr(null,t.th({className:`min-width`},t.div({className:`inline-flex gap-10`},t.i({ariaHidden:!0,className:()=>app.collectionTypes[e.type]?.icon||app.utils.fallbackCollectionIcon}),t.span({className:`txt collection-name`,title:()=>e.name,textContent:()=>e.name}))),()=>{let n;return n=r.activeRuleOption.rule?r.activeRuleOption.rule(e):e[r.activeRuleOption.value],t.td({style:`vertical-align: top`},()=>n===null?r.activeRuleOption.nullLabel?r.activeRuleOption.nullLabel:t.span({className:`label success`},`Superusers only`):n===``?r.activeRuleOption.emptyLabel?r.activeRuleOption.emptyLabel:t.span({className:`label info`},`Public`):app.components.codeBlock({language:`pbrule`,value:n}))})):t.tr(null,t.td({colSpan:99,className:`txt-hint`},t.p(null,`No collections with the selected rule.`))))))}window.app=window.app||{},window.app.oauth2=window.app.oauth2||{},window.app.oauth2.microsoft=function(e,n,r){let i=`microsoft_`+app.utils.randomString();return t.div({pbEvent:`oauth2MicrosoftOptions`,className:`oauth2-microsoft-options`},t.p({className:`txt-bold`},`Azure AD endpoints`),t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.authURL`},`Auth URL`),t.input({id:i+`.authURL`,name:n+`.authURL`,type:`url`,required:!0,value:()=>r.config.authURL||``,oninput:e=>r.config.authURL=e.target.value})),t.div({className:`field-help`},`Ex. https://login.microsoftonline.com/YOUR_DIRECTORY_TENANT_ID/oauth2/v2.0/authorize`)),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.tokenURL`},`Token URL`),t.input({id:i+`.tokenURL`,name:n+`.tokenURL`,type:`url`,required:!0,value:()=>r.config.tokenURL||``,oninput:e=>r.config.tokenURL=e.target.value})),t.div({className:`field-help`},`Ex. https://login.microsoftonline.com/YOUR_DIRECTORY_TENANT_ID/oauth2/v2.0/token`))))},window.app=window.app||{},window.app.oauth2=window.app.oauth2||{},window.app.oauth2.lark=function(e,n,r){let i=`lark_`+app.utils.randomString(),a=[{label:`Feishu (China)`,value:`feishu.cn`},{label:`Lark (International)`,value:`larksuite.com`}],o=store({domain:r.config.authURL?.includes(a[1].value)?a[1].value:a[0].value}),s=[watch(()=>o.domain,e=>{e&&(r.config.authURL=`https://accounts.${e}/open-apis/authen/v1/authorize`,r.config.tokenURL=`https://open.${e}/open-apis/authen/v2/oauth/token`,r.config.userInfoURL=`https://open.${e}/open-apis/authen/v1/user_info`)})];return t.div({pbEvent:`oauth2LarkOptions`,className:`oauth2-lark-options`,onunmount:()=>{s.forEach(e=>e?.unwatch())}},t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.site`},`Site`),app.components.select({options:a,required:!0,value:()=>o.domain||``,onchange:e=>{o.domain=e?.[0]?.value}}))),t.div({className:`col-12`},t.div({className:`alert info`},`Note that the Lark user's `,t.strong(null,`Union ID`),` will be used for the association with the PocketBase user (see `,t.a({href:`https://open.feishu.cn/document/platform-overveiw/basic-concepts/user-identity-introduction/introduction#3f2d4b63`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Different Types of Lark User IDs`}),`).`))))},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.oauth2EndpointFields=function(e,n,r,i={}){let a=`endpoints_`+app.utils.randomString(),o=store({required:!0,title:`Provider endpoints`}),s=app.utils.extendStore(o,i);return t.div({pbEvent:`oauth2Endpoints`,className:`oauth2-endpoints`,onunmount:()=>{s.forEach(e=>e?.unwatch())}},t.p({className:`txt-bold`},e=>(typeof o.title==`function`&&o.title(e),o.title)),t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:a+`.authURL`},`Auth URL`),t.input({id:a+`.authURL`,name:n+`.authURL`,type:`url`,required:()=>!!o.required,value:()=>r.config.authURL||``,oninput:e=>r.config.authURL=e.target.value}))),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:a+`.tokenURL`},`Token URL`),t.input({id:a+`.tokenURL`,name:n+`.tokenURL`,type:`url`,required:()=>!!o.required,value:()=>r.config.tokenURL||``,oninput:e=>r.config.tokenURL=e.target.value}))),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:a+`.userInfoURL`},`User info URL`),t.input({id:a+`.userInfoURL`,name:n+`.userInfoURL`,type:`url`,required:()=>!!o.required,value:()=>r.config.userInfoURL||``,oninput:e=>r.config.userInfoURL=e.target.value})))))},window.app.oauth2=window.app.oauth2||{},window.app.oauth2.gitlab=function(e,n,r){return app.components.oauth2EndpointFields(e,n,r,{required:!1,title:`Self-hosted endpoints (optional)`})},window.app.oauth2.gitea=function(e,n,r){return app.components.oauth2EndpointFields(e,n,r,{required:!1,title:`Self-hosted endpoints (optional)`})},window.app.oauth2.mailcow=function(e,n,r){return app.components.oauth2EndpointFields(e,n,r)},window.app=window.app||{},window.app.oauth2=window.app.oauth2||{},window.app.oauth2.oidc=function(e,n,r){let i=`oidc_`+app.utils.randomString(),a=[{label:`User info URL`,value:!0},{label:`ID Token`,value:!1}],o=store({useUserInfoUrl:!1}),s=[];return t.div({pbEvent:`oauth2OIDCOptions`,className:`oauth2-oidc-options`,onmount:e=>{r.config.displayName===void 0&&(r.config.displayName=`OIDC`),r.config.pkce===void 0&&(r.config.pkce=!0),(r.config.userInfoURL||!r.config.extra)&&(o.useUserInfoUrl=!0),s.push(watch(()=>o.useUserInfoUrl,(e,n)=>{e?r.config.extra=null:(r.config.userInfoURL=``,r.config.extra=r.config.extra||{})}))},onunmount:()=>{s.forEach(e=>e?.unwatch())}},t.div({className:`grid`},t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.displayName`},`Display name`),t.input({id:i+`.displayName`,name:n+`.displayName`,type:`text`,required:!0,value:()=>r.config.displayName||``,oninput:e=>r.config.displayName=e.target.value}))),t.div({className:`col-12`},t.p({className:`txt-bold`},`Endpoints`),t.div({className:`field`},t.label({htmlFor:i+`.authURL`},`Auth URL`),t.input({id:i+`.authURL`,name:n+`.authURL`,type:`url`,required:!0,value:()=>r.config.authURL||``,oninput:e=>r.config.authURL=e.target.value}))),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.tokenURL`},`Token URL`),t.input({id:i+`.tokenURL`,name:n+`.tokenURL`,type:`url`,required:!0,value:()=>r.config.tokenURL||``,oninput:e=>r.config.tokenURL=e.target.value}))),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.userInfoSelect`},`Fetch user info from`),app.components.select({id:i+`.userInfoSelect`,required:!0,options:a,value:()=>o.useUserInfoUrl,onchange:e=>o.useUserInfoUrl=e?.[0]?.value})),t.div({className:`oidc-userinfo-options m-t-10`},()=>o.useUserInfoUrl?t.div({className:`field`},t.label({htmlFor:i+`.userInfoURL`},`User info URL`),t.input({id:i+`.userInfoURL`,name:n+`.userInfoURL`,type:`url`,required:!0,value:()=>r.config.userInfoURL||``,oninput:e=>r.config.userInfoURL=e.target.value})):t.div({className:`grid sm`},t.div({className:`col-12 txt-hint txt-sm`},t.em(null,`Both fields are considered optional because the parsed `,t.code(null,`id_token`),` is a direct result of the TLS code->token exchange server response.`)),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.extra.jwksURL`},t.span({className:`txt`},`JWKS verification URL`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`URL to the public token verification keys.`)})),t.input({id:i+`.extra.jwksURL`,name:n+`.extra.jwksURL`,type:`url`,value:()=>r.config.extra?.jwksURL||``,oninput:e=>{r.config.extra=r.config.extra||{},r.config.extra.jwksURL=e.target.value}}))),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:i+`.extra.issuers`},t.span({className:`txt`},`Issuers`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Comma separated list of accepted values for the iss token claim validation.`)})),t.input({id:i+`.extra.issuers`,name:n+`.extra.issuers`,type:`text`,value:()=>app.utils.joinNonEmpty(r.config.extra?.issuers),oninput:e=>{let n=app.utils.splitNonEmpty(e.target.value,`,`),i=app.utils.joinNonEmpty(n);app.utils.joinNonEmpty(r.config.extra?.issuers)!=i&&(r.config.extra=r.config.extra||{},r.config.extra.issuers=n)}})))))),t.div({className:`col-12`},t.div({className:`field`},t.input({id:i+`.pkce`,name:n+`.pkce`,type:`checkbox`,checked:()=>r.config.pkce||!1,onchange:e=>r.config.pkce=e.target.checked}),t.label({htmlFor:i+`.pkce`},t.span({className:`txt`,textContent:`Support PKCE`}),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Usually it should be safe to be always enabled as most providers will just ignore the extra query parameters if they don't support PKCE.`)}))))))},window.app.oauth2.oidc2=window.app.oauth2.oidc,window.app.oauth2.oidc3=window.app.oauth2.oidc,window.app=window.app||{},window.app.oauth2=window.app.oauth2||{},window.app.oauth2.apple=function(e,n,r){return``+app.utils.randomString(),t.div({pbEvent:`oauth2AppleOptions`,className:`oauth2-apple-options`},t.button({type:`button`,className:`btn sm secondary`,onclick:()=>{app.modals.openAppleSecretGenerator({ongenerate:e=>{r.config.clientSecret=e}})}},t.i({className:`ri-key-line`,ariaHidden:!0}),t.span({className:`txt`},`Generate secret`)))},window.app.modals=window.app.modals||{},window.app.modals.openAppleSecretGenerator=function(e={onbeforeopen:null,onafteropen:null,onbeforeclose:null,onafterclose:null,ongenerate:null}){let n=Vr(e);n&&(document.body.appendChild(n),app.modals.open(n))};function Vr(e={}){let n,r=`secret_generator_`+app.utils.randomString(),i=15777e3,a=store({clientId:``,teamId:``,keyId:``,privateKey:``,duration:i,isSubmitting:!1});async function o(){a.isSubmitting=!0;try{let r=await app.pb.settings.generateAppleClientSecret(a.clientId,a.teamId,a.keyId,a.privateKey.trim(),a.duration);a.isSubmitting=!1,app.toasts.success(`Successfully generated client secret.`),e.ongenerate?.(r.secret),app.modals.close(n)}catch(e){e.isAbort||(app.checkApiError(e),a.isSubmitting=!1)}}return n=t.div({pbEvent:`appleSecretGeneratorModal`,className:`modal popup apple-secret-generator-modal`,onbeforeopen:n=>e.onbeforeopen?.(n),onafteropen:n=>{e.onafteropen?.(n)},onbeforeclose:n=>e.onbeforeclose?.(n),onafterclose:n=>{e.onafterclose?.(n),n?.remove()}},t.header({className:`modal-header`},t.h5({className:`m-auto`},`Generate Apple client secret`)),t.form({id:r+`_form`,className:`modal-content`,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`grid`},t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:r+`.clientId`},`Client ID`),t.input({id:r+`.clientId`,name:`clientId`,type:`text`,required:!0,value:()=>a.clientId||``,oninput:e=>a.clientId=e.target.value}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:r+`.teamId`},`Team ID`),t.input({id:r+`.teamId`,name:`teamId`,type:`text`,required:!0,value:()=>a.teamId||``,oninput:e=>a.teamId=e.target.value}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:r+`.keyId`},`Key ID`),t.input({id:r+`.keyId`,name:`keyId`,type:`text`,required:!0,value:()=>a.keyId||``,oninput:e=>a.keyId=e.target.value}))),t.div({className:`col-sm-6`},t.div({className:`field`},t.label({htmlFor:r+`.duration`},`Duration (in seconds)`),t.input({id:r+`.duration`,name:`duration`,type:`number`,min:0,step:1,max:i,required:!0,value:()=>a.duration||0,oninput:e=>a.duration=parseInt(e.target.value,10)})),t.div({className:`field-help`},`Max ${i} seconds (~${i/(3600*24*30)<<0} months).`)),t.div({className:`col-sm-12`},t.div({className:`field`},t.label({htmlFor:r+`.privateKey`},`Private key`),t.textarea({id:r+`.privateKey`,name:`privateKey`,type:`text`,required:!0,rows:8,placeholder:`-----BEGIN PRIVATE KEY----- ... @@ -83,4 +83,4 @@ Records update will also require an extra unlock step before save.`)})))),t.div( @weekly @daily @midnight -@hourly`)},`macros`),`.`,t.br(),`By default the timezone is in UTC.`)),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`backups.cronMaxKeep`},`Max @auto backups to keep`),t.input({id:`backups.cronMaxKeep`,name:`backups.cronMaxKeep`,type:`number`,required:()=>a.enableAutoBackups,min:1,value:()=>a.formSettings.backups.cronMaxKeep,oninput:e=>{a.formSettings.backups.cronMaxKeep=parseInt(e.target.value,10)}})))))),t.div({className:`col-lg-12`},app.components.s3ConfigFields({toggleLabel:`Store backups in S3 storage`,testFilesystem:`backups`,config:()=>a.formSettings.backups.s3})),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({hidden:()=>!a.hasChanges,type:`button`,className:`btn transparent secondary`,onclick:l},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${a.isSaving?`loading`:``}`,disabled:()=>!a.hasChanges||a.isSaving},t.span({className:`txt`},`Save changes`))))])))}function Fi(e={oncreated:null}){let n=Ii(e);n&&(document.body.appendChild(n),app.modals.open(n))}function Ii(e){let n,r=`backup_create_`+app.utils.randomString(),i=store({name:``,isSubmitting:!1}),a;async function o(){if(!i.isSubmitting){i.isSubmitting=!0,clearTimeout(a),a=setTimeout(()=>{app.modals.close(n)},1500);try{await app.pb.backups.create(i.name,{requestKey:r}),i.isSubmitting=!1,e.oncreated&&e.oncreated(i.name),app.toasts.success(`Successfully generated new backup.`),app.modals.close(n)}catch(e){e.isAbort||(clearTimeout(a),i.isSubmitting=!1,app.checkApiError(e))}}}return n=t.div({pbEvent:`backupCreateModal`,className:`modal popup backup-create-modal`,onbeforeclose:()=>{i.isSubmitting&&app.toasts.info(`The backup was started but may take a while to complete. You can come back later.`)},onafterclose:e=>{clearTimeout(a),e?.remove()}},t.header({className:`modal-header`},t.h5({className:`m-auto txt-center`},`Initialize new backup`)),t.form({id:r,className:`modal-content backup-restore-form`,autocomplete:`off`,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`alert warning`},t.div({className:`content`},t.p(null,`Please note that during the backup other concurrent write requests may fail since the database will be temporary "locked" (this usually happens only during the ZIP generation).`),t.p({className:`txt-bold`},`If you are using S3 storage for the collections file upload, you'll have to backup them separately since they are not locally stored and they will not be included in the generated backup!`)))),t.div({className:`col-lg-12`},t.div({className:`field`},t.label({htmlFor:r+`_name`},`Backup name`),t.input({id:r+`_name`,name:`name`,type:`text`,pattern:`^[a-z0-9_-]+.zip$`,placeholder:`Leave empty to autogenerate`,value:()=>i.name,oninput:e=>i.name=e.target.value})),t.div({className:`field-help`},`Must be in the format [a-z0-9_-].zip`)))),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,disabled:()=>i.isSubmitting,onclick:()=>app.modals.close(n)},t.span({className:`txt`},`Cancel`)),t.button({"html-form":r,type:`submit`,className:()=>`btn ${i.isSubmitting?`loading`:``}`,disabled:()=>i.isSubmitting},t.span({className:`txt`},`Start backup`)))),n}function Li(e){let n=Ri(e);document.body.appendChild(n),app.modals.open(n)}function Ri(e){let n=`backup_restore_`+app.utils.randomString(),r=store({key:e,keyConfirm:``,isSubmitting:!1,get canSubmit(){return r.key&&r.key==r.keyConfirm}}),i;async function a(){if(!(r.isSubmitting||!r.canSubmit)){clearTimeout(i),r.isSubmitting=!0;try{await app.pb.backups.restore(r.keyConfirm),i=setTimeout(()=>{window.location.reload(),r.isSubmitting=!1},2e3)}catch(e){clearTimeout(i),e?.isAbort||(r.isSubmitting=!1,app.checkApiError(e))}}}return t.div({pbEvent:`backupRestoreModal`,className:`modal popup backup-restore-modal`,onbeforeclose:()=>!r.isSubmitting,onafterclose:e=>{e?.remove()},onunmount:()=>{clearTimeout(i)}},t.header({className:`modal-header`},t.h5({className:`m-auto txt-center`},`Restore `,t.strong(null,()=>r.key))),t.form({id:n,className:`modal-content backup-restore-form`,autocomplete:`off`,onsubmit:e=>{e.preventDefault(),a()}},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`alert danger`},t.div({className:`content`},t.p({className:`txt-bold`},`Please proceed with extreme caution and use it only with trusted backups!`),t.p(null,`Backup restore currently works only on UNIX based systems.`),t.p(null,`The restore operation will attempt to replace your existing `,t.code(null,`pb_data`),` with the one from the backup and will restart the application process.`),t.p(null,`This means that on success all of your data (including app settings, users, superusers, etc.) will be replaced with the ones from the backup.`),t.p(null,`The operation will be reverted if the backup is invalid (ex. missing `,t.code(null,`data.db`),` file).`),t.p(null,`Below is an oversimplified version of the restore flow:`),t.ol(null,t.li(null,`Replaces the current `,t.code(null,`pb_data`),` with the content from the backup.`),t.li(null,`Triggers app restart.`),t.li(null,`Applies all migrations that are missing in the restored `,t.code(null,`pb_data`),`.`),t.li(null,`Initializes the app server as usual.`))))),t.div({className:`col-lg-12`},t.div({className:`confirm-key-label m-b-sm`},`Type the backup name `,t.div({className:`label`},()=>r.key,app.components.copyButton(()=>r.key)),` to confirm:`),t.div({className:`field`},t.label({htmlFor:n+`_key`},`Backup name`),t.input({id:n+`_key`,name:`key`,type:`text`,required:!0,value:()=>r.keyConfirm,oninput:e=>r.keyConfirm=e.target.value}))))),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,onclick:()=>app.modals.close(),disabled:()=>r.isSubmitting},t.span({className:`txt`},`Cancel`)),t.button({"html-form":n,type:`submit`,className:()=>`btn ${r.isSubmitting?`loading`:``}`,disabled:()=>r.isSubmitting||!r.canSubmit},t.span({className:`txt`},`Restore backup`))))}function zi(e={}){let n=store({reset:null}),r=app.utils.extendStore(n,e),i=store({canBackup:!0,isLoading:!1,isDownloading:{},isDeleting:{},backups:[]});async function a(){i.isLoading=!0;try{i.backups=await app.pb.backups.getFullList(),i.backups.sort((e,n)=>e.modifiedn.modified?-1:0),i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}async function o(e){app.modals.confirm(`Do you really want to delete ${e}?`,()=>s(e))}async function s(e){if(!i.isDeleting[e]){i.isDeleting[e]=!0;try{await app.pb.backups.delete(e),a(),app.toasts.success(`Successfully deleted ${e}.`)}catch(e){app.checkApiError(e)}delete i.isDeleting[e]}}async function c(){try{let e=await app.pb.health.check({requestKey:null}),n=i.canBackup;i.canBackup=e?.data?.canBackup||!1,i.canBackup&&n!=i.canBackup&&a()}catch(e){console.warn(`failed to load canBackup checks`,e)}}async function l(e){if(!i.isDownloading[e]){i.isDownloading[e]=!0;try{let n=await app.pb.files.getToken({requestKey:null});app.utils.download(app.pb.backups.getDownloadURL(n,e))}catch(e){app.checkApiError(e)}delete i.isDownloading[e]}}return t.div({pbEvent:`backupsList`,className:`list backups-list`,onmount:e=>{r.push(watch(()=>n.reset,()=>{a()})),e._canBackupIntervalId=setInterval(()=>{c()},3500)},onunmount:e=>{clearInterval(e._canBackupIntervalId),r.forEach(e=>e?.unwatch())}},t.div({className:`list-content`},t.div({hidden:()=>!i.isLoading||i.backups.length,className:`list-item`},t.div({className:`skeleton-loader`})),t.div({hidden:()=>i.isLoading||i.backups.length,className:()=>`list-item`},t.div({className:`content block txt-hint`},`No backups found.`)),()=>i.backups.map(e=>t.div({className:()=>`list-item ${i.isLoading?`faded`:``}`},t.i({className:`ri-folder-zip-line`,ariaHidden:!0}),t.div({className:`content`},t.span({className:`backup-name txt-ellipsis`,title:()=>e.key,textContent:()=>e.key}),t.small({className:`backup-size txt-hint txt-nowrap`},`(`,()=>app.utils.formattedFileSize(e.size),`)`)),t.nav({hidden:()=>i.isLoading,className:`actions autohide`},t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Download`),className:()=>`btn sm circle secondary transparent ${i.isDownloading[e.key]?`loading`:``}`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>l(e.key)},t.i({className:`ri-download-line`,ariaHidden:!0})),t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Restore`),className:()=>`btn sm circle secondary transparent`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>Li(e.key)},t.i({className:`ri-restart-line`,ariaHidden:!0})),t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Delete`),className:()=>`btn sm circle secondary transparent ${i.isDeleting[e.key]?`loading`:``}`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>o(e.key)},t.i({className:`ri-delete-bin-7-line`,ariaHidden:!0})))))),t.div({className:`list-item`},t.button({type:`button`,className:()=>`btn secondary block ${i.isLoading?`loading`:``}`,disabled:()=>!i.canBackup||i.isLoading,onclick:()=>{Fi({oncreated:()=>a()})}},()=>i.canBackup?[t.i({className:`ri-play-circle-line`,ariaHidden:!0}),t.span({className:`txt`},`Initialize new backup`)]:[t.span({className:`loader sm`}),t.span({className:`txt`},`Backup/restore operation is in process`)])))}function Bi(e=null){let n=`backup_upload_`+app.utils.randomString(),r=store({isUploading:!1});function i(e){e&&app.modals.confirm(`Note that we don't perform validations for the uploaded backup files. Proceed with extreme caution and only if you trust the source.\n\nDo you really want to upload "${e.name}"?`,()=>{a(e)},()=>{o()})}async function a(i){if(!(!i||r.isUploading)){r.isUploading=!0;try{let a=new FormData;a.set(`file`,i),await app.pb.backups.upload(a,{requestKey:n}),r.isUploading=!1,e(i),app.toasts.success(`Successfully uploaded a new backup.`)}catch(e){e.isAbort||(r.isUploading=!1,e.response?.formData?.file?.message?app.toasts.error(e.response.formData.file.message):app.checkApiError(e))}o()}}function o(){s&&(s.value=``)}let s=t.input({type:`file`,accept:`application/zip`,className:`hidden`,onchange:e=>{i(e.target?.files?.[0])}});return t.div(null,t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Upload backup`),className:()=>`btn sm transparent secondary circle ${r.isUploading?`loading`:``}`,disabled:()=>r.isUploading,onclick:()=>s?.click(),onunmount:()=>{app.pb.cancelRequest(n)}},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0})),s)}function Vi(e){app.store.title=`Backups`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageBackupsSettings`,className:`page page-backups-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`flex gap-10 m-b-sm`},t.div({className:`txt-lg`},`Backup and restore your PocketBase data`),app.components.refreshButton({className:`btn sm transparent secondary circle tooltip-bottom`,onclick:r}),Bi(r)),zi({reset:()=>n.resetList})),t.div({className:`col-lg-12`},Pi({onsave:()=>r()})))),t.footer({className:`page-footer`},app.components.credits())))}function Hi(e={}){let n=store({reset:null}),r=app.utils.extendStore(n,e),i=store({isLoading:!1,isRunning:{},crons:[]});async function a(){i.isLoading=!0;try{i.crons=await app.pb.crons.getFullList(),i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}async function o(e){if(!(!e||i.isRunning[e])){i.isRunning[e]=!0;try{await app.pb.crons.run(e),app.toasts.success(`Successfully triggered "${e}".`),i.isRunning[e]=!1}catch(n){n.isAbort||(ApiClient.error(n),i.isRunning[e]=!1)}}}return t.div({pbEvent:`cronsList`,className:`list`,onmount:()=>{r.push(watch(()=>n.reset,()=>{a()}))},onunmount:()=>{r.forEach(e=>e?.unwatch())}},()=>{if(!i.isLoading||i.crons.length)return;let e=[];for(let n=0;n<4;n++)e.push(t.div({rid:`skeleton_`+n,className:`list-item`},t.div({className:`skeleton-loader`})));return e},t.div({hidden:()=>i.isLoading||i.crons.length,className:`list-item`},t.div({className:`content block txt-hint`},`No registered crons found.`)),()=>i.crons.map(e=>t.div({className:()=>`list-item ${i.isLoading?`faded`:``}`},t.div({className:`content`},t.span({className:`cron-id txt-code txt-ellipsis`,title:()=>e.id,textContent:()=>e.id})),t.small({className:`cron-expression txt-hint txt-nowrap txt-code`},()=>e.expression),t.nav({hidden:()=>i.isLoading,className:`actions`},t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Run`),className:()=>`btn sm circle secondary transparent ${i.isRunning[e.id]?`loading`:``}`,disabled:()=>i.isRunning[e.id],onclick:()=>o(e.id)},t.i({className:`ri-play-large-line`,ariaHidden:!0}))))))}function Ui(e){app.store.title=`Crons`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageCronsSettings`,className:`page`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},t.div({className:`flex gap-10 m-b-sm`},t.div({className:`txt-lg`},`Registered app cron jobs`),app.components.refreshButton({className:`btn sm transparent secondary circle`,onclick:r})),Hi({reset:()=>n.resetList}),t.div({className:`txt-sm txt-hint m-t-sm`},`App cron jobs can be registered only programmatically with `,t.a({href:`https://pocketbase.io/docs/go-jobs-scheduling/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Go`}),` or `,t.a({href:`https://pocketbase.io/docs/js-jobs-scheduling/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`JavaScript`}),`.`)),t.footer({className:`page-footer`},app.components.credits())))}function Wi(e){app.store.title=`Mail settings`;let n=[{label:`Auto (StartTLS)`,value:!1},{label:`Always`,value:!0}],r=[{label:`PLAIN (default)`,value:`PLAIN`},{label:`LOGIN`,value:`LOGIN`}],i=store({isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,showMoreOptions:!1,get hasChanges(){return i.initSerialized!=JSON.stringify(i.formSettings)}});a();async function a(){i.isLoading=!0;try{s(await app.pb.settings.getAll()),i.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function o(){if(!(i.isSaving||!i.hasChanges)){i.isSaving=!0;try{let e=app.utils.filterRedactedProps(i.formSettings);s(await app.pb.settings.update(e)),app.toasts.success(`Successfully saved mail settings.`)}catch(e){app.checkApiError(e)}i.isSaving=!1}}function s(e={}){app.store.settings=JSON.parse(JSON.stringify(e)),i.formSettings={meta:e?.meta||{},smtp:e?.smtp||{}},i.formSettings.smtp.authMethod||(i.formSettings.smtp.authMethod=r[0].value),i.initSerialized=JSON.stringify(i.formSettings)}function c(){i.formSettings=JSON.parse(i.initSerialized)}return t.div({pbEvent:`pageMailSettings`,className:`page page-mail-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>i.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`mailSettingsForm`,className:`grid mail-settings-form`,inert:()=>i.isSaving,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`col-lg-12 txt-lg`},t.p(null,`Configure common settings for sending emails.`)),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`meta.senderName`},`Sender name`),t.input({id:`meta.senderName`,name:`meta.senderName`,type:`text`,required:!0,value:()=>i.formSettings.meta.senderName||``,oninput:e=>i.formSettings.meta.senderName=e.target.value}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`meta.senderAddress`},`Sender address`),t.input({id:`meta.senderAddress`,name:`meta.senderAddress`,type:`email`,required:!0,value:()=>i.formSettings.meta.senderAddress||``,oninput:e=>i.formSettings.meta.senderAddress=e.target.value}))),t.div({className:`col-lg-12`},t.div({className:`field`},t.input({id:`smtp.enabled`,name:`smtp.enabled`,type:`checkbox`,className:`switch`,checked:()=>!!i.formSettings.smtp.enabled,onchange:e=>i.formSettings.smtp.enabled=e.target.checked}),t.label({htmlFor:`smtp.enabled`},t.span({className:`txt`},`Use SMTP mail server `,t.strong(null,`(recommended)`)),t.i({className:`ri-information-line link-faded`,ariaDescription:app.attrs.tooltip(`By default PocketBase uses the unix "sendmail" command for sending emails. For better emails deliverability it is recommended to use a SMTP mail server.`)}))),app.components.slide(()=>i.formSettings.smtp.enabled,t.div({className:`grid m-t-sm`},t.div({className:`col-lg-4`},t.div({className:`field`},t.label({htmlFor:`smtp.host`},`SMTP server host`),t.input({id:`smtp.host`,name:`smtp.host`,type:`text`,required:()=>i.formSettings.smtp.enabled,value:()=>i.formSettings.smtp.host||``,oninput:e=>i.formSettings.smtp.host=e.target.value}))),t.div({className:`col-lg-2`},t.div({className:`field`},t.label({htmlFor:`smtp.port`},`Port`),t.input({id:`smtp.port`,name:`smtp.port`,type:`number`,min:0,step:1,required:()=>i.formSettings.smtp.enabled,value:()=>i.formSettings.smtp.port||``,oninput:e=>i.formSettings.smtp.port=parseInt(e.target.value,10)}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.username`},`Username`),t.input({id:`smtp.username`,name:`smtp.username`,type:`text`,autocomplete:`off`,value:()=>i.formSettings.smtp.username||``,oninput:e=>i.formSettings.smtp.username=e.target.value}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.password`},`Password`),t.input({id:`smtp.password`,name:`smtp.password`,type:`password`,autocomplete:`new-password`,value:()=>i.formSettings.smtp.password||``,oninput:e=>i.formSettings.smtp.password=e.target.value,onkeyup:e=>{e.key==`Backspace`&&i.formSettings.smtp.password===void 0&&(i.formSettings.smtp.password=``)},placeholder:()=>i.formSettings.smtp.password===void 0?`* * * * * *`:``})))),t.button({type:`button`,className:`btn secondary sm m-t-sm`,onclick:()=>i.showMoreOptions=!i.showMoreOptions},t.span({className:`txt`},()=>i.showMoreOptions?`Hide more options`:`Show more options`),t.i({className:()=>i.showMoreOptions?`ri-arrow-drop-up-line`:`ri-arrow-drop-down-line`})),app.components.slide(()=>i.showMoreOptions,t.div({className:`grid m-t-sm`},t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.tls`},`TLS encryption`),app.components.select({id:`smtp.tls`,name:`smtp.tls`,required:!0,options:n,value:()=>i.formSettings.smtp.tls||!1,onchange:e=>{i.formSettings.smtp.tls=e?.[0]?.value}}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.authMethod`},`AUTH method`),app.components.select({id:`smtp.authMethod`,name:`smtp.authMethod`,required:!0,options:r,value:()=>i.formSettings.smtp.authMethod||r[0].value,onchange:e=>{i.formSettings.smtp.authMethod=e?.[0]?.value}}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`smtp.localName`},t.span({className:`txt`},`EHLO/HELO domain`),t.i({className:`ri-information-line link-hint tooltip-top`,ariaDescription:app.attrs.tooltip(`Some SMTP servers, such as the Gmail SMTP-relay, requires a proper domain name in the inital EHLO/HELO exchange and will reject attempts to use localhost.`)})),t.input({id:`smtp.localName`,name:`smtp.localName`,type:`text`,placeholder:`Default to localhost`,value:()=>i.formSettings.smtp.localName||``,oninput:e=>i.formSettings.smtp.localName=e.target.value}))))))),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),()=>i.hasChanges?[t.button({type:`button`,className:`btn transparent secondary`,onclick:c},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${i.isSaving?`loading`:``}`,disabled:()=>!i.hasChanges||i.isSaving},t.span({className:`txt`},`Save changes`))]:t.button({type:`button`,className:()=>`btn expanded-lg outline`,onclick:()=>app.modals.openMailTest()},t.i({className:`ri-mail-check-line`,ariaHidden:!0}),t.span({className:`txt`},`Send test email`)))))),t.footer({className:`page-footer`},app.components.credits())))}var Gi=`pbSQLConsoleHistory`;function Ki(e){app.store.title=`SQL console`;let n=`sql_console_`+app.utils.randomString(),r=n+`editor`,i=n+`executeSQL`,a=store({askedForConfirmationAtLeastOnce:!1,isExecuting:!1,maxRows:250,query:``,result:{},sort:{},errorMsg:``,executedHistory:app.utils.getLocalHistory(Gi,[]),get sortedResultRows(){if(a.sort?.index===void 0){let e=a.result?.rows||[];return a.maxRows>=e.length?e:e.slice(0,a.maxRows)}let e=!!a.sort?.asc,n=a.result?.rows?.toSorted((n,r)=>{let i=n[a.sort.index],o=r[a.sort.index];return e||(i=r[a.sort.index],o=n[a.sort.index]),i==o?0:i==null?-1:o==null?1:i.localeCompare(o)})||[];return a.maxRows>=n.length?n:n.slice(0,a.maxRows)},get totalRemainingRows(){return(a.result?.rows?.length<<0)-a.sortedResultRows.length}});function o(e){return e?.trim()?!a.askedForConfirmationAtLeastOnce&&app.store.settings?.meta?.hideControls?!0:(e=e?.replace(/[\s\;]/gm,` `).toUpperCase()+` `,!![`ALTER `,`REPLACE `,`INSERT `,`CREATE `,`UPDATE `,`DELETE `,`DROP `,`DETACH `,`PRAGMA `].find(n=>e.includes(n))):!1}async function s(){return o(a.query)?(a.askedForConfirmationAtLeastOnce=!0,app.modals.confirm(t.div({className:`txt-center`},t.h6(null,`Be careful and continue only if you really know what you are doing because, depending on the query, the operation could break your application and may not be reversible.`)),()=>c(),null,{yesButton:`Execute`,noButton:`Cancel`})):c()}async function c(){a.isExecuting=!0,a.maxRows=250,a.result={},a.sort={},a.errorMsg=``;let e=a.query.trim();if(!e){app.pb.cancelRequest(i),a.isExecuting=!1;return}try{a.result=await app.pb.sql.run(e,{requestKey:i}),u(e),a.isExecuting=!1}catch(e){e?.isAbort||(a.isExecuting=!1,a.errorMsg=e?.response?.message||e?.message||`Failed to execute query.`)}}function l(e){function n(e){return e.replace(/[\s\;]/gm,``).toUpperCase()}let r=n(e);for(let i=a.executedHistory.length-1;i>=0;i--)(a.executedHistory[i]==e||n(a.executedHistory[i])==r)&&a.executedHistory.splice(i,1)}function u(e){l(e),a.executedHistory.unshift(a.query),a.executedHistory.length>10&&a.executedHistory.splice(10)}function d(){if(!a.sortedResultRows.length)return;let e=[a.result.columns.map(e=>e.name)].concat(a.sortedResultRows),n=`export_`+new Date().toISOString().replace(/[\-\:\.]/g,``)+`.csv`;app.utils.downloadCSV(e,n)}function f(e){a.sort?.index==e?a.sort={index:e,asc:!a.sort.asc}:a.sort={index:e,asc:!0}}let p=[watch(()=>JSON.stringify(a.executedHistory),(e,n)=>{n!==void 0&&window.localStorage.setItem(Gi,e)})];return t.div({pbEvent:`pageSQLConsole`,className:`page`,onunmount:()=>{app.pb.cancelRequest(i),p.forEach(e=>e?.unwatch())}},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title)),t.div({className:`page-header-secondary-btns`},t.button({type:`button`,className:`btn circle transparent secondary`,ariaDescription:app.attrs.tooltip(`Recently executed queries`,`right`),"html-popovertarget":`sql-console-history-dropdown`},t.i({className:`ri-history-line`,ariaHidden:!0})),t.div({id:`sql-console-history-dropdown`,className:()=>`dropdown left sql-console-history-dropdown ${a.executedHistory.length?``:`no-items`}`,popover:`auto`},()=>a.executedHistory.length?a.executedHistory.map(e=>t.button({role:`button`,className:`dropdown-item`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),a.query=e,document.getElementById(r)?.click()}},t.span({className:`query`},()=>app.utils.truncate(e,500)),t.small({role:`button`,className:`remove-btn link-hint m-l-auto p-l-5 p-r-5`,title:`Clear`,onauxclick:e=>(e.stopPropagation(),!1),onclick:n=>(n.stopPropagation(),l(e),!1)},t.i({className:`ri-close-line`,ariaHidden:!0})))):t.span({className:`txt txt-hint p-5`},`No recently executed queries.`))),t.div({className:`page-header-primary-btns`},t.button({type:`button`,className:()=>`btn expanded-lg ${a.isExecuting?`loading`:``}`,disabled:()=>a.isExecuting,onclick:()=>s()},t.i({className:`ri-play-large-line`,ariaHidden:!0}),t.span({className:`txt`},`Execute`)))),t.div({className:`field sql-console-field`},app.components.codeEditor({id:r,language:`sql`,required:!0,name:`query`,placeholder:`e.g. EXPLAIN QUERY PLAN SELECT * from users WHERE verified=true`,value:()=>a.query,oninput:e=>a.query=e,onblur:e=>a.query=e.trim()})),t.div({className:`flex field-help m-b-sm`},t.button({type:`button`,className:`link-hint m-l-auto`,"html-popovertarget":n+`caveats_dropdown`},()=>`SQL console caveats`),t.div({id:n+`caveats_dropdown`,className:`dropdown sm query-caveats-dropdown`,popover:`auto`},t.ul(null,t.li(null,`The returned rows are limited up to 1000.`),t.li(null,`The executed queries have a max timeout of 3 minutes.`),t.li(null,`The data is returned as byte strings without any additional formatting.`),t.li(null,`Multiple queries are supported but only the result of the last one is returned.`)))),t.div({hidden:()=>a.isExecuting||!a.errorMsg,className:`alert danger m-b-sm`},t.pre(null,()=>a.errorMsg)),t.div({hidden:()=>a.isExecuting||a.errorMsg||a.result?.columns?.length||app.utils.isEmpty(a.result),className:`alert success m-b-sm`},t.p({className:`txt-bold`},`Query executed successfully!`),()=>{if(a.result?.affectedRows)return t.p(null,`Affected rows: `,a.result?.affectedRows)}),t.div({hidden:()=>a.isExecuting||!a.result?.columns?.length,className:`page-table-wrapper`},t.table({className:`sql-console-table responsive-table optimize`},t.thead({className:`sticky`},t.tr(null,()=>a.result?.columns?.map((e,n)=>t.th({textContent:e.name,className:()=>{let e=`sort-handle`;return a.sort?.index==n&&(e+=a.sort.asc?` asc`:` desc`),e},onclick:()=>f(n)})))),t.tbody(null,()=>a.sortedResultRows.length?a.sortedResultRows.map(e=>t.tr(null,()=>a.result?.columns?.map((n,r)=>{let i=e[r];return t.td({"html-data-name":n.name},i==null?`NULL`:app.utils.truncate(i,2e3))}))):t.tr(null,t.td({colSpan:a.result?.columns?.length||1,className:`txt-center`},t.span({className:`txt-hint`},`No rows found.`))),t.tr({hidden:()=>a.isExecuting||!a.result?.rows?.length||a.result.rows.length<=a.sortedResultRows.length},t.td({colSpan:99},t.button({type:`button`,className:`btn lg secondary load-more-btn`,onclick:()=>{a.maxRows=a.result?.rows?.length||250}},t.span({className:`txt`,textContent:()=>`Load remaining (${a.totalRemainingRows})`}))))))),t.footer({className:`page-footer`},t.span({className:()=>`exec-time ${a.isExecuting?`faded`:``}`},`Time: `,()=>(a.result?.execTime||0)+`ms`),t.span({hidden:()=>!a.result?.columns?.length,className:()=>`total-count ${a.isExecuting?`faded`:``}`},`Rows: `,()=>a.result?.rows?.length||0,()=>{if(a.result?.rows?.length)return[` (`,t.span({role:`button`,className:`link-hint`,textContent:`Export as CSV`,onclick:d}),`)`]}),app.components.credits())))}function qi(){app.store.title=`File storage`;let e=store({isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,originalFormSettings:null,get hasChanges(){return e.initSerialized!=JSON.stringify(e.formSettings)}});n();async function n(){e.isLoading=!0;try{i(await app.pb.settings.getAll()),e.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function r(){if(!(e.isSaving||!e.hasChanges)){e.isSaving=!0;try{let n=app.utils.filterRedactedProps(e.formSettings);i(await app.pb.settings.update(n)),app.toasts.success(`Successfully saved storage settings.`)}catch(e){app.checkApiError(e)}e.isSaving=!1}}function i(n={}){app.store.settings=JSON.parse(JSON.stringify(n)),e.formSettings={s3:n?.s3||{}},e.initSerialized=JSON.stringify(e.formSettings),e.originalFormSettings=JSON.parse(e.initSerialized)}function a(){e.formSettings=JSON.parse(e.initSerialized)}return t.div({pbEvent:`pageStorageSettings`,className:`page page-storage-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>e.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`storageSettingsForm`,className:`grid storage-settings-form`,inert:()=>e.isSaving,onsubmit:e=>{e.preventDefault(),r()}},t.div({className:`col-lg-12 txt-lg`},t.p(null,`By default PocketBase uses and recommends the local file system to store uploaded files because it is more performant, easier to manage and backup.`),t.p(null,`Alternatively, if you have limited disk space available, you could opt to an S3 compatible external storage.`)),t.div({className:`col-lg-12`},app.components.s3ConfigFields({config:()=>e.formSettings.s3,before:()=>{let n=e.originalFormSettings.s3?.enabled;if(n!=e.formSettings.s3?.enabled)return t.div({className:`alert info m-t-sm`},`If you have existing uploaded files, you'll have to migrate them manually from the `,t.strong(null,n?`S3 storage`:`local file system`),` to the `,t.strong(null,e.formSettings.s3?.enabled?`S3 storage`:`local file system`),`.`,t.br(),`There are several command line tools that can help you, such as: `,t.a({href:`https://github.com/rclone/rclone`,target:`_blank`,rel:`noopener noreferrer`,className:`txt-bold`,textContent:`rclone`}),`, `,t.a({href:`https://github.com/peak/s5cmd`,target:`_blank`,rel:`noopener noreferrer`,className:`txt-bold`,textContent:`s5cmd`}),`, etc.`)}})),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({hidden:()=>!e.hasChanges,type:`button`,className:`btn transparent secondary`,onclick:a},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${e.isSaving?`loading`:``}`,disabled:()=>!e.hasChanges||e.isSaving},t.span({className:`txt`},`Save changes`)))))),t.footer({className:`page-footer`},app.components.credits())))}function Ji(e){app.store.title=`Export collections`;let n=`export_`+app.utils.randomString(),r=store({isLoading:!1,collections:[],bulkSelected:{},get bulkSelectStr(){return JSON.stringify(app.utils.sortedCollectionsByType(Object.values(r.bulkSelected)),null,2)},get totalSelected(){return Object.keys(r.bulkSelected).length},get areAllSelected(){return r.collections.length&&r.collections.length==r.totalSelected}});i();async function i(){r.isLoading=!0;try{let e=await app.pb.collections.getFullList({requestKey:n});for(let n of e)delete n.created,delete n.updated,delete n.oauth2?.providers;r.collections=app.utils.sortedCollectionsByType(e),c(),r.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),r.isLoading=!1)}}function a(){let e=app.utils.sortedCollectionsByType(Object.values(r.bulkSelected));app.utils.downloadJSON(e,`pb_schema`)}function o(){r.areAllSelected?s():c()}function s(){r.bulkSelected={}}function c(){r.bulkSelected={};for(let e of r.collections)r.bulkSelected[e.id]=e}function l(e){let n=JSON.parse(JSON.stringify(r.bulkSelected));r.bulkSelected[e.id]?delete n[e.id]:n[e.id]=e,r.bulkSelected=n}return t.div({pbEvent:`pageExportCollections`,className:`page page-export-collections`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>r.isLoading?t.div({className:`txt-center`},t.span({className:`loader lg`})):t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`txt-lg`},`Below you'll find your current collections configuration that you could import in another PocketBase environment.`)),t.div({className:`col-lg-12`},t.div({className:`export-panel`},t.aside({className:`export-list`},t.div({className:`list-item`},t.div({className:`field`},t.input({id:n+`.select_all`,type:`checkbox`,checked:()=>r.areAllSelected,onchange:()=>o()}),t.label({htmlFor:n+`.select_all`},`Select all`))),()=>r.collections.map(e=>{let i=n+`_c_`+e.id;return t.div({className:`list-item`},t.div({className:`field`},t.input({id:i,type:`checkbox`,checked:()=>!!r.bulkSelected[e.id],onchange:()=>{l(e)}}),t.label({htmlFor:i},e.name)))})),t.output({className:`export-preview`},app.components.codeBlock({value:()=>r.bulkSelectStr,language:`plain`}),t.nav({className:`ctrls`},app.components.copyButton(()=>r.bulkSelectStr))))),t.div({className:`col-lg-12 txt-right`},t.button({className:`btn`,onclick:a},t.i({className:`ri-download-line`,ariaHidden:!0}),t.span({className:`txt`},`Download as JSON`))))),t.footer({className:`page-footer`},app.components.credits())))}function Yi(e){app.store.title=`Import collections`;let n=`import_`+app.utils.randomString(),r=[],i=store({rawNewCollections:``,oldCollections:[],newCollections:[],collectionsToUpdate:[],deleteMissing:!0,isLoadingFile:!1,isLoadingOldCollections:!1,mergeWithOldCollections:!1,get isRawValid(){return!!i.rawNewCollections&&i.newCollections?.length>0&&i.newCollections.length==i.newCollections.filter(e=>!!e.id&&!!e.name).length},get collectionsToDelete(){return i.oldCollections.filter(e=>i.isRawValid&&!i.mergeWithOldCollections&&i.deleteMissing&&!i.newCollections.find(n=>n.id==e.id))},get collectionsToAdd(){return i.newCollections.filter(e=>i.isRawValid&&!i.oldCollections.find(n=>n.id==e.id))},get idReplacableCollections(){return i.newCollections.filter(e=>{let n=i.oldCollections.find(n=>n.name==e.name||n.id==e.id);if(!n)return!1;if(n.id!=e.id)return!0;let r=Array.isArray(n.fields)?n.fields:[],a=Array.isArray(e.fields)?e.fields:[];for(let e of a){if(r.find(n=>n.id==e.id))continue;let n=r.find(n=>n.name==e.name);if(n&&e.id!=n.id)return!0}return!1})},get hasChanges(){return!!i.rawNewCollections&&!!(i.collectionsToDelete.length||i.collectionsToAdd.length||i.collectionsToUpdate.length)},get canReview(){return!i.isLoadingOldCollections&&i.isRawValid&&i.hasChanges}}),a=t.input({id:n+`_load_json`,type:`file`,className:`hidden`,accept:`.json`,onchange:()=>{d(a.files?.[0])}});o();async function o(){i.isLoadingOldCollections=!0;try{let e=await app.pb.collections.getFullList();for(let n of e)delete n.created,delete n.updated,delete n.oauth2?.providers;i.oldCollections=e,i.isLoadingOldCollections=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoadingOldCollections=!1)}}r.push(watch(()=>i.rawNewCollections,()=>{s()}));function s(){let e=[];try{e=JSON.parse(i.rawNewCollections),e=Array.isArray(e)?app.utils.filterDuplicatesByKey(e):[];for(let n of e)delete n.created,delete n.updated,n.fields&&=app.utils.filterDuplicatesByKey(n.fields)}catch{}i.newCollections=e}r.push(watch(()=>[i.newCollections,i.deleteMissing],()=>{c()}));function c(){if(i.collectionsToUpdate=[],i.isRawValid)for(let e of i.newCollections){let n=i.oldCollections.find(n=>n.id==e.id);!n?.id||!app.utils.hasCollectionChanges(n,e,i.deleteMissing)||i.collectionsToUpdate.push({new:e,old:n})}}function l(){for(let e of i.newCollections){let n=i.oldCollections.find(n=>n.name==e.name||n.id==e.id);if(!n)continue;let r=e.id,a=n.id;e.id=a;let o=Array.isArray(n.fields)?n.fields:[],s=Array.isArray(e.fields)?e.fields:[];for(let e of s){let n=o.find(n=>n.name==e.name);n&&n.id&&(e.id=n.id)}for(let e of i.newCollections)if(Array.isArray(e.fields))for(let n of e.fields)n.collectionId&&n.collectionId===r&&(n.collectionId=a);for(let n=0;ne.replace(r,a))}i.rawNewCollections=JSON.stringify(i.newCollections,null,2)}function u(){i.rawNewCollections=``,a.value=``,app.store.errors=null}function d(e){i.isLoadingFile=!0;let n=new FileReader;n.onload=async e=>{i.isLoadingFile=!1,a.value=``,i.rawNewCollections=e.target.result,await new Promise(e=>setTimeout(e,0)),i.newCollections.length||(app.toasts.error(`Invalid collections configuration.`),u())},n.onerror=e=>{app.toasts.error(`Failed to load the imported JSON.`),console.warn(e),i.isLoadingFile=!1,a.value=``},n.readAsText(e)}function f(){let e=i.mergeWithOldCollections?app.utils.filterDuplicatesByKey(i.oldCollections.concat(i.newCollections)):i.newCollections;app.modals.openImportCollectionsReview(i.oldCollections,e,{deleteMissing:i.deleteMissing,onsubmit:()=>{u(),o()}})}return t.div({pbEvent:`pageImportCollections`,className:`page page-import-collections`,onunmount:()=>{r.forEach(e=>e?.unwatch())}},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>i.isLoadingOldCollections?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.div({className:`grid`},t.div({className:`col-lg-12`},t.span({className:`txt-lg m-r-5`},`Paste below the collections configuration you want to import or`),t.label({htmlFor:a.id,className:()=>`btn sm outline ${i.isLoadingFile?`loading`:``}`},t.span({className:`txt`},`Load from JSON file`)),a,t.p({className:`txt-hint`},t.em(null,`You can use the `,t.a({href:`https://pocketbase.io/docs/go-migrations/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Go`}),` or `,t.a({href:`https://pocketbase.io/docs/js-migrations/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`JS`}),` migrations to manage your collections programmatically in more granular and version controlled manner.`))),t.div({className:`col-lg-12`},t.div({className:`field`},t.label({htmlFor:n+`_collections_field`},`Collections`),t.textarea({id:n+`_collections_field`,name:`collections`,rows:12,className:`txt-code`,spellcheck:!1,autocorrect:!1,autocomplete:`off`,autocapitalize:`off`,value:()=>i.rawNewCollections,oninput:e=>i.rawNewCollections=e.target.value})),t.div({className:()=>`field-help error ${i.rawNewCollections&&!i.isRawValid?``:`hidden`}`},`Invalid collections configuration.`)),t.div({className:()=>`col-lg-12 ${i.isRawValid?``:`hidden`}`},t.div({className:`field`},t.input({id:n+`_merge_checkbox`,type:`checkbox`,className:`switch`,checked:()=>i.mergeWithOldCollections,onchange:e=>i.mergeWithOldCollections=e.target.checked}),t.label({htmlFor:n+`_merge_checkbox`},`Merge with the existing collections`))),t.div({className:()=>`col-lg-12 ${i.isRawValid&&!i.hasChanges?``:`hidden`}`},t.div({className:`alert info`},t.div({className:`content`},t.p(null,`Your collections configuration is already up-to-date!`)))),t.div({className:()=>`col-lg-12 ${i.isRawValid&&i.hasChanges?``:`hidden`}`},t.p({className:`txt-hint txt-bold`},`Detected changes`),t.div({className:`list`},()=>i.collectionsToDelete.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label danger`,textContent:`Deleted`}),t.div({className:`inline-flex gap-5`},t.strong({textContent:()=>e.name}),t.small({className:()=>`txt-hint ${e.id?``:`hidden`}`,textContent:()=>e.id})))),()=>i.collectionsToUpdate.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label warning`,textContent:`Changed`}),t.div({className:`inline-flex gap-5`},()=>{if(e.old.name!=e.new.name)return[t.span({className:`txt-strikethrough txt-hint`,textContent:e.old.name}),t.i({className:`ri-arrow-right-line txt-sm`,ariaHidden:!0})]},t.strong({textContent:()=>e.new.name}),t.small({className:()=>`txt-hint ${e.new.id?``:`hidden`}`,textContent:()=>e.new.id})))),()=>i.collectionsToAdd.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label success`,textContent:`Added`}),t.div({className:`inline-flex gap-5`},t.strong({textContent:()=>e.name}),t.small({className:()=>`txt-hint ${e.id?``:`hidden`}`,textContent:()=>e.id})))))),t.div({className:()=>`col-lg-12 ${i.idReplacableCollections?.length?``:`hidden`}`},t.div({className:`alert warning`},t.div({className:`content`},t.p(null,`Some of the imported collections share the same name and/or fields but are imported with different IDs.`),t.p(null,`You can replace them in the import if you want to:`,t.button({type:`button`,className:`btn warning sm m-l-10`,textContent:`Replace with original IDs`,onclick:l}))))),t.div({className:`col-lg-12`},t.div({className:`flex`},t.button({type:`button`,className:()=>`btn secondary ${i.rawNewCollections?``:`hidden`}`,onclick:u},t.span({className:`txt`},`Clear`)),t.button({type:`button`,className:`btn expanded-lg m-l-auto`,disabled:()=>!i.canReview,onclick:f},t.span({className:`txt`},`Review`)))))),t.footer({className:`page-footer`},app.components.credits())))}window.app=window.app||{},window.app.routes=window.app.routes||{},window.app.routes.fallbackPath=`#/collections`,app.routes.guestOnly=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{if(app.pb.authStore.isValid&&app.pb.authStore.record?.id){window.location.hash=`#/`;return}app.store.showHeader=!1,app.store.page=await n(e)}},app.routes.superuserOnly=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{if(!app.pb.authStore.isValid||!app.pb.authStore.record?.id){window.location.hash=`#/login`;return}app.store.showHeader=!0,app.store.page=await n(e)}},app.routes.blank=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{app.store.showHeader=!1,app.store.page=await n(e)}};var Xi={},Zi;function Qi(){Zi&&Zi(),Zi=router(Xi,{fallbackPath:app.routes.fallbackPath})}app.routes.guestOnly(`#/pbinstall/{token}`,async e=>{let{pageInstaller:n}=await W(async()=>{let{pageInstaller:e}=await import(`./pageInstaller-Cs8T3uyd.js`);return{pageInstaller:e}},[],import.meta.url);return n(e)}),app.routes.guestOnly(`#/login`,e=>Yr(e)),app.routes.guestOnly(`#/request-password-reset`,async e=>{let{pageRequestSuperuserPasswordReset:n}=await W(async()=>{let{pageRequestSuperuserPasswordReset:e}=await import(`./pageRequestSuperuserPasswordReset-C39AMhGf.js`);return{pageRequestSuperuserPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-password-reset/{token}`,async e=>{let{pageConfirmPasswordReset:n}=await W(async()=>{let{pageConfirmPasswordReset:e}=await import(`./pageConfirmPasswordReset-DP6OcWeF.js`);return{pageConfirmPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-verification/{token}`,async e=>{let{pageConfirmVerification:n}=await W(async()=>{let{pageConfirmVerification:e}=await import(`./pageConfirmVerification-CmtNepxS.js`);return{pageConfirmVerification:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-email-change/{token}`,async e=>{let{pageConfirmEmailChange:n}=await W(async()=>{let{pageConfirmEmailChange:e}=await import(`./pageConfirmEmailChange-jQ1wgwOY.js`);return{pageConfirmEmailChange:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-success`,async e=>{let{pageOAuth2RedirectSuccess:n}=await W(async()=>{let{pageOAuth2RedirectSuccess:e}=await import(`./pageOAuth2RedirectSuccess-DmZV1eyz.js`);return{pageOAuth2RedirectSuccess:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-failure`,async e=>{let{pageOAuth2RedirectFailure:n}=await W(async()=>{let{pageOAuth2RedirectFailure:e}=await import(`./pageOAuth2RedirectFailure-CRvz4PXa.js`);return{pageOAuth2RedirectFailure:e}},[],import.meta.url);return n(e)}),app.routes.superuserOnly(`#/collections`,di),app.routes.superuserOnly(`#/logs`,Si),app.routes.superuserOnly(`#/settings`,Mi),app.routes.superuserOnly(`#/settings/mail`,Wi),app.routes.superuserOnly(`#/settings/storage`,qi),app.routes.superuserOnly(`#/settings/backups`,Vi),app.routes.superuserOnly(`#/settings/crons`,Ui),app.routes.superuserOnly(`#/settings/export-collections`,Ji),app.routes.superuserOnly(`#/settings/import-collections`,Yi),app.routes.superuserOnly(`#/settings/sql`,Ki);var $i=t;t=new Proxy({},{get(e,n){return function(){let e=arguments?.[0];if(e&&e.pbEvent){let n=e.onmount;e.onmount=r=>{n?.(r),r.dataset.pb=e.pbEvent,document.dispatchEvent(new CustomEvent(`mount:`+e.pbEvent,{detail:r}))};let r=e.onunmount;e.onunmount=n=>{document.dispatchEvent(new CustomEvent(`unmount:`+e.pbEvent,{detail:n})),r?.(n)}}return $i[n](...arguments)}}}),document.body.prepend(t.main({"html-class":`app`,className:()=>`app ${app.store.settings?.meta?.hideControls?`hide-controls`:``}`},Fe(),e=>(typeof app.store.page==`function`&&app.store.page(e),app.store.page))),watch(()=>app.store._ready,e=>{e&&Qi()}),document.body.appendChild(t.script({type:`module`,src:app.pb.buildURL(`/_/extensions.js`),onload:()=>{app.store._ready=!0},onerror:e=>{console.warn(`Failed to load extensions:`,e),app.store._ready=!0}}));export{S as n,se as r,Ee as t}; \ No newline at end of file +@hourly`)},`macros`),`.`,t.br(),`By default the timezone is in UTC.`)),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`backups.cronMaxKeep`},`Max @auto backups to keep`),t.input({id:`backups.cronMaxKeep`,name:`backups.cronMaxKeep`,type:`number`,required:()=>a.enableAutoBackups,min:1,value:()=>a.formSettings.backups.cronMaxKeep,oninput:e=>{a.formSettings.backups.cronMaxKeep=parseInt(e.target.value,10)}})))))),t.div({className:`col-lg-12`},app.components.s3ConfigFields({toggleLabel:`Store backups in S3 storage`,testFilesystem:`backups`,config:()=>a.formSettings.backups.s3})),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({hidden:()=>!a.hasChanges,type:`button`,className:`btn transparent secondary`,onclick:l},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${a.isSaving?`loading`:``}`,disabled:()=>!a.hasChanges||a.isSaving},t.span({className:`txt`},`Save changes`))))])))}function Fi(e={oncreated:null}){let n=Ii(e);n&&(document.body.appendChild(n),app.modals.open(n))}function Ii(e){let n,r=`backup_create_`+app.utils.randomString(),i=store({name:``,isSubmitting:!1}),a;async function o(){if(!i.isSubmitting){i.isSubmitting=!0,clearTimeout(a),a=setTimeout(()=>{app.modals.close(n)},1500);try{await app.pb.backups.create(i.name,{requestKey:r}),i.isSubmitting=!1,e.oncreated&&e.oncreated(i.name),app.toasts.success(`Successfully generated new backup.`),app.modals.close(n)}catch(e){e.isAbort||(clearTimeout(a),i.isSubmitting=!1,app.checkApiError(e))}}}return n=t.div({pbEvent:`backupCreateModal`,className:`modal popup backup-create-modal`,onbeforeclose:()=>{i.isSubmitting&&app.toasts.info(`The backup was started but may take a while to complete. You can come back later.`)},onafterclose:e=>{clearTimeout(a),e?.remove()}},t.header({className:`modal-header`},t.h5({className:`m-auto txt-center`},`Initialize new backup`)),t.form({id:r,className:`modal-content backup-restore-form`,autocomplete:`off`,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`alert warning`},t.div({className:`content`},t.p(null,`Please note that during the backup other concurrent write requests may fail since the database will be temporary "locked" (this usually happens only during the ZIP generation).`),t.p({className:`txt-bold`},`If you are using S3 storage for the collections file upload, you'll have to backup them separately since they are not locally stored and they will not be included in the generated backup!`)))),t.div({className:`col-lg-12`},t.div({className:`field`},t.label({htmlFor:r+`_name`},`Backup name`),t.input({id:r+`_name`,name:`name`,type:`text`,pattern:`^[a-z0-9_-]+.zip$`,placeholder:`Leave empty to autogenerate`,value:()=>i.name,oninput:e=>i.name=e.target.value})),t.div({className:`field-help`},`Must be in the format [a-z0-9_-].zip`)))),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,disabled:()=>i.isSubmitting,onclick:()=>app.modals.close(n)},t.span({className:`txt`},`Cancel`)),t.button({"html-form":r,type:`submit`,className:()=>`btn ${i.isSubmitting?`loading`:``}`,disabled:()=>i.isSubmitting},t.span({className:`txt`},`Start backup`)))),n}function Li(e){let n=Ri(e);document.body.appendChild(n),app.modals.open(n)}function Ri(e){let n=`backup_restore_`+app.utils.randomString(),r=store({key:e,keyConfirm:``,isSubmitting:!1,get canSubmit(){return r.key&&r.key==r.keyConfirm}}),i;async function a(){if(!(r.isSubmitting||!r.canSubmit)){clearTimeout(i),r.isSubmitting=!0;try{await app.pb.backups.restore(r.keyConfirm),i=setTimeout(()=>{window.location.reload(),r.isSubmitting=!1},2e3)}catch(e){clearTimeout(i),e?.isAbort||(r.isSubmitting=!1,app.checkApiError(e))}}}return t.div({pbEvent:`backupRestoreModal`,className:`modal popup backup-restore-modal`,onbeforeclose:()=>!r.isSubmitting,onafterclose:e=>{e?.remove()},onunmount:()=>{clearTimeout(i)}},t.header({className:`modal-header`},t.h5({className:`m-auto txt-center`},`Restore `,t.strong(null,()=>r.key))),t.form({id:n,className:`modal-content backup-restore-form`,autocomplete:`off`,onsubmit:e=>{e.preventDefault(),a()}},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`alert danger`},t.div({className:`content`},t.p({className:`txt-bold`},`Please proceed with extreme caution and use it only with trusted backups!`),t.p(null,`Backup restore currently works only on UNIX based systems.`),t.p(null,`The restore operation will attempt to replace your existing `,t.code(null,`pb_data`),` with the one from the backup and will restart the application process.`),t.p(null,`This means that on success all of your data (including app settings, users, superusers, etc.) will be replaced with the ones from the backup.`),t.p(null,`The operation will be reverted if the backup is invalid (ex. missing `,t.code(null,`data.db`),` file).`),t.p(null,`Below is an oversimplified version of the restore flow:`),t.ol(null,t.li(null,`Replaces the current `,t.code(null,`pb_data`),` with the content from the backup.`),t.li(null,`Triggers app restart.`),t.li(null,`Applies all migrations that are missing in the restored `,t.code(null,`pb_data`),`.`),t.li(null,`Initializes the app server as usual.`))))),t.div({className:`col-lg-12`},t.div({className:`confirm-key-label m-b-sm`},`Type the backup name `,t.div({className:`label`},()=>r.key,app.components.copyButton(()=>r.key)),` to confirm:`),t.div({className:`field`},t.label({htmlFor:n+`_key`},`Backup name`),t.input({id:n+`_key`,name:`key`,type:`text`,required:!0,value:()=>r.keyConfirm,oninput:e=>r.keyConfirm=e.target.value}))))),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,onclick:()=>app.modals.close(),disabled:()=>r.isSubmitting},t.span({className:`txt`},`Cancel`)),t.button({"html-form":n,type:`submit`,className:()=>`btn ${r.isSubmitting?`loading`:``}`,disabled:()=>r.isSubmitting||!r.canSubmit},t.span({className:`txt`},`Restore backup`))))}function zi(e={}){let n=store({reset:null}),r=app.utils.extendStore(n,e),i=store({canBackup:!0,isLoading:!1,isDownloading:{},isDeleting:{},backups:[]});async function a(){i.isLoading=!0;try{i.backups=await app.pb.backups.getFullList(),i.backups.sort((e,n)=>e.modifiedn.modified?-1:0),i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}async function o(e){app.modals.confirm(`Do you really want to delete ${e}?`,()=>s(e))}async function s(e){if(!i.isDeleting[e]){i.isDeleting[e]=!0;try{await app.pb.backups.delete(e),a(),app.toasts.success(`Successfully deleted ${e}.`)}catch(e){app.checkApiError(e)}delete i.isDeleting[e]}}async function c(){try{let e=await app.pb.health.check({requestKey:null}),n=i.canBackup;i.canBackup=e?.data?.canBackup||!1,i.canBackup&&n!=i.canBackup&&a()}catch(e){console.warn(`failed to load canBackup checks`,e)}}async function l(e){if(!i.isDownloading[e]){i.isDownloading[e]=!0;try{let n=await app.pb.files.getToken({requestKey:null});app.utils.download(app.pb.backups.getDownloadURL(n,e))}catch(e){app.checkApiError(e)}delete i.isDownloading[e]}}return t.div({pbEvent:`backupsList`,className:`list backups-list`,onmount:e=>{r.push(watch(()=>n.reset,()=>{a()})),e._canBackupIntervalId=setInterval(()=>{c()},3500)},onunmount:e=>{clearInterval(e._canBackupIntervalId),r.forEach(e=>e?.unwatch())}},t.div({className:`list-content`},t.div({hidden:()=>!i.isLoading||i.backups.length,className:`list-item`},t.div({className:`skeleton-loader`})),t.div({hidden:()=>i.isLoading||i.backups.length,className:()=>`list-item`},t.div({className:`content block txt-hint`},`No backups found.`)),()=>i.backups.map(e=>t.div({className:()=>`list-item ${i.isLoading?`faded`:``}`},t.i({className:`ri-folder-zip-line`,ariaHidden:!0}),t.div({className:`content`},t.span({className:`backup-name txt-ellipsis`,title:()=>e.key,textContent:()=>e.key}),t.small({className:`backup-size txt-hint txt-nowrap`},`(`,()=>app.utils.formattedFileSize(e.size),`)`)),t.nav({hidden:()=>i.isLoading,className:`actions autohide`},t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Download`),className:()=>`btn sm circle secondary transparent ${i.isDownloading[e.key]?`loading`:``}`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>l(e.key)},t.i({className:`ri-download-line`,ariaHidden:!0})),t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Restore`),className:()=>`btn sm circle secondary transparent`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>Li(e.key)},t.i({className:`ri-restart-line`,ariaHidden:!0})),t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Delete`),className:()=>`btn sm circle secondary transparent ${i.isDeleting[e.key]?`loading`:``}`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>o(e.key)},t.i({className:`ri-delete-bin-7-line`,ariaHidden:!0})))))),t.div({className:`list-item`},t.button({type:`button`,className:()=>`btn secondary block ${i.isLoading?`loading`:``}`,disabled:()=>!i.canBackup||i.isLoading,onclick:()=>{Fi({oncreated:()=>a()})}},()=>i.canBackup?[t.i({className:`ri-play-circle-line`,ariaHidden:!0}),t.span({className:`txt`},`Initialize new backup`)]:[t.span({className:`loader sm`}),t.span({className:`txt`},`Backup/restore operation is in process`)])))}function Bi(e=null){let n=`backup_upload_`+app.utils.randomString(),r=store({isUploading:!1});function i(e){e&&app.modals.confirm(`Note that we don't perform validations for the uploaded backup files. Proceed with extreme caution and only if you trust the source.\n\nDo you really want to upload "${e.name}"?`,()=>{a(e)},()=>{o()})}async function a(i){if(!(!i||r.isUploading)){r.isUploading=!0;try{let a=new FormData;a.set(`file`,i),await app.pb.backups.upload(a,{requestKey:n}),r.isUploading=!1,e(i),app.toasts.success(`Successfully uploaded a new backup.`)}catch(e){e.isAbort||(r.isUploading=!1,e.response?.formData?.file?.message?app.toasts.error(e.response.formData.file.message):app.checkApiError(e))}o()}}function o(){s&&(s.value=``)}let s=t.input({type:`file`,accept:`application/zip`,className:`hidden`,onchange:e=>{i(e.target?.files?.[0])}});return t.div(null,t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Upload backup`),className:()=>`btn sm transparent secondary circle ${r.isUploading?`loading`:``}`,disabled:()=>r.isUploading,onclick:()=>s?.click(),onunmount:()=>{app.pb.cancelRequest(n)}},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0})),s)}function Vi(e){app.store.title=`Backups`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageBackupsSettings`,className:`page page-backups-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`flex gap-10 m-b-sm`},t.div({className:`txt-lg`},`Backup and restore your PocketBase data`),app.components.refreshButton({className:`btn sm transparent secondary circle tooltip-bottom`,onclick:r}),Bi(r)),zi({reset:()=>n.resetList})),t.div({className:`col-lg-12`},Pi({onsave:()=>r()})))),t.footer({className:`page-footer`},app.components.credits())))}function Hi(e={}){let n=store({reset:null}),r=app.utils.extendStore(n,e),i=store({isLoading:!1,isRunning:{},crons:[]});async function a(){i.isLoading=!0;try{i.crons=await app.pb.crons.getFullList(),i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}async function o(e){if(!(!e||i.isRunning[e])){i.isRunning[e]=!0;try{await app.pb.crons.run(e),app.toasts.success(`Successfully triggered "${e}".`),i.isRunning[e]=!1}catch(n){n.isAbort||(ApiClient.error(n),i.isRunning[e]=!1)}}}return t.div({pbEvent:`cronsList`,className:`list`,onmount:()=>{r.push(watch(()=>n.reset,()=>{a()}))},onunmount:()=>{r.forEach(e=>e?.unwatch())}},()=>{if(!i.isLoading||i.crons.length)return;let e=[];for(let n=0;n<4;n++)e.push(t.div({rid:`skeleton_`+n,className:`list-item`},t.div({className:`skeleton-loader`})));return e},t.div({hidden:()=>i.isLoading||i.crons.length,className:`list-item`},t.div({className:`content block txt-hint`},`No registered crons found.`)),()=>i.crons.map(e=>t.div({className:()=>`list-item ${i.isLoading?`faded`:``}`},t.div({className:`content`},t.span({className:`cron-id txt-code txt-ellipsis`,title:()=>e.id,textContent:()=>e.id})),t.small({className:`cron-expression txt-hint txt-nowrap txt-code`},()=>e.expression),t.nav({hidden:()=>i.isLoading,className:`actions`},t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Run`),className:()=>`btn sm circle secondary transparent ${i.isRunning[e.id]?`loading`:``}`,disabled:()=>i.isRunning[e.id],onclick:()=>o(e.id)},t.i({className:`ri-play-large-line`,ariaHidden:!0}))))))}function Ui(e){app.store.title=`Crons`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageCronsSettings`,className:`page`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},t.div({className:`flex gap-10 m-b-sm`},t.div({className:`txt-lg`},`Registered app cron jobs`),app.components.refreshButton({className:`btn sm transparent secondary circle`,onclick:r})),Hi({reset:()=>n.resetList}),t.div({className:`txt-sm txt-hint m-t-sm`},`App cron jobs can be registered only programmatically with `,t.a({href:`https://pocketbase.io/docs/go-jobs-scheduling/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Go`}),` or `,t.a({href:`https://pocketbase.io/docs/js-jobs-scheduling/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`JavaScript`}),`.`)),t.footer({className:`page-footer`},app.components.credits())))}function Wi(e){app.store.title=`Mail settings`;let n=[{label:`Auto (StartTLS)`,value:!1},{label:`Always`,value:!0}],r=[{label:`PLAIN (default)`,value:`PLAIN`},{label:`LOGIN`,value:`LOGIN`}],i=store({isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,showMoreOptions:!1,get hasChanges(){return i.initSerialized!=JSON.stringify(i.formSettings)}});a();async function a(){i.isLoading=!0;try{s(await app.pb.settings.getAll()),i.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function o(){if(!(i.isSaving||!i.hasChanges)){i.isSaving=!0;try{let e=app.utils.filterRedactedProps(i.formSettings);s(await app.pb.settings.update(e)),app.toasts.success(`Successfully saved mail settings.`)}catch(e){app.checkApiError(e)}i.isSaving=!1}}function s(e={}){app.store.settings=JSON.parse(JSON.stringify(e)),i.formSettings={meta:e?.meta||{},smtp:e?.smtp||{}},i.formSettings.smtp.authMethod||(i.formSettings.smtp.authMethod=r[0].value),i.initSerialized=JSON.stringify(i.formSettings)}function c(){i.formSettings=JSON.parse(i.initSerialized)}return t.div({pbEvent:`pageMailSettings`,className:`page page-mail-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>i.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`mailSettingsForm`,className:`grid mail-settings-form`,inert:()=>i.isSaving,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`col-lg-12 txt-lg`},t.p(null,`Configure common settings for sending emails.`)),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`meta.senderName`},`Sender name`),t.input({id:`meta.senderName`,name:`meta.senderName`,type:`text`,required:!0,value:()=>i.formSettings.meta.senderName||``,oninput:e=>i.formSettings.meta.senderName=e.target.value}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`meta.senderAddress`},`Sender address`),t.input({id:`meta.senderAddress`,name:`meta.senderAddress`,type:`email`,required:!0,value:()=>i.formSettings.meta.senderAddress||``,oninput:e=>i.formSettings.meta.senderAddress=e.target.value}))),t.div({className:`col-lg-12`},t.div({className:`field`},t.input({id:`smtp.enabled`,name:`smtp.enabled`,type:`checkbox`,className:`switch`,checked:()=>!!i.formSettings.smtp.enabled,onchange:e=>i.formSettings.smtp.enabled=e.target.checked}),t.label({htmlFor:`smtp.enabled`},t.span({className:`txt`},`Use SMTP mail server `,t.strong(null,`(recommended)`)),t.i({className:`ri-information-line link-faded`,ariaDescription:app.attrs.tooltip(`By default PocketBase uses the unix "sendmail" command for sending emails. For better emails deliverability it is recommended to use a SMTP mail server.`)}))),app.components.slide(()=>i.formSettings.smtp.enabled,t.div({className:`grid m-t-sm`},t.div({className:`col-lg-4`},t.div({className:`field`},t.label({htmlFor:`smtp.host`},`SMTP server host`),t.input({id:`smtp.host`,name:`smtp.host`,type:`text`,required:()=>i.formSettings.smtp.enabled,value:()=>i.formSettings.smtp.host||``,oninput:e=>i.formSettings.smtp.host=e.target.value}))),t.div({className:`col-lg-2`},t.div({className:`field`},t.label({htmlFor:`smtp.port`},`Port`),t.input({id:`smtp.port`,name:`smtp.port`,type:`number`,min:0,step:1,required:()=>i.formSettings.smtp.enabled,value:()=>i.formSettings.smtp.port||``,oninput:e=>i.formSettings.smtp.port=parseInt(e.target.value,10)}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.username`},`Username`),t.input({id:`smtp.username`,name:`smtp.username`,type:`text`,autocomplete:`off`,value:()=>i.formSettings.smtp.username||``,oninput:e=>i.formSettings.smtp.username=e.target.value}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.password`},`Password`),t.input({id:`smtp.password`,name:`smtp.password`,type:`password`,autocomplete:`new-password`,value:()=>i.formSettings.smtp.password||``,oninput:e=>i.formSettings.smtp.password=e.target.value,onkeyup:e=>{e.key==`Backspace`&&i.formSettings.smtp.password===void 0&&(i.formSettings.smtp.password=``)},placeholder:()=>i.formSettings.smtp.password===void 0?`* * * * * *`:``})))),t.button({type:`button`,className:`btn secondary sm m-t-sm`,onclick:()=>i.showMoreOptions=!i.showMoreOptions},t.span({className:`txt`},()=>i.showMoreOptions?`Hide more options`:`Show more options`),t.i({className:()=>i.showMoreOptions?`ri-arrow-drop-up-line`:`ri-arrow-drop-down-line`})),app.components.slide(()=>i.showMoreOptions,t.div({className:`grid m-t-sm`},t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.tls`},`TLS encryption`),app.components.select({id:`smtp.tls`,name:`smtp.tls`,required:!0,options:n,value:()=>i.formSettings.smtp.tls||!1,onchange:e=>{i.formSettings.smtp.tls=e?.[0]?.value}}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.authMethod`},`AUTH method`),app.components.select({id:`smtp.authMethod`,name:`smtp.authMethod`,required:!0,options:r,value:()=>i.formSettings.smtp.authMethod||r[0].value,onchange:e=>{i.formSettings.smtp.authMethod=e?.[0]?.value}}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`smtp.localName`},t.span({className:`txt`},`EHLO/HELO domain`),t.i({className:`ri-information-line link-hint tooltip-top`,ariaDescription:app.attrs.tooltip(`Some SMTP servers, such as the Gmail SMTP-relay, requires a proper domain name in the inital EHLO/HELO exchange and will reject attempts to use localhost.`)})),t.input({id:`smtp.localName`,name:`smtp.localName`,type:`text`,placeholder:`Default to localhost`,value:()=>i.formSettings.smtp.localName||``,oninput:e=>i.formSettings.smtp.localName=e.target.value}))))))),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),()=>i.hasChanges?[t.button({type:`button`,className:`btn transparent secondary`,onclick:c},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${i.isSaving?`loading`:``}`,disabled:()=>!i.hasChanges||i.isSaving},t.span({className:`txt`},`Save changes`))]:t.button({type:`button`,className:()=>`btn expanded-lg outline`,onclick:()=>app.modals.openMailTest()},t.i({className:`ri-mail-check-line`,ariaHidden:!0}),t.span({className:`txt`},`Send test email`)))))),t.footer({className:`page-footer`},app.components.credits())))}var Gi=`pbSQLConsoleHistory`;function Ki(e){app.store.title=`SQL console`;let n=`sql_console_`+app.utils.randomString(),r=n+`editor`,i=n+`executeSQL`,a=store({askedForConfirmationAtLeastOnce:!1,isExecuting:!1,maxRows:250,query:``,result:{},sort:{},errorMsg:``,executedHistory:app.utils.getLocalHistory(Gi,[]),get sortedResultRows(){if(a.sort?.index===void 0){let e=a.result?.rows||[];return a.maxRows>=e.length?e:e.slice(0,a.maxRows)}let e=!!a.sort?.asc,n=a.result?.rows?.toSorted((n,r)=>{let i=n[a.sort.index],o=r[a.sort.index];return e||(i=r[a.sort.index],o=n[a.sort.index]),i==o?0:i==null?-1:o==null?1:i.localeCompare(o)})||[];return a.maxRows>=n.length?n:n.slice(0,a.maxRows)},get totalRemainingRows(){return(a.result?.rows?.length<<0)-a.sortedResultRows.length}});function o(e){return e?.trim()?!a.askedForConfirmationAtLeastOnce&&app.store.settings?.meta?.hideControls?!0:(e=e?.replace(/[\s\;]/gm,` `).toUpperCase()+` `,!![`ALTER `,`REPLACE `,`INSERT `,`CREATE `,`UPDATE `,`DELETE `,`DROP `,`DETACH `,`PRAGMA `].find(n=>e.includes(n))):!1}async function s(){return o(a.query)?(a.askedForConfirmationAtLeastOnce=!0,app.modals.confirm(t.div({className:`txt-center`},t.h6(null,`Be careful and continue only if you really know what you are doing because, depending on the query, the operation could break your application and may not be reversible.`)),()=>c(),null,{yesButton:`Execute`,noButton:`Cancel`})):c()}async function c(){a.isExecuting=!0,a.maxRows=250,a.result={},a.sort={},a.errorMsg=``;let e=a.query.trim();if(!e){app.pb.cancelRequest(i),a.isExecuting=!1;return}try{a.result=await app.pb.sql.run(e,{requestKey:i}),u(e),a.isExecuting=!1}catch(e){e?.isAbort||(a.isExecuting=!1,a.errorMsg=e?.response?.message||e?.message||`Failed to execute query.`)}}function l(e){function n(e){return e.replace(/[\s\;]/gm,``).toUpperCase()}let r=n(e);for(let i=a.executedHistory.length-1;i>=0;i--)(a.executedHistory[i]==e||n(a.executedHistory[i])==r)&&a.executedHistory.splice(i,1)}function u(e){l(e),a.executedHistory.unshift(a.query),a.executedHistory.length>10&&a.executedHistory.splice(10)}function d(){if(!a.sortedResultRows.length)return;let e=[a.result.columns.map(e=>e.name)].concat(a.sortedResultRows),n=`export_`+new Date().toISOString().replace(/[\-\:\.]/g,``)+`.csv`;app.utils.downloadCSV(e,n)}function f(e){a.sort?.index==e?a.sort={index:e,asc:!a.sort.asc}:a.sort={index:e,asc:!0}}let p=[watch(()=>JSON.stringify(a.executedHistory),(e,n)=>{n!==void 0&&window.localStorage.setItem(Gi,e)})];return t.div({pbEvent:`pageSQLConsole`,className:`page`,onunmount:()=>{app.pb.cancelRequest(i),p.forEach(e=>e?.unwatch())}},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title)),t.div({className:`page-header-secondary-btns`},t.button({type:`button`,className:`btn circle transparent secondary`,ariaDescription:app.attrs.tooltip(`Recently executed queries`,`right`),"html-popovertarget":`sql-console-history-dropdown`},t.i({className:`ri-history-line`,ariaHidden:!0})),t.div({id:`sql-console-history-dropdown`,className:()=>`dropdown left sql-console-history-dropdown ${a.executedHistory.length?``:`no-items`}`,popover:`auto`},()=>a.executedHistory.length?a.executedHistory.map(e=>t.button({role:`button`,className:`dropdown-item`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),a.query=e,document.getElementById(r)?.click()}},t.span({className:`query`},()=>app.utils.truncate(e,500)),t.small({role:`button`,className:`remove-btn link-hint m-l-auto p-l-5 p-r-5`,title:`Clear`,onauxclick:e=>(e.stopPropagation(),!1),onclick:n=>(n.stopPropagation(),l(e),!1)},t.i({className:`ri-close-line`,ariaHidden:!0})))):t.span({className:`txt txt-hint p-5`},`No recently executed queries.`))),t.div({className:`page-header-primary-btns`},t.button({type:`button`,className:()=>`btn expanded-lg ${a.isExecuting?`loading`:``}`,disabled:()=>a.isExecuting,onclick:()=>s()},t.i({className:`ri-play-large-line`,ariaHidden:!0}),t.span({className:`txt`},`Execute`)))),t.div({className:`field sql-console-field`},app.components.codeEditor({id:r,language:`sql`,required:!0,name:`query`,placeholder:`e.g. EXPLAIN QUERY PLAN SELECT * from users WHERE verified=true`,value:()=>a.query,oninput:e=>a.query=e,onblur:e=>a.query=e.trim()})),t.div({className:`flex field-help m-b-sm`},t.button({type:`button`,className:`link-hint m-l-auto`,"html-popovertarget":n+`caveats_dropdown`},()=>`SQL console caveats`),t.div({id:n+`caveats_dropdown`,className:`dropdown sm query-caveats-dropdown`,popover:`auto`},t.ul(null,t.li(null,`The returned rows are limited up to 1000.`),t.li(null,`The executed queries have a max timeout of 3 minutes.`),t.li(null,`The data is returned as byte strings without any additional formatting.`),t.li(null,`Multiple queries are supported but only the result of the last one is returned.`)))),t.div({hidden:()=>a.isExecuting||!a.errorMsg,className:`alert danger m-b-sm`},t.pre(null,()=>a.errorMsg)),t.div({hidden:()=>a.isExecuting||a.errorMsg||a.result?.columns?.length||app.utils.isEmpty(a.result),className:`alert success m-b-sm`},t.p({className:`txt-bold`},`Query executed successfully!`),()=>{if(a.result?.affectedRows)return t.p(null,`Affected rows: `,a.result?.affectedRows)}),t.div({hidden:()=>a.isExecuting||!a.result?.columns?.length,className:`page-table-wrapper`},t.table({className:`sql-console-table responsive-table optimize`},t.thead({className:`sticky`},t.tr(null,()=>a.result?.columns?.map((e,n)=>t.th({textContent:e.name,className:()=>{let e=`sort-handle`;return a.sort?.index==n&&(e+=a.sort.asc?` asc`:` desc`),e},onclick:()=>f(n)})))),t.tbody(null,()=>a.sortedResultRows.length?a.sortedResultRows.map(e=>t.tr(null,()=>a.result?.columns?.map((n,r)=>{let i=e[r];return t.td({"html-data-name":n.name},i==null?`NULL`:app.utils.truncate(i,2e3))}))):t.tr(null,t.td({colSpan:a.result?.columns?.length||1,className:`txt-center`},t.span({className:`txt-hint`},`No rows found.`))),t.tr({hidden:()=>a.isExecuting||!a.result?.rows?.length||a.result.rows.length<=a.sortedResultRows.length},t.td({colSpan:99},t.button({type:`button`,className:`btn lg secondary load-more-btn`,onclick:()=>{a.maxRows=a.result?.rows?.length||250}},t.span({className:`txt`,textContent:()=>`Load remaining (${a.totalRemainingRows})`}))))))),t.footer({className:`page-footer`},t.span({className:()=>`exec-time ${a.isExecuting?`faded`:``}`},`Time: `,()=>(a.result?.execTime||0)+`ms`),t.span({hidden:()=>!a.result?.columns?.length,className:()=>`total-count ${a.isExecuting?`faded`:``}`},`Rows: `,()=>a.result?.rows?.length||0,()=>{if(a.result?.rows?.length)return[` (`,t.span({role:`button`,className:`link-hint`,textContent:`Export as CSV`,onclick:d}),`)`]}),app.components.credits())))}function qi(){app.store.title=`File storage`;let e=store({isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,originalFormSettings:null,get hasChanges(){return e.initSerialized!=JSON.stringify(e.formSettings)}});n();async function n(){e.isLoading=!0;try{i(await app.pb.settings.getAll()),e.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function r(){if(!(e.isSaving||!e.hasChanges)){e.isSaving=!0;try{let n=app.utils.filterRedactedProps(e.formSettings);i(await app.pb.settings.update(n)),app.toasts.success(`Successfully saved storage settings.`)}catch(e){app.checkApiError(e)}e.isSaving=!1}}function i(n={}){app.store.settings=JSON.parse(JSON.stringify(n)),e.formSettings={s3:n?.s3||{}},e.initSerialized=JSON.stringify(e.formSettings),e.originalFormSettings=JSON.parse(e.initSerialized)}function a(){e.formSettings=JSON.parse(e.initSerialized)}return t.div({pbEvent:`pageStorageSettings`,className:`page page-storage-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>e.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`storageSettingsForm`,className:`grid storage-settings-form`,inert:()=>e.isSaving,onsubmit:e=>{e.preventDefault(),r()}},t.div({className:`col-lg-12 txt-lg`},t.p(null,`By default PocketBase uses and recommends the local file system to store uploaded files because it is more performant, easier to manage and backup.`),t.p(null,`Alternatively, if you have limited disk space available, you could opt to an S3 compatible external storage.`)),t.div({className:`col-lg-12`},app.components.s3ConfigFields({config:()=>e.formSettings.s3,before:()=>{let n=e.originalFormSettings.s3?.enabled;if(n!=e.formSettings.s3?.enabled)return t.div({className:`alert info m-t-sm`},`If you have existing uploaded files, you'll have to migrate them manually from the `,t.strong(null,n?`S3 storage`:`local file system`),` to the `,t.strong(null,e.formSettings.s3?.enabled?`S3 storage`:`local file system`),`.`,t.br(),`There are several command line tools that can help you, such as: `,t.a({href:`https://github.com/rclone/rclone`,target:`_blank`,rel:`noopener noreferrer`,className:`txt-bold`,textContent:`rclone`}),`, `,t.a({href:`https://github.com/peak/s5cmd`,target:`_blank`,rel:`noopener noreferrer`,className:`txt-bold`,textContent:`s5cmd`}),`, etc.`)}})),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({hidden:()=>!e.hasChanges,type:`button`,className:`btn transparent secondary`,onclick:a},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${e.isSaving?`loading`:``}`,disabled:()=>!e.hasChanges||e.isSaving},t.span({className:`txt`},`Save changes`)))))),t.footer({className:`page-footer`},app.components.credits())))}function Ji(e){app.store.title=`Export collections`;let n=`export_`+app.utils.randomString(),r=store({isLoading:!1,collections:[],bulkSelected:{},get bulkSelectStr(){return JSON.stringify(app.utils.sortedCollectionsByType(Object.values(r.bulkSelected)),null,2)},get totalSelected(){return Object.keys(r.bulkSelected).length},get areAllSelected(){return r.collections.length&&r.collections.length==r.totalSelected}});i();async function i(){r.isLoading=!0;try{let e=await app.pb.collections.getFullList({requestKey:n});for(let n of e)delete n.created,delete n.updated,delete n.oauth2?.providers;r.collections=app.utils.sortedCollectionsByType(e),c(),r.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),r.isLoading=!1)}}function a(){let e=app.utils.sortedCollectionsByType(Object.values(r.bulkSelected));app.utils.downloadJSON(e,`pb_schema`)}function o(){r.areAllSelected?s():c()}function s(){r.bulkSelected={}}function c(){r.bulkSelected={};for(let e of r.collections)r.bulkSelected[e.id]=e}function l(e){let n=JSON.parse(JSON.stringify(r.bulkSelected));r.bulkSelected[e.id]?delete n[e.id]:n[e.id]=e,r.bulkSelected=n}return t.div({pbEvent:`pageExportCollections`,className:`page page-export-collections`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>r.isLoading?t.div({className:`txt-center`},t.span({className:`loader lg`})):t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`txt-lg`},`Below you'll find your current collections configuration that you could import in another PocketBase environment.`)),t.div({className:`col-lg-12`},t.div({className:`export-panel`},t.aside({className:`export-list`},t.div({className:`list-item`},t.div({className:`field`},t.input({id:n+`.select_all`,type:`checkbox`,checked:()=>r.areAllSelected,onchange:()=>o()}),t.label({htmlFor:n+`.select_all`},`Select all`))),()=>r.collections.map(e=>{let i=n+`_c_`+e.id;return t.div({className:`list-item`},t.div({className:`field`},t.input({id:i,type:`checkbox`,checked:()=>!!r.bulkSelected[e.id],onchange:()=>{l(e)}}),t.label({htmlFor:i},e.name)))})),t.output({className:`export-preview`},app.components.codeBlock({value:()=>r.bulkSelectStr,language:`plain`}),t.nav({className:`ctrls`},app.components.copyButton(()=>r.bulkSelectStr))))),t.div({className:`col-lg-12 txt-right`},t.button({className:`btn`,onclick:a},t.i({className:`ri-download-line`,ariaHidden:!0}),t.span({className:`txt`},`Download as JSON`))))),t.footer({className:`page-footer`},app.components.credits())))}function Yi(e){app.store.title=`Import collections`;let n=`import_`+app.utils.randomString(),r=[],i=store({rawNewCollections:``,oldCollections:[],newCollections:[],collectionsToUpdate:[],deleteMissing:!0,isLoadingFile:!1,isLoadingOldCollections:!1,mergeWithOldCollections:!1,get isRawValid(){return!!i.rawNewCollections&&i.newCollections?.length>0&&i.newCollections.length==i.newCollections.filter(e=>!!e.id&&!!e.name).length},get collectionsToDelete(){return i.oldCollections.filter(e=>i.isRawValid&&!i.mergeWithOldCollections&&i.deleteMissing&&!i.newCollections.find(n=>n.id==e.id))},get collectionsToAdd(){return i.newCollections.filter(e=>i.isRawValid&&!i.oldCollections.find(n=>n.id==e.id))},get idReplacableCollections(){return i.newCollections.filter(e=>{let n=i.oldCollections.find(n=>n.name==e.name||n.id==e.id);if(!n)return!1;if(n.id!=e.id)return!0;let r=Array.isArray(n.fields)?n.fields:[],a=Array.isArray(e.fields)?e.fields:[];for(let e of a){if(r.find(n=>n.id==e.id))continue;let n=r.find(n=>n.name==e.name);if(n&&e.id!=n.id)return!0}return!1})},get hasChanges(){return!!i.rawNewCollections&&!!(i.collectionsToDelete.length||i.collectionsToAdd.length||i.collectionsToUpdate.length)},get canReview(){return!i.isLoadingOldCollections&&i.isRawValid&&i.hasChanges}}),a=t.input({id:n+`_load_json`,type:`file`,className:`hidden`,accept:`.json`,onchange:()=>{d(a.files?.[0])}});o();async function o(){i.isLoadingOldCollections=!0;try{let e=await app.pb.collections.getFullList();for(let n of e)delete n.created,delete n.updated,delete n.oauth2?.providers;i.oldCollections=e,i.isLoadingOldCollections=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoadingOldCollections=!1)}}r.push(watch(()=>i.rawNewCollections,()=>{s()}));function s(){let e=[];try{e=JSON.parse(i.rawNewCollections),e=Array.isArray(e)?app.utils.filterDuplicatesByKey(e):[];for(let n of e)delete n.created,delete n.updated,n.fields&&=app.utils.filterDuplicatesByKey(n.fields)}catch{}i.newCollections=e}r.push(watch(()=>[i.newCollections,i.deleteMissing],()=>{c()}));function c(){if(i.collectionsToUpdate=[],i.isRawValid)for(let e of i.newCollections){let n=i.oldCollections.find(n=>n.id==e.id);!n?.id||!app.utils.hasCollectionChanges(n,e,i.deleteMissing)||i.collectionsToUpdate.push({new:e,old:n})}}function l(){for(let e of i.newCollections){let n=i.oldCollections.find(n=>n.name==e.name||n.id==e.id);if(!n)continue;let r=e.id,a=n.id;e.id=a;let o=Array.isArray(n.fields)?n.fields:[],s=Array.isArray(e.fields)?e.fields:[];for(let e of s){let n=o.find(n=>n.name==e.name);n&&n.id&&(e.id=n.id)}for(let e of i.newCollections)if(Array.isArray(e.fields))for(let n of e.fields)n.collectionId&&n.collectionId===r&&(n.collectionId=a);for(let n=0;ne.replace(r,a))}i.rawNewCollections=JSON.stringify(i.newCollections,null,2)}function u(){i.rawNewCollections=``,a.value=``,app.store.errors=null}function d(e){i.isLoadingFile=!0;let n=new FileReader;n.onload=async e=>{i.isLoadingFile=!1,a.value=``,i.rawNewCollections=e.target.result,await new Promise(e=>setTimeout(e,0)),i.newCollections.length||(app.toasts.error(`Invalid collections configuration.`),u())},n.onerror=e=>{app.toasts.error(`Failed to load the imported JSON.`),console.warn(e),i.isLoadingFile=!1,a.value=``},n.readAsText(e)}function f(){let e=i.mergeWithOldCollections?app.utils.filterDuplicatesByKey(i.oldCollections.concat(i.newCollections)):i.newCollections;app.modals.openImportCollectionsReview(i.oldCollections,e,{deleteMissing:i.deleteMissing,onsubmit:()=>{u(),o()}})}return t.div({pbEvent:`pageImportCollections`,className:`page page-import-collections`,onunmount:()=>{r.forEach(e=>e?.unwatch())}},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>i.isLoadingOldCollections?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.div({className:`grid`},t.div({className:`col-lg-12`},t.span({className:`txt-lg m-r-5`},`Paste below the collections configuration you want to import or`),t.label({htmlFor:a.id,className:()=>`btn sm outline ${i.isLoadingFile?`loading`:``}`},t.span({className:`txt`},`Load from JSON file`)),a,t.p({className:`txt-hint`},t.em(null,`You can use the `,t.a({href:`https://pocketbase.io/docs/go-migrations/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Go`}),` or `,t.a({href:`https://pocketbase.io/docs/js-migrations/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`JS`}),` migrations to manage your collections programmatically in more granular and version controlled manner.`))),t.div({className:`col-lg-12`},t.div({className:`field`},t.label({htmlFor:n+`_collections_field`},`Collections`),t.textarea({id:n+`_collections_field`,name:`collections`,rows:12,className:`txt-code`,spellcheck:!1,autocorrect:!1,autocomplete:`off`,autocapitalize:`off`,value:()=>i.rawNewCollections,oninput:e=>i.rawNewCollections=e.target.value})),t.div({className:()=>`field-help error ${i.rawNewCollections&&!i.isRawValid?``:`hidden`}`},`Invalid collections configuration.`)),t.div({className:()=>`col-lg-12 ${i.isRawValid?``:`hidden`}`},t.div({className:`field`},t.input({id:n+`_merge_checkbox`,type:`checkbox`,className:`switch`,checked:()=>i.mergeWithOldCollections,onchange:e=>i.mergeWithOldCollections=e.target.checked}),t.label({htmlFor:n+`_merge_checkbox`},`Merge with the existing collections`))),t.div({className:()=>`col-lg-12 ${i.isRawValid&&!i.hasChanges?``:`hidden`}`},t.div({className:`alert info`},t.div({className:`content`},t.p(null,`Your collections configuration is already up-to-date!`)))),t.div({className:()=>`col-lg-12 ${i.isRawValid&&i.hasChanges?``:`hidden`}`},t.p({className:`txt-hint txt-bold`},`Detected changes`),t.div({className:`list`},()=>i.collectionsToDelete.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label danger`,textContent:`Deleted`}),t.div({className:`inline-flex gap-5`},t.strong({textContent:()=>e.name}),t.small({className:()=>`txt-hint ${e.id?``:`hidden`}`,textContent:()=>e.id})))),()=>i.collectionsToUpdate.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label warning`,textContent:`Changed`}),t.div({className:`inline-flex gap-5`},()=>{if(e.old.name!=e.new.name)return[t.span({className:`txt-strikethrough txt-hint`,textContent:e.old.name}),t.i({className:`ri-arrow-right-line txt-sm`,ariaHidden:!0})]},t.strong({textContent:()=>e.new.name}),t.small({className:()=>`txt-hint ${e.new.id?``:`hidden`}`,textContent:()=>e.new.id})))),()=>i.collectionsToAdd.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label success`,textContent:`Added`}),t.div({className:`inline-flex gap-5`},t.strong({textContent:()=>e.name}),t.small({className:()=>`txt-hint ${e.id?``:`hidden`}`,textContent:()=>e.id})))))),t.div({className:()=>`col-lg-12 ${i.idReplacableCollections?.length?``:`hidden`}`},t.div({className:`alert warning`},t.div({className:`content`},t.p(null,`Some of the imported collections share the same name and/or fields but are imported with different IDs.`),t.p(null,`You can replace them in the import if you want to:`,t.button({type:`button`,className:`btn warning sm m-l-10`,textContent:`Replace with original IDs`,onclick:l}))))),t.div({className:`col-lg-12`},t.div({className:`flex`},t.button({type:`button`,className:()=>`btn secondary ${i.rawNewCollections?``:`hidden`}`,onclick:u},t.span({className:`txt`},`Clear`)),t.button({type:`button`,className:`btn expanded-lg m-l-auto`,disabled:()=>!i.canReview,onclick:f},t.span({className:`txt`},`Review`)))))),t.footer({className:`page-footer`},app.components.credits())))}window.app=window.app||{},window.app.routes=window.app.routes||{},window.app.routes.fallbackPath=`#/collections`,app.routes.guestOnly=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{if(app.pb.authStore.isValid&&app.pb.authStore.record?.id){window.location.hash=`#/`;return}app.store.showHeader=!1,app.store.page=await n(e)}},app.routes.superuserOnly=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{if(!app.pb.authStore.isValid||!app.pb.authStore.record?.id){window.location.hash=`#/login`;return}app.store.showHeader=!0,app.store.page=await n(e)}},app.routes.blank=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{app.store.showHeader=!1,app.store.page=await n(e)}};var Xi={},Zi;function Qi(){Zi&&Zi(),Zi=router(Xi,{fallbackPath:app.routes.fallbackPath})}app.routes.guestOnly(`#/pbinstall/{token}`,async e=>{let{pageInstaller:n}=await W(async()=>{let{pageInstaller:e}=await import(`./pageInstaller-DsfqudFD.js`);return{pageInstaller:e}},[],import.meta.url);return n(e)}),app.routes.guestOnly(`#/login`,e=>Yr(e)),app.routes.guestOnly(`#/request-password-reset`,async e=>{let{pageRequestSuperuserPasswordReset:n}=await W(async()=>{let{pageRequestSuperuserPasswordReset:e}=await import(`./pageRequestSuperuserPasswordReset-C39AMhGf.js`);return{pageRequestSuperuserPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-password-reset/{token}`,async e=>{let{pageConfirmPasswordReset:n}=await W(async()=>{let{pageConfirmPasswordReset:e}=await import(`./pageConfirmPasswordReset-BF1KnlqW.js`);return{pageConfirmPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-verification/{token}`,async e=>{let{pageConfirmVerification:n}=await W(async()=>{let{pageConfirmVerification:e}=await import(`./pageConfirmVerification-eMBAC33o.js`);return{pageConfirmVerification:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-email-change/{token}`,async e=>{let{pageConfirmEmailChange:n}=await W(async()=>{let{pageConfirmEmailChange:e}=await import(`./pageConfirmEmailChange-DsOpqfGj.js`);return{pageConfirmEmailChange:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-success`,async e=>{let{pageOAuth2RedirectSuccess:n}=await W(async()=>{let{pageOAuth2RedirectSuccess:e}=await import(`./pageOAuth2RedirectSuccess-DmZV1eyz.js`);return{pageOAuth2RedirectSuccess:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-failure`,async e=>{let{pageOAuth2RedirectFailure:n}=await W(async()=>{let{pageOAuth2RedirectFailure:e}=await import(`./pageOAuth2RedirectFailure-CRvz4PXa.js`);return{pageOAuth2RedirectFailure:e}},[],import.meta.url);return n(e)}),app.routes.superuserOnly(`#/collections`,di),app.routes.superuserOnly(`#/logs`,Si),app.routes.superuserOnly(`#/settings`,Mi),app.routes.superuserOnly(`#/settings/mail`,Wi),app.routes.superuserOnly(`#/settings/storage`,qi),app.routes.superuserOnly(`#/settings/backups`,Vi),app.routes.superuserOnly(`#/settings/crons`,Ui),app.routes.superuserOnly(`#/settings/export-collections`,Ji),app.routes.superuserOnly(`#/settings/import-collections`,Yi),app.routes.superuserOnly(`#/settings/sql`,Ki);var $i=t;t=new Proxy({},{get(e,n){return function(){let e=arguments?.[0];if(e&&e.pbEvent){let n=e.onmount;e.onmount=r=>{n?.(r),r.dataset.pb=e.pbEvent,document.dispatchEvent(new CustomEvent(`mount:`+e.pbEvent,{detail:r}))};let r=e.onunmount;e.onunmount=n=>{document.dispatchEvent(new CustomEvent(`unmount:`+e.pbEvent,{detail:n})),r?.(n)}}return $i[n](...arguments)}}}),document.body.prepend(t.main({"html-class":`app`,className:()=>`app ${app.store.settings?.meta?.hideControls?`hide-controls`:``}`},Fe(),e=>(typeof app.store.page==`function`&&app.store.page(e),app.store.page))),watch(()=>app.store._ready,e=>{e&&Qi()}),document.body.appendChild(t.script({type:`module`,src:app.pb.buildURL(`/_/extensions.js`),onload:()=>{app.store._ready=!0},onerror:e=>{console.warn(`Failed to load extensions:`,e),app.store._ready=!0}}));export{S as n,se as r,Ee as t}; \ No newline at end of file diff --git a/ui/dist/assets/pageConfirmEmailChange-jQ1wgwOY.js b/ui/dist/assets/pageConfirmEmailChange-DsOpqfGj.js similarity index 97% rename from ui/dist/assets/pageConfirmEmailChange-jQ1wgwOY.js rename to ui/dist/assets/pageConfirmEmailChange-DsOpqfGj.js index 6467ff89..456b3be4 100644 --- a/ui/dist/assets/pageConfirmEmailChange-jQ1wgwOY.js +++ b/ui/dist/assets/pageConfirmEmailChange-DsOpqfGj.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-B_EjR-cI.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.newEmail||!a.collectionId){app.toasts.error(`Invalid or expired email change token.`),window.location.hash=`#/`;return}app.store.title=`Confirm email change`;let o=store({password:``,isSubmitting:!1,isSuccess:!1,showPassword:!1});async function s(){if(o.isSubmitting)return;o.isSubmitting=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmEmailChange(i,o.password),o.isSuccess=!0}catch(e){app.checkApiError(e),o.isSuccess=!1}o.isSubmitting=!1}return t.div({pbEvent:`pageConfirmEmailChange`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isSuccess?t.div({pbEvent:`confirmEmailChangeAlert`,className:`alert success txt-center`},t.p(null,`The email was successfully changed.`),t.p(null,`You can go back and sign in with your new email address.`)):t.form({pbEvent:`confirmEmailChangeForm`,className:`grid confirm-email-change-form`,onsubmit:e=>{e.preventDefault(),s()}},t.div({className:`col-12`},t.div({className:`content txt-center m-b-sm`},`Type your password to confirm changing your email address to `,t.strong(null,a.newEmail),`:`),t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`password_confirm`},`Password`),t.input({id:`password_confirm`,name:`password`,required:!0,autofocus:!0,type:()=>o.showPassword?`text`:`password`,value:()=>o.password,oninput:e=>o.password=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showPassword?`Hide password`:`Show password`),onclick:()=>o.showPassword=!o.showPassword},t.i({className:()=>o.showPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg block ${o.isSubmitting?`loading`:``}`,disabled:()=>o.isSubmitting},t.span({className:`txt`},`Confirm new email`)))))}export{r as pageConfirmEmailChange}; \ No newline at end of file +import{n as e,t as n}from"./index-O9odt_Ys.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.newEmail||!a.collectionId){app.toasts.error(`Invalid or expired email change token.`),window.location.hash=`#/`;return}app.store.title=`Confirm email change`;let o=store({password:``,isSubmitting:!1,isSuccess:!1,showPassword:!1});async function s(){if(o.isSubmitting)return;o.isSubmitting=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmEmailChange(i,o.password),o.isSuccess=!0}catch(e){app.checkApiError(e),o.isSuccess=!1}o.isSubmitting=!1}return t.div({pbEvent:`pageConfirmEmailChange`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isSuccess?t.div({pbEvent:`confirmEmailChangeAlert`,className:`alert success txt-center`},t.p(null,`The email was successfully changed.`),t.p(null,`You can go back and sign in with your new email address.`)):t.form({pbEvent:`confirmEmailChangeForm`,className:`grid confirm-email-change-form`,onsubmit:e=>{e.preventDefault(),s()}},t.div({className:`col-12`},t.div({className:`content txt-center m-b-sm`},`Type your password to confirm changing your email address to `,t.strong(null,a.newEmail),`:`),t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`password_confirm`},`Password`),t.input({id:`password_confirm`,name:`password`,required:!0,autofocus:!0,type:()=>o.showPassword?`text`:`password`,value:()=>o.password,oninput:e=>o.password=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showPassword?`Hide password`:`Show password`),onclick:()=>o.showPassword=!o.showPassword},t.i({className:()=>o.showPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg block ${o.isSubmitting?`loading`:``}`,disabled:()=>o.isSubmitting},t.span({className:`txt`},`Confirm new email`)))))}export{r as pageConfirmEmailChange}; \ No newline at end of file diff --git a/ui/dist/assets/pageConfirmPasswordReset-DP6OcWeF.js b/ui/dist/assets/pageConfirmPasswordReset-BF1KnlqW.js similarity index 97% rename from ui/dist/assets/pageConfirmPasswordReset-DP6OcWeF.js rename to ui/dist/assets/pageConfirmPasswordReset-BF1KnlqW.js index dc4810b7..f19a8d02 100644 --- a/ui/dist/assets/pageConfirmPasswordReset-DP6OcWeF.js +++ b/ui/dist/assets/pageConfirmPasswordReset-BF1KnlqW.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-B_EjR-cI.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.email||!a.collectionId){app.toasts.error(`Invalid or expired password reset token.`),window.location.hash=`#/`;return}app.store.title=`Confirm password reset`;let o=store({newPassword:``,newPasswordConfirm:``,showNewPassword:!1,showNewPasswordConfirm:!1,isSubmitting:!1,isSuccess:!1});async function s(){if(o.isSubmitting)return;o.isSubmitting=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmPasswordReset(i,o.newPassword,o.newPasswordConfirm),o.isSuccess=!0}catch(e){app.checkApiError(e)}o.isSubmitting=!1}return t.div({pbEvent:`pageConfirmPasswordReset`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isSuccess?t.div({pbEvent:`confirmPasswordResetAlert`,className:`alert success txt-center`},t.p(null,`The password was successfully changed.`),t.p(null,`You can go back to sign in with your new password.`)):t.form({pbEvent:`confirmPasswordResetForm`,className:`grid confirm-password-reset-form`,onsubmit:e=>{e.preventDefault(),s()}},t.div({className:`col-12`},t.div({className:`content txt-center m-b-sm`},`Type your new password for `,t.strong(null,a.email),`:`),t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`newPassword`},`New password`),t.input({id:`newPassword`,name:`password`,required:!0,autofocus:!0,autocomplete:`new-password`,type:()=>o.showNewPassword?`text`:`password`,value:()=>o.newPassword,oninput:e=>o.newPassword=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showNewPassword?`Hide password`:`Show password`),onclick:()=>o.showNewPassword=!o.showNewPassword},t.i({className:()=>o.showNewPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`newPasswordConfirm`},`New password confirm`),t.input({id:`newPasswordConfirm`,name:`passwordConfirm`,required:!0,autocomplete:`new-password`,type:()=>o.showNewPasswordConfirm?`text`:`password`,value:()=>o.newPasswordConfirm,oninput:e=>o.newPasswordConfirm=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showNewPasswordConfirm?`Hide password`:`Show password`),onclick:()=>o.showNewPasswordConfirm=!o.showNewPasswordConfirm},t.i({className:()=>o.showNewPasswordConfirm?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg block ${o.isSubmitting?`loading`:``}`,disabled:()=>o.isSubmitting},t.span({className:`txt`},`Set new password`)))))}export{r as pageConfirmPasswordReset}; \ No newline at end of file +import{n as e,t as n}from"./index-O9odt_Ys.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.email||!a.collectionId){app.toasts.error(`Invalid or expired password reset token.`),window.location.hash=`#/`;return}app.store.title=`Confirm password reset`;let o=store({newPassword:``,newPasswordConfirm:``,showNewPassword:!1,showNewPasswordConfirm:!1,isSubmitting:!1,isSuccess:!1});async function s(){if(o.isSubmitting)return;o.isSubmitting=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmPasswordReset(i,o.newPassword,o.newPasswordConfirm),o.isSuccess=!0}catch(e){app.checkApiError(e)}o.isSubmitting=!1}return t.div({pbEvent:`pageConfirmPasswordReset`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isSuccess?t.div({pbEvent:`confirmPasswordResetAlert`,className:`alert success txt-center`},t.p(null,`The password was successfully changed.`),t.p(null,`You can go back to sign in with your new password.`)):t.form({pbEvent:`confirmPasswordResetForm`,className:`grid confirm-password-reset-form`,onsubmit:e=>{e.preventDefault(),s()}},t.div({className:`col-12`},t.div({className:`content txt-center m-b-sm`},`Type your new password for `,t.strong(null,a.email),`:`),t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`newPassword`},`New password`),t.input({id:`newPassword`,name:`password`,required:!0,autofocus:!0,autocomplete:`new-password`,type:()=>o.showNewPassword?`text`:`password`,value:()=>o.newPassword,oninput:e=>o.newPassword=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showNewPassword?`Hide password`:`Show password`),onclick:()=>o.showNewPassword=!o.showNewPassword},t.i({className:()=>o.showNewPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`newPasswordConfirm`},`New password confirm`),t.input({id:`newPasswordConfirm`,name:`passwordConfirm`,required:!0,autocomplete:`new-password`,type:()=>o.showNewPasswordConfirm?`text`:`password`,value:()=>o.newPasswordConfirm,oninput:e=>o.newPasswordConfirm=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showNewPasswordConfirm?`Hide password`:`Show password`),onclick:()=>o.showNewPasswordConfirm=!o.showNewPasswordConfirm},t.i({className:()=>o.showNewPasswordConfirm?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg block ${o.isSubmitting?`loading`:``}`,disabled:()=>o.isSubmitting},t.span({className:`txt`},`Set new password`)))))}export{r as pageConfirmPasswordReset}; \ No newline at end of file diff --git a/ui/dist/assets/pageConfirmVerification-CmtNepxS.js b/ui/dist/assets/pageConfirmVerification-eMBAC33o.js similarity index 96% rename from ui/dist/assets/pageConfirmVerification-CmtNepxS.js rename to ui/dist/assets/pageConfirmVerification-eMBAC33o.js index ee99da28..6da92375 100644 --- a/ui/dist/assets/pageConfirmVerification-CmtNepxS.js +++ b/ui/dist/assets/pageConfirmVerification-eMBAC33o.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-B_EjR-cI.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.email||!a.collectionId){app.toasts.error(`Invalid or expired verification token.`),window.location.hash=`#/`;return}app.store.title=`Confirm verification`;let o=store({isConfirming:!1,isConfirmSuccess:!1,isResending:!1,isResendSuccess:!1});s();async function s(){if(o.isConfirming)return;o.isConfirming=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmVerification(i),o.isConfirmSuccess=!0}catch{o.isConfirmSuccess=!1}o.isConfirming=!1}async function c(){if(o.isResending)return;o.isResending=!0;let e=new n(`../`);try{await e.collection(a.collectionId).requestVerification(a.email),o.isResendSuccess=!0}catch(e){app.checkApiError(e),o.isResendSuccess=!1}o.isResending=!1}return t.div({pbEvent:`pageConfirmVerification`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isConfirming?t.div({className:`block txt-center`},t.span({className:`loader`},`Please wait...`)):o.isConfirmSuccess?t.div({pbEvent:`confirmVerificationSuccessAlert`,className:`alert success txt-center`},t.p(null,`Successfully verified `,t.strong(null,a.email),`.`)):o.isResendSuccess?t.div({pbEvent:`confirmVerificationResendAlert`,className:`alert success txt-center`},t.p(null,`Please check your email for the new verification link.`)):[t.div({pbEvent:`confirmVerificationErrorAlert`,className:`alert danger txt-center m-b-base`},t.p(null,`Invalid or expired verification token.`)),t.button({type:`button`,className:()=>`btn transparent lg block ${o.isResending?`loading`:``}`,disabled:()=>o.isResending,onclick:()=>c()},t.span({className:`txt`},`Resend`))])}export{r as pageConfirmVerification}; \ No newline at end of file +import{n as e,t as n}from"./index-O9odt_Ys.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.email||!a.collectionId){app.toasts.error(`Invalid or expired verification token.`),window.location.hash=`#/`;return}app.store.title=`Confirm verification`;let o=store({isConfirming:!1,isConfirmSuccess:!1,isResending:!1,isResendSuccess:!1});s();async function s(){if(o.isConfirming)return;o.isConfirming=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmVerification(i),o.isConfirmSuccess=!0}catch{o.isConfirmSuccess=!1}o.isConfirming=!1}async function c(){if(o.isResending)return;o.isResending=!0;let e=new n(`../`);try{await e.collection(a.collectionId).requestVerification(a.email),o.isResendSuccess=!0}catch(e){app.checkApiError(e),o.isResendSuccess=!1}o.isResending=!1}return t.div({pbEvent:`pageConfirmVerification`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isConfirming?t.div({className:`block txt-center`},t.span({className:`loader`},`Please wait...`)):o.isConfirmSuccess?t.div({pbEvent:`confirmVerificationSuccessAlert`,className:`alert success txt-center`},t.p(null,`Successfully verified `,t.strong(null,a.email),`.`)):o.isResendSuccess?t.div({pbEvent:`confirmVerificationResendAlert`,className:`alert success txt-center`},t.p(null,`Please check your email for the new verification link.`)):[t.div({pbEvent:`confirmVerificationErrorAlert`,className:`alert danger txt-center m-b-base`},t.p(null,`Invalid or expired verification token.`)),t.button({type:`button`,className:()=>`btn transparent lg block ${o.isResending?`loading`:``}`,disabled:()=>o.isResending,onclick:()=>c()},t.span({className:`txt`},`Resend`))])}export{r as pageConfirmVerification}; \ No newline at end of file diff --git a/ui/dist/assets/pageInstaller-Cs8T3uyd.js b/ui/dist/assets/pageInstaller-DsfqudFD.js similarity index 98% rename from ui/dist/assets/pageInstaller-Cs8T3uyd.js rename to ui/dist/assets/pageInstaller-DsfqudFD.js index b13c213e..7818ce24 100644 --- a/ui/dist/assets/pageInstaller-Cs8T3uyd.js +++ b/ui/dist/assets/pageInstaller-DsfqudFD.js @@ -1 +1 @@ -import{n as e,r as n}from"./index-B_EjR-cI.js";function r(r){let i=r.params?.token||``;if(e(i).type!=`auth`||n(i)){app.toasts.error(`The installer token is invalid or has expired.`),window.location.hash=`#/`;return}app.store.title=`Setup your PocketBase instance`;let a=store({email:``,password:``,passwordConfirm:``,showPassword:!1,showPasswordConfirm:!1,isSubmitting:!1,isUploading:!1,get isBusy(){return a.isSubmitting||a.isUploading}});async function o(){if(!a.isBusy){a.isSubmitting=!0;try{await app.pb.collection(`_superusers`).create({email:a.email,password:a.password,passwordConfirm:a.passwordConfirm},{headers:{Authorization:i}}),await app.pb.collection(`_superusers`).authWithPassword(a.email,a.password),window.location.hash=`#/`}catch(e){app.checkApiError(e)}a.isSubmitting=!1}}let s=`backupFileInput`;function c(){let e=document.getElementById(s);e&&(e.value=``)}function l(e){e&&app.modals.confirm(t.h6(null,`Note that we don't perform validations for the uploaded backup files. Proceed with caution and only if you trust the file source.\n\nDo you really want to upload and initialize "${e.name}"?`),()=>{u(e)},()=>{c()})}async function u(e){if(!(!e||a.isBusy)){a.isUploading=!0;try{await app.pb.backups.upload({file:e},{headers:{Authorization:i}}),await app.pb.backups.restore(e.name,{headers:{Authorization:i}}),app.toasts.info(`Please wait while extracting the uploaded archive!`),await new Promise(e=>setTimeout(e,3e3)),window.location.href=`#/`}catch(e){app.checkApiError(e)}c(),a.isUploading=!1}}return t.div({pbEvent:`pageInstaller`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),t.form({pbEvent:`installerForm`,className:`grid installer-form`,onsubmit:e=>{e.preventDefault(),o(a)}},t.div({className:`col-12 txt-center`},`Create your first superuser account in order to continue:`),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:`superuser_email`},`Email`),t.input({id:`superuser_email`,name:`email`,type:`email`,required:!0,autofocus:!0,autocomplete:`off`,disabled:()=>a.isBusy,value:()=>a.email,oninput:e=>a.email=e.target.value}))),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`superuser_password`},`Password`),t.input({id:`superuser_password`,name:`password`,min:10,required:!0,disabled:()=>a.isBusy,type:()=>a.showPassword?`text`:`password`,value:()=>a.password,oninput:e=>a.password=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>a.showPassword?`Hide password`:`Show password`),onclick:()=>a.showPassword=!a.showPassword},t.i({className:()=>a.showPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0})))),t.div({className:`field-help`},`Recommended at least 10 characters.`)),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`superuser_password_confirm`},`Password confirm`),t.input({id:`superuser_password_confirm`,name:`passwordConfirm`,required:!0,disabled:()=>a.isBusy,type:()=>a.showPasswordConfirm?`text`:`password`,value:()=>a.passwordConfirm,oninput:e=>a.passwordConfirm=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>a.showPasswordConfirm?`Hide password`:`Show password`),onclick:()=>a.showPasswordConfirm=!a.showPasswordConfirm},t.i({className:()=>a.showPasswordConfirm?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg next block ${a.isSubmitting?`loading`:``}`,disabled:()=>a.isBusy},t.span({className:`txt`},`Create superuser and login`),t.i({className:`ri-arrow-right-line`,ariaHidden:!0})))),t.hr(),t.label({htmlFor:s,className:()=>`btn secondary transparent lg block ${a.isBusy?`disabled`:``} ${a.isUploading?`loading`:``}`},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0}),t.span({className:`txt`},`Or initialize from backup`)),t.input({id:s,type:`file`,className:`hidden`,accept:`.zip`,onchange:e=>{l(e.target?.files?.[0])}}))}export{r as pageInstaller}; \ No newline at end of file +import{n as e,r as n}from"./index-O9odt_Ys.js";function r(r){let i=r.params?.token||``;if(e(i).type!=`auth`||n(i)){app.toasts.error(`The installer token is invalid or has expired.`),window.location.hash=`#/`;return}app.store.title=`Setup your PocketBase instance`;let a=store({email:``,password:``,passwordConfirm:``,showPassword:!1,showPasswordConfirm:!1,isSubmitting:!1,isUploading:!1,get isBusy(){return a.isSubmitting||a.isUploading}});async function o(){if(!a.isBusy){a.isSubmitting=!0;try{await app.pb.collection(`_superusers`).create({email:a.email,password:a.password,passwordConfirm:a.passwordConfirm},{headers:{Authorization:i}}),await app.pb.collection(`_superusers`).authWithPassword(a.email,a.password),window.location.hash=`#/`}catch(e){app.checkApiError(e)}a.isSubmitting=!1}}let s=`backupFileInput`;function c(){let e=document.getElementById(s);e&&(e.value=``)}function l(e){e&&app.modals.confirm(t.h6(null,`Note that we don't perform validations for the uploaded backup files. Proceed with caution and only if you trust the file source.\n\nDo you really want to upload and initialize "${e.name}"?`),()=>{u(e)},()=>{c()})}async function u(e){if(!(!e||a.isBusy)){a.isUploading=!0;try{await app.pb.backups.upload({file:e},{headers:{Authorization:i}}),await app.pb.backups.restore(e.name,{headers:{Authorization:i}}),app.toasts.info(`Please wait while extracting the uploaded archive!`),await new Promise(e=>setTimeout(e,3e3)),window.location.href=`#/`}catch(e){app.checkApiError(e)}c(),a.isUploading=!1}}return t.div({pbEvent:`pageInstaller`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),t.form({pbEvent:`installerForm`,className:`grid installer-form`,onsubmit:e=>{e.preventDefault(),o(a)}},t.div({className:`col-12 txt-center`},`Create your first superuser account in order to continue:`),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:`superuser_email`},`Email`),t.input({id:`superuser_email`,name:`email`,type:`email`,required:!0,autofocus:!0,autocomplete:`off`,disabled:()=>a.isBusy,value:()=>a.email,oninput:e=>a.email=e.target.value}))),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`superuser_password`},`Password`),t.input({id:`superuser_password`,name:`password`,min:10,required:!0,disabled:()=>a.isBusy,type:()=>a.showPassword?`text`:`password`,value:()=>a.password,oninput:e=>a.password=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>a.showPassword?`Hide password`:`Show password`),onclick:()=>a.showPassword=!a.showPassword},t.i({className:()=>a.showPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0})))),t.div({className:`field-help`},`Recommended at least 10 characters.`)),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`superuser_password_confirm`},`Password confirm`),t.input({id:`superuser_password_confirm`,name:`passwordConfirm`,required:!0,disabled:()=>a.isBusy,type:()=>a.showPasswordConfirm?`text`:`password`,value:()=>a.passwordConfirm,oninput:e=>a.passwordConfirm=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>a.showPasswordConfirm?`Hide password`:`Show password`),onclick:()=>a.showPasswordConfirm=!a.showPasswordConfirm},t.i({className:()=>a.showPasswordConfirm?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg next block ${a.isSubmitting?`loading`:``}`,disabled:()=>a.isBusy},t.span({className:`txt`},`Create superuser and login`),t.i({className:`ri-arrow-right-line`,ariaHidden:!0})))),t.hr(),t.label({htmlFor:s,className:()=>`btn secondary transparent lg block ${a.isBusy?`disabled`:``} ${a.isUploading?`loading`:``}`},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0}),t.span({className:`txt`},`Or initialize from backup`)),t.input({id:s,type:`file`,className:`hidden`,accept:`.zip`,onchange:e=>{l(e.target?.files?.[0])}}))}export{r as pageInstaller}; \ No newline at end of file diff --git a/ui/dist/index.html b/ui/dist/index.html index 9cd5313f..b1012d9a 100644 --- a/ui/dist/index.html +++ b/ui/dist/index.html @@ -13,7 +13,7 @@ - + diff --git a/ui/src/fields/file/settings.js b/ui/src/fields/file/settings.js index db192869..e4f40905 100644 --- a/ui/src/fields/file/settings.js +++ b/ui/src/fields/file/settings.js @@ -257,36 +257,32 @@ export function settings(props) { ), t.div({ className: "field-help" }, "In bytes."), ), - () => { - if (props.field.maxSelect > 1) { - return t.div( - { className: "col-sm-3" }, - t.div( - { className: "field" }, - t.label({ htmlFor: uniqueId + ".maxSelect" }, "Max select"), - t.input({ - type: "number", - id: uniqueId + ".maxSelect", - placeholder: "Default to single", - step: 1, - min: 2, - required: true, - max: Number.MAX_SAFE_INTEGER, - name: () => `fields.${props.fieldIndex}.maxSelect`, - value: () => props.field.maxSelect || "", - onchange: (e) => { - const maxSelect = parseInt(e.target.value, 10); - if (maxSelect > 1) { - props.field.maxSelect = maxSelect; - } else { - props.field.maxSelect = 1; - } - }, - }), - ), - ); - } - }, + t.div( + { className: "col-sm-3", hidden: () => props.field.maxSelect << 0 < 2 }, + t.div( + { className: "field" }, + t.label({ htmlFor: uniqueId + ".maxSelect" }, "Max select"), + t.input({ + type: "number", + id: uniqueId + ".maxSelect", + placeholder: "Default to single", + step: 1, + min: 2, + required: true, + max: Number.MAX_SAFE_INTEGER, + name: () => `fields.${props.fieldIndex}.maxSelect`, + value: () => props.field.maxSelect || "", + onchange: (e) => { + const maxSelect = parseInt(e.target.value, 10); + if (maxSelect > 1) { + props.field.maxSelect = maxSelect; + } else { + props.field.maxSelect = 1; + } + }, + }), + ), + ), t.div( { className: "col-sm-12" }, t.div( diff --git a/ui/src/fields/select/settings.js b/ui/src/fields/select/settings.js index c877f09f..9845ebc1 100644 --- a/ui/src/fields/select/settings.js +++ b/ui/src/fields/select/settings.js @@ -112,35 +112,31 @@ export function settings(props) { content: () => t.div( { className: "grid sm" }, - () => { - if (props.field.maxSelect > 1) { - return t.div( - { className: "col-sm-12" }, - t.div( - { className: "field" }, - t.label({ htmlFor: uniqueId + ".maxSelect" }, "Max select"), - t.input({ - type: "number", - id: uniqueId + ".maxSelect", - placeholder: "Default to single", - step: 1, - min: 2, - max: () => props.field.values?.length || 2, - name: () => `fields.${props.fieldIndex}.maxSelect`, - value: () => props.field.maxSelect || "", - onchange: (e) => { - const maxSelect = parseInt(e.target.value, 10); - if (maxSelect > 1) { - props.field.maxSelect = maxSelect; - } else { - props.field.maxSelect = 1; - } - }, - }), - ), - ); - } - }, + t.div( + { className: "col-sm-12", hidden: () => props.field.maxSelect << 0 < 2 }, + t.div( + { className: "field" }, + t.label({ htmlFor: uniqueId + ".maxSelect" }, "Max select"), + t.input({ + type: "number", + id: uniqueId + ".maxSelect", + placeholder: "Default to single", + step: 1, + min: 2, + max: () => props.field.values?.length || 2, + name: () => `fields.${props.fieldIndex}.maxSelect`, + value: () => props.field.maxSelect || "", + onchange: (e) => { + const maxSelect = parseInt(e.target.value, 10); + if (maxSelect > 1) { + props.field.maxSelect = maxSelect; + } else { + props.field.maxSelect = 1; + } + }, + }), + ), + ), t.div( { className: "col-sm-12" }, t.div(