@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:
327 lines (289 loc) • 11.2 kB
JavaScript
// @ts-nocheck
import {css, html, unsafeCSS} from 'lit';
import {classMap} from 'lit/directives/class-map.js';
import {
ScopedElementsMixin,
MiniSpinner,
Icon,
DBPSelect,
getIconSVGURL,
} from '@dbp-toolkit/common';
import DBPLitElement from '@dbp-toolkit/common/dbp-lit-element';
import {setOverridesByGlobalCache} from '@dbp-toolkit/common/i18next.js';
import {createInstance} from './i18n.js';
import {CustomTabulatorTable} from './table-components.js';
import {MANAGE_FORMS_COMPONENT_STYLES} from './manage-forms-component-styles.js';
export class ManageFormsOverviewPage extends ScopedElementsMixin(DBPLitElement) {
constructor() {
super();
this._i18n = createInstance();
this.lang = this._i18n.language;
this.langDir = '';
this.loadingFormsTable = false;
this.showFormsTable = false;
this.showSubmissionTables = false;
this.optionsForms = {};
this.paginationSizeStorageKey = '';
this.noFormsAvailable = false;
// Number of modules that implement createForm(); the button is only shown when > 0
this.creatableModulesCount = 0;
this.actions = [];
// Number of currently selected forms in the overview table.
this.selectedFormsCount = 0;
this.searchInProgress = false;
}
static get scopedElements() {
return {
'dbp-mini-spinner': MiniSpinner,
'dbp-icon': Icon,
'dbp-tabulator-table': CustomTabulatorTable,
'dbp-select': DBPSelect,
};
}
static get properties() {
return {
...super.properties,
lang: {type: String},
langDir: {type: String, attribute: 'lang-dir'},
loadingFormsTable: {type: Boolean, attribute: false},
showFormsTable: {type: Boolean, attribute: false},
showSubmissionTables: {type: Boolean, attribute: false},
optionsForms: {type: Object, attribute: false},
paginationSizeStorageKey: {type: String, attribute: false},
noFormsAvailable: {type: Boolean, attribute: false},
creatableModulesCount: {type: Number, attribute: false},
actions: {type: Array, attribute: false},
selectedFormsCount: {type: Number, attribute: false},
searchInProgress: {type: Boolean, attribute: false},
};
}
update(changedProperties) {
changedProperties.forEach((oldValue, propName) => {
if (propName === 'lang') {
void this._i18n.changeLanguage(this.lang);
}
if ((propName === 'lang' || propName === 'langDir') && this.langDir) {
void setOverridesByGlobalCache(this._i18n, this);
}
});
super.update(changedProperties);
}
connectedCallback() {
super.connectedCallback();
if (this.langDir) {
void setOverridesByGlobalCache(this._i18n, this);
}
}
static get styles() {
return [
MANAGE_FORMS_COMPONENT_STYLES,
css`
.forms-table-toolbar {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.forms-table-actions {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 0.5rem;
}
.forms-table-actions-select {
--dbp-select-border-color: var(--dbp-content);
--dbp-select-chevron-color: var(--dbp-content);
--dbp-select-placeholder-color: var(--dbp-content);
--dbp-select-placeholder-font-weight: var(--dbp-content);
}
.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;
}
.forms-search .searchbar {
background: calc(100% - 0.5em) center no-repeat
url('${unsafeCSS(getIconSVGURL('search'))}');
background-size: 1em;
}
@media (max-width: 530px) {
.forms-table-actions {
align-items: stretch;
flex-wrap: wrap;
}
.forms-search {
flex-basis: 100%;
}
}
.create-form-btn {
display: inline-flex;
align-items: center;
gap: 0.4rem;
}
.create-form-btn-icon {
flex-shrink: 0;
top: 0;
}
.hidden {
display: none;
}
`,
];
}
getFormsTable() {
return this.renderRoot?.querySelector('#tabulator-table-forms') ?? null;
}
getSearchbar() {
return this.renderRoot?.querySelector('#forms-searchbar') ?? null;
}
handleSearch(event) {
event?.preventDefault();
const searchInput = this.getSearchbar();
if (!searchInput) return;
this.searchInProgress = searchInput.value.trim() !== '';
this.applySearch(searchInput.value.trim());
this.dispatchSearchChange(searchInput.value.trim());
}
applySearch(filterValue) {
const table = this.getFormsTable();
if (!table) return;
if (filterValue === '') {
table.clearFilter();
return;
}
const filters = (this.optionsForms.columns ?? [])
.filter(
(column) => column.field && column.visible !== false && column.formatter !== 'html',
)
.map((column) => ({field: column.field, type: 'like', value: filterValue}));
table.setFilter([filters]);
}
dispatchSearchChange(value) {
this.dispatchEvent(
new CustomEvent('forms-search-change', {
detail: {value},
bubbles: true,
composed: true,
}),
);
}
handleResetSearch() {
const searchInput = this.getSearchbar();
const table = this.getFormsTable();
if (!searchInput || !table) return;
this.searchInProgress = false;
searchInput.value = '';
table.clearFilter();
this.dispatchSearchChange('');
searchInput.focus();
}
/**
* Dispatches an event to request opening the create form dialog.
*/
_onCreateFormClick() {
this.dispatchEvent(
new CustomEvent('create-form-request', {
bubbles: true,
composed: true,
}),
);
}
_onFormAction(event) {
const action = event.detail?.option?.value;
if (!action) return;
this.dispatchEvent(
new CustomEvent('form-action', {
detail: {action},
bubbles: true,
composed: true,
}),
);
}
render() {
const i18n = this._i18n;
const formActions = this.actions;
return html`
<div class="container forms-table ${classMap({hidden: !this.showFormsTable})}">
<div class="forms-table-toolbar">
<span
class="${classMap({
hidden: !this.loadingFormsTable || this.showSubmissionTables,
})}">
<dbp-mini-spinner text="${i18n.t('loading-message')}"></dbp-mini-spinner>
</span>
<button
class="button is-primary create-form-btn ${classMap({
hidden: this.creatableModulesCount === 0,
})}"
type="button"
@click="${this._onCreateFormClick}">
<dbp-icon
class="create-form-btn-icon"
name="plus"
aria-hidden="true"></dbp-icon>
${i18n.t('manage-forms.create-form-button')}
</button>
</div>
<div class="forms-table-actions">
<dbp-select
?disabled=${
this.selectedFormsCount === 0 ||
!formActions.some((action) => !action.disabled)
}
@change=${this._onFormAction}
id="forms-table-actions-select"
class="forms-table-actions-select"
label="${i18n.t('manage-forms.actions-button-text')}"
align="left"
allow-expand
.options=${formActions}></dbp-select>
<form class="search-input forms-search" @submit=${this.handleSearch}>
<label for="forms-searchbar">
${i18n.t('manage-forms.search-input-label')}:
</label>
<input
type="text"
id="forms-searchbar"
class="searchbar"
placeholder="${i18n.t('manage-forms.searchbar-placeholder')}"
@input=${this.handleSearch} />
</form>
<button
type="button"
class="reset-search"
@click=${this.handleResetSearch}
?disabled=${!this.searchInProgress}>
<dbp-icon name="spinner-arrow" aria-hidden="true"></dbp-icon>
${i18n.t('manage-forms.reset-search-label')}
</button>
</div>
<dbp-tabulator-table
lang="${this.lang}"
class="tabulator-table"
id="tabulator-table-forms"
identifier="forms-table"
pagination-enabled
pagination-size="5"
.paginationSizeStorageKey=${this.paginationSizeStorageKey}
.options=${this.optionsForms}></dbp-tabulator-table>
${
this.noFormsAvailable
? html`
<p class="no-forms-message">
${i18n.t('manage-forms.no-forms-available')}
</p>
`
: ''
}
</div>
`;
}
}