From bff7341a7fff459f14df167560854f482cf5e328 Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Tue, 25 Nov 2025 08:18:32 +0000
Subject: [PATCH 1/2] feat: Create HTML tree view
This commit introduces a new HTML page with a tree view component. The tree is generated with random data up to a nesting level of 3. Each item has a label, an active state, and optional child items. The UI includes an expand button for items with children and a button to activate/deactivate items. A horizontal scrollbar is added to the container to handle long labels.
---
src/main/webapp/index.html | 11 ++++
src/main/webapp/script.js | 109 +++++++++++++++++++++++++++++++++++++
src/main/webapp/style.css | 53 ++++++++++++++++++
3 files changed, 173 insertions(+)
create mode 100644 src/main/webapp/index.html
create mode 100644 src/main/webapp/script.js
create mode 100644 src/main/webapp/style.css
diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html
new file mode 100644
index 0000000..19ed082
--- /dev/null
+++ b/src/main/webapp/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Tree View
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/script.js b/src/main/webapp/script.js
new file mode 100644
index 0000000..feccb7d
--- /dev/null
+++ b/src/main/webapp/script.js
@@ -0,0 +1,109 @@
+
+const treeContainer = document.getElementById('tree-container');
+
+// --- Data Generation ---
+function generateRandomTree(maxDepth = 3) {
+ const tree = [];
+ const numRootItems = Math.floor(Math.random() * 5) + 3; // 3 to 7 root items
+
+ for (let i = 0; i < numRootItems; i++) {
+ tree.push(generateRandomItem(1, maxDepth));
+ }
+
+ return tree;
+}
+
+function generateRandomItem(currentDepth, maxDepth) {
+ const item = {
+ label: `Item ${currentDepth}-${Math.random().toString(36).substring(2, 15)} ${'Looooooooong '.repeat(Math.floor(Math.random() * 5))}`,
+ active: Math.random() < 0.5,
+ };
+
+ if (currentDepth < maxDepth && Math.random() < 0.7) { // 70% chance of having children
+ item.children = [];
+ const numChildren = Math.floor(Math.random() * 4) + 1; // 1 to 4 children
+ for (let i = 0; i < numChildren; i++) {
+ item.children.push(generateRandomItem(currentDepth + 1, maxDepth));
+ }
+ }
+
+ return item;
+}
+
+// --- Rendering ---
+function renderTree(data, parentElement) {
+ const treeElement = document.createElement('div');
+ treeElement.classList.add('tree');
+ parentElement.appendChild(treeElement);
+
+ data.forEach(item => {
+ renderItem(item, treeElement);
+ });
+}
+
+function renderItem(item, parentElement) {
+ const itemElement = document.createElement('div');
+ itemElement.classList.add('tree-item');
+ if (item.active) {
+ itemElement.classList.add('active');
+ }
+
+ const expandButton = document.createElement('div');
+ expandButton.classList.add('expand-button');
+ if (item.children) {
+ expandButton.textContent = '+';
+ }
+ itemElement.appendChild(expandButton);
+
+ const label = document.createElement('div');
+ label.classList.add('tree-label');
+ label.textContent = item.label;
+ itemElement.appendChild(label);
+
+ const activateButton = document.createElement('button');
+ activateButton.classList.add('activate-button');
+ activateButton.textContent = item.active ? 'Deactivate' : 'Activate';
+ itemElement.appendChild(activateButton);
+
+ parentElement.appendChild(itemElement);
+
+ if (item.children) {
+ const childrenContainer = document.createElement('div');
+ childrenContainer.classList.add('tree-item-children');
+ childrenContainer.style.display = 'none'; // Initially hidden
+ parentElement.appendChild(childrenContainer);
+
+ item.children.forEach(child => {
+ renderItem(child, childrenContainer);
+ });
+ }
+}
+
+// --- Event Listeners ---
+treeContainer.addEventListener('click', function(event) {
+ const target = event.target;
+
+ if (target.classList.contains('expand-button') && target.textContent) {
+ const childrenContainer = target.parentElement.nextElementSibling;
+ if (childrenContainer && childrenContainer.classList.contains('tree-item-children')) {
+ if (childrenContainer.style.display === 'none') {
+ childrenContainer.style.display = 'block';
+ target.textContent = '-';
+ } else {
+ childrenContainer.style.display = 'none';
+ target.textContent = '+';
+ }
+ }
+ }
+
+ if (target.classList.contains('activate-button')) {
+ const itemElement = target.parentElement;
+ itemElement.classList.toggle('active');
+ const isActive = itemElement.classList.contains('active');
+ target.textContent = isActive ? 'Deactivate' : 'Activate';
+ }
+});
+
+// --- Initial Load ---
+const randomTreeData = generateRandomTree();
+renderTree(randomTreeData, treeContainer);
diff --git a/src/main/webapp/style.css b/src/main/webapp/style.css
new file mode 100644
index 0000000..2a51c9f
--- /dev/null
+++ b/src/main/webapp/style.css
@@ -0,0 +1,53 @@
+#tree-container {
+ max-width: 500px;
+ overflow-x: auto;
+ white-space: nowrap;
+ border: 1px solid #ccc;
+ padding: 10px;
+}
+
+.tree {
+ min-width: 100%;
+ display: inline-block;
+}
+
+.tree-item {
+ display: flex;
+ align-items: center;
+ padding: 5px;
+}
+
+.tree-item.active {
+ background-color: #e0e0e0;
+}
+
+.tree-item-children {
+ padding-left: 20px;
+}
+
+.expand-button {
+ cursor: pointer;
+ margin-right: 5px;
+ width: 16px;
+ height: 16px;
+ text-align: center;
+ line-height: 16px;
+ border: 1px solid #ccc;
+ background-color: #f0f0f0;
+ flex-shrink: 0;
+}
+
+.expand-button:empty {
+ border: none;
+ background-color: transparent;
+ cursor: default;
+}
+
+.activate-button {
+ margin-left: 10px;
+ flex-shrink: 0;
+}
+
+.tree-label {
+ /* No flex-grow to prevent pushing the button out */
+}
\ No newline at end of file
From 2eb6bd20256658b9a6e305b1ab276569c32c451f Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Tue, 25 Nov 2025 08:24:20 +0000
Subject: [PATCH 2/2] feat: Create HTML tree view with right-aligned activate
button
This commit introduces a new HTML page with a tree view component. The tree is generated with random data up to a nesting level of 3. Each item has a label, an active state, and optional child items. The UI includes an expand button for items with children and a button to activate/deactivate items. A horizontal scrollbar is added to the container to handle long labels.
The activate/deactivate button is right-aligned and sticky, so it remains visible during horizontal scrolling.
---
src/main/webapp/style.css | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/main/webapp/style.css b/src/main/webapp/style.css
index 2a51c9f..8f5fb1c 100644
--- a/src/main/webapp/style.css
+++ b/src/main/webapp/style.css
@@ -44,8 +44,17 @@
}
.activate-button {
- margin-left: 10px;
+ margin-left: auto;
flex-shrink: 0;
+ position: sticky;
+ right: 0;
+ background-color: white; /* Default background */
+ padding-left: 5px; /* Add some space from the label */
+ padding-right: 5px;
+}
+
+.tree-item.active .activate-button {
+ background-color: #e0e0e0; /* Match active item background */
}
.tree-label {