Drag events from the list on the left side and drop them onto the timeline.
<style>
.ui-datalist-item .ui-draggable:hover {
background: var(--surface-c);
}
.ui-datalist-data {
margin: 0;
padding: 0;
list-style: none;
}
.ui-datalist-item {
margin-bottom: .5rem;
width: 100%;
}
</style>
<div class="card">
<h:form id="form">
<p:growl id="growl" showSummary="true" showDetail="false">
<p:autoUpdate />
</p:growl>
<div style="float: left; width: 130px;">
<p:dataList id="eventsList" value="#{dndTimelineView.events}" var="event" itemType="circle">
<p:outputPanel id="eventBox" style="z-index:9999; cursor:move;" styleClass="p-2">
#{event.name}
</p:outputPanel>
<p:draggable for="eventBox" revert="true" helper="clone" cursor="move"/>
</p:dataList>
</div>
<p:timeline id="timeline" value="#{dndTimelineView.model}" var="event" editable="true" eventMargin="10"
eventMarginAxis="0" minHeight="400" start="#{dndTimelineView.start}" end="#{dndTimelineView.end}"
style="margin-left:135px;" dropActiveStyleClass="ui-state-highlight"
dropHoverStyleClass="ui-state-hover">
<p:ajax event="drop" listener="#{dndTimelineView.onDrop}" global="false" update="eventsList" />
<h:panelGrid columns="1">
<h:outputText value="#{event.name}" />
<h:outputText value="#{event.start}">
<f:convertDateTime type="localDateTime" pattern="hh:mm:ss a" />
</h:outputText>
<h:outputText value="#{event.end}">
<f:convertDateTime type="localDateTime" pattern="hh:mm:ss a" />
</h:outputText>
</h:panelGrid>
</p:timeline>
</h:form>
</div>
@Named("dndTimelineView")
@ViewScoped
public class DndTimelineView implements Serializable {
private TimelineModel<Event, ?> model;
private LocalDateTime start;
private LocalDateTime end;
private final List<Event> events = new ArrayList<>();
@PostConstruct
public void init() {
start = LocalDateTime.now().minusHours(4);
end = LocalDateTime.now().plusHours(8);
model = new TimelineModel<>();
for (int i = 1; i <= 10; i++) {
events.add(new Event("Event " + i));
}
}
public void onDrop(TimelineDragDropEvent<Event> e) {
// get dragged model object (event class) if draggable item is within a data iteration component,
// update event's start and end dates.
Event dndEvent = e.getData();
dndEvent.setStart(e.getStartDate());
dndEvent.setEnd(e.getEndDate());
// create a timeline event (not editable)
TimelineEvent event = TimelineEvent.builder()
.data(dndEvent)
.startDate(e.getStartDate())
.endDate(e.getEndDate())
.editable(false)
.group(e.getGroup())
.build();
// add a new event
TimelineUpdater timelineUpdater = TimelineUpdater.getCurrentInstance(":form:timeline");
model.add(event, timelineUpdater);
// remove from the list of all events
events.remove(dndEvent);
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "The " + dndEvent.getName() + " was added", null);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onSwitchTimeZone(AjaxBehaviorEvent e) {
model.clear();
}
public TimelineModel<Event, ?> getModel() {
return model;
}
public List<Event> getEvents() {
return events;
}
public LocalDateTime getStart() {
return start;
}
public LocalDateTime getEnd() {
return end;
}
}
public class Event implements Serializable {
private String name;
private LocalDateTime start;
private LocalDateTime end;
public Event(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDateTime getStart() {
return start;
}
public void setStart(LocalDateTime start) {
this.start = start;
}
public LocalDateTime getEnd() {
return end;
}
public void setEnd(LocalDateTime end) {
this.end = end;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Event event = (Event) o;
if (name != null ? !name.equals(event.name) : event.name != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
}