| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 | using Comal.Classes;using InABox.Clients;using InABox.Core;using InABox.DynamicGrid;using InABox.WPF;using PRS.Shared.Events;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Media;using System.Windows.Media.Imaging;namespace PRS.Shared;public class EventGrid : DynamicDataGrid<Event>{    private readonly BitmapImage _email = InABox.Wpf.Resources.email.AsBitmapImage();    private readonly BitmapImage _notification = InABox.Wpf.Resources.notification.AsBitmapImage();    private Button? EnableButton = null;    private Dictionary<Guid, EventSubscriberType> _subscribedSet = new();    public Guid EmployeeID { get; set; }    protected override void Init()    {        base.Init();        HiddenColumns.Add(x => x.Data);        HiddenColumns.Add(x => x.Enabled);        HiddenColumns.Add(x => x.Visible);        ActionColumns.Add(new DynamicMenuColumn(BuildMenu, getImage: Menu_GetImage) { ToolTip = Subscribed_ToolTip });        if (Security.IsAllowed<CanManageEvents>())        {            EnableButton = AddButton("Disable", null, Enable_Click);            EnableButton.Visibility = Visibility.Collapsed;        }    }    protected override void SelectItems(CoreRow[]? rows)    {        base.SelectItems(rows);        if(EnableButton is not null)        {            if(rows is not null && rows.Length > 0)            {                EnableButton.Visibility = Visibility.Visible;                EnableButton.Content = rows.Any(x => !x.Get<Event, bool>(x => x.Enabled))                    ? "Enable" : "Disable";            }            else            {                EnableButton.Visibility = Visibility.Collapsed;            }        }    }    private bool Enable_Click(Button button, CoreRow[] rows)    {        var items = LoadItems(rows);        if(items.Any(x => !x.Enabled))        {            foreach(var item in items)            {                item.Enabled = true;            }            Client.Save(items, "Event enabled.");            return true;        }        else        {            foreach(var item in items)            {                item.Enabled = false;            }            Client.Save(items, "Event disabled.");            return true;        }    }    #region UIComponent    private class UIComponent : DynamicGridGridUIComponent<Event>    {        protected override Brush? GetCellBackground(CoreRow row, DynamicColumnBase column)        {            if(row.Get<Event, bool>(x => x.Enabled))            {                return null;            }            else            {                return Colors.Gainsboro.ToBrush(0.5);            }        }    }    protected override IDynamicGridUIComponent CreateUIComponent()    {        return new UIComponent { Parent = this };    }    #endregion    protected override void DoReconfigure(DynamicGridOptions options)    {        base.DoReconfigure(options);        if (Security.IsAllowed<CanManageEvents>())        {            options.AddRows = true;            options.EditRows = true;            options.DeleteRows = true;        }        else        {            options.AddRows = false;            options.EditRows = false;            options.DeleteRows = false;        }    }    #region Action Columns    private FrameworkElement? Subscribed_ToolTip(DynamicActionColumn column, CoreRow? row)    {        if(row is null)        {            return column.TextToolTip("Are you subscribed to this event?");        }        else        {            return _subscribedSet.TryGetValue(row.Get<Event, Guid>(x => x.ID), out var type)                ? (type == EventSubscriberType.Notification                    ? column.TextToolTip("You are subscribed to this event by notification.")                    : column.TextToolTip("You are subscribed to this event by email."))                : null;        }    }    private void BuildMenu(DynamicMenuColumn column, CoreRow? row)    {        if (row is null) return;        var menu = column.GetMenu();        var eventID = row.Get<Event, Guid>(x => x.ID);        if (_subscribedSet.TryGetValue(eventID, out var type))        {            menu.AddItem("Unsubscribe", null, row, Unsubscribe);            if(type == EventSubscriberType.Notification)            {                menu.AddItem("Subscribe by Email", null, (row, EventSubscriberType.Email), ChangeSubscription);            }            else            {                menu.AddItem("Subscribe by Notification", null, (row, EventSubscriberType.Notification), ChangeSubscription);            }        }        else        {            menu.AddItem("Subscribe by Notification", null, (row, EventSubscriberType.Notification), Subscribe);            menu.AddItem("Subscribe by Email", null, (row, EventSubscriberType.Email), Subscribe);        }    }    private BitmapImage? Menu_GetImage(CoreRow? row)    {        if (row is null) return _notification;        return _subscribedSet.TryGetValue(row.Get<Event, Guid>(x => x.ID), out var type)            ? (type == EventSubscriberType.Notification ? _notification : _email)            : null;    }    private void ChangeSubscription((CoreRow row, EventSubscriberType Notification) tuple)    {        Unsubscribe(tuple.row, false);        Subscribe(tuple);    }    private void Subscribe((CoreRow row, EventSubscriberType type) tuple)    {        var ev = tuple.row.ToObject<Event>();        var subscriber = new EventSubscriber();        subscriber.Event.CopyFrom(ev);        subscriber.Employee.ID = EmployeeID;        subscriber.SubscriberType = tuple.type;        Client.Save(subscriber, "");        _subscribedSet.Add(ev.ID, subscriber.SubscriberType);        Refresh(false, true);    }    private void Unsubscribe(CoreRow row)    {        Unsubscribe(row, true);    }    private void Unsubscribe(CoreRow row, bool refresh)    {        var eventID = row.Get<Event, Guid>(x => x.ID);        var subscriber = Client.Query(            new Filter<EventSubscriber>(x => x.Employee.ID).IsEqualTo(EmployeeID)                .And(x => x.Event.ID).IsEqualTo(eventID),            Columns.None<EventSubscriber>().Add(x => x.ID))            .ToObjects<EventSubscriber>().FirstOrDefault();        if(subscriber is not null)        {            Client.Delete(subscriber, "");        }        _subscribedSet.Remove(eventID);        if (refresh)        {            Refresh(false, true);        }    }    #endregion    private readonly Column<Event> EventTypeColumn = new(x => x.EventType);    private readonly Column<Event> NotificationExpressionColumn = new(x => x.NotificationExpression);    private IEventData? EventData;    protected override void BeforeLoad(IDynamicEditorForm form, Event[] items)    {        base.BeforeLoad(form, items);        form.ReadOnly = !Security.IsAllowed<CanManageEvents>();        var ev = items.First();        IEventData? data = null;        if(ev.Data is not null && ev.Data.Length != 0)        {            data = EventUtils.Deserialize(ev.Data);        }        EventData = data;    }    protected override void CustomiseEditor(IDynamicEditorForm form, Event[] items, DynamicGridColumn column, BaseEditor editor)    {        base.CustomiseEditor(form, items, column, editor);        if(EventTypeColumn.IsEqualTo(column.ColumnName) && editor is EnumLookupEditor enumEditor)        {            var ev = items.First();            var editButton = new EditorButton(ev, "Edit Event", 100, (e, i) => EditEvent_Click(form, e, i), false);            enumEditor.Buttons = [editButton];        }        else if(NotificationExpressionColumn.IsEqualTo(column.ColumnName) && editor is ExpressionEditor exprEditor)        {            exprEditor.OnGetVariables += ExprEditor_OnGetVariables;        }    }    private IEnumerable<string> ExprEditor_OnGetVariables()    {        return EventData?.Event.DataModelDefinition().GetVariables().Select(x => x.Name) ?? [];    }    private void EditEvent_Click(IDynamicEditorForm form, object editor, object? item)    {        if (item is not Event ev) return;        var type = ev.EventType;        var data = EventData;        if(EventEditor.Run(ref type, ref data))        {            EventData = data;            ev.EventType = type;            form.SetEditorValue(nameof(Event.EventType), type);            if(data is not null)            {                ev.Data = EventUtils.Serialize(data);            }            else            {                ev.Data = "";            }        }        else        {            // We have to 'cancel' by just re-deserialising.            if(ev.Data is not null && ev.Data.Length != 0)            {                EventData = EventUtils.Deserialize(ev.Data);            }        }    }    protected override void Reload(Filters<Event> criteria, Columns<Event> columns, ref SortOrder<Event>? sort, CancellationToken token, Action<CoreTable?, Exception?> action)    {        if (!Security.IsAllowed<CanManageEvents>())        {            criteria.Add(new Filter<Event>(x => x.Visible).IsEqualTo(true));        }        base.Reload(criteria, columns, ref sort, token, (data, error) =>        {            if(data is not null)            {                var ids = data.ExtractValues<Event, Guid>(x => x.ID);                _subscribedSet = Client.Query(                    new Filter<EventSubscriber>(x => x.Employee.ID).IsEqualTo(EmployeeID)                        .And(x => x.Event.ID).InList(ids),                    Columns.None<EventSubscriber>().Add(x => x.Event.ID).Add(x => x.SubscriberType))                    .ToObjects<EventSubscriber>().ToDictionary(x => x.Event.ID, x => x.SubscriberType);            }            action(data, error);        });    }}
 |