/* tslint:disable:no-use-before-declare */ import { lazy } from '@fuselab/ui-shared/lib'; import { IconNames } from '@uifabric/icons'; import { BaseComponent, IBaseProps } from '@uifabric/utilities/lib'; import { CommandBar } from 'office-ui-fabric-react/lib-commonjs/CommandBar'; import { IContextualMenu, IContextualMenuItem } from 'office-ui-fabric-react/lib-commonjs/ContextualMenu'; import * as React from 'react'; import { commandBarClassNames } from '../themes/commandBar'; import { Preference } from '../themes/themes.types'; import { History, WithRouter } from '../withRouter'; import classNames from './form.classNames'; /* tslint:enable:no-use-before-declare */ export interface FormAttributes extends Preference { entity: T; rollback: T; id?: string; } export interface FormActions { load(id: string); discard(rollback: T, history: History); save(entity: T); delete(entity: T); } export enum FormState { loading, loaded, saving, saved, deleting, deleted, error } export interface EditorState { status: FormState; } export interface IFormEditor { update(state: FormState); } export type FormProps = FormAttributes & FormActions & WithRouter & FormActions> & IBaseProps; const iconSave: IconNames = 'Save' as IconNames; const iconRemove: IconNames = 'Remove' as IconNames; const iconDiscard: IconNames = 'Undo' as IconNames; /** * Generic form editor */ export class GenericForm extends BaseComponent, EditorState> implements IFormEditor { constructor(props: FormProps) { super(props); this.state = { status: FormState.loading }; } public componentDidMount() { this.update(FormState.loading); this.props.load(this.params.id); } public update(state: FormState) { this.setState({ status: state }); } public componentDidUpdate(prevProps: FormProps, prevState: EditorState) { if (this.state.status === FormState.deleted || this.state.status === FormState.saved) { this.props.history.goBack(); } } public render(): JSX.Element { return (
{this.props.children}
); } private get params(): FormAttributes { return this.props.match ? this.props.match.params : this.props; } @lazy() private get formButtons(): IContextualMenuItem[] { return [ { key: 'save', name: 'Save', iconProps: { iconName: iconSave }, onClick: this.onSave }, { key: 'discard', name: 'Discard', iconProps: { iconName: iconDiscard }, onClick: this.onDiscard }, { key: 'delete', name: 'Remove', iconProps: { iconName: iconRemove }, onClick: this.onDelete } ]; } @lazy() private get onSave(): (ev?: React.MouseEvent, item?: IContextualMenu) => void { return e => { this.update(FormState.saving); this.props.save(this.props.entity); }; } @lazy() private get onDiscard(): (ev?: React.MouseEvent, item?: IContextualMenu) => void { return e => { this.props.discard(this.props.rollback, this.props.history); }; } @lazy() private get onDelete(): (ev?: React.MouseEvent, item?: IContextualMenu) => void { return e => { this.update(FormState.deleting); this.props.delete(this.props.entity); }; } }