[Haik]: and so it begins

This commit is contained in:
haikdc
2026-03-13 12:09:25 -07:00
commit 23621306a1
190 changed files with 51641 additions and 0 deletions
@@ -0,0 +1,57 @@
.color-button-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 0;
margin: 0;
}
.color-button-img {
height: 100px;
}
.color-button-content {
display: flex;
flex-direction: column;
justify-content: center;
}
.color-button {
background-color: rgba(255, 255, 255, 0);
color: black;
border: none;
font-size: 1.45rem;
font-weight: bold; /* Changed from 900 to bold */
font-family: 'Consolas', monospace;
cursor: pointer;
border-radius: 400px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 10px;
}
.color-button:hover {
background-color: #9292926c;
}
.color-button:active {
background-color: #929292ce;
}
.color-button:focus {
outline: none;
}
.color-button-container p {
color: #D9D9D9;
font-family: 'Consolas', monospace;
margin: 0;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
@@ -0,0 +1,30 @@
import React from 'react';
import axios from 'axios';
import pushImg from '../../assets/color-reset.png'; // Adjust the path according to your project structure
import './ColorReset.css'; // Import the CSS file
const ColorReset = ({ projectStructure, setProjectStructure }) => {
const pushStructure = async () => {
try {
console.log("Resetting colors");
const response = await axios.post('http://127.0.0.1:6969/reset_color');
console.log('Project structure:', response.data);
setProjectStructure(response.data);
} catch (error) {
console.error('Error pushing project structure:', error);
}
};
return (
<div className="color-button-container">
<div className="color-button-content">
<button className="color-button" onClick={pushStructure}>
<img src={pushImg} alt="Project Structure" className="color-button-img" />
</button>
<p>Wipe colors</p>
</div>
</div>
);
};
export default ColorReset;
@@ -0,0 +1,129 @@
/* EmojiPicker.css */
.picker-wrapper {
position: relative;
display: inline-block;
}
.picker-button {
font-size: 1.5rem;
background: none;
border: none;
cursor: pointer;
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.emoji-popup {
position: absolute;
top: 2.5rem;
left: 0;
width: fit-content;
padding: 10px;
border: 7px solid #cccccc46;
border-radius: 35px;
background-color: #181818ef;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.folder-section {
display: flex;
flex-direction: row;
justify-content: space-around;
height: fit-content;
width: 100%;
}
.folder-item {
cursor: pointer;
padding: 10px;
text-align: left;
background-color: #00000000;
margin: 5px 0;
border-radius: 5px;
color: #ffffff;
}
.folder-item:hover {
background-color: #ffffff35;
}
.folder-item.active {
background-color: #ffffff15; /* Active color for the selected folder */
}
.folder-item.active:hover {
background-color: #ffffff35; /* Active color for the selected folder */
}
.emoji-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 10px;
height: 260px;
width: 330px;
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.emoji-item {
cursor: pointer;
padding: 5px;
text-align: center;
height: fit-content;
border-radius: 5px;
font-size: 1.5rem;
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.emoji-item:hover {
background-color: #ffffff35;
}
.pagination {
margin-top: 10px;
text-align: center;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 5px;
}
.pagination button {
background-color: #00000000;
border: 0;
gap: 0;
width: 18px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
padding: 0 16px;
border-radius: 50px;
color: #ffffff;
height: fit-content;
}
.pagination button img {
height: 100px;
width: 30px;
object-fit: cover;
}
.pagination button:disabled {
cursor: default;
}
.pagination button:hover {
background-color: #ffffff15;
}
.selected-emoji-display {
margin-top: 20px;
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
@@ -0,0 +1,141 @@
import React, { useState, useEffect } from "react";
import { emojiList } from '../../assets/emojis';
import PrevPage from '../../assets/prev-page.png';
import NextPage from '../../assets/next-page.png';
import './EmojiPicker.css'; // Import CSS file
const EMOJIS_PER_PAGE = 30;
const EmojiPicker = ({ defaultEmoji, handleEmojiChange }) => {
const folderNames = Object.keys(emojiList); // Get all folder names
const firstFolder = folderNames[0]; // Get the first folder name
const [showPicker, setShowPicker] = useState(false);
const [selectedEmoji, setSelectedEmoji] = useState(defaultEmoji || "😀"); // Initialize with the default emoji from props or fallback to smiley
const [currentPage, setCurrentPage] = useState(0);
const [currentFolder, setCurrentFolder] = useState(firstFolder); // Initialize with first folder
// When defaultEmoji changes (e.g., from backend data), update selectedEmoji
useEffect(() => {
if (defaultEmoji) {
setSelectedEmoji(defaultEmoji);
}
}, [defaultEmoji]);
// Handle folder click
const handleFolderClick = (folderName) => {
setCurrentFolder(folderName); // Set the current folder
setCurrentPage(0); // Reset page to 0 when switching folders
};
// Get the emojis for the selected folder
const emojis = currentFolder ? emojiList[currentFolder] : [];
const totalPages = Math.ceil(emojis.length / EMOJIS_PER_PAGE);
const currentEmojis = emojis.slice(
currentPage * EMOJIS_PER_PAGE,
(currentPage + 1) * EMOJIS_PER_PAGE
);
const handleEmojiClick = (emoji) => {
setSelectedEmoji(emoji);
setShowPicker(false); // Close the picker when an emoji is selected
handleEmojiChange(emoji); // Call the parent handler with the selected emoji
};
const togglePicker = () => {
setShowPicker((prev) => !prev); // Toggle the picker visibility
};
const goToNextFolder = () => {
const currentIndex = folderNames.indexOf(currentFolder);
const nextFolderIndex = currentIndex + 1;
if (nextFolderIndex < folderNames.length) {
setCurrentFolder(folderNames[nextFolderIndex]);
setCurrentPage(0); // Reset to the first page of the next folder
}
};
const goToPreviousFolder = () => {
const currentIndex = folderNames.indexOf(currentFolder);
const previousFolderIndex = currentIndex - 1;
if (previousFolderIndex >= 0) {
const previousFolder = folderNames[previousFolderIndex];
setCurrentFolder(previousFolder);
const lastPageOfPreviousFolder = Math.ceil(emojiList[previousFolder].length / EMOJIS_PER_PAGE) - 1;
setCurrentPage(lastPageOfPreviousFolder); // Set to the last page of the previous folder
}
};
const goToNextPage = () => {
if (currentPage < totalPages - 1) {
setCurrentPage(currentPage + 1);
} else {
goToNextFolder();
}
};
const goToPreviousPage = () => {
if (currentPage > 0) {
setCurrentPage(currentPage - 1);
} else {
goToPreviousFolder();
}
};
const isLastFolder = currentFolder === folderNames[folderNames.length - 1];
const isLastPageOfLastFolder = isLastFolder && currentPage === totalPages - 1;
const isFirstFolder = currentFolder === folderNames[0];
const isFirstPageOfFirstFolder = isFirstFolder && currentPage === 0;
return (
<div className="picker-wrapper">
{/* The emoji picker icon that changes when an emoji is selected */}
<button onClick={togglePicker} className="picker-button">
{selectedEmoji}
</button>
{/* Hoverable emoji picker */}
{showPicker && (
<div className="emoji-popup">
<div className="emoji-section">
<div className="pagination">
<button onClick={goToPreviousPage} disabled={isFirstPageOfFirstFolder}>
<img src={PrevPage} alt="Previous Page" />
</button>
<div className="emoji-grid">
{currentEmojis.map((emoji, index) => (
<span
key={index}
className="emoji-item"
onClick={() => handleEmojiClick(emoji)}
>
{emoji}
</span>
))}
</div>
<button
onClick={goToNextPage}
disabled={isLastPageOfLastFolder}
>
<img src={NextPage} alt="Next Page" />
</button>
</div>
</div>
<div className="folder-section">
{folderNames.map((folderName, index) => (
<div
key={index}
className={`folder-item ${folderName === currentFolder ? 'active' : ''}`}
onClick={() => handleFolderClick(folderName)}
>
{emojiList[folderName][0]}
</div>
))}
</div>
</div>
)}
</div>
);
};
export default EmojiPicker;
@@ -0,0 +1,49 @@
.pull-button-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
width: 40vw;
}
.pull-button-img {
margin-right: 20px;
height: 100px;
}
.pull-button-content {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.pull-button {
background-color: #A3FFA9;
color: black;
border: none;
padding: 10px 20px;
font-size: 1.45rem;
font-weight: bold; /* Changed from 900 to bold */
font-family: 'Consolas', monospace;
cursor: pointer;
margin: 20px 0;
border-radius: 4px;
}
.pull-button:hover {
background-color: #84d488;
}
.pull-button:active {
background-color: #65a568;
}
.pull-button:focus {
outline: none;
}
.pull-button-container p {
color: #A3FFA9;
font-family: 'Consolas', monospace;
margin: 0;
}
@@ -0,0 +1,32 @@
import React from 'react';
import { Button } from '@mui/material';
import axios from 'axios';
import pullImg from '../../assets/pull.png'; // Adjust the path according to your project structure
import './PullButton.css';
const PullButton = ({ setProjectStructure }) => {
const pullStructure = async () => {
try {
const response = await axios.get('http://127.0.0.1:6969/pull_structure');
console.log('Project structure:', response.data);
setProjectStructure(response.data);
} catch (error) {
console.error('Error fetching project structure:', error);
}
};
return (
<div className="pull-button-container">
<img src={pullImg} alt="Project Structure" className="pull-button-img" />
<div className="pull-button-content">
<button className="pull-button" onClick={pullStructure}>
Pull
</button>
<p>Pull debugger config from backend</p>
</div>
</div>
);
};
export default PullButton;
@@ -0,0 +1,50 @@
.push-button-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
width: 40vw;
text-align: right;
}
.push-button-img {
margin-left: 20px;
height: 100px;
}
.push-button-content {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.push-button {
background-color: #FFA3A4;
color: black;
border: none;
padding: 10px 20px;
font-size: 1.45rem;
font-weight: bold; /* Changed from 900 to bold */
font-family: 'Consolas', monospace;
cursor: pointer;
margin: 20px 0;
border-radius: 4px;
}
.push-button:hover {
background-color: #cc8182;
}
.push-button:active {
background-color: #a86768;
}
.push-button:focus {
outline: none;
}
.push-button-container p {
color: #FFA3A4;
font-family: 'Consolas', monospace;
margin: 0;
}
@@ -0,0 +1,33 @@
import React from 'react';
import axios from 'axios';
import pushImg from '../../assets/push.png'; // Adjust the path according to your project structure
import './PushButton.css'; // Import the CSS file
const PushButton = ({ projectStructure, setProjectStructure }) => {
const pushStructure = async () => {
try {
console.log("Pushing project structure to backend: ", projectStructure);
const response = await axios.post('http://127.0.0.1:6969/push_structure', {
projectStructure // Include the projectStructure in the POST request body
});
console.log('Project structure pushed:', response.data);
setProjectStructure(response.data);
} catch (error) {
console.error('Error pushing project structure:', error);
}
};
return (
<div className="push-button-container">
<div className="push-button-content">
<button className="push-button" onClick={pushStructure}>
Push
</button>
<p>Push debugger config to backend</p>
</div>
<img src={pushImg} alt="Project Structure" className="push-button-img" />
</div>
);
};
export default PushButton;
@@ -0,0 +1,16 @@
.sync-section-container {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100vw;
align-items: center;
padding: 20px;
box-sizing: border-box;
gap: 0
}
.sync-section-container > div {
flex: 1;
display: flex;
justify-content: center;
}
@@ -0,0 +1,17 @@
import React from 'react';
import PullButton from '../pull-button/PullButton';
import PushButton from '../push-button/PushButton';
import ColorReset from '../color-reset/ColorReset';
import './SyncSection.css'; // Import the CSS file
const SyncSection = ({ projectStructure, setProjectStructure }) => {
return (
<div className="sync-section-container">
<PullButton setProjectStructure={setProjectStructure} />
<ColorReset setProjectStructure={setProjectStructure} />
<PushButton projectStructure={projectStructure} setProjectStructure={setProjectStructure} />
</div>
);
};
export default SyncSection;
@@ -0,0 +1,7 @@
.tree-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
align-items: center;
}
@@ -0,0 +1,33 @@
import React from 'react';
import TreeNode from '../tree_node/TreeNode';
import './Tree.css';
const Tree = ({ projectStructure, expanded, handleExpandClick, handleCheckboxChange, handleColorChange, handleEmojiChange}) => {
const renderTree = (node, parentId = '') => {
const nodeId = parentId ? `${parentId}/${node.name}` : node.name;
return (
<TreeNode
key={nodeId}
node={node}
nodeId={nodeId}
expanded={expanded}
handleExpandClick={handleExpandClick}
handleCheckboxChange={handleCheckboxChange}
handleColorChange={handleColorChange}
handleEmojiChange={handleEmojiChange}
renderTree={renderTree}
/>
);
};
if (!Array.isArray(projectStructure)) return null; // Ensure projectStructure is an array
return (
<div className='tree-container'>
{projectStructure.map((node) => renderTree(node))}
</div>
);
};
export default Tree;
@@ -0,0 +1,88 @@
.tree-node {
border: 1px solid #ccc;
margin-top: 10px;
margin-bottom: 10px;
padding: 10px;
border-radius: 4px;
width: 100%;
background-color: #181818;
}
.tree-node-content {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
}
.tree-node-content-main {
display: flex;
align-items: center;
width: fit-content;
}
.expand-button {
background: none;
border: none;
cursor: pointer;
margin-right: 10px;
padding: 0; /* Ensure no padding around the button */
display: flex;
align-items: center;
justify-content: center;
}
.expand-button img {
width: 16px; /* Adjust the width as needed */
height: 16px; /* Adjust the height as needed */
max-width: 100%; /* Ensure it doesn't exceed button size */
max-height: 100%; /* Ensure it doesn't exceed button size */
}
.tree-node-text {
margin-left: 10px;
font-size: 1.45rem;
font-weight: 600;
font-family: 'Consolas', monospace; /* Specify fallback font */
color: #ffffff; /* Adjust text color to ensure it's visible on the dark background */
}
.tree-node-children {
margin-left: 20px;
margin-right: 20px;
margin-bottom: 10px;
padding-left: 20px;
padding-right: 20px;
gap: 10px;
}
.tree-node-content-secondary {
display: flex;
align-items: center;
}
.color-picker-wrapper {
position: relative;
}
.color-picker-icon {
display: inline-block;
width: 24px;
height: 24px;
cursor: pointer;
border: 1px solid #000;
border-radius: 4px;
overflow: hidden;
background-size: 100% 100%; /* Ensure the background color scales to fit */
background-clip: content-box;
background-color: transparent; /* Ensure the background is transparent */
-webkit-mask: url('../../assets/color-picker.png') center no-repeat;
mask: url('../../assets/color-picker.png') center no-repeat;
-webkit-mask-size: 20px; /* Adjust this value to fit your icon */
mask-size: 20px; /* Adjust this value to fit your icon */
}
.color-picker-icon img {
display: none;
}
@@ -0,0 +1,52 @@
import './TreeNode.css';
import React from 'react';
import plusIcon from '../../assets/collapsed.png';
import minusIcon from '../../assets/expanded.png';
import colorIcon from '../../assets/color-picker.png'; // Import your custom color icon
import EmojiPicker from '../emoji-picker/EmojiPicker';
const TreeNode = ({ node, nodeId, expanded, handleExpandClick, handleCheckboxChange, handleColorChange, handleEmojiChange, renderTree }) => (
<div className="tree-node">
<div className="tree-node-content">
<div className="tree-node-content-main">
{node.children && node.children.length > 0 && (
<button className="expand-button" onClick={() => handleExpandClick(nodeId)}>
<img src={expanded[nodeId] ? minusIcon : plusIcon} alt="Expand/Collapse Icon" />
</button>
)}
<input
type="checkbox"
checked={node.is_toggled}
onChange={(e) => handleCheckboxChange(nodeId, e.target.checked)}
/>
{/* Pass node.emoji along with handleEmojiChange */}
<EmojiPicker
defaultEmoji={node.emoji}
handleEmojiChange={(emoji) => handleEmojiChange(nodeId, emoji)}
/>
<span className="tree-node-text" style={{ color: node.color || '#000000' }}>{node.name}</span>
</div>
<div className="tree-node-content-secondary">
<div className="color-picker-wrapper">
<input
type="color"
value={node.color || '#000000'}
onChange={(e) => handleColorChange(nodeId, e.target.value)}
style={{ display: 'none' }} // Hide the default color input
id={`color-picker-${nodeId}`}
/>
<label htmlFor={`color-picker-${nodeId}`} className="color-picker-icon" style={{ backgroundColor: node.color || '#000000' }}>
<img src={colorIcon} alt="Color Picker Icon" />
</label>
</div>
</div>
</div>
{node.children && expanded[nodeId] && (
<div className="tree-node-children">
{node.children.map((childNode) => renderTree(childNode, nodeId))}
</div>
)}
</div>
);
export default TreeNode;