[ELMA3] Создание собственных событий в календаре
В статье приведен пример создания собственных событий в календаре для объекта типа Справочник IDelivery. Данный справочник служит для фиксирования заказов на доставку. Справочник IDelivery содержит следующие поля:
- Базовые поля (Наименование, Дата создания, Дата изменения, Автор создания, Автор изменения);
- Дата отправки (Дата/время);
- Планируемая дата доставки (Дата/время);
- Адрес доставки (Текст);
- Посылка доставлена (Да/нет);
- Исполнитель (Пользователь, тип связи - Одиночная);
- Информировать (Пользователь, тип связи – Многие-ко-многим).
При использовании данных свойств будет доступно следующее:
- отображение всего срока события (от Даты начала до Даты окончания события);
- отображение места события (в примере за место отвечает поле Адрес доставки);
- отображение завершения события (в примере используется поле Посылка доставлена, если значение будет Да, то в календаре событие будет зачеркнутым);
- возможность информировать несколько участников (поле Информировать).
Пример отображения данных
Рис. 1. Событие в календаре для объекта
Рис. 2. Завершенное событие и место события
Методы расширения (интерфейса) ICalendarItemProvider
Точка расширения (интерфейс) ICalendarItemProvider имеет следующие методы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | /// <summary> /// Уникальный идентификатор провайдера /// </summary> Guid Uid { get ; } /// <summary> /// Список событий в календаре /// </summary> /// <param name="user">Пользователь</param> /// <param name="startDate">Дата начала</param> /// <param name="endDate">Дата окончания</param> /// <param name="checkPermission">Проверять привилегии?</param> /// <param name="showExpired">Отображать ли истекшие события</param> /// <returns>Коллекцию событий в календаре</returns> ICollection<ICalendarItem> GetItems(IUser user, DateTime startDate, DateTime endDate, bool checkPermission = true , bool showExpired = false ); /// <summary> /// Список событий в календаре /// </summary> /// <param name="schedule">Календарь</param> /// <param name="startDate">Дата начала</param> /// <param name="endDate">Дата окончания</param> /// <param name="checkPermission">Проверять привилегии?</param> /// <param name="showExpired">Отображать ли истекшие события</param> /// <returns>Коллекцию событий в календаре</returns> ICollection<ICalendarItem> GetItems(ISchedule schedule, DateTime startDate, DateTime endDate, bool checkPermission = true , bool showExpired = false ); /// <summary> /// Список событий в календаре /// </summary> /// <param name="schedules">Коллекция календарей</param> /// <param name="startDate">Дата начала</param> /// <param name="endDate">Дата окончания</param> /// <param name="checkPermission">Проверять привилегии?</param> /// <param name="showExpired">Отображать ли истекшие события</param> /// <returns>Коллекцию событий в календаре</returns> ICollection<ICalendarItem> GetItems(ICollection<ISchedule> schedules, DateTime startDate, DateTime endDate, bool checkPermission = true , bool showExpired = false ); /// <summary> /// События которые можно запланировать несколько раз /// </summary> /// <param name="user">Пользователь</param> /// <returns>Коллекцию событий в календаре</returns> ICollection<ICalendarPlannedItem> GetRePlannedItems(IUser user); /// <summary> /// Не запланированные события /// </summary> /// <param name="user">Пользователь</param> /// <returns>Коллекцию событий в календаре</returns> ICollection<ICalendarPlannedItem> GetUnPlannedItems(IUser user); /// <summary> /// Получить пересекающиеся события сгруппированые по календарям /// </summary> /// <param name="schedules">Коллекция календарей</param> /// <param name="startDate">Дата начала</param> /// <param name="endDate">Дата окончания</param> /// <returns>События, сгруппированные по календарям</returns> IDictionary<ISchedule, ICollection<ICalendarItem>> CrossingItems(ICollection<ISchedule> schedules, DateTime startDate, DateTime endDate); /// <summary> /// Добавить событие в календарь /// </summary> /// <param name="user">Пользователь</param> /// <param name="id">CalendarPlannedItem.Id</param> /// <param name="startDate">Дата начала</param> /// <param name="endDate">Дата окончания</param> /// <returns>Событие календаря</returns> ICalendarItem AddItem(IUser user, string id, DateTime startDate, DateTime endDate, bool removeOther); /// <summary> /// Изменить время события событие в календарь /// </summary> /// <param name="id">ICalendarItem.Id</param> /// <param name="dayDelta">дельта смещения в днях</param> /// <param name="minuteDelta">дельта смещения в минутах</param> /// <param name="moved">смещено все событие</param> /// <returns>Событие календаря</returns> ICalendarItem ModifyTime( string id, int dayDelta, int minuteDelta, bool moved); /// <summary> /// Удалить событие /// </summary> /// <param name="id">ICalendarItem.Id</param> void Remove( string id); /// <summary> /// Календарь является внешним (события загружаются с внешних ресурсов) /// </summary> bool External { get ; } |
Пример класса точки расширения ICalendarItemProvider
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | [Component] public class CalendarItemProvider : ICalendarItemProvider { private readonly Guid _uid = new Guid( "{03B3D20A-0807-4b20-B1FC-819833399602}" ); private IDeliveryFilter GetFilter(ICollection<ISchedule> schedules, DateTime startDate, DateTime endDate) { return new InstanceOf<IDeliveryFilter> { New = { EndDate = new DateTimeRange { From = startDate, To = endDate } } }.New; } private IUser CurrentUser { get { return AuthenticationService.GetCurrentUser<IUser>(); } } public DeliveryManager DeliveryManager { get ; set ; } public ScheduleManager ScheduleManager { get ; set ; } public ISecurityService SecurityService { get ; set ; } public IEntityManager<ITaskTimePlan, long > TaskTimePlanManager { get ; set ; } public Guid Uid { get { return _uid; } } public ICollection<ICalendarItem> GetItems(IUser user, DateTime startDate, DateTime endDate, bool checkPermission = true , bool showExpired = false ) { return GetItems(ScheduleManager.GetUserSchedule(user), startDate, endDate, checkPermission, showExpired); } public ICollection<ICalendarItem> GetItems(ISchedule schedule, DateTime startDate, DateTime endDate, bool checkPermission = true , bool showExpired = false ) { return schedule.Owner != null ? GetItems( new List<ISchedule> { schedule }, startDate, endDate, checkPermission, showExpired) : new List<ICalendarItem>(); } public ICollection<ICalendarItem> GetItems(ICollection<ISchedule> schedules, DateTime startDate, DateTime endDate, bool checkPermission = true , bool showExpired = false ) { if (schedules.All(s => s.Owner == null )) return new List<ICalendarItem>(); var filter = GetFilter(schedules, startDate, endDate); IList<ICalendarItem> ret = new List<ICalendarItem>(); if (checkPermission) { ret = DeliveryManager.Find(filter, FetchOptions.All).Select(t => new DeliveryCalendarItem(t)).Cast<ICalendarItem>().ToList(); } else { SecurityService.RunWithElevatedPrivilegies(() => ret = DeliveryManager.Find(filter, FetchOptions.All).Select(t => new DeliveryCalendarItem(t)).Cast<ICalendarItem>().ToList()); } return ret; } public ICollection<ICalendarPlannedItem> GetRePlannedItems(IUser user) { return new List<ICalendarPlannedItem>(); } public ICollection<ICalendarPlannedItem> GetUnPlannedItems(IUser user) { return new List<ICalendarPlannedItem>(); } public IDictionary<ISchedule, ICollection<ICalendarItem>> CrossingItems(ICollection<ISchedule> schedules, DateTime startDate, DateTime endDate) { if (schedules.All(s => s.Owner == null )) return new Dictionary<ISchedule, ICollection<ICalendarItem>>(); startDate = new DateTime(startDate.Ticks + 1000000000); //необходимо для того, чтобы события не пересекались, если время начала одного события = времени завершения другого endDate = new DateTime(endDate.Ticks - 1000000000); //необходимо для того, чтобы события не пересекались, если время начала одного события = времени завершения другого var filter = GetFilter(schedules, startDate, endDate); var list = new List<IDelivery>(); SecurityService.RunWithElevatedPrivilegies(() => list = DeliveryManager.Find(filter, FetchOptions.All).ToList()); var ret = schedules.ToDictionary<ISchedule, ISchedule, ICollection<ICalendarItem>>(schedule => schedule, schedule => list.Where(e => e.Executor == schedule.Owner) .Select(e => new DeliveryCalendarItem(e) { OnlyInfo = !SecurityService.CanCheckPermission(PermissionProvider.ViewTaskPermission, e) || (SecurityService.CanCheckPermission(PermissionProvider.ViewTaskPermission, e) && !SecurityService.HasPermission(PermissionProvider.ViewTaskPermission, e)) }) .Cast<ICalendarItem>() .ToList() ); return ret.Where(s => s.Value.Any()).ToDictionary(s => s.Key, s => s.Value); } public ICalendarItem AddItem(IUser user, string id, DateTime startDate, DateTime endDate, bool removeOther) { return null ; } public ICalendarItem ModifyTime( string id, int dayDelta, int minuteDelta, bool moved) { return null ; } public void Remove( string id) { } public bool External { get { return false ; } } } |
Методы расширения (интерфейса) ICalendarItem
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | /// <summary> /// Идентификатор обьекта /// </summary> string Id { get ; } /// <summary> /// Идентификатор исходного обьекта /// </summary> string SourceId { get ; } /// <summary> /// Тип исходного объекта /// </summary> Guid SourceTypeUid { get ; } /// <summary> /// Дата начала /// </summary> DateTime StartDate { get ; set ; } /// <summary> /// Дата окончания /// </summary> DateTime EndDate { get ; set ; } /// <summary> /// Завершено ли событие /// </summary> bool Completed { get ; set ; } /// <summary> /// Выделять просроченные события /// </summary> bool MarkExpired { get ; } /// <summary> /// Определяет есть ли текущий пользователь в информируемых событиях /// </summary> bool ToInform { get ; } /// <summary> /// Тема события /// </summary> string Theme { get ; set ; } /// <summary> /// Место события /// </summary> string Place { get ; set ; } /// <summary> /// Кому /// </summary> string To { get ; set ; } /// <summary> /// Участники события /// </summary> IDictionary< string , string > EventUsers { get ; set ; } /// <summary> /// Описание события /// </summary> string Description { get ; set ; } /// <summary> /// Флаг означает можно ли копировать событие, перетаскиванием в календаре /// </summary> bool HasCopy { get ; set ; } /// <summary> /// Клонировать событие /// </summary> /// <returns></returns> ICalendarItem Clone(); /// <summary> /// Флаг означает что пользователь не имеет доступа к обьекту события и данные только для информации /// </summary> bool OnlyInfo { get ; set ; } /// <summary> /// Ид автора /// </summary> long CreationAuthor { get ; set ; } /// <summary> /// Событие только для показа /// </summary> bool ReadOnly { get ; set ; } /// <summary> /// Возвращает список комментариев /// </summary> /// <returns></returns> ICollection<EleWise.ELMA.Common.Models.IComment> Comments { get ; } /// <summary> /// Конфиденциален ли элемент календаря /// </summary> bool PrivateAccess { get ; } |
Пример класса точки расширения ICalendarItem
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | [Serializable] public class DeliveryCalendarItem : ICalendarItem { [ScriptIgnore] public readonly IDelivery Delivery; public DeliveryCalendarItem(IDelivery delivery, IUser currentUser = null ) { if (delivery == null ) throw new ArgumentNullException( "delivery" ); Delivery = delivery; StartDate = delivery.StartDate; EndDate = delivery.EndDate; Completed = delivery.IsComplete == true ; Theme = delivery.Name; Place = delivery != null ? delivery.Adress : "" ; Description = "" ; HasCopy = true ; OnlyInfo = false ; CreationAuthor = delivery.CreationAuthor.Id; ReadOnly = false ; var users = new List<IUser> { delivery.Executor }; if (delivery.InformTo.Any()) users.AddRange(delivery.InformTo); EventUsers = users.Distinct((a, b) => a.Id == b.Id, c => c.Id.GetHashCode()).ToDictionary(u => u.Id.ToString(), u => u.GetShortName()); } public string Id { get { return Delivery.Id.ToString(); } } public string SourceId { get { return Delivery.Id.ToString(); } } public Guid SourceTypeUid { get { return InterfaceActivator.UID<IDelivery>(); } } public DateTime StartDate { get ; set ; } public DateTime EndDate { get ; set ; } public DateTime? LimitStartDate { get ; set ; } public DateTime? LimitEndDate { get ; set ; } public CalendarEventPeriod Period { get ; set ; } public bool Completed { get ; set ; } public bool MarkExpired { get { return false ; } } public bool ToInform { get ; private set ; } public string Theme { get ; set ; } public string Place { get ; set ; } public string To { get ; set ; } public IDictionary< string , string > EventUsers { get ; set ; } public string Description { get ; set ; } public bool Periodical { get ; private set ; } public ICalendarItem Template { get ; set ; } public bool HasCopy { get ; set ; } public bool OnlyInfo { get ; set ; } public long CreationAuthor { get ; set ; } public bool ReadOnly { get ; set ; } public ICalendarItem Clone() { return new DeliveryCalendarItem(Delivery); } public ICollection<EleWise.ELMA.Common.Models.IComment> Comments { get { return null ; } } public bool PrivateAccess { get { return false ; } } } |
При использовании данного примера для реализации Ваших собственных событий в календаре – события будут без иконок и без ссылок. Чтобы записи в календаре имели ссылки на объекты и иконки, необходимо реализовать следующие точки расширения: IObjectIcon и IObjectLink. Данные точки расширения необходимо реализовать для объекта DeliveryCalendarItem (реализованного в данном примере).