Skip to content

Контракт данных представлений

Данные хранятся одновременно в двух формах. preset — живая конфигурация: фильтры, обе оси и вид ячейки по умолчанию. snapshot — зафиксированный результат генерации: готовые строки, столбцы и ячейки. Это даёт два режима работы — быстрый предпросмотр по фильтрам и ручная доводка зафиксированной таблицы.

Контракт общий для builder и портала — сохранённое представление открывается одинаково в обоих приложениях.

Структура представления

ts
/**
 * Объект прав доступа для компонента-фасада LibMenuFolderView.
 * Определяет, какие интерактивные действия разрешены в представлении.
 */
export interface MenuFolderViewPermissions {
  /** Разрешить приём внешнего перетаскивания (D&D из дерева). */
  canDropExternal?: boolean;
  /** Разрешить ручную перестановку строк (осей). */
  canReorderRows?: boolean;
  /** Разрешить ручную перестановку столбцов (осей). */
  canReorderColumns?: boolean;
  /** Режим только для чтения: скрывает элементы управления и блокирует правки. */
  readonly?: boolean;
}

export interface MenuFolderTableView {
  /**
   * Версия схемы сохранённого представления. Растёт при любом несовместимом
   * изменении структуры `preset`/`snapshot`. Точка входа миграций: при
   * десериализации (import, загрузка из БД) значение прогоняется через
   * `migrateMenuFolderTableView` до `MENU_FOLDER_TABLE_VIEW_VERSION`.
   * Свежесозданные представления всегда получают текущую версию.
   */
  version: number;
  /** Live-конфигурация таблицы: фильтры, обе оси и вид ячеек для генерации. */
  preset: TableViewPreset;
  /** Зафиксированный результат генерации или `null`, если snapshot ещё не создан. */
  snapshot: TableViewSnapshot | null;
  /**
   * Выбранный источник данных превью (онлайн/snapshot). При `snapshot`, если сам
   * snapshot ещё не сгенерирован, фактически показывается `preset`.
   */
  displaySource: MenuFolderTableViewSource;
  /**
   * Режим отрисовки представления: `list` (сгруппированный список) или `table`
   * (таблица). Не меняет структуру данных — те же `preset` и `snapshot`
   * используются в обоих режимах, отличается только рендер. В режиме `list` ось
   * столбцов скрывается, но её настройки сохраняются.
   */
  displayMode: MenuFolderViewDisplayMode;
}

/**
 * @description Текущая версия схемы `MenuFolderTableView`. Любое несовместимое
 * изменение структуры preset/snapshot требует увеличения этого значения и
 * регистрации соответствующего migrator'а в `migrateMenuFolderTableView`.
 * Начальное значение — `0`.
 */
export const MENU_FOLDER_TABLE_VIEW_VERSION = 0;

Preset: живая конфигурация

preset — живая конфигурация представления. Описывает, из каких объектов и каких полей собирать таблицу. Состоит из двух одинаковых по структуре осей rows/columns и вида ячейки по умолчанию.

Каждая ось — это набор "признаков" объекта. Для каждой оси через фильтр отбираются объекты. Таблица строится на пересечении "признаков". Объекты, полученные после фильтрации имеют множество "признаков". valuePath - путь до "признака" объекта. При наличии этого поля ось таблицы принимает все возможные значения этого "признака". Есть возомжность использовать для построения осей только их уникальные значения. Если у объекта одновременно встречается оба "признака" - строковый и столцевой, то этот объект отображается на пересечении строки и столбца. Если таких объектов несколько, отображается первый попавшийся.

ts
export interface TableViewAxisPreset {
  /** Пресет {@link_doc object-filter}: отбирает объекты, участвующие в оси. */
  filter: TableViewObjectFilterPreset;
  /** Путь к полю объекта, значение которого становится ключом и подписью элемента оси (например `name`, `objectType`). */
  valuePath: string;
  /** Если `true` — одинаковые значения по `valuePath` схлопываются в один элемент оси; `false` оставляет каждое значение отдельным элементом. */
  unique: boolean;
  /**
   * @description
   * Словарь ручных подписей для значений оси. Ключом остаётся исходное
   * значение, полученное по `valuePath`, потому что именно оно участвует в
   * поиске пересечений таблицы и в повторной генерации snapshot. Значение
   * словаря влияет только на отображаемый label строки, столбца или элемента
   * списка.
   */
  labelOverrides: Record<string, string>;
}

export interface TableViewPreset {
  /** Конфигурация оси строк: фильтр, путь значения и подписи. */
  rows: TableViewAxisPreset;
  /** Конфигурация оси столбцов: фильтр, путь значения и подписи. В режиме `list` скрывается, но сохраняется. */
  columns: TableViewAxisPreset;
  /** Вид ячейки по умолчанию для свежесгенерированных ячеек таблицы. */
  defaultCellView: TableViewCellView;
}

Snapshot: зафиксированный результат

snapshot — зафиксированный результат генерации. Содержит готовые строки, столбцы и ячейки, собранные из preset. После генерации snapshot становится самостоятельным: его элементы переименовывают, переставляют, удаляют и переопределяют по отдельности, связь с preset разрывается. Это даёт ручную доводку первоначально выстроеной черзе preset таблицы.

ts
export interface TableViewSnapshot {
  /** Зафиксированные строки оси на момент генерации. */
  rows: TableViewAxisItem[];
  /** Зафиксированные столбцы оси на момент генерации. В режиме `list` не отображаются, но сохраняются. */
  columns: TableViewAxisItem[];
  /** Зафиксированные ячейки таблицы — пересечения строк и столбцов. */
  cells: TableViewCell[];
  /** ISO-метка времени генерации snapshot. */
  generatedAt: string;
}

Строки, столбцы и ячейки

ts
export interface TableViewAxisItem {
  /** Стабильный идентификатор элемента оси; используется в ссылках ячеек snapshot. */
  id: string;
  /** Исходное значение, полученное из объекта по `valuePath` пресета оси. */
  value: string;
  /** Отображаемый текст — значение или ручная подпись из `labelOverrides`. */
  label: string;
}

export interface TableViewCell {
  /** id строки, на пересечении которой стоит ячейка. */
  rowId: string;
  /** id столбца, на пересечении которого стоит ячейка. */
  columnId: string;
  /** id объекта портала в ячейке или `null`, если ячейка пуста. */
  objectId: string | null;
  /** Сохранённый вид ячейки (рендерер); если не задан — берётся `defaultCellView`. */
  view?: TableViewCellView;
}

Mentioned In