import {mdiFloppy} from '@mdi/js'; import collect, {Collection} from 'collect.js'; import { Children, Vnode, VnodeDOM } from 'mithril'; import Stream from 'mithril/stream'; import {Class} from 'type-fest'; import Form from '~/Components/Form'; import MdIcon from '~/Components/MdIcon'; import RecordDialog, {RecordDialogAttributes} from '~/Components/Dialogs/RecordDialog'; import Model from '~/Models/Model'; import { VnodeCollection, VnodeCollectionItem } from '~/typings/jsx'; import {isFormValid} from '~/utils/misc'; export default abstract class AddEditRecordDialog> extends RecordDialog { // eslint-disable-next-line unicorn/no-null protected formElement: HTMLFormElement | null = null; protected abstract formState: Map>; protected abstract modelType: Class; // Recommended: <= 3 protected numberOfColumns: number = 3; protected record!: M; oninit(vnode: Vnode, this>) { super.oninit(vnode); if (!this.record) { this.record = new this.modelType(); } this.fillForm(); } oncreate(vnode: VnodeDOM, this>) { super.oncreate(vnode); this.formElement = this.element.querySelector('form'); } fillForm() { for (const [key, value] of this.formState) { value(this.record.getAttribute(key) ?? value()); } } contents(): Children { return ( <>

{this.record.isNew() ? __('Nuovo record') : __('Modifica record')}

{this.form()} {this.afterForm().toArray()} ); } form(): Children { return (
{this.formContents()}
); } formContents(): Children { return ( {...this.fields().map((item, key: string) => { // TODO: Remove this cast when new collection library is done const field = item as Vnode<{name?: string, 'grid-span'?: number}>; field.attrs.name ??= key; field.attrs['grid-span'] ??= Math.floor(12 / this.numberOfColumns); return item; }).values().all()} ); } abstract fields(): Collection; onCancelButtonClicked(): void { this.close('cancel'); } async onFormSubmit() { if (isFormValid(this.formElement!) && await this.save()) { this.close(); } } abstract save(): boolean | Promise; afterForm(): VnodeCollection { return collect({ cancelButton: ( {__('Annulla')} ), saveButton: ( {__('Salva')} ) }); } onSaveButtonClicked(): void { this.formElement?.requestSubmit(); } protected static createFormState(entries: Record>): Map> { return new Map(Object.entries(entries)); } get formStateRecord(): Record { const state: Record = {}; for (const [key, value] of this.formState) { state[key] = value(); } return state; } }