1. Привязка календаря к данным
В этом разделе вы создадите:
-
Сущность JPA
Meeting
. -
Компонент
FullCalendar
с поставщиком данных.
Событие встречи
Сущность Meeting
будет представлять событие в компоненте FullCalendar
. Для корректного отображения требуются определенные свойства:
-
name
- название события. -
startDate
- дата и время начала события. Компонент не будет отображать события безstartDate
. -
endDate
- дата окончания события. ЕслиendDate
не указано, компонент применит продолжительность по умолчанию на основе свойстваallDay
. В этом руководстве свойствоallDay
не используется; следовательно, события рассматриваются как события, не охватывающие весь день.
Создание сущности Meeting
Подробные инструкции по созданию сущностей JPA смотрите в разделе Простой CRUD самоучителя.
Сущность Meeting
имеет следующие атрибуты:
-
name
типаString
type. Установите флажок Mandatory. -
startDate
типаLocalDateTime
. Установите флажок Mandatory. -
endDate
типаLocalDateTime
. -
user
- тип атрибутаAssociation
, сущностьUser
в качестве типа Java и кардинальность many-to-one (многие-к-одному). Установите флажок Mandatory.
Сущность Meeting
не требует стандартных экранов списка и деталей, поскольку она будет генерироваться программно и отображаться в компоненте FullCalendar
.
Генерация Meeting
После того как пользователь завершит все этапы онбординга, приложение сгенерирует событие встречи для обсуждения выполненных задач. Это событие будет отображаться в экране Мой календарь пользователя.
Наилучший момент для проверки того, завершил ли пользователь все этапы, - это событие PreSaveEvent контекста данных (DataContext). Слушатель этого события проверяет наличие незавершенных этапов адаптации. Если незавершенных этапов нет, создается новое событие встречи.
@Subscribe(target = Target.DATA_CONTEXT)
public void onPreSave(final DataContext.PreSaveEvent event) {
List<UserStep> userSteps = userStepsDc.getItems().stream()
.filter(us -> us.getCompletedDate() == null)
.toList();
if (userSteps.isEmpty()) {
generateOnboardingResultsMeeting();
}
}
Далее мы реализуем метод generateOnboardingResultsMeeting()
. Этот метод создает экземпляр события Meeting
, запланированного на следующий рабочий день.
protected void generateOnboardingResultsMeeting() {
Meeting meeting = dataContext.create(Meeting.class); (1)
meeting.setName("Results meeting");
meeting.setUser((User) currentAuthentication.getUser());
int inDays = LocalDate.now().getDayOfWeek() == DayOfWeek.FRIDAY ? 3 : 1; (2)
LocalDateTime start = LocalDateTime.of( (3)
LocalDate.now().plusDays(inDays),
LocalTime.of(9, 30));
meeting.setStartDate(start);
meeting.setEndDate(start.plusMinutes(30));
}
1 | Создает и добавляет новый экземпляр Meeting в DataContext , автоматически сохраняя сущность. |
2 | Вычисляет следующий рабочий день; если сегодня пятница, встреча планируется на понедельник. |
3 | Устанавливает дату и время начала встречи на 9:30 утра следующего рабочего дня. |
Добавление компонентов в MyCalendar
Сначала создайте новый пустой экран с именем MyCalendar.
Studio сгенерирует и отобразит пустой экран в дизайнере.
Загрузка данных
Перед добавлением компонента FullCalendar
создайте контейнер коллекций для сущности Meeting
.
В панели действий нажмите кнопку Add Component, перейдите в раздел Data components и дважды щелкните Collection container. В появившемся диалоговом окне выберите Meeting
в поле Entity и нажмите OK.
<collection id="meetingsDc" class="com.company.onboarding.entity.Meeting">
<loader id="meetingsDl" readOnly="true">
<query>
<![CDATA[select e from Meeting e]]>
</query>
</loader>
<fetchPlan extends="_base"/>
</collection>
Текущая конфигурация загрузчика данных извлекает все события от всех пользователей. Однако пользователи должны видеть только свои собственные события. Для реализации этой фильтрации необходимо изменить запрос JPQL - либо с помощью редактора, либо вручную - добавив условие, которое ограничивает результаты текущим пользователем, который вошел в систему:
<query>
<![CDATA[select e from Meeting e where e.user = :user]]>
</query>
Мы получаем данные о текущем авторизованном пользователе из бина CurrentAuthentication
и передаем эту информацию загрузчику данных в обработчике события BeforeShowEvent:
-
Подпишитесь на событие
BeforeShowEvent
. -
Инжектируйте загрузчик
meetingsDl
. -
Инжектируйте бин
CurrentAuthentication
.
Теперь мы можем установить параметр для загрузчика, чтобы он извлекал события для текущего пользователя:
@ViewComponent
private CollectionLoader<Meeting> meetingsDl;
@Autowired
private CurrentAuthentication currentAuthentication;
@Subscribe
public void onBeforeShow(final BeforeShowEvent event) {
final User user = (User) currentAuthentication.getUser();
meetingsDl.setParameter("user", user);
meetingsDl.load();
}
Добавление компонента FullCalendar
В панели действий нажмите Add Component, найдите элемент FullCalendar
и дважды щелкните по нему.
После этого будет создан новый элемент calendar
. Настройте атрибуты id
, height
и width
, как показано ниже.
<calendar:calendar id="calendar"
height="100%"
width="100%"/>
Добавление поставщика данных
Поставщик данных является источником событий, отображаемых в FullCalendar
. Существуют различные типы поставщиков данных, но мы будем использовать поставщик данных на основе контейнера данных.
Чтобы добавить ContainerDataProvider в компонент FullCalendar
:
-
Выберите компонент
calendar
в панели структуры Jmix UI или в XML-дескрипторе экрана. -
Нажмите кнопку Add на панели инспектора.
-
В выпадающем меню выберите Data Providers → ContainerDataProvider.
В появившемся диалоговом окне выберите meetingsDc
.
Элемент containerDataProvider
позволяет настроить сопоставление свойств сущности. Сущность Meeting
содержит следующие свойства:
-
name
-
startDate
-
endDate
Поэтому следует указать следующие атрибуты:
<calendar:dataProviders>
<calendar:containerDataProvider dataContainer="meetingsDc"
title="name"
startDateTime="startDate"
endDateTime="endDate"/>
</calendar:dataProviders>
Давайте посмотрим: полное описание нашего календаря выглядит следующим образом:
<calendar:calendar id="calendar"
height="100%"
width="100%">
<calendar:dataProviders>
<calendar:containerDataProvider dataContainer="meetingsDc"
title="name"
startDateTime="startDate"
endDateTime="endDate"/>
</calendar:dataProviders>
</calendar:calendar>
Запустите приложение и войдите в систему как пользователь admin
. У пользователя admin
нет шагов онбординга, поэтому необходимо их сгенерировать:
-
Перейдите в экран
User.list
, выбрав Users в меню приложения. -
Выберите пользователя
admin
в DataGrid и нажмите кнопку Edit. Затем заполните поле Joining Date, сгенерируйте шаги онбординга и сохраните изменения. -
Перейдите в экран
MyCalendar
, выбрав My Calendar в меню приложения.