Написание ролевого приложения
Введение
Ролевым приложением называют web-приложение, которое можно установить в домен системы R, создав объект типа roleapp
и загрузив в него файл архива.
Архив будет распакован системой и отображён на веб-сервере по определённому пути, частично заданному администратором домена.
Для связи с сервером ролевое веб-приложение должно использовать http и/или websocket API открытое на том же самом сервере, что и загруженное ролевое приложение.
Одним из способов расширения функциональности ролевых приложений является возможность запускать служебный сценарий в системе по запросу web-приложения.
Если такой сценарий существует (создан и настроен администратором домена), то привязка сценария происходит путём указания его кода в roleapp entity в поле svcscriptcode
.
Запуск связанного служебного сценария происходит через выполнение запроса /exec ролевым приложением.
В данной статье описан сам файл ролевого приложения, его значимые элементы, а также видный снаружи результат установки ролевого приложения.
Ниже описаны особенности реализации ролевого приложения, которые исходят из требований платформы и примеры.
Файл ролевого приложения
Ролевое приложение представляет из себя zip-архив, который будет распакован на сервере при установке.
При этом архив должен содержать файл roleapp.json на верхнем уровне.
├── assets
│ └── img
│ └── desktop.svg
├── css
│ └── jsoneditor.min.css
├── index.html
├── js
│ ├── aes-js.js
│ ├── base64.js
│ ├── jquery-3.1.1.min.js
│ └── jsoneditor.min.js
├── monitor.js
└── roleapp.json
Файл roleapp.json в корне архива содержит описание приложения. Как правило все файлы и папки приложения находятся также в корне архива (index.html и другие).
roleapp.json
Должен быть валидным json файлом, размер которого не превышает 10Kb. Все поля опциональные. Минимальный json может быть пустым объектом ({}).
{
"name": "Roleapp Sample", (1)
"description": "Monitor (old) as RoleApp description", (2)
"order": 5000, (3)
"fa-icon": "fa-paw" (4)
"icon": "assets/img/desktop.svg" (5)
}
1 | name – название ролевого приложения. Значение поля будет использовано для названия ролевого приложения в списке если администратор оставил поле "title" объекта ролевого приложения пустым. Тип поля строка, иначе значение будет проигнорированно. |
2 | description – описание ролевого приложения, идёт напрямую в /rest/v1/iam/sessions/current. Тип поля строка, иначе значение будет проигнорированно. |
3 | order – порядок ролевого приложения при сортировке для отображения в списке. Администратор может принудительно его задать в поле ext.order объекта roleapp, чтобы заменить значение из roleapp.json. |
4 | fa-icon – имя класса иконки Font Awesome. |
5 | icon – путь до иконки для списка приложений относительно папки ролевого приложения. |
Есть возможность указать подпапку внутри архива в качестве папки с web-документами (по-умолчанию будет использован весь архив от корня). Если roleapp.json содержит поле "folder", то в результате по url’у установленного приложения будет доступен не корень архива, а эта подпапка (в url не появляется).
Таким образом, разницу между режимом по-умолчанию и режимом с подпапкой можно проследить на примере roleapp.json: в режиме по-умолчанию файл становится доступным по http: /app/ccoper/roleapp.json
но в режиме с подпапкой он оказывается не виден.
Пример:
├── dist
│ └── index.html
└── roleapp.json
{
"name": "Def roleapp",
"order": 5000,
"fa-icon": "fa-folder-open",
"folder": "dist"
}
Установка ролевого приложения
После установки ролевого приложения оно появляется в списке приложений если проходит все этапы фильтрации. Фильтруются приложения по следующему правилу:
-
пользователь должен иметь хотя бы одну роль доступа из списка ролей приложения (поле
"roles"
объектаroleapp
) - задаются администратором.
Результат установки
Приложение становится доступным по URL указанном в выдаче /rest/v1/iam/sessions/current, например /app/ccoper/
.
{
...,
"webapps": [
...,
{
"description": "OktellSutdio Contact Center Operator web application",
"fa-icon": "fa-headphones",
"icon": "/app/ccoper/logo192.png",
"name": "CC Operator",
"order": 5000,
"roles": [
"admin",
"ccoperator"
],
"url": "/app/ccoper/"
}
]
}
Первая часть пути URL /app
определяется системой, а вторая часть /app/ccoper
(ccoper) определяется администратором в поле folder
объекта roleapp
.
Веб-сервер системы настроен таким образом, что при запросе на адрес, указанный в поле "url"
, будет отдаваться содержимое index.html (только корень приложения).
Все ресурсы приложения (другие файлы кроме index.html) будут доступны в этой подпапке, например, /app/ccoper/css/main.css
Особенности реализации ролевого приложения
Здесь нужно понимать, что URL установки не известен автору приложения заранее, ведь folder
определяется администратором в момент установки.
Более того, администратор имеет возможность установить, например, разные версии ролевого приложения в разные папки и пользоваться ими одновременно.
Требования платформы
Исходя из вышесказанного ролевое приложение должно обеспечить свою корректную работу в таких обстоятельствах.
Изменения адреса в строке браузера не длжно противоречить описанной выше схеме.
-
приложение будет загружено из произвольной папки на сервере (напр.
/app/ccoper/
) и должно считаться корнем приложения. -
приложение может также быть загружено с явным указанием файла внутри приложения (напр.
/app/ccoper/index.html
) но данный вариант на практике не используется по эстетическим соображениям. -
все остальные запросы в пределах папки приложений обслуживаются статическим веб-сервером без выдачи индексов подкаталогов и без подмены их содержимым index.html (как это происходит с корнем приложения).
-
использование виртуальных путей запрещено, т.к. перезагрузка страницы пользователем не будет удаваться.
-
например, приложение совершит переход на виртуальный адрес
/app/ccoper/main
при отображении главной страницы. Перезагрузка страницы выдаст404 Not Found
.
-
Примеры реализации требований
Следствием вышесказанного является необходимость ссылаться на ресурсы ролевого приложения по относительным путям, например:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>R.API Monitor</title>
<link rel="stylesheet" href="css/jsoneditor.min.css">
<script src="js/jsoneditor.min.js"></script>
<script src="js/jquery-3.1.1.min.js"></script>
<script src="js/aes-js.js"></script>
<script src="js/base64.js"></script>
<script src="monitor.js"></script>
Где ресурсы будут загружаться из папок /app/ccoper/css/
, /app/ccoper/js/
и т.д. или как /app/ccoper/monitor.js
из папки ролевого приложения, что является стандартной работой браузера.
Типичным вариантом при сборке приложений React/др. является указание префикса "./"
означающего текущую папку в качестве папки установи приложения, напр. PUBLIC_URL=.
.
С другой стороны, применяя javascript очень легко динамически узнать путь установки ролевого приложения при загрузке страницы (из переменной window.location.pathname), например:
<html>
<body>
<h1>Role Application "Def2".<h1>
<div id="abc"></div>
<script>
console.log('1');
(function() {
var path = window.location.pathname;
console.log('path = ', path);
document.getElementById('abc').innerHTML = path;
})();
console.log('2');
</script>
</body>
</html>
После загрузки страницы и ресурсов в процессе работы приложение может использовать адрес URL в строке браузера как хранилище части своего состояния (т.н. Routing).
Чтобы пользователь мог в любой момент перезагрузить страницу приложения и продолжить свою работу с ним, необходимо избегать модификации адреса URL в части path.
Этого легко достичь, используя в качестве хранилища состояния идентификатор фрагмента вместо пути. В приложениях React это достигается использованием класса HashRouter
вместо BrowserRouter
.
/app/ccoper/main
→ /app/ccoper/#/main