import TypeNode from 'type/type-node'; import SystemId from 'system/enum/id'; import ActionType from 'enum/action-type'; import DraftField from 'type/draft-field'; import HtmlEndpoint from 'endpoint/html'; import BadRequestError from 'http/error/bad-request'; import TypeFormTemplate from 'template/page/type-form'; import FetchTypeInstancesOperation from 'operation/fetch-type-instances'; import CheckNodePermissionOperation from 'operation/check-node-permission'; interface DraftFieldInput { readonly key: string | undefined; readonly value: string | string[] | undefined; } interface Input { readonly id: string | undefined; readonly fields: DraftFieldInput[] | undefined; } class HtmlTypeFormEndpoint extends HtmlEndpoint { protected async process(): Promise { const generic_type = await this.fetchType(SystemId.GENERIC_TYPE); await this.checkPermission(generic_type); const type_nodes = await this.fetchTypeNodes(generic_type); return this.renderFormForTypeNode(generic_type, type_nodes); } private checkPermission(node: TypeNode): Promise { const action_type = ActionType.CREATE; const repository = this.getRepository(); const account = this.getAccount(); const input = { node, action_type, repository, account }; const operation = new CheckNodePermissionOperation(input); return operation.perform(); } private async fetchTypeNodes(type_node: TypeNode): Promise { const repository = this.getRepository(); const account = this.getAccount(); const input = { type_node, repository, account }; const operation = new FetchTypeInstancesOperation(input); const result = await operation.perform(); return result as TypeNode[]; } private renderFormForTypeNode( generic_type: TypeNode, type_nodes: TypeNode[] ): string { const account = this.getAccount(); const draft_id = this.getDraftId(); const draft_fields = this.getDraftFields(); const template = new TypeFormTemplate({ generic_type, draft_id, draft_fields, type_nodes, account }); return template.render(); } private getDraftFields(): DraftField[] { const body = this.getRequestBody(); if (body.fields === undefined) { return [ { key: '', value: '' } ]; } const draft_fields = body.fields.map((field) => { const key = field.key || ''; let value: string | undefined; if (Array.isArray(field.value)) { value = field.value.find((element) => { return element !== ''; }); } else { value = field.value; } value ||= ''; return { key, value }; }); const action = this.getQueryParameter('action'); if (action === undefined) { return draft_fields; } switch (action) { case 'add_field': return this.processAddFieldAction(draft_fields); case 'remove_field': return this.processRemoveFieldAction(draft_fields); case undefined: return draft_fields; default: throw new BadRequestError(); } } private processAddFieldAction(draft_fields: DraftField[]): DraftField[] { return [ ...draft_fields, { key: '', value: '' } ]; } private processRemoveFieldAction(draft_fields: DraftField[]): DraftField[] { const index_param = this.getQueryParameter('index'); if (index_param === undefined) { throw new BadRequestError(); } const removal_index = parseInt(index_param, 10); if (isNaN(removal_index)) { throw new BadRequestError(); } return draft_fields.filter((_field, index) => { return index !== removal_index; }); } private getDraftId(): string { const request_body = this.getRequestBody(); return request_body.id || ''; } } export default HtmlTypeFormEndpoint;