Демоприложение Один плюс один, разработка ПО Логотип
Презентация 03

Слой интерфейса
UI + App/ButtonClicked

Движок, который превращает сущность в полноценный экран управления, — и один серверный метод на каждую страницу.

TableMakerEx<T> — универсальный экран управления

// 1. класс таблицы (DemoApp/Tables)
public class CarsTable : TableMakerEx<Car>
{
    public CarsTable()
    {
        this["Color"].HeaderText = "Цвет";
        this["Color"].Filterable = true;
    }
}

// 2. одна строка в HTML страницы
<div id="CarsTable" class="table"></div>
  • Столбцы выводятся автоматически из [Column] сущности.
  • Бесплатно получаем: таблицу, сортировку по клику на заголовок, постраничный вывод, форму добавления, редактирования и удаления, экспорт и импорт.
  • Имя div = имя класса; ClassManager находит его по этому имени.

Как это работает?

div.table + JS tablemaker.js api/tablemaker/GetTable CarsTableGetTableAsync → HTML
  • JS отправляет имя класса + сортировку, фильтр и номер страницы; сервер возвращает готовый HTML или строки для обновления.
  • Сохранение формы: SaveFormSaveFormAsyncSaveAsync самой сущности. Всё асинхронно.

Универсальная панель фильтров

this["IsAutomatic"].Filterable = true;              // флажок → да/нет/все
this["Grade"].Filterable = true;
this["Grade"].DataSource = new[] {1,2,3,4,5,6,7,8}; // → выпадающий список
this["Color"].Filterable = true;                    // текст → точное совпадение
  • Поле свободного поиска ищет по всем текстовым столбцам (LIKE с параметрами).
  • Любое изменение фильтра обновляет таблицу без перезагрузки страницы.
  • Реализация — в одном универсальном BuildFilter: отдельного кода фильтрации для экрана не существует.

Специальные поля — UIField

  • ImageField — загрузка изображения перетаскиванием, сохраняется в JPG по идентификатору записи.
  • ColorField — выбор цвета с образцом прямо в таблице.
  • ButtonUiField / LinkUiField / IconUiField — действие в каждой строке.
  • ListField<P> — множественный выбор связанных сущностей (флажки).
  • Декларативная валидация: IsMandatory, RegExp, собственные сообщения — проверяется на стороне клиента.

Шаблон App + ButtonClicked

// каждая страница = метод, возвращающий ReturnDetails
public ReturnDetails Cars() => AdminPage("Cars");

// кнопка в HTML — без onclick:
<button id="Cars">Автомобили</button>
// id кнопки = имя метода, который выполнится на сервере
  • Одна конечная точка: api/app/ButtonClicked.
  • ReturnDetails сообщает клиенту, что делать: html для вставки, popUp, script, наполнение списка…
  • Состояние приложения возвращается клиенту зашифрованным и сжатым (ProtectAppState) — любая подмена обнаруживается сразу.
  • Полноценная история браузера: у каждой страницы свой URL, включая прямой вход (deep-link).

Новый экран — чек-лист

  1. Сущность в BLL: class Invoice : Record с [Column].
  2. Таблица: class InvoicesTable : TableMakerEx<Invoice> — заголовки на нужном языке + Filterable.
  3. Страница: Pages/Invoices.html с <div id="InvoicesTable" class="table">.
  4. Метод: public ReturnDetails Invoices() => AdminPage("Invoices");
  5. Кнопка в меню: <input type="button" id="Invoices" value="Счета">

Пять шагов, ноль SQL, ноль JavaScript — вот и вся история.