286 lines
15 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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; }
}
}