All files / src/form/create App.tsx

91.54% Statements 65/71
80% Branches 32/40
82.6% Functions 19/23
91.42% Lines 64/70

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182                                          66x           37x   36x 36x 36x 36x 36x 36x 36x 36x       36x 36x   36x 1x 1x     1x   1x         36x 4x 4x 4x       36x   8x     8x   8x 8x 8x 8x             36x 12x 7x     7x 105x 7x     7x 7x     7x 105x   7x 7x             7x 105x 7x   7x     12x 12x 3x 3x 3x   9x 4x   4x 4x 4x                     36x 16x 8x       36x 4x 1x 1x 1x 1x               36x                                                          
import React, { ReactElement, useEffect, useMemo, useRef, useState } from "react";
import { ValidateErrorEntity } from "rc-field-form/lib/interface";
 
import {
  CreateProps,
  FormProps,
  GroupMetaProps,
  RecordProps,
  SaveOptionProps,
  TableMetaProps
} from "@props/RecordProps";
import { fetchDomainMeta, fetchFormIdAndExtInfoByName, onFinishFailed, } from "@utils/FetchUtils";
import { FieldsToHideOnCreatePage } from '@config/base';
import { DataCollectForm } from "../";
import { LargeSpin } from "../../components";
import { fetchFormIdAndExtInfoByType, fetchFormFieldGroups } from "@utils/FetchUtils";
import { callSaveDomainWithCallback, getLastTrigger, setLastTrigger } from '@utils/SaveDomainUtils';
import { pureObjectIsEmpty } from "@utils/ObjectUtils";
import { emptyMethod } from "@utils/Constants";
import { getFormFieldsValue, useCustomHookForm } from "@utils/FormUtils";
 
const CreateComponent = (props: CreateProps): ReactElement => {
  const {
    formId, domainName, callback, ownerClass,
    ownerId, columnNameInOwnerClass, zIndex, queryParameters,
    triggerSave, continueOperate, validationCallback,
    formName, setCancelConfirmMessage
  } = props;
 
  const [columns, setColumns] = useState<Array<TableMetaProps>>([] as TableMetaProps[]);
  const [createFormGroups, setCreateFormGroups] = useState<Array<GroupMetaProps>>();
  const [loading, setLoading] = useState<boolean>(true);
  const [record, setRecord] = useState<RecordProps>(queryParameters as RecordProps);
  const [createFormId, setCreateFormId] = useState<number | undefined>(undefined);
  const [inited, setInited] = useState<boolean>(false);
  const path = `/Create|${domainName}`;
  const saveOptions = useMemo<SaveOptionProps>(() => ({
    arrayColumnOptions: {},
    dynamicTemplateAttributesFieldOptions: {},
  }), []);
  const finishCallbackRef = useRef<() => void>(emptyMethod);
  const form = useCustomHookForm();
 
  finishCallbackRef.current = () => {
    let values = getFormFieldsValue(form);
    Iif (pureObjectIsEmpty(values)) {
      values = {};
    }
    callSaveDomainWithCallback({
      callback, values, continueOperate, domainName, options: saveOptions, columns
    }).then(() => console.info(
      `Domain ${domainName} has been saved with parameters ${JSON.stringify(values)}`
    ));
  };
 
  useEffect(() => {
    Eif (formId != null) {
      const createObjectUrl = `/${formId}/${domainName}/create`;
      window.history.pushState('', '', createObjectUrl);
    }
  }, [domainName, formId]);
 
  useEffect(() => {
    let promise: Promise<FormProps>;
    Iif (formName) {
      promise = fetchFormIdAndExtInfoByName(domainName, formName);
    } else {
      promise = fetchFormIdAndExtInfoByType(domainName, "Create");
    }
    promise.then(json => {
      setCreateFormId(json.id);
      fetchFormFieldGroups(domainName, json.id).then(json => {
        setCreateFormGroups(json.length > 0 ? json : []);
      });
    }).catch(e => {
      console.error(`Failed to get create form Id of domain ${domainName}: ${e}`);
    });
  }, [domainName, formId, createFormId, formName]);
 
  useEffect(() => {
    const init = (domainMeta: Array<TableMetaProps>): void => {
      const r = (record ?? {}) as RecordProps;
 
      // 以下是根据元数据中的 defaultValue 来设置对应字段的默认值
      domainMeta
        ?.filter(c => (c.defaultValue != null))
        .forEach(c => r[c.key] = c.defaultValue);
 
      // 下面一句的判断是说当编辑关联对象的时候
      const editRelateObject = (ownerClass != null && ownerId != null);
      Eif (editRelateObject) {
        // 以下是根据元数据中的 backReferenceField 信息来设置 owner 字段
        // 举例:如果是在合同显示界面编辑合同行,那么下面的代码会将合同行中的合同字段的值设置为当前打开的合同
        domainMeta
          ?.filter(c => c.backReferenceField === columnNameInOwnerClass && c.backReferenceField != null)
          .forEach(c => {
            Eif (c.backReferenceField === columnNameInOwnerClass && c.backReferenceField != null) {
              r[c.key] = ownerId;
            }
          });
      }
      // 以下是将没有设定默认值,且类型为 boolean 的字段值设置为 false
      // 避免出现界面上显示的 boolean switch 控件的值看上去是 false,
      // 但是用户点击保存按钮,系统提示用户没有设置值
      domainMeta
        ?.filter(c => (c.type === "boolean" && c.defaultValue == null))
        .forEach(c => r[c.key] = false);
 
      setRecord(r);
    };
 
    Eif (!inited) {
      if (columns.length > 0) {
        setInited(true);
        init(columns);
        return;
      } else {
        if (createFormId != null) {
          fetchDomainMeta(domainName, createFormId)
            .then((domainMeta: Array<TableMetaProps>) => {
              setColumns(domainMeta);
              init(domainMeta);
              setInited(true);
            }).catch(error => {
            console.error(`Failed to get domain meta ${createFormId}: ${JSON.stringify(error)}`);
          });
        }
      }
    }
    // To avoid duplicate API call
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [formId, domainName, ownerClass, ownerId, columnNameInOwnerClass, record, createFormId]);
 
  useEffect(() => {
    if (columns?.length > 0 && createFormGroups != null) {
      setLoading(false);
    }
  }, [columns, createFormGroups]);
 
  useEffect(() => {
    if (!!triggerSave && getLastTrigger() !== triggerSave) {
      setLastTrigger(triggerSave);
      const values = form.getFieldsValue();
      setRecord(values);
      form.validateFields()
        .then(finishCallbackRef.current)
        .catch(() => validationCallback?.(false));
    }
    // Only include triggerSave to avoid duplicate API call
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [triggerSave]);
 
  return loading ?
    <LargeSpin /> :
      <DataCollectForm
        page="create"
        zIndex={zIndex + 1}
        ownerId={ownerId}
        ownerClass={ownerClass}
        columnNameInOwnerClass={columnNameInOwnerClass}
        columns={columns}
        setColumns={setColumns}
        groups={createFormGroups == null ? [] : createFormGroups}
        domainName={domainName}
        onFinish={finishCallbackRef.current}
        onFinishFailed={(e: ValidateErrorEntity): void => {
          onFinishFailed(e);
        }}
        onChange={emptyMethod}
        form={form}
        record={record}
        hideFields={FieldsToHideOnCreatePage}
        operation="create"
        validationCallback={validationCallback}
        saveOptions={saveOptions}
        setCancelConfirmMessage={setCancelConfirmMessage}
        path={path}
      />;
};
 
export default CreateComponent;