MastermindCMS2 – Теги

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Эта статья продолжение статьи MastremindCMS2 - Как начать?. В ней я рассказывал как установить и настроить community-версию "безголовой" MastermindCMS2.

В этой статье речь пойдет о специальных тегах, которые вы можете использовать для сборки динамических шаблонов в MastermindCMS2.

За свою карьеру программиста я видел множество разных технологий и фреймворков от гигантов индустрии, таких как Oracle, Microsoft, IBM и т. п. Но в каждом из них было какое-то неудобство. А конкретнее у них у всех было одно общее, это необходимость реализовывать серверную логику чтобы можно было использовать ее в шаблонах. И это мне сильно не нравилось, приходилось делать одну и ту же работу из проекта в проект.

Один из таких подходов разнесения логики был паттерн программирования MVVM(Model-View-ViewModel). Его активно продвигали во фреймворках для C#. Структурно с точки зрения разнесения логики, я считаю этот паттерн самым удобным.

Когда я поставил задачу себе разработать удобный фреймворк для работы, то у меня в голове был только один концепт реализации. Который содержал в основе именно MVVM, но я не считал, что это то, что я хочу получить в итоге. Так как проблема написания серверной логики оставалась открытой. И я поставил себе задачу спроектировать фреймворк так чтобы не нужно было каждый раз писать бэк для очередного проекта. Ведь грубо говоря, мы с вами коллеги, решаем одни и те же задачи для разных проектов. Авторизация, управление каталогом продуктов, отправка писем по электронной почте, чаты и прочая энтерпрайз муть. Соответственно опираясь на эти задачи, я начал думать, что нужно сделать чтобы напрямую оперировать с этим на бэке. В результате я решил писать логику парсинга шаблонов на беке, а фронтенд часть делать гибкой и независимой.

Первым шагом я продумал маршрутизацию для обработки HTTP-запросов. Основной задачей было сделать обработку GET-запроса и при этом достать шаблон, где уже будет логика, состоящая из кастомных тегов, которые динамически соберут валидный HTML и отдадут его назад.

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

  • Разбиение визуальных блоков на компоненты, и подключение их на страницы

  • Получение данных со сторонних микро-сервисов и отображение их на странице

  • Итеративное отображение данных

  • Отображения одиночных объектов из базы данных

  • Логические операции и отрисовка данных на основе выполнения условия отображения

  • Отображение данных в виде дерева

  • Расширение возможностей отображения выпадающего списка на основе HTML-элемента select

  • Отображение текстовых данных напрямую из базы данных

И в итоге я получил 8 специальных тегов которые решают вышеописанные задачи. А теперь по порядку я расскажу на примере этих задач как можно проектировать страницы с использованием тегов фреймворка MastermindCMS2.

Подключение фрагмента

Разработка фронтенд-приложения на MastermindCMS2 не отличается ничем от принципов разработки на других фреймворках. Фронтенд часть полностью автономна, и вам не нужно собирать приложение для того чтобы бекенд-логика заработала у вас в приложении. Вот несколько шагов демонстрирующих принципы разработки на нашей headless-cms.

<msm:fragment>- тег предназначен для использования внешних фрагментов HTML-кода для подключения их на страницы.

  1. Для начала создадим новый файл.

    Создание нового HTML-файла
    Создание нового HTML-файла
  2. Скопируем все содержимое страницы в новый файл

    Копирование HTML
    Копирование HTML
  3. Далее мы удалим некоторые части HTML, для того чтобы их перенести отдельно во внешние фрагменты.

    Убираем навигационное меню и основную часть страницы
    Убираем навигационное меню и основную часть страницы
  4. Обратимся к документации на сайте MastermindCMS2. Для примера мы используем <msm:fragment>

    Описание MSM Fragment Tag
    Описание MSM Fragment Tag
  5. <msm:fragment id="navbar" path="admin/components/navbar.html"/> - этот код вам нужно добавить на страницу

  6. Создаем новый файл для фрагмента.

    Перенос HTML для навигационной панели в отдельный файл
    Перенос HTML для навигационной панели в отдельный файл
  7. Подключаем созданный нами фрагмент на страницу.

    Подключение фрагмента HTML на страницу
    Подключение фрагмента HTML на страницу

Запросы на внешний REST API

<msm:rest>- тег предназначен для выполнения запроса на внешний ресурс, который доступен по REST API и возвращает данные в виде JSON.

Пример запроса который получает ответ в виде объекта
Пример запроса который получает ответ в виде объекта
Пример запроса который получает ответ в виде массива
Пример запроса который получает ответ в виде массива

Исходный код:

    <div class="container">
        <h1>Star Wars Ships</h1>
        <ul id="starWarsRestApiWrapper1" class="container">
            <msm:rest id="starWarsRestApi"
                      endpoint="https://swapi.dev/api/starships/9/?format=json"
                      request="{}" method="GET" item-name="ship">
                <msm:template><li>${ship|name}</li></msm:template>
            </msm:rest>
        </ul>
        <h1>Locations</h1>
        <ul id="locationsApiWrapper2" class="container">
            <msm:rest id="locationsApi"
                      endpoint="https://ghibliapi.herokuapp.com/locations"
                      request="{}" method="GET" item-name="loc">
                <msm:template><li>${loc|value.name}</li></msm:template>
            </msm:rest>
        </ul>
    </div>

Итерирование - цикл foreach

msm:foreach - тег позволяет сделать итерацию по элементам и отобразить их как повторяющийся HTML-элемент, который определен во вложенном теге msm:template.

Пример использования тега Foreach
Пример использования тега Foreach
Вид объектов в базе данных
Вид объектов в базе данных

Исходный код:

<form>
    <div class="form-group">
        <label for="inputFirstName">First Name</label>
        <input type="text" class="form-control" name="firstName" id="inputFirstName" autocomplete="off" placeholder="First Name">
    </div>
    <div class="form-group">
        <label for="inputLastName">Last Name</label>
        <input type="text" class="form-control" name="lastName" id="inputLastName" autocomplete="off" placeholder="Last Name">
    </div>
    <div class="form-group form-check">
        <input type="checkbox" class="form-check-input" name="status" value="false" id="checkStatus">
        <label class="form-check-label" for="checkStatus">Check me out</label>
    </div>
    <button type="button" class="btn btn-primary" onclick="app.addDocumentAndRender('foo','custom-users',this)">Submit</button>
</form>

<div id="userListWrapper" class="row gx-lg-5">
    <msm:foreach id="userList"
                 database="foo"
                 collection="custom-users"
                 filter="{}"
                 mode="DATABASE"
                 item-name="user">
        <msm:empty>
            <p>No users</p>
        </msm:empty>
        <msm:template>
            <div class="col-lg-6 col-xxl-4 mb-5">
                <div class="card bg-light border-0 h-100">
                    <div class="card-body text-center p-4 p-lg-5 pt-0 pt-lg-0">
                        <div class="feature bg-primary bg-gradient text-white rounded-3 mb-4 mt-n4"><i class="bi bi-collection"></i></div>
                        <h2 class="fs-4 fw-bold">${user|firstName} ${user|lastName}</h2>
                        <p class="mb-0">${user|_id}</p>
                    </div>
                </div>
            </div>
        </msm:template>
    </msm:foreach>
</div>

Отображение объектов - элемент block

msm:block - тег позволяет выводить объект на основе определенного HTML-элемента внутри вложенного тега msm:template.

В этом примере видно как входящий параметр от внешнего тега может быть использован на внутренних тегах:

<div id="userBlockWrapper">
    <msm:block id="userBlock"
               value="{  fullName: '${user|firstName} ${user|lastName}', movie : 'Last Hope'}"
               item-name="usr">
        <msm:template><h6 style="text-align:center">${usr|fullName} - ${usr|movie}</h6></msm:template>
    </msm:block>
</div>

Исходный код:

<div id="userListWrapper" class="row gx-lg-5">
    <msm:foreach id="userList"
                 database="foo"
                 collection="custom-users"
                 filter="{}"
                 mode="DATABASE"
                 item-name="user">
        <msm:empty>
            <p>No users</p>
        </msm:empty>
        <msm:template>
            <div class="col-lg-6 col-xxl-4 mb-5">
                <div class="card bg-light border-0 h-100">
                    <div class="card-body text-center p-4 p-lg-5 pt-0 pt-lg-0">
                        <div class="feature bg-primary bg-gradient text-white rounded-3 mb-4 mt-n4"><i class="bi bi-collection"></i></div>
                        <h2 class="fs-4 fw-bold">${user|firstName} ${user|lastName}</h2>
                        <p class="mb-0">${user|_id}</p>
                    </div>
                    <div id="userBlockWrapper">
                        <msm:block id="userBlock"
                                   value="{  fullName: '${user|firstName} ${user|lastName}', movie : 'Last Hope'}"
                                   item-name="usr">
                            <msm:template><h6 style="text-align:center">${usr|fullName} - ${usr|movie}</h6></msm:template>
                        </msm:block>
                    </div>
                </div>
            </div>
        </msm:template>
    </msm:foreach>
</div>

Логический оператор "если"

msm:if - тег позволяет выводить объект на основе условия, которое будет проверяться в атрибуте test.

Для примера изменим свойство в объектах следующим образом:

Пример данных для анализа условия
Пример данных для анализа условия
Пример использования тега msm:if
Пример использования тега msm:if

Исходный код:

<div id="userListWrapper" class="row gx-lg-5">
    <msm:foreach id="userList"
                 database="foo"
                 collection="custom-users"
                 filter="{}"
                 mode="DATABASE"
                 item-name="user">
        <msm:empty>
            <p>No users</p>
        </msm:empty>
        <msm:template>
            <div class="col-lg-6 col-xxl-4 mb-5">
                <div class="card bg-light border-0 h-100">
                    <div class="card-body text-center p-4 p-lg-5 pt-0 pt-lg-0">
                        <div class="feature bg-primary bg-gradient text-white rounded-3 mb-4 mt-n4"><i class="bi bi-collection"></i></div>
                        <h2 class="fs-4 fw-bold">${user|firstName} ${user|lastName}</h2>
                        <p class="mb-0">${user|_id}</p>
                    </div>
                    <div id="showUserBlockWrapper">
                        <msm:if id="showUserBlock" test="${user|status}">
                            <div id="userBlockWrapper">
                                <msm:block id="userBlock"
                                           value="{  fullName: '${user|firstName} ${user|lastName}', movie : 'Last Hope'}"
                                           item-name="usr">
                                    <msm:template><h6 style="text-align:center">${usr|fullName} - ${usr|movie}</h6></msm:template>
                                </msm:block>
                            </div>
                        </msm:if>
                    </div>
                </div>
            </div>
        </msm:template>
    </msm:foreach>
</div>

Отображение элемента в виде дерева

msm:tree - тег позволяет выполнить итерацию по элементам и отобразить их в виде древовидной HTML-структуры. Каждый вложенный элемент, имеющий подэлементы, должен содержать свойство children для отображения в виде элемента вложенного поддерева. Элемент для элемента итерации определяется во вложенном теге msm:template.

Исходный код:

<div class="dd" id="product-groups-tree">
    <msm:tree id="productGroups"
              database="msm2-application"
              collection="categories"
              filter="{}"
              mode="DATABASE" item-name="cat">
        <msm:template>
            <ol class="dd-list">
                <li class="dd-item dd3-item" data-id="${cat|id}" data-name="${cat|name}">
                    <div class="dd-handle dd3-handle"></div>
                    <div class="dd3-content">
                        <a href="#product-group/view/${cat|id}" class="truncate">${cat|name}</a>
                    </div>
                    <a class="dd3-right-handle modal-trigger" href="#remove-pgroup-dialog" data-item-id="${cat|id}"></a>
                </li>
            </ol>
        </msm:template>
    </msm:tree>
</div>

Выпадающий список

msm:select - тег выполняет рендеринг для на основе определения HTML-шаблона во вложенном теге msm:template в качестве дочернего элемента.

Исходный код:

<div id="selectTagWrapper" class="root">
    <msm:select id="selectTag"
                database="foo"
                collection="custom-users"
                filter="{}"
                selected="Darth"
                mode="DATABASE" item-name="option" class="select-file-types">
        <msm:template><option class="item" value="${option|firstName}" ${option|selected}>${option|firstName} ${option|lastName}</option></msm:template>
    </msm:select>
</div>

Получение текстовых значений из базы данных

msm:text - тег позволяет отображать свойства объекта в виде текста, который определяется согласно шаблону объявленному внутри.

<div id="textTagWrapper">
    <msm:text id="textTag"
              bean="dummyBean"
              function="getDummyUser"
              scope="PROTOTYPE"
              mode="BEAN" item-name="emp">
        ${emp|name} - ${emp|age}
    </msm:text>
</div>

Заключение

Все 8 специальных тегов были рассмотрены в статье с примерами. Я пострарался максимально подробно рассказать как все-таки это работает. В следующей статье я расскажу как использовать эти теги в связке с JavaScript-частью от данной технологии. Дата-байдинг, роутинг уже реализованы на уровне фреймворка, поэтому вам не придется писать тонны JS чтобы сделать интеграции с базой данных, и вам не нужно писать бэкенд часть для REST API. Основные все инструменты уже реализованы в фреймворке.

Как обычно напишу планы на развитие данной технолгии. Я думаю основной задачей для меня сейчас, стоит задача это создание маркетплейса для всех программистов, которые смогут там продавать свой модули и шаблоны написанные на этом фреймворке.

Я делюсь этой информацией тут, потому-что я хочу чтобы рутинная разработка веб-приложений превратилась в искусство шаблонизации. Где вы можете собрать в короткие сроки сложные платформы с поиском и интеграциями как простой конструктор LEGO.

Я делюсь с вами прежде своим инструментом, который мне сейчас позволяет работать быстрее и эффективнее. Но без вас я не смогу сделать это. И это хоть на грамм, на капельку сделает нашу жизнь программиста проще.

Спасибо что дочитали мою статью до конца, продолжение следует...

Источник: https://habr.com/ru/post/581584/


Интересные статьи

Интересные статьи

Внимание! Если данная статья наберет 1000 положительных голосов, то я организую хакатон по алготрейдингу с ценными призами.Предыдущая статья о "Расчете дневного изменения...
Процесс знакомства с компаниями, прохождения многочисленных cобеседований и технические интервью порой очень утомителен и вызывает много стресса как у кандидатов, так и у...
Среди советов по улучшению юзабилити интернет-магазина, которые можно встретить в инете, один из явных лидеров — совет «сообщайте посетителю стоимость доставки как можно раньше».
Тема статьи навеяна результатами наблюдений за методикой создания шаблонов различными разработчиками, чьи проекты попадали мне на поддержку. Порой разобраться в, казалось бы, такой простой сущности ка...
Основанная в 1998 году компания «Битрикс» заявила о себе в 2001 году, запустив первый в России интернет-магазин программного обеспечения Softkey.ru.