Система управления порталом (ЦМС)
Система управления порталом или ЦМС (от англ. CMS — Content Management System) — система управления сайтом, позволяющая обычному пользователю обновлять содержимое без привлечения программиста.
CMS могут быть коммерческими и бесплатными, с открытым кодом и созданными для конкретного веб-проекта — видов много, многие пересекаются, поэтому точная классификация затруднительна.
Содержание
Модуль «Система управления порталом» в Nemo.Travel
Модуль позволяет пользователю сконструировать веб-сайт, на котором возможно размещать текстовые, графические, мультимедийные и иные материалы и управлять ими. Система позволяет управлять содержимым, шаблонами вывода содержимого, макетами и шаблонами макетов, задавать сопоставление оформления функциональным страницам системы бронирования.
Упрощенная структура CMS Nemo.Travel
Функционально CMS состоит из 2-х частей:
- Административная часть
- Фронт-энд
Административная часть имеет привязку к агентству, зарегистрированному в рамках системы бронирования, и закрыта от доступа посторонних лиц. С помощью административной панели авторизованный пользователь имеет возможность редактировать контент, изменять структуру сайта и настраивать его связь с компонентами Nemo.Travel.
Фронт-энд, в свою очередь, отвечает за формирование потока HTML для просмотра его браузером конечного пользователя.
Административная панель CMS
Административная часть CMS состоит из 2-х независимых функциональных блоков:
Также здесь присутствует блок настроек для связи CMS с другими системами.
Функции CMS
Основной конечной функцией CMS является формирование законченных HTML-документов определенной структуры, наполненных произвольным контентом и доступных для просмотра с помощью WEB-браузера.
Для обеспечения данной функциональности CMS реализует следующие функции:
- Организация закрытого административного раздела в рамках системы Nemo.Travel;
- Механизм привязки CMS к определенному агентству;
- Настройки сайта и интеграция с системой Nemo.Travel;
- Создание и редактирование пользовательского контента;
- Создание и редактирование структуры сайта, блоков контента;
- Создание и редактирование шаблонов;
- Формирования выходного потока в формате HTML на основе структуры сайта и пользовательского контента.
Доступ пользователей
Полным доступом к управляющей части CMS обладает менеджер агентства. Также существует возможность предоставления доступа к разделам редактирования содержательной части сайта (контента) произвольным пользователям, зарегистрированных в данном агентстве.
Распределением доступа занимается менеджер агентства.
Последовательность предоставления доступа к CMS следующая:
- Необходимо войти в систему под учетной записью менеджера агентства.
- С помощью административной панели «Аккаунт менеджмент» → «Агенты и пользователи» → «Управление» создать нового пользователя, для которого планируется предоставлять доступ.
- Перейти в раздел CMS «Управление сайтом» → «Nemo CMS» → «Менеджеры контента», а данном разделе отображается список пользователей, которым разрешено изменять контент сайта агентства.
- Нажать кнопку «Добавить пользователя» и перейти по ссылке «Выбрать».
- Во всплывающем окне нажать мышью на учетной записи пользователя, созданного в п. 2. (незарегистрированным пользователям и группам доступ не предоставляется).
- Нажать кнопку «Создать» в форме добавления пользователя.
На этом процесс распределения доступа завершен. Чтобы проверить работоспособность, необходимо выйти из системы и зайти под учетной записью пользователя, созданного в п.2 и использованного в п.5 соответственно. При переходе в административную панель пользователь получает доступ к разделам CMS «Управление сайтом» → «Nemo CMS» → «Менеджер файлов» для редактирования файлового хранилища сайта агентства и «Управление сайтом» → «Nemo CMS» → «Модули» для управления контентом.
Из соображений обеспечения безопасности и структурной целостности, доступ к остальным разделам CMS для рядовых пользователей запрещен.
Сокращение путей
Для вывода содержимого контента по переменной можно использовать ссылки такого формата:
http://domain/?go=content&page=1&article=2
где «page=1» — указание макета страницы, «article=2» — вывод статьи с ID=2 (имя переменной article задается в свойствах элемента, отвечающего за вывод).
Однако можно использовать и следующий равнозначный формат:
http://domain/1__article__2.html
где «1» — ID макета страницы, «2» — значение переменной article.
Внимание! Использовано двойное нижнее подчеркивание.
Если определен макет страницы по умолчанию и нет необходимости добавлять его в адрес, то можно вместо
http://domain/?go=content&article=1
использовать
http://domain/article__1.html
При работе с модулем «Страницы контента» можно использовать алиасы для короткого именования страниц. Предположим, имеется страница с алиасом (псевдонимом) about. Тогда для вывода этой страницы можно использовать или полную форму:
http://domain/?go=frontend&page=about
или сокращенную
http://domain/about.html
Сокращение путей страниц с выводом системы бронирования
Для вывода на странице контента элемента движка и произвольного контента необходимо использовать URL определенного вида.
http://domain/?go=search/index&source=frontend&page=home
Здесь:
- «search/index» — имя контроллера и действия системы бронирования (форма поиска авиабилетов);
- «source=frontend» — переменная, указывающая на то, что необходимо использовать функционал модуля контентных страниц;
- «page=home» — алиас контентной страницы (можно также указать ее ID, например page=123);
Элемент с движком на странице нужен только в том случае, если к странице подключен макет без элемента с движком, иначе на странице будет сразу две формы поиска.
Для страницы с алиасом home и формой поиска авиабилетов на ней можно использовать короткую ссылку вида
http://domain/avia_home
где «home» — алиас страницы контента.
Внимание! Вместо алиасов допускается использовать ID страниц контента.
Внимание! Для страниц с формой поиска отелей можно использовать префикс hotel_
Краткий пример по разворачиванию ЦМС
1) В разделе "Управление сайтом - Nemo CMS - Шаблоны" создаем шаблон блока. https://drive.google.com/file/d/0B2geuk8VO4nOdjd1VDFQcDU1YWs/view?usp=sharing
block.generic.tpl
{foreach from=$elements item=element}{cms_render_element id=$element.id}{/foreach}
2) В разделе "Управление сайтом - Nemo CMS - Блоки элементов" создаем 3 блока: блок шапки, блок контента и блок подвала. Для всех блоков используется "Шаблон блока", пример: https://drive.google.com/file/d/0B2geuk8VO4nOYkp2bmhPTlFqR3c/view?usp=sharing
3) В разделе "Управление сайтом - Nemo CMS - Шаблоны" создаем шаблон страницы. https://drive.google.com/file/d/0B2geuk8VO4nON2h0RnVRM1NUVE0/view?usp=sharing
page.generic.tpl
{foreach from=$global item=item key=key}{assign var=$key value=$item}{/foreach} {if $go == 'search/index' || $go == 'search/view_results'} <div class="nemo-common-pageWrapper"> {cms_render_block id=1} {cms_render_block id=2} </div> {cms_render_block id=3} {else} <div class="{if $go != "poffice/table" && $go != 'poffice/exare_table' && $go != "pomessage/inbox" && $go != 'pomessage/create' && $go != 'pomessage/fromtpl' && $go != 'pomessage/index' && $go != 'pomessage/reply' && $go != 'pomessage/search' && $go != 'pomessage/show' && $go != 'pomessage/sent' && $go != 'pomessage/from_orders' && $go != 'pomessage/agency_messages' && $go != "poffice/my_passengers" && $go != 'poclaim/list' && $go != "poclaim/show" && $go != 'poffice/finances' && $go != 'poffice/finances_log' && $go != "base/user_settings" && $go != "base/mini_agency_settings"}pro-wrapper js-pageWrapper pro-wrapper_wide{else} nemo-common-pageWrapper nemo-common-po{/if}"> {cms_render_block id=1} {if $go != "poffice/bookinfo" && $go != "poffice/table" && $go != "poffice/exare_table" && $go != 'pomessage/inbox' && $go != 'pomessage/create' && $go != 'pomessage/fromtpl' && $go != 'pomessage/index' && $go != 'pomessage/reply' && $go != 'pomessage/search' && $go != 'pomessage/show' && $go != 'pomessage/sent' && $go != 'pomessage/from_orders' && $go != 'pomessage/agency_messages' && $go != "poffice/my_passengers" && $go != 'poclaim/list' && $go != "poclaim/show" && $go != 'poffice/finances' && $go != 'poffice/finances_log' && $go != "base/user_settings" && $go != "base/mini_agency_settings"} {assign var=needWrapper value=true} {/if} {if $needWrapper}<div class="pro-wrapper">{/if} {cms_render_block id=2} {if $needWrapper}</div>{/if} </div> {cms_render_block id=3} {if}
{cms_render_block id=1} идентификатор блока нужно посмотреть в разделе "Управление сайтом - Nemo CMS - Блоки элементов", в примере выше 1 - шапка, 2 - контент, 3 - подвал.
4) В разделе "Управление сайтом - Nemo CMS - Шаблоны" создаем шаблон шапки. https://drive.google.com/file/d/0B2geuk8VO4nOUkZ5NDZwelVDaUk/view?usp=sharing
module.textsystem.single.header.tpl
{foreach from=$global item=item key=key}{assign var=$key value=$item}{/foreach} {* Loading registration forms *} {registrationForms} {getCurrencyConverterData} <div class="nemo-common-mobileControl nemo-common-mobileControl_links js-nemo-mobileControl js-nemo-mobileControl_links"> <div class="nemo-common-mobileControl__pseudoHeader"> <div class="nemo-common-mobileControl__pseudoHeader__close js-nemo-mobileControl__close"></div> <div class="nemo-common-mobileControl__pseudoHeader__options js-nemo-mobileControl__toOptions"></div> <div class="nemo-common-mobileControl__pseudoHeader__title js-nemo-mobileControl__title"></div> </div> <div class="nemo-ui-subContainer nemo-common-mobileControl__sideblock"> <div class="nemo-common-mobileControl__sideblock__user"> {if $info_user_status == 'gst'} {if $mode_auth_form} <button class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__sideblock__user__button js-header-auth_adaptive"> {'new-header-enter'|language} </button> {else} <a href="{go_and_back controller='authorization' action='auth_client'}" class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__sideblock__user__button"> {'new-header-enter'|language} </a> {/if} {if isset($registrationFormsData.b2c)} <a href="/{url controller='authorization' action='registration' get=''}" class="{if $registrationFormsData.b2c->popup}nemo-ui-pseudoLink js-header-register_adaptive {/if}nemo-common-pageHeader__inner__headerLinks__item"> {'new-header-registration'|language} </a> {/if} {else} <div class="nemo-common-mobileControl__sideblock__user__name"> {$info_name} {$info_surname} {$info_login} {if $info_user_status !== 'usr'} ({$info_user_status|language}) {/if} </div> {strip} {if !$hide_poffice} <a class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__sideblock__user__button" href="/{url controller="poffice" action="table"}">{'new-header-privateOffice'|language}</a> {/if} <a class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__sideblock__user__button" href="/{url controller="settings" action="dashboard"}" target="_blank">{'new-header-settings'|language}</a> <a class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__sideblock__user__button" href="/{go_and_back controller='authorization' action='logout'}">{'new-header-logout'|language}</a> {/strip} {/if} {if $show_booking_status_check} <a href="/{url controller='booking' action='status'}" class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__sideblock__user__button js-header-checkOrder_adaptive"> {'new-header-checkBookStatus'|language} </a> {/if} </div> {if in_array('FLIGHTS', $enabled_components)} {if $current_component != 'FLIGHTS'} <a class="nemo-common-mobileControl__sideblock__componentLink" href="/avia"> {'header.components_menu--flights'|language} </a> {else} <span class="nemo-common-mobileControl__sideblock__componentLink nemo-common-mobileControl__sideblock__componentLink_active">{'header.components_menu--flights'|language}</span> {/if} {/if} {if in_array('HOTELS', $enabled_components)} {if $current_component != 'HOTELS'} <a class="nemo-common-mobileControl__sideblock__componentLink" href="/hotels"> {'header.components_menu--hotels'|language} </a> {else} <span class="nemo-common-mobileControl__sideblock__componentLink nemo-common-mobileControl__sideblock__componentLink_active">{'header.components_menu--hotels'|language}</span> {/if} {/if} {if in_array('TRAINS', $enabled_components)} {if $current_component != 'TRAINS'} <a class="nemo-common-mobileControl__sideblock__componentLink" href="/trains"> {'header.components_menu--trains'|language} </a> {else} <span class="nemo-common-mobileControl__sideblock__componentLink nemo-common-mobileControl__sideblock__componentLink_active">{'header.components_menu--trains'|language}</span> {/if} {/if} </div> </div> <div class="nemo-common-mobileControl nemo-common-mobileControl_options js-nemo-mobileControl js-nemo-mobileControl_options"> <div class="nemo-common-mobileControl__optionsInner"> <div class="nemo-common-mobileControl__optionsBlock js-nemo-mobileControl__optionsBlock js-nemo-mobileControl__optionsBlock_selector"> {assign var=locale_up value=$locale|upper} <div class="nemo-ui-subContainer nemo-common-mobileControl__optionsBlock__options"> <div class="nemo-common-mobileControl__optionsBlock__option" data-block="userInfo"> <span class="nemo-common-mobileControl__optionsBlock__option__value"> {strip} <a href="/profile"> {if $info_name} {$info_name} {elseif $info_surname} {$info_surname} {else} {$info_login} {/if} </a> {/strip} {if $info_user_status !== 'usr'} ({$info_user_status|language}) {/if} </span> </div> <div class="nemo-common-mobileControl__optionsBlock__option js-nemo-mobileControl__optionsBlock__selector" data-block="language"> <span class="nemo-common-mobileControl__optionsBlock__option__additional">{'new-header-mobileOptions__change'|language}</span> <span class="nemo-common-mobileControl__optionsBlock__option__value"> {'lang_'|cat:$locale_up|language} </span> </div> <div class="nemo-common-mobileControl__optionsBlock__option js-nemo-mobileControl__optionsBlock__selector" data-block="currency"> <span class="nemo-common-mobileControl__optionsBlock__option__additional">{'new-header-mobileOptions__change'|language}</span> <span class="nemo-common-mobileControl__optionsBlock__option__value js-nemo-mobileControl__currency__selected">{'currency_'|cat:$currencyConverter.defaultCurrency|language}</span> </div> </div> <div class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__optionsBlock__cancel js-nemo-mobileControl__close">{'new-header-mobileOptions__close'|language}</div> </div> <div class="nemo-common-mobileControl__optionsBlock js-nemo-mobileControl__optionsBlock js-nemo-mobileControl__optionsBlock_language" style="display: none;"> <div class="nemo-ui-subContainer nemo-common-mobileControl__optionsBlock__options"> {foreach item=lang from=$agency_langs key=lang_code} {if $locale != $lang_code} <div class="nemo-common-mobileControl__optionsBlock__option js-nemo-header-dropmenu__drop__language" data-language="{$lang_code}"> {$lang} </div> {/if} {/foreach} </div> <div class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__optionsBlock__cancel js-nemo-mobileControl__optionsBlock__selector" data-block="selector">{'new-header-mobileOptions__cancel'|language}</div> </div> <div class="nemo-common-mobileControl__optionsBlock js-nemo-mobileControl__optionsBlock js-nemo-mobileControl__optionsBlock_currency" style="display: none;"> <div class="nemo-ui-subContainer nemo-common-mobileControl__optionsBlock__options"> {foreach from=$currencyConverter.rates item=oneCur key=key} <div class="nemo-common-mobileControl__optionsBlock__option js-nemo-mobileControl__currency__option" data-currency="{$key}"> {'currency_'|cat:$key|language} </div> {/foreach} </div> <div class="nemo-ui-button nemo-ui-button_common nemo-common-mobileControl__optionsBlock__cancel js-nemo-mobileControl__optionsBlock__selector" data-block="selector">{'new-header-mobileOptions__cancel'|language}</div> </div> </div> </div> <header class="nemo-common-pageHeader"> <div class="nemo-common-pageHeader__inner"> <div class="nemo-common-pageHeader__mobileControl nemo-common-pageHeader__mobileControl_links js-nemo-mobileControl__toggler" data-control="links"></div> <div class="nemo-common-pageHeader__mobileControl nemo-common-pageHeader__mobileControl_options js-nemo-mobileControl__toggler" data-control="options"></div> <a href="/" class="nemo-common-pageHeader__logo"> <img class="nemo-common-pageHeader__logo__image" src="/templates/wurst/f2.0/img/nemo.travel.svg" alt=""> </a> <div class="nemo-common-pageHeader__inner__headerLinks"> {if $test_mode} {'system_test_mode'|language} {/if} {if $info_user_status == 'gst'} {if $mode_auth_form} <button class="nemo-ui-button nemo-ui-button_common nemo-ui-button_medium nemo-common-pageHeader__inner__headerLinks__item js-header-auth"> {'new-header-enter'|language} </button> {else} <a href="{go_and_back controller='authorization' action='auth_client'}" class="nemo-ui-button nemo-ui-button_common nemo-ui-button_medium nemo-common-pageHeader__inner__headerLinks__item"> {'new-header-enter'|language} </a> {/if} <div class="js-header-restorepass" style="display: none;"></div> {include file='authorization_popup.tpl'} {include file='authorization_passRecovery_popup.tpl'} {if isset($registrationFormsData.b2c)} <a href="/{url controller='authorization' action='registration' get=''}" class="{if $registrationFormsData.b2c->popup}nemo-ui-pseudoLink js-header-register {else}js-header-register-link {/if}nemo-common-pageHeader__inner__headerLinks__item"> {'new-header-registration'|language} </a> {if $registrationFormsData.b2c->popup} <div class="js-registration-formcontainer_b2c" style="display: none;"> {include file="registration_inline.tpl" form=$registrationFormsData.b2c} </div> {/if} {/if} {else} <span class="nemo-common-pageHeader__inner__headerLinks__item"> {'new-header-welcome'|language} {strip} <a href="/profile"> {$info_logged_in_as} </a> {/strip} {if $info_user_status !== 'usr'} ({$info_user_status|language}) {/if} </span> <a class="nemo-common-pageHeader__inner__headerLinks__item" href="/{go_and_back controller='authorization' action='logout'}">{'new-header-logout'|language}</a> <a class="nemo-common-pageHeader__inner__headerLinks__item" href="/{url controller="settings" action="dashboard"}" target="_blank">{'new-header-settings'|language}</a> {if !$hide_poffice} <a class="nemo-common-pageHeader__inner__headerLinks__item" href="/{url controller="poffice" action="table"}">{'new-header-privateOffice'|language}</a> {/if} {/if} {if $show_booking_status_check} <a href="/{url controller='booking' action='status'}" class="nemo-ui-pseudoLink nemo-common-pageHeader__inner__headerLinks__item js-header-checkOrder"> {'new-header-checkBookStatus'|language} </a> {include file='checkBooking_popup.tpl'} {/if} </div> <div class="nemo-common-pageHeader__inner__headerRight"> <div class="nemo-ui-dropMenu js-nemo-header-dropmenu nemo-common-pageHeader__dropMenu nemo-common-pageHeader__dropMenu_language"> <div class="nemo-ui-dropMenu__main"> <button class="nemo-ui-button nemo-ui-button_common nemo-common-pageHeader__dropMenu__button js-nemo-header-dropmenu__button"> <span class="nemo-common-pageHeader__langSelectImage flag flag-{if $locale neq 'en'}{$locale|upper}{else}GB{/if}"></span> </button> </div> <div class="nemo-ui-dropMenu__drop js-nemo-header-dropmenu__drop nemo-common-pageHeader__droplist nemo-common-pageHeader__droplist_language"> <span class="nemo-common-pageHeader__droplist__header">Язык</span> {foreach item=lang from=$agency_langs key=lang_code} {if $locale != $lang_code} <div class="nemo-common-pageHeader__droplist__option js-nemo-header-dropmenu__drop__option js-nemo-header-dropmenu__drop__language" data-language="{$lang_code}"> <div class="nemo-common-pageHeader__droplist__option__icon"> <span class="nemo-common-pageHeader__langSelectImage flag flag-{if $lang_code neq 'en'}{$lang_code|upper}{else}GB{/if}"></span> </div> <span class="nemo-common-pageHeader__droplist__option__text"> {$lang} </span> </div> {/if} {/foreach} </div> </div> {if count($currencyConverter.rates) > 1 && $currencyConverter.conversionEnabled} <div class="nemo-ui-dropMenu js-nemo-header-dropmenu nemo-common-pageHeader__dropMenu nemo-common-pageHeader__dropMenu_currency"> <div class="nemo-ui-dropMenu__main"> <button class="nemo-ui-button nemo-ui-button_common nemo-common-pageHeader__dropMenu__button js-nemo-header-dropmenu__button"> {if $currencyConverter.defaultCurrency == "RUB"} <money><currency type="symbol" currency="RUB">RUB</currency></money> {else} {"currency_"|cat:$currencyConverter.defaultCurrency|cat:"_symbol"|language} {/if} </button> </div> <div class="nemo-ui-dropMenu__drop js-nemo-header-dropmenu__drop nemo-common-pageHeader__droplist"> <span class="nemo-common-pageHeader__droplist__header">Валюта поиска и оплаты</span> {foreach from=$currencyConverter.rates item=oneCur key=key} <div class="nemo-common-pageHeader__droplist__option js-nemo-header-dropmenu__drop__option js-nemo-header-dropmenu__drop__currency" data-currency="{$key}"> <div class="nemo-common-pageHeader__droplist__option__icon"> {if $key == "RUB"} <money><currency type="symbol" currency="RUB">RUB</currency></money> {else} {"currency_$key"|cat:"_symbol"|language} {/if} </div> <span class="nemo-common-pageHeader__droplist__option__text"> {"currency_$key"|language} </span> <span class="js-nemo-header-dropmenu__drop__currency__text" style="display: none;"> {if $key == "RUB"} <money><currency type="symbol" currency="RUB">RUB</currency></money> {else} {"currency_$key"|cat:"_symbol"|language} {/if} </span> </div> {/foreach} </div> </div> {/if} </div> </div> {include file="authenticationWarning.tpl"} {include file="header_scripts.tpl"} </header>
5) В разделе "Управление сайтом - Nemo CMS - Шаблоны" создаем шаблон подвала. https://drive.google.com/file/d/0B2geuk8VO4nOVEtjMm1GMi1XU1E/view?usp=sharing
<footer class="nemo-common-footer"> <div class="nemo-common-footer__footerInner"> <div class="nemo-common-footer__copyRight"> © nemo.travel </div> <div class="nemo-common-footer__footerMenu"> <a href="#" class="nemo-common-footer__footerMenu__item"> Помощь </a> <a href="#" class="nemo-common-footer__footerMenu__item"> Обратная связь </a> </div> </div> </footer>
6) В разделе "Управление сайтом - Nemo CMS - Модули - Системные тексты" создаем категорию "Служебные". Внутри категории создаем текстовую статью с заголовком "Служебный текст" и пустым содержанием. Эта пустышка понадобится далее при создании элементов шапки и подвала внутри макета.
7) В разделе "Управление сайтом - Nemo CMS - Макеты страниц" создаем макет с любым заголовком, Родитель - не определено, Шаблон - Шаблон страницы, Режим создания элементов страницы - наследовать далее, Включено - да. Внутри макета создаем 3 элемента: шапка, движок и подвал. https://drive.google.com/file/d/0B2geuk8VO4nOT2g2UmdvRUVlUkE/view?usp=sharing https://drive.google.com/file/d/0B2geuk8VO4nOX0VvTTQ0bm5HMzA/view?usp=sharing https://drive.google.com/file/d/0B2geuk8VO4nONHF0QmZpY3NlT3M/view?usp=sharing При заполнение элементов некоторых полей со скриншотов может не хватать, нужно сохранить элемент и они появятся.