tableForm = async (table, req) => {
  const fields = table.getFields();
  const roleOptions = (await User.get_roles()).map((r) => ({
    value: r.id,
    label: r.role,
  }));
  const ownership_opts = await table.ownership_options();
  const form = new Form({
    action: "/table",
    noSubmitButton: true,
    onChange: "saveAndContinue(this)",
    fields: [
      {
        label: req.__("Minimum role to read"),
        sublabel: req.__(
          "User must have this role or higher to read rows from the table, unless they are the owner"
        ),
        help: {
          topic: "Table roles",
          context: {},
        },
        name: "min_role_read",
        input_type: "select",
        options: roleOptions,
        attributes: { asideNext: !table.external && !table.provider_name },
      },
      ...(!table.external && !table.provider_name
        ? [
            {
              label: req.__("Minimum role to write"),
              name: "min_role_write",
              input_type: "select",
              help: {
                topic: "Table roles",
                context: {},
              },
              sublabel: req.__(
                "User must have this role or higher to edit or create new rows in the table, unless they are the owner"
              ),
              options: roleOptions,
            },
            {
              label: req.__("Ownership field"),
              name: "ownership_field_id",
              sublabel: req.__(
                "The user referred to in this field will be the owner of the row"
              ),
              help: {
                topic: "Ownership field",
                context: {},
              },
              input_type: "select",
              options: [
                { value: "", label: req.__("None") },
                ...ownership_opts,
                { value: "_formula", label: req.__("Formula") },
              ],
            },
            {
              name: "ownership_formula",
              label: req.__("Ownership formula"),
              validator: expressionValidator,
              type: "String",
              class: "validate-expression",
              help: {
                topic: "Ownership formula",
                context: {},
              },
              sublabel:
                req.__("User is treated as owner if true. In scope: ") +
                ["user", ...fields.map((f) => f.name)]
                  .map((fn) => code(fn))
                  .join(", "),
              showIf: { ownership_field_id: "_formula" },
            },
            {
              label: req.__("User group"),
              sublabel: req.__(
                "Add relations to this table in dropdown options for ownership field"
              ),
              help: {
                topic: "User groups",
                context: {},
              },
              name: "is_user_group",
              type: "Bool",
            },
          ]
        : []),
      // description of table
      {
        label: req.__("Description"),
        name: "description",
        input_type: "text",
        sublabel: req.__(
          "Description allows you to give more information about the table"
        ),
        //options: roleOptions,
      },
      ...(table.external || table.provider_name
        ? []
        : [
            {
              label: req.__("Version history"),
              sublabel: req.__("Track table data changes over time"),
              name: "versioned",
              attributes: {
                onChange:
                  "if(!this.checked && !confirm('Are you sure? This will delete all history')) {this.checked = true; return false}",
              },
              type: "Bool",
              help: {
                topic: "Table history",
              },
            },
            ...(table.name === "users"
              ? []
              : [
                  {
                    label: req.__("Sync information"),
                    sublabel: req.__(
                      "Sync information tracks the last modification or deletion timestamp " +
                        "so that the table data can be synchronized with the mobile app"
                    ),
                    name: "has_sync_info",
                    type: "Bool",
                  },
                ]),
          ]),
    ],
  });
  if (table) {
    if (table.id) form.hidden("id");
    if (table.external) form.hidden("name");
    if (table.external) form.hidden("external");
    form.values = table;
  }
  return form;
}
Show Table Form
@param {object} table
@param {object} req
@returns {Promise<Form>}