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>
package org.primefaces.showcase.view.data.timeline;
import org.primefaces.component.timeline.TimelineUpdater;
import org.primefaces.event.timeline.TimelineDragDropEvent;
import org.primefaces.model.timeline.TimelineEvent;
import org.primefaces.model.timeline.TimelineModel;
import org.primefaces.showcase.domain.Event;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.event.AjaxBehaviorEvent;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
@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;
    }
}
package org.primefaces.showcase.domain;
import java.io.Serializable;
import java.time.LocalDateTime;
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;
    }
}