UNPKG

@digital-blueprint/formalize-app

Version:

[GitHub Repository](https://github.com/digital-blueprint/formalize-app) | [npmjs package](https://www.npmjs.com/package/@digital-blueprint/formalize-app) | [Unpkg CDN](https://unpkg.com/browse/@digital-blueprint/formalize-app/) | [Formalize Bundle](https:

244 lines (227 loc) • 22.5 kB
/*! * License: LGPL-2.1-or-later * Dependencies: * * @webcomponents/scoped-custom-element-registry: BSD-3-Clause * @dbp-toolkit/app-shell: LGPL-2.1-or-later * lit-html: BSD-3-Clause * @dbp-toolkit/language-select: LGPL-2.1-or-later * @dbp-toolkit/auth: LGPL-2.1-or-later * @dbp-toolkit/theme-switcher: LGPL-2.1-or-later * universal-router: MIT * @dbp-toolkit/matomo: LGPL-2.1-or-later * cssfilter: MIT * xss: MIT */ import{f as e,i as t,n,p as r,r as i,s as a,t as o,v as s,w as c}from"./shared/ref.DqB7ABXf.js";import{A as l,C as u,F as d,J as f,X as p,g as m,k as h,s as g,v as _}from"./shared/directive-helpers.C6Xz79AM.js";import{n as v}from"./shared/feature-flags.DdD1PCm9.js";import{n as y,r as b,t as x}from"./shared/dbp-formalize-lit-element.a7wlQ90-.js"; /** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ const S=Symbol.for(``),C=e=>{if(e?.r===S)return e?._$litStatic$},w=e=>({_$litStatic$:e,r:S}),T=/* @__PURE__ */ new Map,E=(e=>(t,...n)=>{let r=n.length,i,a,o=[],s=[],c,l=0,u=!1;for(;l<r;){for(c=t[l];l<r&&(a=n[l],(i=C(a))!==void 0);)c+=i+t[++l],u=!0;l!==r&&s.push(a),o.push(c),l++}if(l===r&&o.push(t[r]),u){let e=o.join(`$$lit$$`);(t=T.get(e))===void 0&&(o.raw=o,T.set(e,t=o)),n=s}return e(t,...n)})(f),D=e=>{if(Array.isArray(e))return e;if(typeof e!=`string`||e.trim()===``)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return e.split(`,`).map(e=>e.trim()).filter(Boolean)};function O(e,n,r,a=[],o=[]){return e.filter(e=>{let n=e.frontendKey??null;if(a.length>0&&(!n||!a.includes(n))||n&&o.includes(n))return!1;let r=e.grantedFormActions??[],s=e.grantedSubmissionCollectionActions??[];return r.includes(i.CREATE_SUBMISSIONS)||r.includes(i.MANAGE)||s.includes(t.CREATE_SUBMISSIONS)||s.includes(t.MANAGE)}).map(e=>{let t=Object.keys(n).find(t=>n[t]===e.identifier);if(!t)return null;let i=(e.localizedNames??[]).find(e=>e.languageTag===r);return{identifier:e.identifier,name:i?.name??e.name??t,slug:t}}).filter(Boolean).sort((e,t)=>e.name.localeCompare(t.name,r))}var k=class extends h(x){constructor(){super(),this.formIsRendered=!1,this.formComponents={},this.formIdentifiers={},this.formRef=o(),this.formUrlSlug=``,this.submissionId=``,this.loadedSubmission={},this.userAllSubmissions=[],this.usersSubmittedSubmissionCount=null,this.formProperties={},this.authTokenExists=!1,this.submissionAllowed=!1,this.formDisplayDenied=!1,this.disableBeforeUnloadWarning=!1,this.availableForms=[],this.availableFormsLoading=!0,this.availableFormsLoadFailed=!1,this.availableFormsTableOptions=this.getAvailableFormsTableOptions(),this.allowListFrontendKeys=[],this.denyListFrontendKeys=[],this._onReceiveBeforeUnload=this.onReceiveBeforeUnload.bind(this),this._onDisableBeforeunloadWarning=this.onDisableBeforeunloadWarning.bind(this),this._onFormDataUpdated=this.onFormDataUpdated.bind(this),this._onFormReset=this.onFormReset.bind(this)}static get scopedElements(){return{"dbp-icon":l,"dbp-mini-spinner":c,"dbp-tabulator-table":y,"dbp-formalize-get-details-button":b}}static get properties(){return{...super.properties,submissionAllowed:{type:Boolean,attribute:!1},formDisplayDenied:{type:Boolean,attribute:!1},loadedSubmission:{type:Object,attribute:!1},userAllSubmissions:{type:Object,attribute:!1},formProperties:{type:Array,attribute:!1},availableForms:{type:Array,attribute:!1},availableFormsLoading:{type:Boolean,attribute:!1},availableFormsLoadFailed:{type:Boolean,attribute:!1},availableFormsTableOptions:{type:Object,attribute:!1},allowListFrontendKeys:{type:Array,attribute:`allow-list-frontend-keys`,converter:{fromAttribute:D}},denyListFrontendKeys:{type:Array,attribute:`deny-list-frontend-keys`,converter:{fromAttribute:D}}}}connectedCallback(){super.connectedCallback(),window.addEventListener(`beforeunload`,this._onReceiveBeforeUnload),window.addEventListener(`disableBeforeunloadWarning`,this._onDisableBeforeunloadWarning),window.addEventListener(`dbpFormDataUpdated`,this._onFormDataUpdated),window.addEventListener(`DbpFormalizeFormReset`,this._onFormReset),this.updateComplete.then(()=>{console.log(`-- updateComplete --`),this.loadModules()})}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener(`beforeunload`,this._onReceiveBeforeUnload),window.removeEventListener(`disableBeforeunloadWarning`,this._onDisableBeforeunloadWarning),window.removeEventListener(`dbpFormDataUpdated`,this._onFormDataUpdated),window.removeEventListener(`DbpFormalizeFormReset`,this._onFormReset)}updateFormUrlSlug(){let e=this.getRoutingData().pathSegments[0]||``,t=this.getRoutingData().pathSegments[1]||``;/^[a-z,0-9,-]{36,36}$/.test(t)&&(this.submissionId=t),this.readOnly=!!(this.submissionId&&this.getRoutingData().pathSegments[2]===`readonly`),this.formUrlSlug!==e&&(this.formUrlSlug=e,console.log(`updateFormUrlSlug this.formUrlSlug`,this.formUrlSlug),this.handlePermissionsForCurrentForm())}async handlePermissionsForCurrentForm(){let e=this.formIdentifiers[this.formUrlSlug];this.submissionAllowed=e?await this.checkPermissionsToForm(e):!1}async checkPermissionsToForm(e){if(this.getToken()===``)return!1;this.authTokenExists=!0;let t,n,r={method:`GET`,headers:{"Content-Type":`application/ld+json`,Authorization:`Bearer `+this.getToken()}};try{if(t=await fetch(this.entryPointUrl+`/formalize/forms/`+e,r),!t.ok)return!1;n=await t.json()}catch(e){return this.sendErrorAnalyticsEvent(`checkPermissionsToForm`,`WrongResponse`,e),console.error(e),!1}return n.error?(console.error(`checkPermissionsToForm data.error`,n.error),!1):n[`@type`]===`hydra:Error`?(console.error(`checkPermissionsToForm hydra:Error`,n.detail),!1):(this.formProperties=n,!0)}async loadModules(){try{let e=await(await fetch(this.basePath+`modules.json`)).json(),t={},n={};for(let[r,i]of Object.entries(e.forms)){let e=await import(i);console.log(`formKey`,r);let a=new e.default;a.getFormComponent&&(t[a.getUrlSlug()]=a.getFormComponent()),a.getFormIdentifier&&(n[a.getUrlSlug()]=a.getFormIdentifier())}this.formComponents=t,this.formIdentifiers=n,await this.handlePermissionsForCurrentForm(),await this.loadAvailableForms(),await this.getUserAllSubmissionsData(this.formIdentifiers[this.formUrlSlug]),this.requestUpdate()}catch(e){console.error(`Error loading modules:`,e)}}async loadAvailableForms(){if(!v()||!this.auth?.token||this.formUrlSlug!==``){this.availableFormsLoading=!1;return}this.availableFormsLoading=!0,this.availableFormsLoadFailed=!1;try{let e=await fetch(`${this.entryPointUrl}/formalize/forms?perPage=9999`,{headers:{"Content-Type":`application/ld+json`,Authorization:`Bearer ${this.auth.token}`}});if(!e.ok)throw Error(`Failed to load forms: ${e.status}`);let t=await e.json();this.availableForms=O(t[`hydra:member`]??[],this.formIdentifiers,this.lang,this.allowListFrontendKeys,this.denyListFrontendKeys).map(e=>({...e,actionButton:this.createAvailableFormAction(e)})),this.availableFormsTableOptions=this.getAvailableFormsTableOptions()}catch(e){console.error(`Error loading available forms:`,e),this.availableForms=[],this.availableFormsLoadFailed=!0}finally{this.availableFormsLoading=!1}}getAvailableFormsTableOptions(){return{data:this.availableForms,layout:`fitColumns`,langs:{en:{columns:{name:this._i18n.t(`render-form.form-name`,{lng:`en`})}},de:{columns:{name:this._i18n.t(`render-form.form-name`,{lng:`de`})}}},columns:[{field:`name`,sorter:`string`},{field:`identifier`,visible:!1},{field:`slug`,visible:!1},{field:`actionButton`,formatter:`html`,hozAlign:`right`,widthShrink:1,minWidth:44,headerSort:!1}],columnDefaults:{vertAlign:`middle`,hozAlign:`left`,resizable:!1},initialSort:[{column:`name`,dir:`asc`}]}}createAvailableFormAction(e){let t=document.createElement(`span`);t.style.cssText=`display: inline-flex; align-items: center;`;let n=this.createScopedElement(`dbp-formalize-get-details-button`);return n.setAttribute(`subscribe`,`lang`),n.title=this._i18n.t(`render-form.open-form`),n.ariaLabel=this._i18n.t(`render-form.open-form`),n.addEventListener(`click`,()=>{this.sendSetPropertyEvent(`routing-url`,`/${e.slug}`,!0)}),t.appendChild(n),t}getAvailableFormsTable(){return this.renderRoot?.querySelector(`#available-forms-table`)??null}getAvailableFormsSearchInput(){return this.renderRoot?.querySelector(`#available-forms-search`)??null}handleAvailableFormsSearch(e){e?.preventDefault();let t=this.getAvailableFormsSearchInput();t&&this.applyAvailableFormsSearch(t.value.trim())}applyAvailableFormsSearch(e){let t=this.getAvailableFormsTable();if(!t)return;if(e===``){t.clearFilter();return}let n=(this.availableFormsTableOptions.columns??[]).filter(e=>e.field&&e.visible!==!1&&e.formatter!==`html`).map(t=>({field:t.field,type:`like`,value:e}));t.setFilter([n])}handleAvailableFormsSearchReset(){let e=this.getAvailableFormsSearchInput(),t=this.getAvailableFormsTable();e&&t&&(e.value=``,t.clearFilter(),e.focus())}rebuildAvailableFormsTable(){let e=this.getAvailableFormsTable();e&&e.updateComplete.then(()=>{e.options=this.availableFormsTableOptions,e.data=this.availableForms,e.tabulatorTable&&e.tabulatorTable.destroy(),e.tableReady=!1,e.tableBuilding=!1,e.buildTable()})}async getUserAllSubmissionsData(e){let t=this.auth;if(!e||!t?.token)return;let n={method:`GET`,headers:{"Content-Type":`application/ld+json`,Authorization:`Bearer `+t.token}};try{let t=await fetch(this.entryPointUrl+`/formalize/submissions?formIdentifier=${e}&perPage=100000&creatorIdEquals=`+this.getUserId(),n);if(!t.ok)return;let r=await t.json();r!==void 0&&r[`hydra:member`]&&r[`hydra:member`].length>0&&(this.userAllSubmissions=r[`hydra:member`],this.requestUpdate())}catch(e){console.error(e)}}async getSubmissionData(){if(!this.submissionId)return!1;let e={},t={method:`GET`,headers:{"Content-Type":`application/ld+json`,Authorization:`Bearer `+this.getToken()}};try{let n=await fetch(this.entryPointUrl+`/formalize/submissions/`+this.submissionId,t);n.ok||(this.handleErrorResponse(n),this.formDisplayDenied=!0),e=await n.json()}catch(e){console.error(e),this.formDisplayDenied=!0}this.loadedSubmission=e}async onFormReset(){this.loadedSubmission={},this.submissionId=``,this.readOnly=!1,this.formIdentifiers[this.formUrlSlug]&&await this.getUserAllSubmissionsData(this.formIdentifiers[this.formUrlSlug]),this.requestUpdate()}async onFormDataUpdated(e){e.detail&&e.detail.needUpdate&&(await this.getSubmissionData(),this.formIdentifiers[this.formUrlSlug]&&await this.getUserAllSubmissionsData(this.formIdentifiers[this.formUrlSlug]))}onDisableBeforeunloadWarning(e){this.disableBeforeUnloadWarning=!0}onReceiveBeforeUnload(e){if(this.formIsRendered===!1||this.readOnly||this.disableBeforeUnloadWarning){this.disableBeforeUnloadWarning=!1;return}(e.isTrusted||!confirm(this._i18n.t(`render-form.form-exit-warning-message`)))&&(e.preventDefault(),e.returnValue=``)}getFormHtml(){let t=this.formUrlSlug,i=this.formComponents;if(Object.keys(i).length===0)return f` Loading... `;if(t===``)return v()?this.availableFormsLoading?f` <dbp-mini-spinner text="${this._i18n.t(`loading-message`)}"></dbp-mini-spinner> `:this.availableFormsLoadFailed?f` <div class="notification is-danger"> <dbp-icon name="warning-high"></dbp-icon> ${this._i18n.t(`render-form.available-forms-load-failed`)} </div> `:f` <section class="available-forms" aria-labelledby="available-forms-title"> <h1 id="available-forms-title"> ${this._i18n.t(`render-form.available-forms-title`)} </h1> <p>${this._i18n.t(`render-form.available-forms-description`)}</p> ${this.availableForms.length===0?f` <p>${this._i18n.t(`render-form.no-available-forms`)}</p> `:f` <div class="forms-table-actions"> <form class="search-input forms-search" @submit=${this.handleAvailableFormsSearch}> <label for="available-forms-search"> ${this._i18n.t(`render-form.search-input-label`)}: </label> <input id="available-forms-search" class="searchbar" type="text" placeholder="${this._i18n.t(`render-form.search-placeholder`)}" @input=${this.handleAvailableFormsSearch} /> <button class="button search-button" type="submit" title="${this._i18n.t(`render-form.search-button`)}" aria-label="${this._i18n.t(`render-form.search-button`)}"> <dbp-icon name="search" aria-hidden="true"></dbp-icon> </button> </form> <button class="reset-search" type="button" @click=${this.handleAvailableFormsSearchReset}> <dbp-icon name="spinner-arrow" aria-hidden="true"></dbp-icon> ${this._i18n.t(`render-form.reset-search-label`)} </button> </div> <dbp-tabulator-table id="available-forms-table" identifier="available-forms-table" lang="${this.lang}" pagination-enabled pagination-size="10" .options=${this.availableFormsTableOptions}></dbp-tabulator-table> `} </section> `:f` <div class="notification is-warning"> <dbp-icon name="warning-high"></dbp-icon> ${this._i18n.t(`render-form.form-not-found`)} </div> `;if(!i[t])return f` <div class="notification is-warning"> <dbp-icon name="warning-high"></dbp-icon> ${this._i18n.t(`render-form.form-with-slug-not-found`,{slug:t,interpolation:{escapeValue:!1}})} </div> `;if(!this.submissionAllowed)return f` <div class="notification is-warning"> <dbp-icon name="warning-high"></dbp-icon> ${this._i18n.t(`render-form.form-not-accessible`)} </div> `;let o=`dbp-formalize-form-`+s(t),c=this.formComponents[t];this.defineScopedElement(o,c);let l=this.formIdentifiers[this.formUrlSlug],u=this.formProperties.allowedSubmissionStates,d=this.formProperties.maxNumSubmissionsPerCreator;if(this.grantedActions=this.formProperties.grantedActions,this.usersSubmittedSubmissionCount=this.userAllSubmissions.filter(e=>e.submissionState===a.SUBMITTED).length,this.usersSubmittedSubmissionCount===null)return;if(this.usersSubmittedSubmissionCount>0&&d===1){let e=``;if(this.userAllSubmissions.length>0){let t=this.userAllSubmissions[0].identifier;e=`${r(this.formUrlSlug,this.lang)}/${t}/readonly`}return f` <div class="notification is-warning"> <dbp-icon name="warning-high"></dbp-icon> ${this._i18n.t(`render-form.form-already-submitted-warning`)} ${e?f` <a href="${e}"> ${this._i18n.t(`render-form.check-previous-submissions-warning`)} </a> `:``} </div> `}let p={};if(Object.keys(this.loadedSubmission).length>0&&(this.loadedSubmission.form===`/formalize/forms/${this.formIdentifiers[t]}`?p=this.loadedSubmission:(g({summary:this._i18n.t(`errors.error-title`),body:this._i18n.t(`errors.invalid-submission-data`),type:`danger`,timeout:0}),this.formDisplayDenied=!0)),this.formDisplayDenied)return f` <div class="notification is-warning"> <dbp-icon name="warning-high"></dbp-icon> ${this._i18n.t(`render-form.form-not-accessible`)} </div> `;if(this.usersSubmittedSubmissionCount>=d)return f` <div class="notification is-warning"> <dbp-icon name="warning-high"></dbp-icon> ${this._i18n.t(`render-form.form-already-submitted-n-times-warning`,{n:this.usersSubmittedSubmissionCount})} <a href="${e(this.formIdentifiers[this.formUrlSlug],this.lang)}"> ${this._i18n.t(`render-form.check-previous-submissions-warning`)} </a> </div> `;let m=f``;return this.usersSubmittedSubmissionCount>0&&(m=f` <div class="notification is-info"> <dbp-icon name="information-circle"></dbp-icon> <a href="${e(this.formIdentifiers[this.formUrlSlug],this.lang)}"> ${this._i18n.t(`render-form.check-previous-submissions-warning`)} </a> </div> `),this.formIsRendered=!0,E` ${m} <${w(o)} ${n(this.formRef)} id="edit-form" subscribe="auth,lang,entry-point-url,nextcloud-web-app-password-url,nextcloud-web-dav-url,nextcloud-auth-url,nextcloud-name,nextcloud-file-url" form-identifier=${l} form-url-slug=${t} max-number-of-submissions=${d} allowed-submission-states=${u} ?read-only=${this.readOnly} .formProperties=${this.formProperties} .userAllSubmissions=${this.userAllSubmissions} .data=${p}></${w(o)}> `}static get styles(){return p` ${_(!1)} ${u()} ${m()} .notification { margin-bottom: 2em; display: flex; justify-content: flex-start; align-items: center; } .notification dbp-icon { position: static; } .notification a { text-underline-offset: 2px; } .available-forms h1 { margin-top: 0; } .forms-table-actions { display: flex; align-items: center; gap: 1rem; margin: 1.5rem 0 0.5rem; } .forms-search { flex: 1; min-width: 12rem; } .forms-search label { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } .search-input { display: flex; position: relative; } .searchbar, .search-button { box-sizing: border-box; height: 32px; } .searchbar { flex-grow: 1; padding: 0 0.5em; border: 1px solid var(--dbp-content); } .search-button { position: absolute; top: 0; right: 0; border: 0; background: transparent; } .reset-search { border: 0; background: none; cursor: pointer; padding: 5px; } .search-button dbp-icon, .reset-search dbp-icon { position: static; } @media (max-width: 530px) { .forms-table-actions { align-items: stretch; flex-wrap: wrap; } .forms-search { flex-basis: 100%; } } `}_onLoginClicked(e){this.sendSetPropertyEvent(`requested-login-status`,`logged-in`),e.preventDefault()}render(){let e=this._i18n;return!this.isLoggedIn()&&!this.isAuthPending()?f` <div class="notification is-warning"> ${e.t(`error-login-message`)} <a href="#" @click="${this._onLoginClicked}">${e.t(`error-login-link`)}</a> </div> `:f` ${this.getFormHtml()} `}async update(e){e.has(`auth`)&&(!this.authTokenExists&&this.auth&&this.auth.token!==``&&(this.authTokenExists=!0,this.handlePermissionsForCurrentForm(),await this.getUserAllSubmissionsData(this.formIdentifiers[this.formUrlSlug]),await this.getSubmissionData()),this.auth?.token&&Object.keys(this.formIdentifiers).length>0&&await this.loadAvailableForms()),e.has(`routingUrl`)&&(this.updateFormUrlSlug(),Object.keys(this.formIdentifiers).length>0&&await this.loadAvailableForms()),(e.has(`lang`)||e.has(`allowListFrontendKeys`)||e.has(`denyListFrontendKeys`))&&Object.keys(this.formIdentifiers).length>0&&await this.loadAvailableForms(),super.update(e)}updated(e){super.updated(e),!this.availableFormsLoading&&this.availableForms.length>0&&(e.has(`availableFormsTableOptions`)||e.has(`availableFormsLoading`))&&this.rebuildAvailableFormsTable()}};d(`dbp-formalize-render-form`,k);export{O as filterAvailableForms}; //# sourceMappingURL=dbp-formalize-render-form.js.map