field_picker_fields = async ({
  table,
  viewname,
  req,
  has_click_to_edit,
  has_align,
  no_fieldviews,
  has_showif,
}) => {
  const __ = (...s) => (req ? req.__(...s) : s.join(""));
  const fields = table.getFields();
  for (const field of fields) {
    if (field.type === "Key") {
      field.reftable = Table.findOne({ name: field.reftable_name });
      if (field.reftable) await field.reftable.getFields();
    }
  }
  const boolfields = fields.filter((f) => f.type && f.type.name === "Bool");

  const stateActions = getState().actions;
  const stateActionKeys = Object.entries(stateActions)
    .filter(([k, v]) => !v.disableInList)
    .map(([k, v]) => k);

  const actions = [
    "Delete",
    ...boolfields.map((f) => `Toggle ${f.name}`),
    ...stateActionKeys,
  ];
  const triggers = Trigger.find({
    when_trigger: { or: ["API call", "Never"] },
    table_id: null,
  });
  triggers.forEach((tr) => {
    actions.push(tr.name);
  });
  if (!table.external)
    Trigger.find({
      table_id: table.id,
    }).forEach((tr) => {
      actions.push(tr.name);
    });
  const actionConfigFields = [];
  for (const [name, action] of Object.entries(stateActions)) {
    if (!stateActionKeys.includes(name)) continue;
    const cfgFields = await getActionConfigFields(action, table, { req });

    for (const field of cfgFields) {
      const cfgFld = {
        ...field,
        showIf: {
          action_name: name,
          type: "Action",
          ...(field.showIf || {}),
        },
      };
      if (cfgFld.input_type === "code") cfgFld.input_type = "textarea";
      actionConfigFields.push(cfgFld);
    }
  }
  const fldOptions = fields.map((f) => ({
    label: `${f.name} [${f.pretty_type}]`,
    name: f.name,
  }));
  const { field_view_options } = calcfldViewOptions(fields, "list");
  const rel_field_view_options = await calcrelViewOptions(table, "list");

  const fvConfigFields = [];
  if (req.staticFieldViewConfig) {
    //TODO the following line is slow
    const fieldViewConfigForms = await calcfldViewConfig(fields, false);
    for (const [field_name, fvOptFields] of Object.entries(
      fieldViewConfigForms
    )) {
      for (const [fieldview, formFields] of Object.entries(fvOptFields)) {
        for (const formField of formFields) {
          if (field_name.includes("."))
            fvConfigFields.push({
              ...formField,
              showIf: {
                type: "JoinField",
                join_field: field_name,
                join_fieldview: fieldview,
              },
            });
          else
            fvConfigFields.push({
              ...formField,
              showIf: {
                type: "Field",
                field_name,
                fieldview,
              },
            });
        }
      }
    }
  }
  //TODO the following line is slow
  const { link_view_opts, view_name_opts, view_relation_opts } =
    await get_link_view_opts(table, viewname);
  const { parent_field_list } = await table.get_parent_relations(true, true);
  const { child_field_list, child_relations } =
    await table.get_child_relations(true);
  const join_field_options = await table.get_join_field_options(true, true);
  const join_field_view_options = {
    ...field_view_options,
    ...rel_field_view_options,
  };
  const relation_options = await table.get_relation_options();
  const aggStatOptions = {};
  const agg_fieldviews = [];
  Object.values(getState().types).forEach((t) => {
    const fvnames = Object.entries(t.fieldviews)
      .filter(([k, v]) => !v.isEdit && !v.isFilter)
      .map(([k, v]) => k);
    agg_fieldviews.push({
      name: `agg_fieldview`,
      label: __("Field view"),
      type: "String",
      attributes: {
        options: fvnames,
      },
      showIf: {
        "agg_field|_@_1": t.name,
        type: "Aggregation",
      },
    });
  });
  const agg_fieldview_cfg_opts = [
    {
      name: "format",
      label: __("Format"),
      type: "String",
      sublabel: __("moment.js format specifier"),
      showIf: {
        type: "Aggregation",
        "agg_field|_@_1": "Date",
        agg_fieldview: "format",
      },
    },
  ];

  const agg_field_opts = child_relations.map(
    ({ table, key_field, through }) => {
      const aggKey =
        (through ? `${through.name}->` : "") +
        `${table.name}.${key_field.name}`;
      aggStatOptions[aggKey] = [
        "Count",
        "CountUnique",
        "Avg",
        "Sum",
        "Max",
        "Min",
        "Array_Agg",
      ];
      table.fields.forEach((f) => {
        if (f.type && f.type.name === "Date") {
          aggStatOptions[aggKey].push(`Latest ${f.name}`);
          aggStatOptions[aggKey].push(`Earliest ${f.name}`);
        }
      });
      return {
        name: `agg_field`,
        label: __("On Field"),
        type: "String",
        required: true,
        attributes: {
          options: table.fields
            .filter((f) => !f.calculated || f.stored)
            .map((f) => ({ label: f.name, name: `${f.name}@${f.type_name}` })),
        },
        showIf: {
          agg_relation: aggKey,
          type: "Aggregation",
        },
      };
    }
  );
  return [
    {
      name: "type",
      label: __("Type"),
      type: "String",
      required: true,
      attributes: {
        //TODO omit when no options
        options: [
          {
            name: "Field",
            label: __(`Field in %s table`, table.name),
          },
          { name: "Action", label: __("Action on row") },

          ...(link_view_opts.length > 0
            ? [{ name: "ViewLink", label: __("Link to other view") }]
            : []),
          { name: "Link", label: __("Link to anywhere") },
          ...(parent_field_list.length > 0
            ? [{ name: "JoinField", label: __("Join Field") }]
            : []),
          ...(child_field_list.length > 0
            ? [{ name: "Aggregation", label: __("Aggregation") }]
            : []),
          { name: "FormulaValue", label: __("Formula value") },
        ],
      },
    },
    {
      name: "formula",
      label: __("Formula"),
      type: "String",
      fieldview: "textarea",

      class: "validate-expression",
      showIf: { type: "FormulaValue" },
      attributes: {
        rows: 2,
        spellcheck: false,
      },
    },
    {
      name: "field_name",
      label: __("Field"),
      type: "String",
      required: true,
      attributes: {
        options: fldOptions,
      },
      showIf: { type: "Field" },
    },
    ...(no_fieldviews
      ? []
      : [
          {
            name: "fieldview",
            label: __("Field view"),
            type: "String",
            required: false,
            attributes: {
              calcOptions: ["field_name", field_view_options],
            },
            showIf: { type: "Field" },
            help: {
              topic: "Field views",
              context: { table_name: table.name, mode: "list" },
              dynContext: ["field_name"],
            },
          },
        ]),

    {
      name: "join_field",
      label: __("Join Field"),
      type: "String",
      input_type: "join_field_picker",
      required: true,
      attributes: {
        join_field_options,
        relation_options,
      },
      showIf: { type: "JoinField" },
    },
    {
      name: "join_fieldview",
      label: __("Field view"),
      type: "String",
      required: false,
      attributes: {
        calcOptions: ["join_field", join_field_view_options],
      },
      showIf: { type: "JoinField" },
    },
    ...(req.staticFieldViewConfig
      ? fvConfigFields
      : [
          {
            name: "fvcfg",
            input_type: "dynamic_fields",
            attributes: {
              //getFields: `({type, field, join_field, fieldview, join_fieldview})=>'/field/fieldviewcfgform/${table.name}/'+(type==='Field'?field:join_field)+'/'+(type==='Field'?fieldview:join_fieldview)`,
              getFields: `/field/fieldviewcfgform/${table.name}`,
              relevantFields: [
                "field_name",
                "fieldview",
                "type",
                "join_field",
                "join_fieldview",
                "_columndef",
              ],
            },
            //showIf: { type: ["Field", "JoinField"] },
          },
          { name: "_columndef", input_type: "hidden" },
        ]),
    ...(has_click_to_edit
      ? [
          {
            name: "click_to_edit",
            label: __("Click to edit?"),
            type: "Bool",
            showIf: { type: ["Field", "JoinField"] },
          },
        ]
      : []),
    {
      name: "action_name",
      label: __("Action"),
      type: "String",
      required: true,
      attributes: {
        options: actions,
      },
      showIf: { type: "Action" },
    },
    {
      name: "action_label",
      label: __("Action Label"),
      class: "validate-expression validate-expression-conditional",
      type: "String",
      showIf: { type: "Action" },
    },
    {
      name: "action_label_formula",
      label: __("Action label is a formula?"),
      type: "Bool",
      required: false,
      showIf: { type: "Action" },
    },
    {
      name: "action_style",
      label: __("Action Style"),
      type: "String",
      required: true,
      attributes: {
        asideNext: true,
        options: [
          { name: "btn-primary", label: __("Primary button") },
          { name: "btn-secondary", label: __("Secondary button") },
          { name: "btn-success", label: __("Success button") },
          { name: "btn-danger", label: __("Danger button") },
          { name: "btn-outline-primary", label: __("Primary outline button") },
          {
            name: "btn-outline-secondary",
            label: __("Secondary outline button"),
          },
          { name: "btn-link", label: __("Link") },
        ],
      },

      showIf: { type: "Action" },
    },
    {
      name: "action_size",
      label: __("Button size"),
      type: "String",
      required: true,
      attributes: {
        options: [
          { name: "", label: __("Standard") },
          { name: "btn-lg", label: __("Large") },
          { name: "btn-sm", label: __("Small") },
          { name: "btn-sm btn-xs", label: __("X-Small") },
          { name: "btn-block", label: __("Block") },
          { name: "btn-block btn-lg", label: __("Large block") },
        ],
      },
      showIf: { type: "Action" },
    },
    {
      name: "confirm",
      label: __("User confirmation?"),
      type: "Bool",
      showIf: { type: "Action" },
    },
    ...actionConfigFields,
    {
      name: "view_name",
      label: __("View"),
      type: "String",
      required: true,
      attributes: {
        options: view_name_opts,
        asideNext: true,
      },
      showIf: { type: "ViewLink" },
    },
    {
      name: "view",
      label: __("Relation"),
      type: "String",
      required: true,
      attributes: {
        //options: link_view_opts,
        calcOptions: ["view_name", view_relation_opts],
      },
      showIf: { type: "ViewLink" },
    },
    {
      name: "view_label",
      label: __("View label"),
      sublabel: __("Leave blank for default label."),
      class: "validate-expression validate-expression-conditional",
      type: "String",
      required: false,
      showIf: { type: "ViewLink" },
    },
    {
      name: "view_label_formula",
      label: __("View label is a formula?"),
      type: "Bool",
      required: false,
      showIf: { type: "ViewLink" },
    },

    {
      name: "link_style",
      label: __("Link Style"),
      type: "String",
      required: true,
      attributes: {
        asideNext: true,
        options: [
          { name: "", label: __("Link") },
          { name: "btn btn-primary", label: __("Primary button") },
          { name: "btn btn-secondary", label: __("Secondary button") },
          { name: "btn btn-success", label: __("Success button") },
          { name: "btn btn-danger", label: __("Danger button") },
          {
            name: "btn btn-outline-primary",
            label: __("Primary outline button"),
          },
          {
            name: "btn btn-outline-secondary",
            label: __("Secondary outline button"),
          },
        ],
      },

      showIf: { type: "ViewLink" },
    },
    {
      name: "link_size",
      label: __("Link size"),
      type: "String",
      required: true,
      attributes: {
        options: [
          { name: "", label: __("Standard") },
          { name: "btn-lg", label: __("Large") },
          { name: "btn-sm", label: __("Small") },
          { name: "btn-sm btn-xs", label: __("X-Small") },
          { name: "btn-block", label: __("Block") },
          { name: "btn-block btn-lg", label: __("Large block") },
        ],
      },
      showIf: { type: "ViewLink" },
    },
    {
      name: "extra_state_fml",
      label: __("Extra state Formula"),
      sublabel: __(
        "Formula for JavaScript object that will be added to state parameters"
      ),
      help: {
        topic: "Extra state formula",
        context: { srcTable: table.name },
        dynContext: ["view_name"],
      },
      type: "String",
      class: "validate-expression",
      showIf: { type: "ViewLink" },
    },
    {
      name: "link_text",
      label: __("Link text"),
      type: "String",
      class: "validate-expression validate-expression-conditional",
      required: true,
      showIf: { type: "Link" },
    },
    {
      name: "link_text_formula",
      label: __("Link text is a formula?"),
      type: "Bool",
      required: false,
      showIf: { type: "Link" },
    },
    {
      name: "link_url",
      label: __("Link URL"),
      class: "validate-expression validate-expression-conditional",
      type: "String",
      required: true,
      showIf: { type: "Link" },
    },
    {
      name: "link_url_formula",
      label: __("Link URL is a formula?"),
      type: "Bool",
      required: false,
      showIf: { type: "Link" },
    },
    {
      name: "icon_btn",
      label: __("Icon"),
      input_type: "custom_html",
      attributes: {
        html: `<button type="button" id="myEditor_icon" class="btn btn-outline-secondary"></button>`,
      },
      showIf: { type: ["Link", "ViewLink", "Action"] },
    },
    {
      name: "icon",
      class: "item-menu",
      input_type: "hidden",
    },
    {
      name: "link_target_blank",
      label: __("Open in new tab"),
      type: "Bool",
      required: false,
      showIf: { type: ["ViewLink", "Link"] },
    },
    {
      name: "in_modal",
      label: __("Open in popup modal?"),
      type: "Bool",
      required: false,
      showIf: { type: ["ViewLink", "Link"] },
    },
    {
      name: "in_dropdown",
      label: __("Place in dropdown"),
      type: "Bool",
      showIf: { type: ["Action", "ViewLink", "Link"] },
    },
    {
      name: "agg_relation",
      label: __("Relation"),
      type: "String",
      required: true,
      attributes: {
        options: child_field_list,
      },
      showIf: { type: "Aggregation" },
    },
    ...agg_field_opts,
    {
      name: "stat",
      label: __("Statistic"),
      type: "String",
      required: true,
      attributes: {
        calcOptions: ["agg_relation", aggStatOptions],
      },

      showIf: { type: "Aggregation" },
    },
    ...agg_fieldviews,
    ...agg_fieldview_cfg_opts,
    {
      name: "aggwhere",
      label: __("Where"),
      sublabel: __("Formula"),
      class: "validate-expression",
      type: "String",
      required: false,
      showIf: { type: "Aggregation" },
    },
    {
      name: "header_label",
      label: __("Header label"),
      type: "String",
    },
    ...(has_showif
      ? [
          {
            name: "showif",
            label: __("Show if true"),
            sublabel: __("Formula. Leave blank to always show"),
            class: "validate-expression",
            type: "String",
            required: false,
          },
        ]
      : []),
    {
      name: "col_width",
      label: __("Column width"),
      type: "Integer",
      attributes: { asideNext: true },
    },
    {
      name: "col_width_units",
      label: __("Units"),
      type: "String",
      required: true,
      attributes: {
        inline: true,
        options: ["px", "%", "vw", "em", "rem", "cm"],
      },
    },
    ...(has_align
      ? [
          {
            name: "alignment",
            label: __("Alignment"),
            input_type: "select",
            options: ["Default", "Left", "Center", "Right"],
          },
        ]
      : []),
  ];
}
@function
@param {Table|object} table - Table object
@param {string} viewname - view name
@param {object} req - Request Object
@param has_click_to_edit - boolean
@param has_align - boolean
@param no_fieldviews - boolean
@returns {Promise<object[]>}