calcfldViewConfig = async (fields, isEdit, nrecurse = 2, mode, req) => {
  const fieldViewConfigForms = {};
  for (const f of fields) {
    f.fill_table();
    fieldViewConfigForms[f.name] = {};
    const fieldviews =
      f.type === "Key"
        ? getState().keyFieldviews
        : f.type === "File"
          ? getState().fileviews
          : (f.type && f.type.fieldviews) || {};
    for (const [nm, fv] of Object.entries(fieldviews)) {
      if (fv.configFields)
        fieldViewConfigForms[f.name][nm] = await applyAsync(
          fv.configFields,
          f,
          { mode, req, ...(req?.__ ? { __: req.__ } : {}) }
        );
    }
    if (f.type === "Key") {
      if (f.reftable_name && nrecurse > 0) {
        const reftable = Table.findOne({ name: f.reftable_name });
        if (reftable && reftable.fields) {
          const joinedCfg = await calcfldViewConfig(
            reftable.fields,
            isEdit,
            nrecurse - 1,
            mode,
            req
          );
          Object.entries(joinedCfg).forEach(([nm, o]) => {
            fieldViewConfigForms[`${f.name}.${nm}`] = o;
          });
        }
      }
    }
  }
  return fieldViewConfigForms;
}
@function
@param {Field[]} fields
@param isEdit
@param nrecurse
@returns {Promise<object>}