SimpleWEB

SimpleWEB это решение для создания десктопных, веб – фронтов, веб-приложений на семантике Simple. В отличии от SimpleUI, который предназначен только для Android, SimpleWEB закрывает все остальные ниши фронт-энд решений – фронты для облачных решений, для клиент-серверных решений, внешние фронты для ERP и т.д..

SimpleWEB технически представляет из себя библиотеку Python (uiweb) которая умеет читать конфигурации в семантике Simple (ui-файлы) и создавать веб приложения, которые могут быть развернуты в локальной сети или у любого хостинг-провайдера, который поддерживает Python. При этом веб приложение использует web-сокеты для обеспечения высокой производительности и отзывчивости интерфейса и реализации более глубокого асинхрона и разнообразного взаимодействия через сокеты (прямое взаимодействие с клиентом от сервера). В процессе работы библиотека генерирует чистый html+CSS+JS/JQuery код и вставляет его динамически, т.е. элементы интерфейса, обработчики событий – все это создается на лету, адресно.

Веб-приложение состоит из стартового приложения (например app.py), которое вызывает библиотеку uiweb и сервирует веб-сервер (например Flask), имеет некоторые вспомогательные методы (например команды загрузки/выгрузки файлов, редирект на страницу настроек). Библиотека в свою очередь обращается к конфигурации (*.ui) и файлу обработчиков, которые задаются в настройках через панель администрирования (http://localhost:1555/admin). Фактически, после загрузки через панель администрирования конфигурация и файл обработчиков копируются в файлы current_configuration.ui и current_handlers.py в папке приложения и далее библиотека работает уже с ними напрямую. Таким образом отладка и правка кода возможна прямо в current_handlers.py (после чего изменения можно перенести во внешний файл). Правку конфигурации в режиме разработки также проще делать сразу в current_configuration.ui чтобы изменения коммитились сразу в веб-приложение.

Для установки необходимо:

  1. Скачать с GitHub папку со стартовым скриптом app.py и развернуть там где она будет запускаться: https://github.com/dvdocumentation/simpleweb

  2. Установить зависимости:

pip install -r requirements.txt

и желательно еще потом обновить саму библиотеку uiweb (которая и есть SimpleWEB:

pip install uiweb –upgrade

  1. Запустить приложение app.py:

python3 app.py

  1. Приложение доступно по адресу http://localhost:1555/ после чего можно зайти в админку (http://localhost:1555/admin) и поставить конфигурацию (ui-файл), при необходимости файл с c обработчиками и путь к веб-сервису если есть. На этом настройка закончена, можно пользоваться.

Отдельного обучения на SimpleWEB нет, т.к. оно мало отличается от SimpleUI. Для начала рекомендуется посмотреть конфигурацию first_configuration https://github.com/dvdocumentation/simpleweb/tree/main/samples/first_configuration

Особенности разработки в SimpleWEB, по сравнению с SimpleUI и основные возможности.

Выполнение скриптов при загрузке страницы

Не смотря на то, что в SimpleWEB присутствует событие onLaunch (которое запускается после окончании загрузки сеанса), есть также возможность встраивание кода непосредственно в HTML страницу, секцию head. Это могут быть скрипты, подключение библиотек, все что угодно. И это будет выполнено при загрузке страницы конфигурации (при открытии либо обновлении в браузере). Доступно в он-лайн конструкторе, в разделе «Конфигурация»

Вкладки

Так как SimpleWEB - это десктопная система то основное действие происходит внутри вкладок, в отличии от SimpleUI где отрисовываются экраны. Но вкладку недостаточно просто открыть – есть еще ситуации, например повторного открытия такой же вкладки, при котором может потребоваться не создавать новую вкладку, а переоткрыть существующую и другие потребности в управлении вкладками.

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

OpenScreen, параметры {«process»:<процесс> screen»:<экран>, [«key»:<ключ>], [«reopen»:true|false], [«no_close»:true|false]}

Также есть необязательные параметры:

key (необязательный) – можно задать уникальный ключ вкладки (например uid документа или название операции) по которому система будет понимать что такая вкладка уже открыта.Вкладки из основного меню, автоматически создаются с key = имени процесса

reopen (необязательный)– если задать истина и потом повторно отправить OpenScreen с таким же key то вместо новой вкладки будет переоткрыта/обновлена ранее открытая. Это удобно, т.к. не надо задумываться о том, как найти уже открытую, чтобы не плодить новые вкладки

no_close (необязательный) – запрет на ручное закрытие вкладки (убирается крестик)

Закрыть вкладку (помимо ручного закрытия) можно командой CloseTab:

CloseTab, с пустым параметром – закрывает текущую вкладку. В новой версии предыдущая вкладка становится активной.

CloseTab, <ключ> - закрывает вкладку с определенным ключом из пула открытых вкладок

Переключиться на открытую вкладку из кода можно с помощью SelectTab:

SelectTab, <ключ>

Блокировка/разблокировка всей линейки вкладок:

BlockTabs – заблокировать все вкладки от пользователя

UnblockTabs – разблокировать вкладки

Отслеживание события выбора вкладки пользователем.

Когда пользователь выбирает какую то из открытых вкладок, возникает общее событие onWEBMainTabSelected

В стек переменных попадает переменная CurrentTabKey, в которой содержится ключ открытой вкладки и CurrentTabID с внутренним ИД открытой вкладки. listener = MainTabSelect

Прочие функции для работы с экранами и элементами экрана

RefreshScreen , без параметра – обновляет текущий экран. В SimpleWEB обновление не идет автоматом после события ввода, его надо запускать по необходимости, либо бользоваться командами SetValues, SetShow и т.п.

ShowScreen, имя экрана либо {«process»:<процесс>,»screen»:<экран>} – выводит на текущей вкладке заданный экран. Экран задается либо просто указанием экрана (из текущего процесса) либо в виде JSON с указанием процесса и экрана.

Show_<переменная>,<видимость: «-1»,»0»,»1»> - управление видимостью элементов аналогично команде в SimpleUI. Переменная элемента передается в ключе Show_, режим видимости срыт/невидим/виден- «-1»/»0»/»1» в параметре

SetShow_<переменная>,<видимость: «-1»,»0»,»1»> - управление видимостью, аналогичное Show_ но с той разницей, что изменение происходит не после обновления экрана, а мгновенно

Мгновенное обновление значений без обновления экрана

Значения могут быть перечитаны при обновлении вкладки/экрана, но кроме того они могут быть отправлены с сервера напрямую в элемент (через веб-сокеты):

Параметры передаются в виде JSON- массива :

[<переменная>:<новое значение>]

SetValues – заменяет текстовые значения (например надписи)

SetVauesPulse – заменяет текстовые значения с эффектом затухающей подсветки

SetValuesTable – обновляет таблицу

SetValuesEdit – обновляет поле ввода (текст в поле ввода)

SetValuesCards – обновляет список карточек

SetValuesHTML – заменяет HTML элемента с указанной переменной на ваш HTML

Диалоги

Поддерживается (синтаксис аналогичен SimpleUI: https://uitxt.readthedocs.io/ru/latest/common_functions.html#id24 ):

  • ShowDialog

  • ShowDialogStyle

  • ShowDialogLayout

В случае использования ShowDialogLayout данные элементов ввода помещаются в JSON-словарь dialog_values Также для SimpleWEB доступна опция назначать некоторые элементы диалога источниками событий. Это делается командой:

ShowDialogActive, <список переменных элементов через ;> - назначает некотрые элементы диалога «активными» - по ним будет генерироваться событие с listener=<имя переменной>.

Файлы

Загрузка файлов.

UploadFile, [<id>] – команда, инициирующая диалог загрузки, можно передать id Для загрузки в модуле приложения должна быть функция примерно такого вида:

@fapp.route('/upload_file', methods = ['PUT', 'POST'])
def upload_file_ui():
   file = request.files['file']
   if file.filename == '':
            #'No selected file'
            return redirect(request.url)
   if file:
          filename = request.args.get('sid')+"_"+secure_filename(file.filename)
          os.makedirs(PYTHONPATH+os.sep+fapp.config['UPLOAD_FOLDER'],exist_ok=True)
          file.save(PYTHONPATH+os.sep+os.path.join(fapp.config['UPLOAD_FOLDER'], filename))

          user = get_current_connection(request.args.get('sid'))
          user[2].input_event({"data":"upload_file","filename":filename,"source":request.args.get('id')})

После загрузки возникает событие listener = „upload_file“ с переменной „filename“, в которой храниться путь к файлу

Поле Файл на форме диалога

Для загрузки файла например в составе Диалога с содержимым, можно разместить поле Файл (file) в контейнере. После выбора файла, его содержимое в виде base64 помещается в переменную „base64“

Скачивание файла через ссылку на экране

Для этого нужно :

  1. Разместить функцию такого вида:

@fapp.route('/download_file', methods = ['GET', 'POST'])
def download_file():
   os.makedirs(PYTHONPATH+os.sep+fapp.config['UPLOAD_FOLDER'],exist_ok=True)
   filename = request.args.get('filename')
   return send_from_directory(PYTHONPATH+os.sep+os.path.join(fapp.config['UPLOAD_FOLDER']), filename, as_attachment=True)
  1. Ссылку надписи сделать вида:

'Файл можно скачать тут: <a href="/download_file?filename='+Path(filename).name+'" target="_blank">скачать</a>'

Работа с буфером обмена

Запись текста в буфер обмена

WriteClipboard,<текст> - копирует текст в буфер обмена. Для всех браузеров.

Чтение текста из текущего буфера обмена

ReadClipboard,без параметра - читает буфер обмена, помещает в clipboard_result и вызывает событие listener=clipboard_result. Работает на Chrome либо в https либо в localhost.

Работа с cookies

SetCookie, [{«key»:<ключ>,»value»:<значение>,»expires»:<количество дней>}] - устанавливает массив значений cookie для текущего сайта на ткущем компьютере. expires (время действия в днях) можно не задавать. GetCookies - получить все ранее установленные значения cookie

Таблицы

Доступны таблицы типа table с описанием аналогичным https://uitxt.readthedocs.io/ru/latest/common_functions.html#id2

В веб-версии есть отличия:

  1. Помимо TableClick доступен также TableDoubleClick – отдельное событие по двойному щелчку мыши

  2. Возможно использование автоматической сортировки , разбивки на страницы, поиска по полям с помощью компонента DataTable для этого надо использовать опцию useDatatable: true

_images/data_table.png
  1. Доступно редактирование прямо в таблице для этого в заголовке надо установить режим «editmode»: «table» и в полях, в которых требуется редактирование нужно указать тип элемента редактирование в поле «input»:

  • «input»:»CheckBox»

  • «input»:»EditTextText»

  • «input»:»EditTextNumeric»

В результате после редактирования возникнет событие TableEdit с доступными переменными selected_line, table_column, table_value

_images/table_edit.png
  1. Доступно формирование обработчиков для упрощенного добавления/редактирования записей в виде мобальных окон, которые формируются автоматически по полям таблицы. Для этого нужно:

    1. В таблице указать «editmode»: «modal»

    2. указать тип элемента редактирование в поле «input»: «input»:»CheckBox» «input»:»EditTextText» «input»:»EditTextNumeric»

    3. Вынести кнопки, в обработчиках которых формируются команды TableAddRow, <имя таблицы> и TableEditRow, <имя таблицы> . По этим кнопкам и будут запускаться диалоги. TableEditRow логичнее повесить на двойной клик например

    4. По результату ввода в мобальном диалоге формируется событие TableEditModal в котором доступны переменные table_values и selected_line

_images/modal_edit.png

Списки карточек

Списки карточек имею аналогичную функциональность, в т.ч. размещение активных элементов спискам customcards: https://uitxt.readthedocs.io/ru/latest/common_functions.html#id4

Закладки внутри экрана

В качестве элементов контейнера можно использовать наборы закладок «Закладки», состоящие из контейнера типа «Закладка»

_images/tabs.png

Доступно использование команды SelectTab, <переменная закладки> для внутренних вкладок для выбора текущей вкладки

Логин

Доступно использование признака процесса «Запускать при запуске» - тогда при загрузке страницы конфигурации будет запускаться выбранный процесс, при этом остальное меню процессов загружаться не будет, тем самым блокируя доступ к остальным процессам (доступен только процесс логина). В случае успешного прохождения логина (например, проверки пароля) нужно вызвать команду LoginCommit для того чтобы основное меню загрузилось в обычном режиме и можно было продолжить работу с конфигурацией

Асинхронные обработчики

Асинхронные обработчики возвращают результат в ту вкладку, из которой были запущены.

Стили оформления

Для элементов доступно задание стиля оформления в виде CSS (через элементы стилей). Таким образом можно получить доступ к люому оформлению элементов. В элементе стиля надо включить галочку «Использовать как класс» и заполнить поле CSS

Уведомления, тосты, звуки

toast, <текст сообщения> - всплывающее уведомление, возможно указание в виде HTML

basic_notification, {«message»:<сообщение>,»title»:<заголовок>} – уведомление в отдеьном окне с заголовком

beep,пустой параметр – проигрывание звука

Упрощенное определение полей ввода

Для задания конструкции в виде «Заголовок поля ввода» - «Поле ввода», вместо горизонтального контейнера, надписи и поля ввода для поле типа «Поле ввода текст», «Поле ввода строка», «Поле ввода с автозаполнением», «Выпадающий список» и подобных можно определи конструкцию формата:

<Заголовок поля>|@<значение по умолчанию>

Или для списков:

<заголовок поля>|@<переменная списка>

_images/short_inputs.png

Расширенная работа с меню.

По умолчанию меню формируется по списку процессов (за исключением процессов «Не показывать в меню», «Запускать при запуске»). Также можно сгруппировать меню по разделам. Для этого нужно указать в поле Шаблон меню, структуру меню например в таком формате:

[{«caption»:<заголовок раздела>,»elements»:[{«caption»:<заголовок процесса>,»process»:<имя процесса>}]}]

Например:

[{«caption»:»Раздел 1»,»elements»:[{«caption»:»Экран»,»process»:»экран»},{«caption»:»список карточек»,»process»:»список карточек»}]},{«caption»:»Прочее»,»elements»:[{«caption»:»Асинхрон»,»process»:»Асинхрон»}]}]

_images/web_menu.png

Особенности работы с полем HTML

Поле HTML позволяет разместить в контейнере любой свой код HTML со скриптами, стилями и т.д. Пример подходит например от https://infostart.ru/1c/articles/1716745/ (накладная) Особенность заключается в том, что если вы хотите чтобы клик на элементе обработался стандартным образом, например на кнопке, то нужно указать id, начинающийся с решетки:

<button id="#btn_1" style="text-align: center;;margin: 3px">Кнопка 1</button>

Но, также можно вызвать например свою функцию, которая отработает в вашем JS -скрипте.

Штрихкоды

Возможно подключение сканера штрих-кодов на клиенте в режиме «разрыв клавиатуры», эмуляция клавиш. Распознавание ведется по принципу определения быстрого ввода (генерация клавиш со сканера происходит быстро, задержка меньше 1 секунды). Генерируется событие barcode которое обрабатывается по тому же принципу что и в SimpleUI

Список общих событий, поддерживаемых SimpleWeb

  • onLaunch - событие при загрузке конфигурации

  • onWEBMainTabSelected - событие при активации вкладки

Список поддерживаемых визуальных элементов контейнера

  • Закладки, закладка

  • Контейнер

  • Надпись

  • Поле ввода текст

  • Поле с автозаполнением

  • Поле ввода число

  • Поле ввода пароля

  • Многострочный текст

  • Файл

  • Поле ввода даты

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

  • Галочка

  • Кнопка

  • Картинка

  • Таблица

  • Список карточек

  • Поле HTML