286 lines
15 KiB
C#
286 lines
15 KiB
C#
using ClientModelsPrivate.Main.Menus;
|
||
using ExtensionModules.Interfaces;
|
||
using ExtensionModules.Interfaces.Extensions;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using FlowControl.Builder.Elements;
|
||
using ParusClient.Activities;
|
||
using System.Xml;
|
||
using System.IO;
|
||
using CommonActivities.Activities;
|
||
using Common.Extensions;
|
||
using CommonActivities.Activities.Common;
|
||
using FlowControl.Core;
|
||
using Parus.Database.Specialized;
|
||
using System.Web;
|
||
using FlowControl.Extensioins;
|
||
|
||
//"Панели" - расширение для "ПАРУС 8 Онлайн" (библиотека для сервера приложений)
|
||
namespace P8PanelsParusOnlineExt
|
||
{
|
||
//Вспомогательные методы
|
||
public static class P8PanelUtils
|
||
{
|
||
//Имена специальных параметров "встроенных" методов
|
||
public const string SPECIAL_PRM_CAPTION = "SCAPTION";
|
||
public const string SPECIAL_PRM_PANEL = "SPANEL";
|
||
public const string SPECIAL_PRM_IDENT = "NIDENT";
|
||
|
||
//Формирование адреса панели
|
||
public static string BuildPanelURL(P8PanelConfig config, P8Panel panel, IDictionary<string, object> parameters = null)
|
||
{
|
||
string panelUrl = config.panelsUrlBase;
|
||
if (!panelUrl.EndsWith("/") && !panel.url.StartsWith("/")) panelUrl += "/";
|
||
panelUrl += panel.url;
|
||
if (parameters != null)
|
||
{
|
||
var prms = "";
|
||
foreach (KeyValuePair<string, object> entry in parameters)
|
||
{
|
||
if ((entry.Key != SPECIAL_PRM_CAPTION) && (entry.Key != SPECIAL_PRM_PANEL))
|
||
prms += entry.Key + "=" + HttpUtility.UrlEncode(Convert.ToString(parameters.SafeValue(entry.Key))) + "&";
|
||
}
|
||
if (!string.IsNullOrEmpty(prms)) panelUrl += "?" + prms;
|
||
}
|
||
return panelUrl;
|
||
}
|
||
}
|
||
|
||
//Настройки расширения
|
||
[Serializable]
|
||
public class P8PanelConfig
|
||
{
|
||
private List<P8PanelMenuApp> _menuApps = new List<P8PanelMenuApp>();
|
||
private List<P8PanelMenuItem> _menuItems = new List<P8PanelMenuItem>();
|
||
private List<P8Panel> _panels = new List<P8Panel>();
|
||
private string _panelsUrlBase;
|
||
|
||
//Конструктор
|
||
public P8PanelConfig(string confiFileName)
|
||
{
|
||
//Читаем указанный файл конфигурации как XML
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.Load(confiFileName);
|
||
XmlNode section = doc.DocumentElement.SelectSingleNode("/CITK.P8Panels");
|
||
//Обходим десериализованный XML
|
||
foreach (XmlNode sectionNode in section.ChildNodes)
|
||
{
|
||
//Настройки пунктов меню приложений
|
||
if (sectionNode.Name == "MenuItems")
|
||
{
|
||
foreach (XmlNode menuAppNode in sectionNode.ChildNodes)
|
||
{
|
||
_menuApps.Add(new P8PanelMenuApp() { name = menuAppNode.Attributes["name"].Value });
|
||
foreach (XmlNode menuItemsNode in menuAppNode.ChildNodes)
|
||
{
|
||
_menuItems.Add(new P8PanelMenuItem()
|
||
{
|
||
app = menuAppNode.Attributes["name"].Value,
|
||
parent = menuItemsNode.Attributes["parent"].Value,
|
||
separator = menuItemsNode.Attributes["separator"] != null ? bool.Parse(menuItemsNode.Attributes["separator"].Value) : false,
|
||
name = menuItemsNode.Attributes["name"]?.Value,
|
||
caption = menuItemsNode.Attributes["caption"]?.Value,
|
||
url = menuItemsNode.Attributes["url"]?.Value,
|
||
panelName = menuItemsNode.Attributes["panelName"]?.Value
|
||
});
|
||
}
|
||
}
|
||
}
|
||
//Настройки панелей
|
||
if (sectionNode.Name == "Panels")
|
||
{
|
||
_panelsUrlBase = sectionNode.Attributes["urlBase"].Value;
|
||
foreach (XmlNode panelNode in sectionNode.ChildNodes)
|
||
{
|
||
_panels.Add(new P8Panel()
|
||
{
|
||
name = panelNode.Attributes["name"].Value,
|
||
caption = panelNode.Attributes["caption"].Value,
|
||
url = panelNode.Attributes["url"].Value,
|
||
path = panelNode.Attributes["path"].Value,
|
||
icon = panelNode.Attributes["icon"].Value,
|
||
showInPanelsList = panelNode.Attributes["showInPanelsList"] != null ? bool.Parse(panelNode.Attributes["showInPanelsList"].Value) : false,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//Поиск панели в настройке по наименованию
|
||
public P8Panel FindPanelByName(string name)
|
||
{
|
||
return _panels.Find(panel => panel.name == name);
|
||
}
|
||
|
||
//Список приложений для подключения панелей
|
||
public List<P8PanelMenuApp> menuApps { get => _menuApps; }
|
||
|
||
//Список подключаемых к приложениям пунктов меню панелей
|
||
public List<P8PanelMenuItem> menuItems { get => _menuItems; }
|
||
|
||
//Настройки панелей
|
||
public List<P8Panel> panels { get => _panels; }
|
||
|
||
//Базовый URL к WEB-приложению "Парус 8 - Панели мониторинга"
|
||
public string panelsUrlBase { get => _panelsUrlBase; }
|
||
}
|
||
|
||
//Приложение панели
|
||
[Serializable]
|
||
public class P8PanelMenuApp
|
||
{
|
||
public string name { get; set; }
|
||
}
|
||
|
||
//Элемент меню панели
|
||
[Serializable]
|
||
public class P8PanelMenuItem
|
||
{
|
||
public string app { get; set; }
|
||
public string parent { get; set; }
|
||
public bool separator { get; set; }
|
||
public string name { get; set; }
|
||
public string caption { get; set; }
|
||
public string url { get; set; }
|
||
public string panelName { get; set; }
|
||
}
|
||
|
||
//Параметры панели
|
||
[Serializable]
|
||
public class P8Panel
|
||
{
|
||
public string name { get; set; }
|
||
public string caption { get; set; }
|
||
public string url { get; set; }
|
||
public string path { get; set; }
|
||
public string icon { get; set; }
|
||
public bool showInPanelsList { get; set; }
|
||
}
|
||
|
||
//Обработчик "встроенного" метода открытия панели
|
||
public class OpenPanelActivity : OpenExternalLinkActivity
|
||
{
|
||
private P8PanelConfig _pconf;
|
||
private readonly IContextualParusDatabaseFactoryProvider _contextualParusDatabaseFactoryProvider;
|
||
private string _contextCaption;
|
||
private string _contextLink;
|
||
|
||
//Конструктор
|
||
public OpenPanelActivity(string caption, P8PanelConfig pconf, IContextualParusDatabaseFactoryProvider contextualParusDatabaseFactoryProvider) : base(caption, "stub")
|
||
{
|
||
_pconf = pconf ?? throw new ArgumentNullException("pconf");
|
||
_contextualParusDatabaseFactoryProvider = contextualParusDatabaseFactoryProvider ?? throw new ArgumentNullException("contextualParusDatabaseFactoryProvider");
|
||
}
|
||
|
||
//Исполнение действия
|
||
protected override void InternalExecute(IContext context)
|
||
{
|
||
//Читаем параметры из контекста
|
||
if (context == null) throw new ArgumentNullException("context");
|
||
var parameters = context.SafeParameterValue("MethodParameterValues") as IDictionary<string, object>;
|
||
var nIdent = parameters.SafeValue(P8PanelUtils.SPECIAL_PRM_IDENT);
|
||
var sPanel = (string) parameters.SafeValue(P8PanelUtils.SPECIAL_PRM_PANEL);
|
||
_contextCaption = (string)parameters.SafeValue(P8PanelUtils.SPECIAL_PRM_CAPTION);
|
||
//Определяем панель, которую будем открывать
|
||
if (string.IsNullOrEmpty(sPanel)) throw new Exception("Не указан код панели. Проверьте, что задано значение параметра \"SPANEL\".");
|
||
P8Panel panel = _pconf.FindPanelByName(name: sPanel);
|
||
//Если панель определена
|
||
if (panel != null)
|
||
{
|
||
//Если был указан идентификатор отмеченных записей
|
||
if (nIdent != null)
|
||
{
|
||
//Скопируем системный буфер отмеченных в буфер для панелей (чтобы не потерять при завершении транзакции)
|
||
var parusDatabaseFactory = _contextualParusDatabaseFactoryProvider.GetDatabaseFactory();
|
||
using (var connection = parusDatabaseFactory.CreateConnection())
|
||
{
|
||
using (var command = parusDatabaseFactory.CreateProcedure(connection, "PKG_P8PANELS.SELECTLIST_INIT"))
|
||
{
|
||
command.Parameters.Add(P8PanelUtils.SPECIAL_PRM_IDENT, (long) nIdent);
|
||
command.ExecuteNonQuery();
|
||
}
|
||
}
|
||
}
|
||
//Если не передали заголовок панели в параметрах - используем её заголовок из конфигурации
|
||
if (string.IsNullOrEmpty(_contextCaption)) _contextCaption = panel.caption;
|
||
//Сформируем ссылку на панель
|
||
_contextLink = P8PanelUtils.BuildPanelURL(config: _pconf, panel: panel, parameters: parameters);
|
||
} else throw new Exception($"Панель \"{sPanel}\" не определена.");
|
||
//Выполним алгоритм родительского класса
|
||
base.InternalExecute(context);
|
||
}
|
||
|
||
//Переопределение параметров открываемой закладки
|
||
protected override IDictionary<string, object> CreateClientParameters(IContext context)
|
||
{
|
||
//Сформируем словарь параметров открываемой закладки
|
||
var clientParameters = base.CreateClientParameters(context);
|
||
//Если удалось сформировать заголовок - переопределим его
|
||
if (!string.IsNullOrEmpty(_contextCaption)) clientParameters.AddOrReplace(WellknownOpenMainTabActivityParameterNames.Caption, _contextCaption);
|
||
//Переопределим адрес панели тем, который сформировали
|
||
clientParameters.AddOrReplace(WellknownOpenMainTabActivityParameterNames.Url, _contextLink);
|
||
//Вернём измененный словарь параметров
|
||
return clientParameters;
|
||
}
|
||
}
|
||
|
||
//Точка входа в модуль расширения
|
||
public class Module : ExtensionModuleBase
|
||
{
|
||
private static string _configFile = Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile) + "\\Config\\p8panels.config";
|
||
private static IList<IHook> _hooks = new List<IHook>();
|
||
public override string ModuleName => "P8Panels";
|
||
public override string AuthorInfo => "ЦИТК";
|
||
public override IList<IHook> Hooks => _hooks;
|
||
public override bool HasViews => false;
|
||
|
||
//Конструктор
|
||
public Module()
|
||
{
|
||
//Читаем и десериализуем настройки
|
||
P8PanelConfig pconf = new P8PanelConfig(_configFile);
|
||
//Вешаем хуки на создание элементов меню для всех упомянутых в настройках приложений
|
||
pconf.menuApps.ForEach(menuApp => {
|
||
_hooks.Add(MainMenuProcessorHook.Make(menuApp.name, mainMenu => {
|
||
pconf.menuItems.ForEach(menuItem => {
|
||
if (menuItem.app == menuApp.name)
|
||
{
|
||
var parentMenuItem = mainMenu.Root?.Children?.First(x => x.Value?.Name == menuItem.parent);
|
||
parentMenuItem.Children.Add(new MainMenuItemNode { Value = new MainMenuItem { IsSeparator = menuItem.separator, Name = menuItem.name, Caption = menuItem.caption } });
|
||
}
|
||
});
|
||
return mainMenu;
|
||
}));
|
||
});
|
||
//Вешаем хуки на нажатие всех сформированных элементов меню
|
||
Dictionary<string, Func<Sequence>> menuItemsActions = new Dictionary<string, Func<Sequence>>();
|
||
pconf.menuItems.ForEach(menuItem => {
|
||
if (!menuItem.separator)
|
||
if (menuItem.panelName == null)
|
||
menuItemsActions.Add(menuItem.name, () => new Sequence().Add<OpenExternalLinkActivity>(new { caption = menuItem.caption, url = menuItem.url }));
|
||
else
|
||
{
|
||
P8Panel panel = pconf.FindPanelByName(name: menuItem.panelName);
|
||
if (panel != null)
|
||
menuItemsActions.Add(menuItem.name, () => new Sequence().Add<OpenExternalLinkActivity>(new { caption = panel.caption, url = P8PanelUtils.BuildPanelURL(config: pconf, panel: panel) }));
|
||
else
|
||
menuItemsActions.Add(menuItem.name, () => new Sequence().Add<MessageActivity>(new { caption = "Панель не определена", text = $"Панель \"{menuItem.panelName}\" не определена." }));
|
||
}
|
||
|
||
});
|
||
_hooks.Add(MainMenuItemBuilderHook.Make(menuItemsActions));
|
||
//Хуки "встроенных" действий с панелями в разделах
|
||
_hooks.Add(MethodBuilderHook.Make(new Dictionary<string, Func<Sequence>>{
|
||
{
|
||
"P8PANELS_OPEN",
|
||
() => new Sequence().Add<OpenPanelActivity>(new { caption = "Панель", pconf = pconf })
|
||
}
|
||
}));
|
||
}
|
||
|
||
//Путь к файлу конфигурации расширения
|
||
public static string configFile { get => _configFile; }
|
||
}
|
||
}
|