Моя первая панель

Материал из ISPWiki
Перейти к: навигация, поиск

Введение

COREmanager предоставляет широкий набор функций для создания практически любую панель(в теории хоть Центр Управления Полетами), но мы будем создавать панель отображающую список пациентов.

Начало

Подготовка: Скачайте и установите последнюю версию COREmanager,после чего она должна быть доступна по адресу https://ip-адрес:1500/core. По умолчанию COREmanager устанавливаается в каталог /usr/local/mgr5/. Вся дальнейшая работа будет вестись относительно пути установки по умолчанию.

Для удобства сборки и настройки мы создадим нашу панель в каталоге src/.

Примечание:

Для автоматизации процесса сборки мы рекомендуем помещать все проекты связанные с COREmanager 
в каталог src/.

Создайте каталог mypanel и перейдите в него.

Создадим типовой Makefile следующего вида:

LIB += mypanel
LANGS += ru en
mypanel_SOURCES = mypanel.cpp
mypanel_LDADD = -lbase


include ../isp.mk

Если вы не читали как собирать собственный модуль то пройдите по ссылке

Создайте в этом же каталоге файл mypanel.cpp:

#include <api/module.h>

using namespace  isp_api;

MODULE_INIT(mypanel,""){
}

Теперь перейдите в консоль и выполните команду: make install. После выполнения этой команды каталоге /usr/local/mgr5/lib появиться файл mypanel.so. Всё что теперь осталось это перейти в корень каталога /usr/local/mgr5 и установить нашу панель выполнив команду:bin/core mypanel install. Поздравляем Вы написали и установили свою первую панель, теперь откройте Ваш любимый браузер (FireFox например) и прейдите по адресу: https://ip-адрес:1500/mypanel

Расширение функционала панели

Расширение функционала можно условно разбить на несколько этапов:

1. Описание меню и настроек интерфейса (фаил mypanel.xml).

2. Перевод меню (mypanel_msg_ru.xml).

3. Реализация Событий и Действий в коде.

Описание меню и настроек интерфейса

Детальное описание настроек меню вы найдёте в статье Работа с XML

При запуске панель подключает меню по умолчанию, описанное в файле core.xml и своё меню. Для описания интерфейса панели и меню создайте в каталоге etc/xml файлы mypanel.xml и mypanel_msg_ru.xml. Файл mypanel.xml описывает логическую структуру интерфейса, а файл mypanel_msg_ru.xml хранит названия меню на русском языке.

Примечание: Имена файлов могут быть любыми, но мы рекомендуем создавать файлы со следующими именами имяпанели.xml и имяпанели_msg_язык.xml


Для созданной панели мы добавим своё главное меню Очередь и подменю: Список пациентов (будет выводить список всех записанных на приём), Последний (Будет отображать форму с именем поледнего записавшегося пациента).

И так файл mypanel.xml будет иметь следующий вид:

 <?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
  <mainmenu level="registered" name="">
    <node name="Stack" first="yes">
      <node name="pacientlist"/>
      <node name="showlast"/>
      <node name="myreport"/>
    </node>
  </mainmenu>

  <metadata name="showlast" type="form">
    <form title="LastPacient">
      <field name="LastPacient">
        <input type="text" name="lastpacient" readonly="yes"/>
      </field>
    </form>
  </metadata>

  <metadata name="pacientlist" type="list" key="index" keyname="index">
    <toolbar>
      <toolbtn func="pacientlist.edit" type="new" default="yes" img="t-new" name="new"/>
      <toolbtn func="pacientlist.edit" type="edit" img="t-edit" name="edit"/>
      <toolbtn func="pacientlist.delete" type="group" img="t-delete" name="delete"/>
    </toolbar>
    <coldata>
      <col name="index" type="data" sort="alpha" sorted="desc" hide ="yes" />
      <col name="date" type="data" sort="alpha" sorted="desc"/>
      <col name="pacientname" type="data" sort="alpha"/>
    </coldata>
  </metadata>

  <metadata name="pacientlist.edit" type="form">
    <form title="addPacient">
      <field name="uname">
        <input type="text" name="uname"/>
      </field>
      <field name="ulastname">
        <input type="text" name="ulastname"/>
      </field>
      <field name="rdate">
        <input type="text" name="rdate" date="text"/>
      </field>
    </form>
  </metadata>


  <metadata name="myreport" type="report" level="registered" firstrun="yes">
     <text name="title"/>
     <band name="report" headcolor="#f4d0bc">
        <diagram label="report" data="count" type="pie"/>
        <col name="uname" type="data" total="count" sort="alpha" link="no"/>
      </band>
   </metadata>

</mgrdata>

Текстовые сообщения

Файл mypanel_msg_ru.xml обязательно должен быть создан и заполнен, иначе у вас не будет названий в пунктах меню.

Пример файла mypanel_msg_ru.xml :

<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
  <lang name="ru">
    <messages name="desktop">
      <msg name="menu_showlast">Последний</msg>
      <msg name="menu_Stack">Очередь</msg>
      <msg name="menu_pacientlist">Список больных</msg>
      <msg name="menu_myreport">Отчёт</msg>
    </messages>

   <messages name="showlast">
      <msg name="title">Последний больной</msg>
      <msg name="LastPacient">Имя последнего на голову больного.</msg>
      <msg name="Last">Версия</msg>
    </messages>

   <messages name="pacientlist">
        <msg name="title">Список больных</msg>
	<msg name="date">Дата и время записи</msg>
	<msg name="pacientname">Имя больного</msg>
        <msg name="short_new">Добавить</msg>
        <msg name="short_delete">Удалить</msg>
	<msg name="short_edit">Редактировать</msg>
   </messages>

   <messages name="pacientlist.edit">
	<msg name="title">Добавить</msg>
	<msg name="uname">Имя больного</msg>
	<msg name="ulastname">Фамилия больного</msg>
	<msg name="rdate">Дата приёма</msg>
   </messages>

   <messages name="myreport">
	<msg name="title">Отчёт</msg>
	<msg name="uname">Имя больного</msg>
	<msg name="ulastname">Фамилия больного</msg>
	<msg name="rdate">Дата приёма</msg>
   </messages>

   </lang>
</mgrdata>

Если у вас не отображается какое-то меню то это значит у вас ошибка в файле перевода!

Реализация Событий и Действий

В COREmanager существует ряд классов упрощающих работу с обработкой событий, в данном примере будут использоваться:

- FormAction
- StdListAction

Подробнее о Действиях и Событиях находящихся в пространстве имён можено прочесть Namespace isp api

В COREmanager есть несколько готовых классов упрощающих работу со списками, например StdListAction. В этом классе автоматически создаётся действие ИмяДействия.delete, которое можно использовать лишь описав использование соответствующей функции в xml файле. Стоит отметить, что данное действие вызывается для выделенной группы элементов поочерёдно. Например: На панели инструментов списка создана кнопка Удалить, которая вызывает функцию pacientlist.delete. В коде нет созданного отдельного действия для обработки этой кнопки т.к. в классе ActionPacientList автоматически создается действие с именем pacientlist.delete. Всё что нужно это переопределить метод Del(Session &ses, const string &elid) и при нажатии на кнопку Удалить действие pacientlist.delete вызовется автоматически. Ключевым полем для списка является индекс в массиве переменная elid будет содержать индекс удаляемого элемента. Если в списке выделить две строки и нажать кнопку Удалить то метод Del() вызовется поочередно для каждого элемента.

Также автоматически создаётся действие с именем pacientlist.edit. Причём для Добавления и Редактирования записи будет вызываться одно и тоже действие. При нажатии на кнопку Редактировать или Добавить вызовиться метод Get(Session &ses, const string &elid), если была нажата кнопка Редактирорвать то elid будет содержать праметр ключевого поля выделенной строки. В данном случае это будет индекс элемента в массиве. При нажатии на кнопку Добавить elid = "", по этому признаку можно определить дальнейшее поведение при заполнении формы. При нажатии на кнопку Ок, формы Редактирования или Добавления, вызовиться метод Set(Session &ses, const string &elid) или New(Session &ses). Код нашего класса:

class ActionPacientList : public  StdListAction {
public:

    ActionPacientList() : StdListAction("pacientlist", MinLevel(lvRegistered)) {}

    void Get(Session &ses, const string &elid) const {
        if (elid=="") {
            DateTime date;
            ses.NewNode("rdate",date.AsDate());
        } else {
            ses.NewNode("rdate",_users::Instance().userAt(str::Int(elid))->date().AsDate());
            ses.NewNode("uname",_users::Instance().userAt(str::Int(elid))->name());
            ses.NewNode("ulastname",_users::Instance().userAt(str::Int(elid))->LastName());
        }
    }
    void Set(Session &ses, const string &elid) const {
         user * new_user = _users::Instance().userAt(str::Int(elid));
         new_user->setLastName(ses.Param("ulastname"));
         new_user->setName(ses.Param("uname"));
         new_user->setDateTime(DateTime(ses.Param("rdate")+" 00:00:00"));
         _users::Instance().save();
     }
    void New(Session &ses) const {
        user * new_user = new user;
        new_user->setName(ses.Param("uname"));
        new_user->setLastName(ses.Param("ulastname"));
        new_user->setDateTime(DateTime(ses.Param("rdate")+" 00:00:00"));
        _users::Instance().AddUser(new_user);
    }
     void Del(Session &ses, const string &elid) const {
            _users::Instance().RemoveUser(str::Int(elid));
        }

     void List(Session& ses) const {
        for (int i = 0; i < _users::Instance().count(); ++i) {
           ses.NewElem();
           ses.AddChildNode("index",str::Str(i));
           ses.AddChildNode("pacientname", _users::Instance().userAt(i)->name()+" "+_users::Instance().userAt(i)->LastName());
           ses.AddChildNode("date", _users::Instance().userAt(i)->date().AsDate());
       }
    }
};

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

class ActionShowLast : public FormAction {
public:
    ActionShowLast() : FormAction("showlast", MinLevel(lvRegistered)) {}
    //Обработка события при показе формы
    void Get(Session &ses, const string &elid) const {
        int index = _users::Instance().count()-1;
        std::string lastName = _users::Instance().userAt(index)->name() + " "+_users::Instance().userAt(index)->LastName();
        ses.NewTag("lastpacient",lastName);
    }
};

Авторизация пользователей

О том как реализовать механизмы авторизации пользователей читайте в отдельной статье - Мой первый пользователь