Перейти к основному содержимому
Версия: 7.0

Rules: view logic

Правила: формы

Правила форм

  1. Чтобы разместить несколько объектов в одной таблице сразу, ассистенту СЛЕДУЕТ объединить их в одну группу объектов с помощью скобок.

  2. В секции FORM ... ORDERS ассистент ОБЯЗАН использовать только свойства формы, уже добавленные на форму через блок PROPERTIES.

    В ORDERS ассистент ОБЯЗАН указывать одно из:

    • имя свойства формы с его параметрами, если явный алиас не задан
    • явный алиас свойства формы, если такой алиас был указан

    Сырые выражения, объекты или свойства, не добавленные на форму, НЕ ДОЛЖНЫ помещаться в ORDERS.

  3. Ассистент НЕ ДОЛЖЕН использовать INPUT внутри действий, добавленных непосредственно на форму через PROPERTIES, если это действие не используется в обработчике ON CHANGE: значение встроенного класса вводится в редакторе свойства, изменение которого обрабатывается, поэтому вне обработчика изменения его негде отобразить. Исключение — значения файлов и цветов: они вводятся отдельным диалогом, и их МОЖНО запрашивать из любого действия формы.

    Чтобы запросить значения из кнопки, ассистенту СЛЕДУЕТ либо разместить вводимые свойства на самой форме (первичные свойства, в том числе локальные, в панели) и прочитать их в действии, либо открыть диалоговую форму, возвращающую введённые значения (DIALOG с объектами, помеченными INPUT).

  4. Ассистент НЕ ДОЛЖЕН выводить на форму внутренние идентификаторы объектов, в том числе через свойства, значениями которых являются объекты: значение-объект отображается его внутренним идентификатором — числом, ничего не говорящим пользователю.

    Вместо них ДОЛЖНЫ выводиться осмысленные примитивные или производные примитивные / текстовые свойства.

    Самый частый случай — связь со статическим объектом класса-перечисления (status = DATA Status (Project)): заголовок статического объекта платформа сама НЕ подставляет. На форму выводится композиция заголовка — captionStatus 'Статус' = caption(status(p)): запись через композицию уходит в связь, а не в заголовок статического объекта (см. правило 7), и при небольшом числе вариантов, как у перечислений, веб-клиент показывает её элементом выбора (группа кнопок / список / выпадающий список — по числу вариантов и длине заголовков).

  5. Объект PANEL пользовательского класса по умолчанию НЕ выбирается пользователем.

    Если такой объект должен выбираться пользователем (например, параметр фильтра, показанный на форме), ассистент ОБЯЗАН пометить отображаемое свойство этого объекта как SELECTOR в блоке PROPERTIES.

    Без SELECTOR ячейка панели не открывает диалог выбора, и объект нельзя изменить. Ассистент НЕ ДОЛЖЕН предполагать, что ячейка панели редактируема по аналогии с редактированием в таблице.

  6. В блоке PROPERTIES формы стиль параметров у свойства или действия, добавляемого на форму, ДОЛЖЕН соответствовать заголовку блока:

    • С заголовком с общими параметрами PROPERTIES(p1, ..., pN) каждая запись ДОЛЖНА указываться только своим идентификатором — общие параметры связываются неявно. Запись propName(p1, ..., pN) после идентификатора — это ошибка разбора.
    • Без заголовка с общими параметрами (просто PROPERTIES) каждая запись ДОЛЖНА нести явные скобки, например propName(t) с параметрами, либо propName() / actionName() для свойств и действий без параметров. Скобки ОБЯЗАТЕЛЬНЫ, даже когда параметров нет — пустые скобки всё равно ДОЛЖНЫ быть записаны. Голое имя без скобок — это ошибка разбора.

    Ассистент НЕ ДОЛЖЕН смешивать два стиля в одном блоке и НЕ ДОЛЖЕН повторять общие параметры после имени свойства, когда используется заголовок с общими параметрами.

    Это правило применяется только к записи, добавляемой на форму. Списки аргументов внутри опций вроде ON CHANGE actionName(...), READONLYIF expr, BACKGROUND expr и т. д. — это обычные вызовы действий / выражения и ВСЕГДА используют явные параметры, независимо от заголовка блока.

    Записи, чьё выражение несёт запятую, не заключённую в собственные скобки, нужна форма, которую принимает этот блок: без заголовка общих параметров её пишут как алиас = (выражение), потому что голое (выражение) — parse error; с PROPERTIES(o) запись остаётся использованием свойства и после алиас =, выражение там не принимается вовсе, и единственное средство — именованное свойство, добавленное по идентификатору.

  7. Обработка изменения CHANGE по умолчанию у свойства, показанного на форме, выводится не из вида его выражения, а из пути записи: изменяемыми являются первичные свойства, оператор выбора и композиции изменяемых свойств — запись передаётся через композицию в нижележащее изменяемое свойство. Путь записи не виден в месте использования, поэтому ассистент НЕ ДОЛЖЕН предполагать, что вычисляемое на вид свойство нередактируемо.

    Внешне похожие записи при этом редактируются по-разному:

    • композиция через объектную связь (name(customer(o))) — пользователю предлагается выбрать связанный объект, и записывается связь (customer(o)); это обычный способ ввода;
    • атрибут самого объекта строки (name(c)) — введённое значение записывается на месте, то есть объект переименовывается;
    • свойство статического объекта (caption(st)) — запись уходит в хранимый заголовок статического объекта и живёт до очередной синхронизации базы данных с кодом (обычно при старте сервера), которая возвращает заголовок из кода.

    Каждое свойство, показываемое только для чтения, ДОЛЖНО быть явно помечено READONLY — во всех контекстах формы: не только в таблицах списочных форм, но и в панелях, диалогах, дашбордах и графиках. Когда только для чтения показывается весь блок, СЛЕДУЕТ помечать блок целиком (PROPERTIES(o) READONLY ...), а не каждую запись; пометка у отдельной записи остаётся для блоков, где часть записей предназначена для ввода. В контекстах просмотра и выбора каждая запись явно помечается READONLY, кроме записей, сознательно предназначенных для ввода. Явная пометка заодно документирует намерение для читателя кода.

Правила потока управления (WAIT, NOWAIT)

  1. Если не задана ни одна опция, платформа выбирает режим сама: оператор работает синхронно, когда форма открывается в модальном месте, когда модальна форма, из которой его открывают, или когда текущая сессия может использоваться дальше, — и асинхронно в остальных случаях.

    Поэтому два одинаково выглядящих вызова могут вести себя по-разному. Там, где код после вызова зависит от того, что форма закрыта, или, наоборот, должен выполниться не дожидаясь, ассистент ОБЯЗАН сказать это явно — через WAIT или NOWAIT у SHOW, единственного оператора, синтаксис которого их принимает.

    У DIALOG такой опции нет: он синхронен, когда его результат используется, и отдан той же эвристике в остальных случаях. Когда диалог должен блокировать, ассистент добивается этого тем, что использует возвращаемое им значение.

Правила: дизайн форм

  1. Эти правила дизайна НЕ покрывают модель раскладки DESIGN — дерево контейнеров по умолчанию, модель flexbox fill / выравнивания или идиомы контейнеров. Они дают лишь мета-советы по размещению. Перед написанием или изменением любого DESIGN ассистент ОБЯЗАН получить документацию Form_design; он НЕ ДОЛЖЕН полагаться на эти правила так, будто они описывают модель раскладки.

    Полные таблицы свойств компонентов всех видов (контейнеров, компонентов свойств и действий на форме, тулбаров, таблиц) содержатся в документации инструкции DESIGN (DESIGN_statement). Задавая компоненту свойство, ассистент ОБЯЗАН сверить его имя и допустимые значения с этими таблицами, а НЕ ДОЛЖЕН угадывать их по аналогии.

  2. Ассистенту СЛЕДУЕТ задавать DESIGN для всех интерактивных форм, содержащих более четырёх свойств.

  3. Исключение: для тривиальной формы с одним-двумя объектами в режиме GRID и без других свойств, показанных в режиме PANEL, опускание DESIGN допустимо.

  4. В DESIGN ассистенту СЛЕДУЕТ предпочитать перемещение контейнеров BOX(...) для таблиц в первую очередь.

    GRID(...) СЛЕДУЕТ использовать только при крайней необходимости.

  5. По возможности ассистенту СЛЕДУЕТ избегать дизайнов форм с более чем двумя таблицами по вертикали и более чем двумя таблицами по горизонтали.

  6. Кастомные действия, добавляемые на грид-форму (смена статуса, генерация документов, массовые операции), ДОЛЖНЫ получать явный вид TOOLBAR, например PROPERTIES(o) confirmDoc TOOLBAR. Действия по умолчанию имеют вид PANEL, поэтому без TOOLBAR кастомная кнопка рисуется отдельной группой под таблицей, а не в тулбаре грида рядом с предопределёнными NEW / EDIT / DELETE, которым платформа задает тот же вид TOOLBAR, — то есть они делят с ней контейнер TOOLBAR, а не TOOLBARSYSTEM, на чем и промахивается MOVE или REMOVE не того контейнера. Виды свойств / действий: GRID, TOOLBAR, PANEL, POPUP.

  7. Свойство типа TEXT, показанное колонкой грида, отрисовывается многострочной строкой высотой по умолчанию в четыре строки, снижая плотность списка. Такие колонки часто возникают из стандартных строковых свойств (lpad[TEXT, INTEGER, TEXT], substr[TEXT, INTEGER, INTEGER], trim[TEXT] и остальных): они, как правило, возвращают TEXT независимо от классов аргументов, и конкатенация операнда класса TEXT с ограниченной строкой — тоже TEXT. На списочных формах ассистенту СЛЕДУЕТ вместо него выставлять значение, приведённое к STRING[n]. Запись с приведением подчиняется правилам записей-выражений: в блоке PROPERTIES без заголовка с общими параметрами и с явным алиасом (shortNote = STRING[100](note(o))). Голое приведение без алиаса, как и любое выражение внутри блока с заголовком общих параметров PROPERTIES(o), — ошибка разбора; там объявите именованное свойство с приведением и добавьте его по идентификатору.

  8. Для отображения данных ассистент ДОЛЖЕН сначала рассматривать стандартные виды представления группы объектов: таблицу, сводную таблицу с её диаграммами (PIVOT), календарь (CALENDAR), карту (MAP). Пользовательское представление на компоненте React — контейнер в DESIGN с атрибутом custom; только веб-клиент, десктоп-клиент отрисовывает обычное поддерево контейнера — применяется, когда требуется что-то сверх простой таблицы, простого календаря, простой диаграммы или сводной таблицы: канбан-доска, расписание, лента карточек, схема рассадки, перетаскивание, которого нет в стандартных видах, нестандартная раскладка или интерактивность. Перед созданием такого представления ассистент ОБЯЗАН получить документацию How-to_Custom_React_views.

  9. FALSE допустим в логических атрибутах блока DESIGNdefaultComponent, activated и подобных, — потому что их значения являются литералами, а не выражениями. Правило ядра, запрещающее FALSE, касается только выражений, и его НЕ ДОЛЖНО применять здесь, переписывая на NULL.

Правила: навигатор

  1. Папка, потомки которой должны появляться только при её выборе, ОБЯЗАНА размещать этих потомков в другом окне, чем сама папка (как правило, WINDOW toolbar). В горизонтальном тулбаре, таком как System.root, папка, оставляющая потомков в своём окне, ничего не переключает — они показываются расплющенными рядом с ней, и выбор папки ничего не делает. Вертикальный тулбар, наоборот, отображает потомков из того же окна как вложенную группу под папкой, поэтому там отдельное окно не требуется.

Правила: отчёты

  1. Прежде чем проектировать или править jrxml-шаблоны отчётов либо рассуждать о структуре отчёта или именовании шаблонов, ассистент ОБЯЗАН получить документацию Report_design; он НЕ ДОЛЖЕН полагаться на эти правила как на справочник по формату шаблона или раскладке.

  2. Когда у формы нет независимых друг от друга групп объектов (все группы образуют единую цепочку зависимостей), по умолчанию создаётся ТОЛЬКО ОДИН jrxml-шаблон, называемый по каноническому имени формы (пространство имён + имя формы, каждая . заменяется на _) БЕЗ постфикса — единственный потомок группы сливается с ней.

    Единственный шаблон получается именно из-за слияния, поэтому разработчик может его и отключить: опция SUBREPORT у дочерней группы объектов не даёт слить её с родительской, и такой группе нужен собственный шаблон с постфиксом _<группа>. Поэтому ассистент ОБЯЗАН читать блоки объектов формы, а не только форму её зависимостей: линейной цепочке с SUBREPORT внутри нужен не один шаблон, а отсутствие хотя бы одного молча отбрасывает их все (правило 3).

  3. Ассистент ОБЯЗАН именовать каждый шаблон точно: верхний отчёт — по каноническому имени формы без постфикса, каждый подотчёт — по каноническому имени формы плюс постфикс _<группа> его первой непустой группы объектов. Если хоть у одного шаблона имя неверно (с точки зрения платформы не найден), платформа молча откатывается к полностью автоматическому дизайну на ВЕСЬ отчёт, без ошибки в логах, — то есть единственное несовпадение молча отбрасывает все кастомные шаблоны.

Правила: интернационализация

  1. Ассистент ОБЯЗАН использовать файлы *ResourceBundle.properties для локализации UI.

    Значение внутри {...} ДОЛЖНО трактоваться как ключ поиска, который lsFusion разрешает согласно текущей локали.

  2. Ассистент ОБЯЗАН сначала определить, используется ли обратный перевод в текущей области проекта.

    Если используется, ассистент ОБЯЗАН продолжать его использовать в этой области и ОБЯЗАН следовать существующей политике проекта.

    Ассистент ОБЯЗАН сохранять выбор идентификаторов согласованным с уже установленным там паттерном.

    Ассистент НЕ ДОЛЖЕН вводить новую явную политику идентификаторов, если этого не просит пользователь.

  3. Обратный перевод означает перевод в направлении, обратном обычной локализации UI: не ключ -> локализованный текст, а локализованный текст -> ключ, и затем, при необходимости, в другую локаль.

    Если идентификаторы не заданы в коде явно, этим каноническим значением является сам текст на исходном языке. Это то, что платформа ИЩЕТ, а не то, что она хранит ключом: запись остается id = исходный текст, а словарь, строящийся для поиска, — обратный, значение -> id. Ассистент, записавший бандл наоборот, получит записи, с которыми обратный перевод никогда не совпадет.

  4. Обратный перевод включается параметром запуска, задающим язык строковых литералов lsf-кода (logics.lsfStrLiteralsLanguage). Когда он активен, ЛЮБОЙ обычный литерал '...' в позиции, допускающей локализацию, — в том числе литерал-константа в любом выражении, — совпавший со значением записи ResourceBundle, при разборе кода молча заменяется на её ключ {id} и в рантайме подставляется в текущей локали: 'position' может стать 'pozycja'. Ведущие и конечные пробелы в сопоставлении не участвуют и сохраняются вокруг подстановки; литерал пустой или состоящий из одних пробелов не заменяется никогда.

    Поэтому технические литералы — ключи JSON, URL, форматы, канонические имена, внешние идентификаторы — ассистент ОБЯЗАН записывать сырыми литералами r'...', которые не участвуют ни в локализации, ни в обратном переводе. Обычные литералы '...' предназначены для текста, видимого пользователю.