Interactive Demo
Explore Oorian's core capabilities with this interactive Task Manager demo.
Add New Task
Task List
| Task | Priority | Assignee | Due Date | Status | Actions |
|---|---|---|---|---|---|
Implement user authentication TASK-101 | High | AJ | Dec 28 | Pending | |
Fix navigation bug on mobile TASK-102 | Urgent | BS | Dec 27 | Overdue | |
Write API documentation TASK-103 | Medium | CW | Dec 30 | Pending | |
Design new dashboard layout TASK-104 | High | DB | Jan 02 | Pending | |
Optimize database queries TASK-105 | Medium | AJ | Jan 05 | Pending | |
Add export to PDF feature TASK-106 | Low | BS | Dec 25 | Completed | |
Update dependencies TASK-107 | Low | CW | Dec 24 | Completed | |
Review pull requests TASK-108 | Medium | DB | Dec 26 | Completed |
What This Demo Shows
Rich HTML Elements
Div, Form, Input, Select, Table, Button, and more — all created as Java objects with type-safe styling methods.
Form Handling
Text inputs, textareas, selects, and date pickers. Form values are read server-side in Java event handlers.
Data Tables
Dynamic tables built from Java collections. Add and remove rows programmatically with automatic UI updates.
Event System
JDK-style event listeners for clicks and changes. All processing happens on the server in Java.
Real-Time Updates
Server-side changes automatically push to the browser. Call sendUpdate() and the UI refreshes instantly.
Pure Java
No JavaScript, HTML templates, or frontend build tools. Everything is built programmatically in Java.
Explore More Demos
Browser APIs
Access browser features from Java: Geolocation, Clipboard, Storage, Notificat...
Weather Forecast
Real-time weather app with current conditions, 10-day forecast, hourly temper...
Sales Dashboard
Line and bar charts showing monthly sales data with smooth animations and too...
/***********************************************************************************
* Copyright (c) 2025 Corvus Engineering
* All Rights Reserved
***********************************************************************************/
package com.oorian.website.demos;
import com.oorian.Parameters;
import com.oorian.css.*;
import com.oorian.html.Element;
import com.oorian.html.elements.*;
import com.oorian.messaging.events.client.FormEvent;
import com.oorian.messaging.events.client.FormListener;
import com.oorian.messaging.events.client.InputChangeEvent;
import com.oorian.messaging.events.client.InputCompleteEvent;
import com.oorian.messaging.events.client.InputListener;
import com.oorian.messaging.events.client.MouseClickListener;
import com.oorian.messaging.events.client.MouseClickedEvent;
import java.util.ArrayList;
import java.util.List;
/****************************************************************************************************************
* Demo component showcasing pure Oorian core features.
* Displays an interactive Task Manager with forms, tables, and real-time updates.
* All interactivity is handled server-side with Java event handlers.
****************************************************************************************************************/
public class OorianCoreDemo extends Div implements FormListener, InputListener
{
private final List<Task> tasks = new ArrayList<>();
private int taskCounter = 100;
// Form elements
private OorianForm taskForm;
private TextInput taskNameInput;
private TextArea descriptionInput;
private Select prioritySelect;
private Input dateInput;
private Select assigneeSelect;
// Table body for dynamic updates
private Tbody taskTableBody;
// Stat cards for updating counts
private Span totalTasksValue;
private Span pendingValue;
private Span overdueValue;
private Span completedValue;
// Filter elements
private TextInput searchInput;
private Select statusFilter;
private Select priorityFilter;
public OorianCoreDemo()
{
initializeTasks();
buildDemo();
}
private void initializeTasks()
{
tasks.add(new Task(++taskCounter, "Implement user authentication", "High", "Alice Johnson", "Dec 28", "Pending"));
tasks.add(new Task(++taskCounter, "Fix navigation bug on mobile", "Urgent", "Bob Smith", "Dec 27", "Overdue"));
tasks.add(new Task(++taskCounter, "Write API documentation", "Medium", "Carol Williams", "Dec 30", "Pending"));
tasks.add(new Task(++taskCounter, "Design new dashboard layout", "High", "David Brown", "Jan 02", "Pending"));
tasks.add(new Task(++taskCounter, "Optimize database queries", "Medium", "Alice Johnson", "Jan 05", "Pending"));
tasks.add(new Task(++taskCounter, "Add export to PDF feature", "Low", "Bob Smith", "Dec 25", "Completed"));
tasks.add(new Task(++taskCounter, "Update dependencies", "Low", "Carol Williams", "Dec 24", "Completed"));
tasks.add(new Task(++taskCounter, "Review pull requests", "Medium", "David Brown", "Dec 26", "Completed"));
}
private void buildDemo()
{
setPadding("80px 40px");
setBackgroundColor("#ffffff");
Div container = new Div();
container.setMaxWidth("1200px");
container.setMargin("0 auto");
// Section title
H2 title = new H2();
title.setText("Interactive Demo");
title.setColor("#1f2937");
title.setFontSize("32px");
title.setFontWeight("700");
title.setMarginTop("0");
title.setMarginBottom("16px");
container.addElement(title);
P subtitle = new P();
subtitle.setText("Explore Oorian's core capabilities with this interactive Task Manager demo.");
subtitle.setColor("#6b7280");
subtitle.setFontSize("16px");
subtitle.setMarginBottom("40px");
container.addElement(subtitle);
// Demo content area
Div demoContent = new Div();
demoContent.setBackgroundColor("#f8fafc");
demoContent.setBorderRadius("12px");
demoContent.setPadding("40px");
createDemoContent(demoContent);
container.addElement(demoContent);
// Code explanation
container.addElement(createCodeExplanation());
addElement(container);
}
private void createDemoContent(Div container)
{
// Stats Row
container.addElement(createStatsRow());
// Main content grid
Div mainGrid = new Div();
mainGrid.setDisplay(Display.GRID);
mainGrid.addStyleAttribute("grid-template-columns", "320px minmax(0, 1fr)");
mainGrid.addStyleAttribute("gap", "30px");
mainGrid.setMarginTop("30px");
// Left column: Add Task Form
mainGrid.addElement(createTaskForm());
// Right column: Task Table
Div tableWrapper = new Div();
tableWrapper.addStyleAttribute("overflow-x", "auto");
tableWrapper.addStyleAttribute("min-width", "0");
tableWrapper.addElement(createTaskTable());
mainGrid.addElement(tableWrapper);
container.addElement(mainGrid);
}
private Div createStatsRow()
{
Div statsRow = new Div();
statsRow.setDisplay(Display.GRID);
statsRow.addStyleAttribute("grid-template-columns", "repeat(4, 1fr)");
statsRow.addStyleAttribute("gap", "20px");
totalTasksValue = new Span();
pendingValue = new Span();
overdueValue = new Span();
completedValue = new Span();
statsRow.addElement(createStatCard("Total Tasks", totalTasksValue, "#3b82f6", "\uD83D\uDCCB"));
statsRow.addElement(createStatCard("Pending", pendingValue, "#f59e0b", "\u23F3"));
statsRow.addElement(createStatCard("Overdue", overdueValue, "#ef4444", "\u26A0\uFE0F"));
statsRow.addElement(createStatCard("Completed", completedValue, "#10b981", "\u2705"));
updateStats();
return statsRow;
}
private void updateStats()
{
int total = tasks.size();
int pending = 0;
int overdue = 0;
int completed = 0;
for (Task task : tasks)
{
switch (task.status)
{
case "Pending":
pending++;
break;
case "Overdue":
overdue++;
break;
case "Completed":
completed++;
break;
}
}
totalTasksValue.setText(String.valueOf(total));
pendingValue.setText(String.valueOf(pending));
overdueValue.setText(String.valueOf(overdue));
completedValue.setText(String.valueOf(completed));
}
private Div createStatCard(String label, Span valueSpan, String color, String icon)
{
Div card = new Div();
card.setBackgroundColor("#ffffff");
card.setBorderRadius("12px");
card.setPadding("20px");
card.addStyleAttribute("box-shadow", "0 1px 3px rgba(0, 0, 0, 0.1)");
card.setBorderLeft("4px solid " + color);
Div header = new Div();
header.setDisplay(Display.FLEX);
header.setJustifyContent(JustifyContent.SPACE_BETWEEN);
header.setAlignItems(AlignItems.CENTER);
header.setMarginBottom("8px");
Span iconSpan = new Span();
iconSpan.setText(icon);
iconSpan.setFontSize("24px");
header.addElement(iconSpan);
valueSpan.setColor(color);
valueSpan.setFontSize("28px");
valueSpan.setFontWeight("700");
header.addElement(valueSpan);
card.addElement(header);
Div labelDiv = new Div();
labelDiv.setText(label);
labelDiv.setColor("#6b7280");
labelDiv.setFontSize("14px");
labelDiv.setFontWeight("500");
card.addElement(labelDiv);
return card;
}
private Div createTaskForm()
{
Div formCard = new Div();
formCard.setBackgroundColor("#ffffff");
formCard.setBorderRadius("12px");
formCard.setPadding("24px");
formCard.addStyleAttribute("box-shadow", "0 1px 3px rgba(0, 0, 0, 0.1)");
H3 formTitle = new H3();
formTitle.setText("Add New Task");
formTitle.setColor("#1f2937");
formTitle.setFontSize("18px");
formTitle.setFontWeight("600");
formTitle.setMarginTop("0");
formTitle.setMarginBottom("20px");
formCard.addElement(formTitle);
// Create OorianForm and register FormListener
taskForm = new OorianForm();
taskForm.registerListener(this, FormEvent.class);
// Task Name
taskNameInput = new TextInput();
taskNameInput.setName("taskName");
taskNameInput.setPlaceholder("Enter task name...");
taskNameInput.setWidth("100%");
taskNameInput.setPadding("12px");
taskNameInput.setBorder("1px solid #d1d5db");
taskNameInput.setBorderRadius("8px");
taskNameInput.setFontSize("14px");
taskForm.addElement(createFormField("Task Name", taskNameInput));
// Description
descriptionInput = new TextArea();
descriptionInput.setName("description");
descriptionInput.addAttribute("placeholder", "Task description...");
descriptionInput.addAttribute("rows", "3");
descriptionInput.setWidth("100%");
descriptionInput.setPadding("12px");
descriptionInput.setBorder("1px solid #d1d5db");
descriptionInput.setBorderRadius("8px");
descriptionInput.setFontSize("14px");
descriptionInput.addStyleAttribute("font-family", "inherit");
descriptionInput.addStyleAttribute("resize", "vertical");
taskForm.addElement(createFormField("Description", descriptionInput));
// Priority Select
prioritySelect = new Select();
prioritySelect.setName("priority");
prioritySelect.setWidth("100%");
prioritySelect.setPadding("12px");
prioritySelect.setBorder("1px solid #d1d5db");
prioritySelect.setBorderRadius("8px");
prioritySelect.setFontSize("14px");
prioritySelect.setBackgroundColor("#ffffff");
prioritySelect.addOption(createOption("low", "Low Priority"));
prioritySelect.addOption(createOption("medium", "Medium Priority", true));
prioritySelect.addOption(createOption("high", "High Priority"));
prioritySelect.addOption(createOption("urgent", "Urgent"));
taskForm.addElement(createFormField("Priority", prioritySelect));
// Due Date
dateInput = new Input();
dateInput.setName("dueDate");
dateInput.addAttribute("type", "date");
dateInput.setWidth("100%");
dateInput.setPadding("12px");
dateInput.setBorder("1px solid #d1d5db");
dateInput.setBorderRadius("8px");
dateInput.setFontSize("14px");
taskForm.addElement(createFormField("Due Date", dateInput));
// Assignee Select
assigneeSelect = new Select();
assigneeSelect.setName("assignee");
assigneeSelect.setWidth("100%");
assigneeSelect.setPadding("12px");
assigneeSelect.setBorder("1px solid #d1d5db");
assigneeSelect.setBorderRadius("8px");
assigneeSelect.setFontSize("14px");
assigneeSelect.setBackgroundColor("#ffffff");
assigneeSelect.addElement(createOption("alice", "Alice Johnson"));
assigneeSelect.addElement(createOption("bob", "Bob Smith"));
assigneeSelect.addElement(createOption("carol", "Carol Williams"));
assigneeSelect.addElement(createOption("david", "David Brown"));
taskForm.addElement(createFormField("Assignee", assigneeSelect));
// Submit Button
Button submitBtn = new Button();
submitBtn.setText("Add Task");
submitBtn.setWidth("100%");
submitBtn.setBackgroundColor("#2563eb");
submitBtn.setColor("#ffffff");
submitBtn.setPadding("14px 24px");
submitBtn.setBorder("none");
submitBtn.setBorderRadius("8px");
submitBtn.setFontSize("15px");
submitBtn.setFontWeight("600");
submitBtn.addStyleAttribute("cursor", "pointer");
submitBtn.addStyleAttribute("transition", "background-color 0.2s");
taskForm.addElement(submitBtn);
formCard.addElement(taskForm);
return formCard;
}
private Option createOption(String value, String text)
{
return createOption(value, text, false);
}
private Option createOption(String value, String text, boolean selected)
{
Option opt = new Option();
opt.setValue(value);
opt.setText(text);
if (selected)
{
opt.addAttribute("selected", "selected");
}
return opt;
}
private Div createFormField(String labelText, Element input)
{
Div field = new Div();
field.setMarginBottom("20px");
Label label = new Label();
label.setText(labelText);
label.setColor("#374151");
label.setFontSize("14px");
label.setFontWeight("500");
label.setDisplay(Display.BLOCK);
label.setMarginBottom("8px");
field.addElement(label);
field.addElement(input);
return field;
}
private Div createFilterBar()
{
Div filterBar = new Div();
filterBar.setDisplay(Display.FLEX);
filterBar.setAlignItems(AlignItems.CENTER);
filterBar.addStyleAttribute("gap", "16px");
filterBar.setMarginBottom("20px");
filterBar.setFlexWrap(FlexWrap.WRAP);
// Search input
searchInput = new TextInput();
searchInput.setName("search");
searchInput.setPlaceholder("Search tasks...");
searchInput.setWidth("200px");
searchInput.setPadding("10px 12px");
searchInput.setBorder("1px solid #d1d5db");
searchInput.setBorderRadius("6px");
searchInput.setFontSize("14px");
searchInput.registerListener(this, InputChangeEvent.class);
filterBar.addElement(searchInput);
// Status filter
statusFilter = new Select();
statusFilter.setName("statusFilter");
statusFilter.setWidth("140px");
statusFilter.setPadding("10px 12px");
statusFilter.setBorder("1px solid #d1d5db");
statusFilter.setBorderRadius("6px");
statusFilter.setFontSize("14px");
statusFilter.setBackgroundColor("#ffffff");
statusFilter.addOption(createOption("all", "All Status"));
statusFilter.addOption(createOption("pending", "Pending"));
statusFilter.addOption(createOption("overdue", "Overdue"));
statusFilter.addOption(createOption("completed", "Completed"));
statusFilter.registerListener(this, InputChangeEvent.class);
filterBar.addElement(statusFilter);
// Priority filter
priorityFilter = new Select();
priorityFilter.setName("priorityFilter");
priorityFilter.setWidth("140px");
priorityFilter.setPadding("10px 12px");
priorityFilter.setBorder("1px solid #d1d5db");
priorityFilter.setBorderRadius("6px");
priorityFilter.setFontSize("14px");
priorityFilter.setBackgroundColor("#ffffff");
priorityFilter.addOption(createOption("all", "All Priority"));
priorityFilter.addOption(createOption("urgent", "Urgent"));
priorityFilter.addOption(createOption("high", "High"));
priorityFilter.addOption(createOption("medium", "Medium"));
priorityFilter.addOption(createOption("low", "Low"));
priorityFilter.registerListener(this, InputChangeEvent.class);
filterBar.addElement(priorityFilter);
// Filter button
Button filterBtn = new Button();
filterBtn.setText("Filter");
filterBtn.setBackgroundColor("#4b5563");
filterBtn.setColor("#ffffff");
filterBtn.setPadding("10px 20px");
filterBtn.setBorder("none");
filterBtn.setBorderRadius("6px");
filterBtn.setFontSize("14px");
filterBtn.setFontWeight("500");
filterBtn.addStyleAttribute("cursor", "pointer");
filterBtn.registerListener(new FilterButtonListener(), MouseClickedEvent.class);
filterBar.addElement(filterBtn);
// Clear button
Button clearBtn = new Button();
clearBtn.setText("Clear");
clearBtn.setBackgroundColor("#f3f4f6");
clearBtn.setColor("#4b5563");
clearBtn.setPadding("10px 20px");
clearBtn.setBorder("1px solid #d1d5db");
clearBtn.setBorderRadius("6px");
clearBtn.setFontSize("14px");
clearBtn.setFontWeight("500");
clearBtn.addStyleAttribute("cursor", "pointer");
clearBtn.registerListener(new ClearFilterButtonListener(), MouseClickedEvent.class);
filterBar.addElement(clearBtn);
return filterBar;
}
/****************************************************************************************************************
* Inner class to handle filter button clicks.
****************************************************************************************************************/
private class FilterButtonListener implements MouseClickListener
{
@Override
public void onEvent(MouseClickedEvent event)
{
applyFilters();
}
}
/****************************************************************************************************************
* Inner class to handle clear filter button clicks.
****************************************************************************************************************/
private class ClearFilterButtonListener implements MouseClickListener
{
@Override
public void onEvent(MouseClickedEvent event)
{
clearFilters();
}
}
/****************************************************************************************************************
* Applies the current filter settings to the task table.
****************************************************************************************************************/
private void applyFilters()
{
rebuildTaskTable();
sendUpdate();
}
/****************************************************************************************************************
* Clears all filters and shows all tasks.
****************************************************************************************************************/
private void clearFilters()
{
searchInput.setValue("");
statusFilter.setSelectedIndex(0);
priorityFilter.setSelectedIndex(0);
rebuildTaskTable();
sendUpdate();
}
/****************************************************************************************************************
* Checks if a task matches the current filter criteria.
****************************************************************************************************************/
private boolean matchesFilters(Task task, String searchText, String statusValue, String priorityValue)
{
// Search text filter
if (searchText != null && !searchText.trim().isEmpty())
{
String search = searchText.toLowerCase().trim();
boolean matchesSearch = task.name.toLowerCase().contains(search) ||
task.assignee.toLowerCase().contains(search) ||
("TASK-" + task.id).toLowerCase().contains(search);
if (!matchesSearch)
{
return false;
}
}
// Status filter - compare lowercase versions
if (statusValue != null && !statusValue.isEmpty() && !"all".equals(statusValue))
{
if (!task.status.equalsIgnoreCase(statusValue))
{
return false;
}
}
// Priority filter - compare lowercase versions
if (priorityValue != null && !priorityValue.isEmpty() && !"all".equals(priorityValue))
{
if (!task.priority.equalsIgnoreCase(priorityValue))
{
return false;
}
}
return true;
}
/****************************************************************************************************************
* FormListener implementation - handles form submission events.
****************************************************************************************************************/
@Override
public void onEvent(FormEvent event)
{
onAddTaskSubmitted(event.getParameters());
}
/****************************************************************************************************************
* InputListener implementation - handles input change events for filter synchronization.
****************************************************************************************************************/
@Override
public void onEvent(InputChangeEvent event)
{
// Values are automatically synchronized when the event is received.
// No action needed here - the filter button handler will read current values.
}
/****************************************************************************************************************
* InputListener implementation - handles input complete events.
****************************************************************************************************************/
@Override
public void onEvent(InputCompleteEvent event)
{
// Not used, but required by InputListener interface.
}
/****************************************************************************************************************
* Server-side event handler for the Add Task form submission.
*
* @param params The form parameters containing task data.
****************************************************************************************************************/
private void onAddTaskSubmitted(Parameters params)
{
String taskName = params.getParameterValue("taskName");
if (taskName == null || taskName.trim().isEmpty())
{
return;
}
// Get form values from Parameters
String priority = getPriorityLabel(params.getParameterValue("priority"));
String assignee = getAssigneeName(params.getParameterValue("assignee"));
String dueDate = formatDueDate(params.getParameterValue("dueDate"));
// Create new task
Task newTask = new Task(++taskCounter, taskName.trim(), priority, assignee, dueDate, "Pending");
tasks.add(0, newTask); // Add to beginning of list
// Add new row to table
taskTableBody.insertElement(0, createTaskRow(newTask));
// Update stats
updateStats();
// Clear form
taskNameInput.setValue("");
descriptionInput.setValue("");
prioritySelect.setValue("medium");
dateInput.setValue("");
assigneeSelect.setSelectedIndex(0);
// Push updates to client
sendUpdate();
}
private String getPriorityLabel(String value)
{
if (value == null)
{
return "Medium";
}
switch (value)
{
case "urgent":
return "Urgent";
case "high":
return "High";
case "low":
return "Low";
default:
return "Medium";
}
}
private String getAssigneeName(String value)
{
if (value == null)
{
return "Alice Johnson";
}
switch (value)
{
case "bob":
return "Bob Smith";
case "carol":
return "Carol Williams";
case "david":
return "David Brown";
default:
return "Alice Johnson";
}
}
private String formatDueDate(String value)
{
if (value == null || value.isEmpty())
{
return "No date";
}
try
{
String[] parts = value.split("-");
if (parts.length == 3)
{
int month = Integer.parseInt(parts[1]);
int day = Integer.parseInt(parts[2]);
String[] months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
return months[month - 1] + " " + String.format("%02d", day);
}
}
catch (Exception e)
{
// Ignore parsing errors
}
return value;
}
private Div createTaskTable()
{
Div tableCard = new Div();
tableCard.setBackgroundColor("#ffffff");
tableCard.setBorderRadius("12px");
tableCard.setPadding("24px");
tableCard.addStyleAttribute("box-shadow", "0 1px 3px rgba(0, 0, 0, 0.1)");
// Header with title
Div header = new Div();
header.setDisplay(Display.FLEX);
header.setJustifyContent(JustifyContent.SPACE_BETWEEN);
header.setAlignItems(AlignItems.CENTER);
header.setMarginBottom("20px");
H3 tableTitle = new H3();
tableTitle.setText("Task List");
tableTitle.setColor("#1f2937");
tableTitle.setFontSize("18px");
tableTitle.setFontWeight("600");
tableTitle.setMargin("0");
header.addElement(tableTitle);
tableCard.addElement(header);
// Filter bar
tableCard.addElement(createFilterBar());
// Table
Table table = new Table();
table.setWidth("100%");
table.addStyleAttribute("border-collapse", "collapse");
// Table Header
Thead thead = new Thead();
Tr headerRow = new Tr();
headerRow.setBackgroundColor("#f9fafb");
String[] headers = {"Task", "Priority", "Assignee", "Due Date", "Status", "Actions"};
String[] widths = {"", "100px", "120px", "110px", "100px", "80px"};
for (int i = 0; i < headers.length; i++)
{
Th th = new Th();
th.setText(headers[i]);
th.setPadding("12px 16px");
th.setTextAlign(i == 0 ? TextAlign.LEFT : TextAlign.CENTER);
th.setColor("#6b7280");
th.setFontSize("12px");
th.setFontWeight("600");
th.addStyleAttribute("text-transform", "uppercase");
th.addStyleAttribute("letter-spacing", "0.05em");
if (!widths[i].isEmpty())
{
th.setWidth(widths[i]);
}
headerRow.addElement(th);
}
thead.addElement(headerRow);
table.addElement(thead);
// Table Body
taskTableBody = new Tbody();
for (Task task : tasks)
{
taskTableBody.addElement(createTaskRow(task));
}
table.addElement(taskTableBody);
tableCard.addElement(table);
return tableCard;
}
private Tr createTaskRow(Task task)
{
Tr row = new Tr();
row.addStyleAttribute("border-bottom", "1px solid #f3f4f6");
// Task name
Td tdTask = new Td();
tdTask.setPadding("16px");
Div taskInfo = new Div();
Div taskName = new Div();
taskName.setText(task.name);
taskName.setColor("#1f2937");
taskName.setFontSize("14px");
taskName.setFontWeight("500");
taskInfo.addElement(taskName);
Div taskId = new Div();
taskId.setText("TASK-" + task.id);
taskId.setColor("#9ca3af");
taskId.setFontSize("12px");
taskId.setMarginTop("4px");
taskInfo.addElement(taskId);
tdTask.addElement(taskInfo);
row.addElement(tdTask);
// Priority
Td tdPriority = new Td();
tdPriority.setPadding("16px");
tdPriority.setTextAlign(TextAlign.CENTER);
Span priorityBadge = new Span();
priorityBadge.setText(task.priority);
priorityBadge.setFontSize("12px");
priorityBadge.setFontWeight("500");
priorityBadge.setPadding("4px 10px");
priorityBadge.setBorderRadius("12px");
stylePriorityBadge(priorityBadge, task.priority);
tdPriority.addElement(priorityBadge);
row.addElement(tdPriority);
// Assignee
Td tdAssignee = new Td();
tdAssignee.setPadding("16px");
tdAssignee.setTextAlign(TextAlign.CENTER);
Div assigneeInfo = new Div();
assigneeInfo.setDisplay(Display.FLEX);
assigneeInfo.setAlignItems(AlignItems.CENTER);
assigneeInfo.setJustifyContent(JustifyContent.CENTER);
Div avatar = new Div();
avatar.setWidth("28px");
avatar.setHeight("28px");
avatar.setBorderRadius("50%");
avatar.setBackgroundColor("#e0e7ff");
avatar.setColor("#4f46e5");
avatar.setFontSize("12px");
avatar.setFontWeight("600");
avatar.setDisplay(Display.FLEX);
avatar.setAlignItems(AlignItems.CENTER);
avatar.setJustifyContent(JustifyContent.CENTER);
avatar.setText(getInitials(task.assignee));
assigneeInfo.addElement(avatar);
tdAssignee.addElement(assigneeInfo);
row.addElement(tdAssignee);
// Due Date
Td tdDate = new Td();
tdDate.setText(task.dueDate);
tdDate.setPadding("16px");
tdDate.setTextAlign(TextAlign.CENTER);
tdDate.setColor("#6b7280");
tdDate.setFontSize("14px");
row.addElement(tdDate);
// Status
Td tdStatus = new Td();
tdStatus.setPadding("16px");
tdStatus.setTextAlign(TextAlign.CENTER);
Span statusBadge = new Span();
statusBadge.setText(task.status);
statusBadge.setFontSize("12px");
statusBadge.setFontWeight("500");
statusBadge.setPadding("4px 10px");
statusBadge.setBorderRadius("12px");
styleStatusBadge(statusBadge, task.status);
tdStatus.addElement(statusBadge);
row.addElement(tdStatus);
// Actions
Td tdActions = new Td();
tdActions.setPadding("16px");
tdActions.setTextAlign(TextAlign.CENTER);
Div actionBtns = new Div();
actionBtns.setDisplay(Display.FLEX);
actionBtns.setJustifyContent(JustifyContent.CENTER);
actionBtns.addStyleAttribute("gap", "8px");
Button deleteBtn = createDeleteButton(task);
actionBtns.addElement(deleteBtn);
tdActions.addElement(actionBtns);
row.addElement(tdActions);
return row;
}
private Button createDeleteButton(Task task)
{
Button btn = new Button();
btn.setText("\u2715");
btn.setWidth("28px");
btn.setHeight("28px");
btn.setPadding("0");
btn.setBorder("none");
btn.setBorderRadius("6px");
btn.setBackgroundColor("#ef444410");
btn.setColor("#ef4444");
btn.setFontSize("14px");
btn.addStyleAttribute("cursor", "pointer");
// Register server-side delete handler
btn.registerListener(new DeleteButtonListener(task), MouseClickedEvent.class);
return btn;
}
/****************************************************************************************************************
* Inner class to handle delete button clicks for individual tasks.
****************************************************************************************************************/
private class DeleteButtonListener implements MouseClickListener
{
private final Task task;
DeleteButtonListener(Task task)
{
this.task = task;
}
@Override
public void onEvent(MouseClickedEvent event)
{
onDeleteTaskClicked(task);
}
}
/****************************************************************************************************************
* Server-side event handler for deleting a task.
****************************************************************************************************************/
private void onDeleteTaskClicked(Task task)
{
// Remove the task from the list
tasks.remove(task);
// Rebuild the table to reflect current state (handles filtered views correctly)
rebuildTaskTable();
// Update stats
updateStats();
// Push updates to client
sendUpdate();
}
/****************************************************************************************************************
* Rebuilds the task table body based on current filter state.
****************************************************************************************************************/
private void rebuildTaskTable()
{
String searchText = searchInput.getValue();
String statusValue = statusFilter.getSelectedValue();
String priorityValue = priorityFilter.getSelectedValue();
taskTableBody.removeAllElements();
for (Task task : tasks)
{
if (matchesFilters(task, searchText, statusValue, priorityValue))
{
taskTableBody.addElement(createTaskRow(task));
}
}
}
private void stylePriorityBadge(Span badge, String priority)
{
switch (priority)
{
case "Urgent":
badge.setBackgroundColor("#fef2f2");
badge.setColor("#dc2626");
break;
case "High":
badge.setBackgroundColor("#fff7ed");
badge.setColor("#ea580c");
break;
case "Medium":
badge.setBackgroundColor("#fefce8");
badge.setColor("#ca8a04");
break;
default:
badge.setBackgroundColor("#f0fdf4");
badge.setColor("#16a34a");
}
}
private void styleStatusBadge(Span badge, String status)
{
switch (status)
{
case "Pending":
badge.setBackgroundColor("#fef3c7");
badge.setColor("#f59e0b");
break;
case "Completed":
badge.setBackgroundColor("#d1fae5");
badge.setColor("#10b981");
break;
case "Overdue":
badge.setBackgroundColor("#fee2e2");
badge.setColor("#ef4444");
break;
default:
badge.setBackgroundColor("#f3f4f6");
badge.setColor("#6b7280");
}
}
private String getInitials(String name)
{
if (name == null || name.isEmpty())
{
return "?";
}
String[] parts = name.split(" ");
if (parts.length >= 2)
{
return parts[0].substring(0, 1) + parts[1].substring(0, 1);
}
return name.substring(0, 1);
}
private Div createCodeExplanation()
{
Div section = new Div();
section.setMarginTop("40px");
H3 title = new H3();
title.setText("What This Demo Shows");
title.setColor("#1f2937");
title.setFontSize("24px");
title.setFontWeight("700");
title.setMarginTop("0");
title.setMarginBottom("20px");
section.addElement(title);
Div grid = new Div();
grid.setDisplay(Display.GRID);
grid.addStyleAttribute("grid-template-columns", "repeat(auto-fit, minmax(280px, 1fr))");
grid.addStyleAttribute("gap", "20px");
grid.addElement(createFeatureCard("fa-solid fa-code", "Rich HTML Elements",
"Div, Form, Input, Select, Table, Button, and more \u2014 all created as Java objects with type-safe styling methods."));
grid.addElement(createFeatureCard("fa-solid fa-rectangle-list", "Form Handling",
"Text inputs, textareas, selects, and date pickers. Form values are read server-side in Java event handlers."));
grid.addElement(createFeatureCard("fa-solid fa-table", "Data Tables",
"Dynamic tables built from Java collections. Add and remove rows programmatically with automatic UI updates."));
grid.addElement(createFeatureCard("fa-solid fa-bolt", "Event System",
"JDK-style event listeners for clicks and changes. All processing happens on the server in Java."));
grid.addElement(createFeatureCard("fa-solid fa-arrows-rotate", "Real-Time Updates",
"Server-side changes automatically push to the browser. Call sendUpdate() and the UI refreshes instantly."));
grid.addElement(createFeatureCard("fa-brands fa-java", "Pure Java",
"No JavaScript, HTML templates, or frontend build tools. Everything is built programmatically in Java."));
section.addElement(grid);
return section;
}
private Div createFeatureCard(String iconClass, String title, String description)
{
Div card = new Div();
card.setBackgroundColor("#f8fafc");
card.setBorderRadius("12px");
card.setPadding("24px");
I iconEl = new I();
iconEl.addAttribute("class", iconClass);
iconEl.setFontSize("28px");
iconEl.setColor("#2563eb");
iconEl.setDisplay(Display.BLOCK);
iconEl.setMarginBottom("12px");
card.addElement(iconEl);
H4 titleEl = new H4();
titleEl.setText(title);
titleEl.setColor("#1f2937");
titleEl.setFontSize("16px");
titleEl.setFontWeight("600");
titleEl.setMarginTop("0");
titleEl.setMarginBottom("8px");
card.addElement(titleEl);
P desc = new P();
desc.setText(description);
desc.setColor("#6b7280");
desc.setFontSize("14px");
desc.setLineHeight("1.6");
desc.setMargin("0");
card.addElement(desc);
return card;
}
/****************************************************************************************************************
* Simple task data class.
****************************************************************************************************************/
private static class Task
{
final int id;
final String name;
final String priority;
final String assignee;
final String dueDate;
final String status;
Task(int id, String name, String priority, String assignee, String dueDate, String status)
{
this.id = id;
this.name = name;
this.priority = priority;
this.assignee = assignee;
this.dueDate = dueDate;
this.status = status;
}
}
}