get_link_view_opts = async (table, viewname, accept = () => true) => {
  const own_link_views = await View.find_possible_links_to_table(table);
  const all_views = await View.find({}, { cached: true });
  const all_tables = await Table.find({}, { cached: true });
  const table_id_to_name = {};
  all_tables.forEach((t) => {
    table_id_to_name[t.id] = t.name;
  });
  const view_name_opts = all_views.filter(accept).map((v) => ({
    label: `${v.name} [${v.viewtemplate} ${
      table_id_to_name[v.table_id] || ""
    }]`,
    name: v.name,
    table: table_id_to_name[v.table_id] || "",
  }));
  const view_relation_opts = {};
  const link_view_opts = [];
  const push_view_option = ({ name, label, view, relation }) => {
    link_view_opts.push({ name, label });
    if (!view_relation_opts[view]) view_relation_opts[view] = [];
    view_relation_opts[view].push({ value: name, label: relation });
  };
  own_link_views.forEach((v) => {
    push_view_option({
      view: v.name,
      label: `${v.name} [${v.viewtemplate} ${table.name}]`,
      name: `Own:${v.name}`,
      relation: table.name,
    });
  });
  const link_view_opts_push_legacy = (o) => {
    if (!link_view_opts.map((v) => v.name).includes(o.name))
      push_view_option(o);
  };
  const link_view_opts_push = (o) => {
    if (
      !view_relation_opts[o.view] ||
      !view_relation_opts[o.view].find(({ value }) => value === o.name)
    )
      push_view_option(o);
  };
  const child_views = await get_child_views(table, viewname);
  for (const {
    relation,
    related_table,
    through,
    throughTable,
    views,
  } of child_views) {
    for (const view of views) {
      if (through && throughTable) {
        link_view_opts_push_legacy({
          view: view.name,
          name: `ChildList:${view.name}.${throughTable.name}.${through.name}.${related_table.name}.${relation.name}`,
          label: `${view.name} [${view.viewtemplate} ${related_table.name}.${relation.name}.${through.name}]`,
          relation: `${related_table.name}.${relation.name}.${through.name}`,
        });
      } else {
        link_view_opts_push_legacy({
          view: view.name,
          name: `ChildList:${view.name}.${related_table.name}.${relation.name}`,
          label: `${view.name} [${view.viewtemplate} ${related_table.name}.${relation.name}]`,
          relation: `${related_table.name}.${relation.name}`,
        });
      }
    }
  }

  const parent_views = await get_parent_views(table, viewname);
  for (const { relation, related_table, views } of parent_views) {
    for (const view of views) {
      link_view_opts_push_legacy({
        view: view.name,
        name: `ParentShow:${view.name}.${related_table.name}.${relation.name}`,
        label: `${view.name} [${view.viewtemplate} ${relation.name}.${related_table.name}]`,
        relation: `${relation.name}.${related_table.name}`,
      });
    }
  }
  const onetoone_views = await get_onetoone_views(table, viewname);
  for (const { relation, related_table, views } of onetoone_views) {
    for (const view of views) {
      link_view_opts_push_legacy({
        view: view.name,
        name: `OneToOneShow:${view.name}.${related_table.name}.${relation.name}`,
        label: `${view.name} [${view.viewtemplate} ${related_table.name}.${relation.label}]`,
        relation: `${related_table.name}.${relation.label}`,
      });
    }
  }
  const independent_views = await View.find_all_views_where(
    ({ state_fields }) => !state_fields.some((sf) => sf.required)
  );
  independent_views.forEach((view) => {
    link_view_opts_push_legacy({
      view: view.name,
      label: `${view.name} [${view.viewtemplate}]`,
      name: `Independent:${view.name}`,
      relation: "None",
    });
  });
  const cache = await tableFieldCache();
  const inbound_rel_opts = await get_inbound_relation_opts(
    table,
    viewname,
    cache
  );
  for (const { path, views } of inbound_rel_opts) {
    for (const view of views) {
      link_view_opts_push({
        view: view.name,
        label: `${view.name} [${view.viewtemplate} ${table.name}]`,
        name: path,
        relation: path,
      });
    }
  }

  const self_inbounds = await get_inbound_self_relation_opts(table, viewname);
  for (const { path, views } of self_inbounds) {
    for (const view of views) {
      link_view_opts_push({
        view: view.name,
        label: `${view.name} [${view.viewtemplate} ${table.name}]`,
        name: path,
        relation: path,
      });
    }
  }

  const many_to_many = await get_many_to_many_relation_opts(
    table,
    viewname,
    cache,
    [`.${table.name}`]
  );
  for (const { path, views } of many_to_many) {
    for (const view of views) {
      link_view_opts_push({
        view: view.name,
        label: `${view.name} [${view.viewtemplate} ${table.name}]`,
        name: path,
        relation: path,
      });
    }
  }
  return { link_view_opts, view_name_opts, view_relation_opts };
}
@function
@param {Table|object} table
@param {string} viewname
@returns {Promise<{link_view_opts: object[]}>}