commit fef8e70f2353c54462ae0ba3dc08a6c70c42c43d
Author: root <root@hub.scroll.pub> Date: 2024-12-28 14:02:45 +0000 Subject: Initial commit diff --git a/body.html b/body.html new file mode 100644 index 0000000..8b87b9c --- /dev/null +++ b/body.html @@ -0,0 +1,18 @@ +<main class="dashboard"> + <div class="canvas-container"> + <canvas id="dashboardCanvas"></canvas> + </div> + <div class="controls"> + <button id="addNode" aria-label="Add new node">+ Add Node</button> + </div> + <dialog id="editDialog"> + <form> + <label for="nodeContent">Edit Node:</label> + <textarea id="nodeContent" rows="4"></textarea> + <div class="dialog-buttons"> + <button type="submit">Save</button> + <button type="button" id="cancelEdit">Cancel</button> + </div> + </form> + </dialog> +</main> \ No newline at end of file diff --git a/index.scroll b/index.scroll new file mode 100644 index 0000000..b835e8d --- /dev/null +++ b/index.scroll @@ -0,0 +1,8 @@ +buildHtml +baseUrl https://nodedash.scroll.pub +metaTags +editButton /edit.html +title NodeDash - Interactive 3D Dashboard +style.css +body.html +script.js \ No newline at end of file diff --git a/prompt.json b/prompt.json new file mode 100644 index 0000000..d019c75 --- /dev/null +++ b/prompt.json @@ -0,0 +1,25 @@ +{ + "id": "07bdc191-1fc8-4c3f-b4ef-9d171f5b023b", + "object": "chat.completion", + "created": 1735394537, + "model": "deepseek-chat", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "---domain---\nnodedash.scroll.pub\n---index.scroll---\nbuildHtml\nbaseUrl https://nodedash.scroll.pub\nmetaTags\neditButton /edit.html\ntitle NodeDash - Interactive 3D Dashboard\nstyle.css\nbody.html\nscript.js\n---body.html---\n<main class=\"dashboard\">\n <div class=\"canvas-container\">\n <canvas id=\"dashboardCanvas\"></canvas>\n </div>\n <div class=\"controls\">\n <button id=\"addNode\" aria-label=\"Add new node\">+ Add Node</button>\n </div>\n <dialog id=\"editDialog\">\n <form>\n <label for=\"nodeContent\">Edit Node:</label>\n <textarea id=\"nodeContent\" rows=\"4\"></textarea>\n <div class=\"dialog-buttons\">\n <button type=\"submit\">Save</button>\n <button type=\"button\" id=\"cancelEdit\">Cancel</button>\n </div>\n </form>\n </dialog>\n</main>\n---style.css---\n:root {\n --primary-color: #6366f1;\n --secondary-color: #4f46e5;\n --background: #1e1e2f;\n --text-color: #f8fafc;\n --node-color: #3b82f6;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n background-color: var(--background);\n color: var(--text-color);\n font-family: system-ui, -apple-system, sans-serif;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\n.dashboard {\n flex: 1;\n position: relative;\n}\n\n.canvas-container {\n width: 100%;\n height: 100vh;\n overflow: hidden;\n}\n\ncanvas {\n width: 100%;\n height: 100%;\n background: radial-gradient(circle at center, #2c2c44, #1e1e2f);\n}\n\n.controls {\n position: absolute;\n bottom: 2rem;\n right: 2rem;\n z-index: 10;\n}\n\nbutton {\n background-color: var(--primary-color);\n color: white;\n border: none;\n padding: 0.75rem 1.5rem;\n border-radius: 0.5rem;\n cursor: pointer;\n font-size: 1rem;\n transition: background-color 0.2s;\n}\n\nbutton:hover {\n background-color: var(--secondary-color);\n}\n\n#editDialog {\n background-color: var(--background);\n color: var(--text-color);\n border: 1px solid #333;\n border-radius: 0.5rem;\n padding: 1.5rem;\n max-width: 400px;\n}\n\n#editDialog::backdrop {\n background: rgba(0, 0, 0, 0.5);\n}\n\n.dialog-buttons {\n display: flex;\n gap: 1rem;\n margin-top: 1rem;\n}\n\ntextarea {\n width: 100%;\n padding: 0.5rem;\n border-radius: 0.25rem;\n border: 1px solid #333;\n background-color: #2c2c44;\n color: var(--text-color);\n resize: vertical;\n}\n\n@media (max-width: 768px) {\n .controls {\n bottom: 1rem;\n right: 1rem;\n }\n \n button {\n padding: 0.5rem 1rem;\n font-size: 0.9rem;\n }\n}\n---script.js---\nclass Node {\n constructor(x, y, content = 'New Node') {\n this.x = x;\n this.y = y;\n this.width = 150;\n this.height = 100;\n this.content = content;\n this.isDragging = false;\n }\n\n draw(ctx) {\n ctx.save();\n ctx.translate(this.x, this.y);\n \n // Node background\n ctx.fillStyle = '#3b82f6';\n ctx.beginPath();\n ctx.roundRect(0, 0, this.width, this.height, 12);\n ctx.fill();\n \n // Node content\n ctx.fillStyle = '#ffffff';\n ctx.font = '14px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(this.content, this.width/2, this.height/2);\n \n ctx.restore();\n }\n\n isPointInside(x, y) {\n return x > this.x && x < this.x + this.width &&\n y > this.y && y < this.y + this.height;\n }\n}\n\nclass Dashboard {\n constructor(canvas) {\n this.canvas = canvas;\n this.ctx = canvas.getContext('2d');\n this.nodes = [];\n this.selectedNode = null;\n this.isDragging = false;\n this.offsetX = 0;\n this.offsetY = 0;\n \n this.setupEventListeners();\n this.resizeCanvas();\n this.animate();\n }\n\n setupEventListeners() {\n this.canvas.addEventListener('mousedown', this.handleMouseDown.bind(this));\n this.canvas.addEventListener('mousemove', this.handleMouseMove.bind(this));\n this.canvas.addEventListener('mouseup', this.handleMouseUp.bind(this));\n this.canvas.addEventListener('dblclick', this.handleDoubleClick.bind(this));\n this.canvas.addEventListener('contextmenu', this.handleRightClick.bind(this));\n window.addEventListener('resize', this.resizeCanvas.bind(this));\n }\n\n handleMouseDown(e) {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n \n for (let node of this.nodes) {\n if (node.isPointInside(x, y)) {\n this.selectedNode = node;\n this.isDragging = true;\n this.offsetX = x - node.x;\n this.offsetY = y - node.y;\n break;\n }\n }\n }\n\n handleMouseMove(e) {\n if (this.isDragging && this.selectedNode) {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n \n this.selectedNode.x = x - this.offsetX;\n this.selectedNode.y = y - this.offsetY;\n }\n }\n\n handleMouseUp() {\n this.isDragging = false;\n this.selectedNode = null;\n }\n\n handleDoubleClick(e) {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n \n for (let node of this.nodes) {\n if (node.isPointInside(x, y)) {\n this.editNode(node);\n break;\n }\n }\n }\n\n handleRightClick(e) {\n e.preventDefault();\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n \n for (let i = this.nodes.length - 1; i >= 0; i--) {\n if (this.nodes[i].isPointInside(x, y)) {\n this.nodes.splice(i, 1);\n break;\n }\n }\n }\n\n editNode(node) {\n const dialog = document.getElementById('editDialog');\n const textarea = document.getElementById('nodeContent');\n textarea.value = node.content;\n \n dialog.showModal();\n \n dialog.querySelector('form').onsubmit = (e) => {\n e.preventDefault();\n node.content = textarea.value;\n dialog.close();\n };\n \n document.getElementById('cancelEdit').onclick = () => dialog.close();\n }\n\n addNode() {\n const x = this.canvas.width / 2 - 75;\n const y = this.canvas.height / 2 - 50;\n this.nodes.push(new Node(x, y));\n }\n\n resizeCanvas() {\n this.canvas.width = window.innerWidth;\n this.canvas.height = window.innerHeight;\n }\n\n animate() {\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n \n for (let node of this.nodes) {\n node.draw(this.ctx);\n }\n \n requestAnimationFrame(this.animate.bind(this));\n }\n}\n\n// Initialize dashboard\nconst canvas = document.getElementById('dashboardCanvas');\nconst dashboard = new Dashboard(canvas);\n\n// Add node button\ndocument.getElementById('addNode').addEventListener('click', () => {\n dashboard.addNode();\n});\n---end---" + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 259, + "completion_tokens": 1885, + "total_tokens": 2144, + "prompt_cache_hit_tokens": 0, + "prompt_cache_miss_tokens": 259 + }, + "system_fingerprint": "fp_f1afce2943" +} \ No newline at end of file diff --git a/readme.scroll b/readme.scroll new file mode 100644 index 0000000..3da0341 --- /dev/null +++ b/readme.scroll @@ -0,0 +1,2 @@ +# nodedash.scroll.pub +Website generated by DeepSeek from prompt: an animated interactive 3d dashboard with draggable nodes that the user can double click - edit. right click - delete \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..3bbdb65 --- /dev/null +++ b/script.js @@ -0,0 +1,165 @@ +class Node { + constructor(x, y, content = 'New Node') { + this.x = x; + this.y = y; + this.width = 150; + this.height = 100; + this.content = content; + this.isDragging = false; + } + + draw(ctx) { + ctx.save(); + ctx.translate(this.x, this.y); + + // Node background + ctx.fillStyle = '#3b82f6'; + ctx.beginPath(); + ctx.roundRect(0, 0, this.width, this.height, 12); + ctx.fill(); + + // Node content + ctx.fillStyle = '#ffffff'; + ctx.font = '14px sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(this.content, this.width/2, this.height/2); + + ctx.restore(); + } + + isPointInside(x, y) { + return x > this.x && x < this.x + this.width && + y > this.y && y < this.y + this.height; + } +} + +class Dashboard { + constructor(canvas) { + this.canvas = canvas; + this.ctx = canvas.getContext('2d'); + this.nodes = []; + this.selectedNode = null; + this.isDragging = false; + this.offsetX = 0; + this.offsetY = 0; + + this.setupEventListeners(); + this.resizeCanvas(); + this.animate(); + } + + setupEventListeners() { + this.canvas.addEventListener('mousedown', this.handleMouseDown.bind(this)); + this.canvas.addEventListener('mousemove', this.handleMouseMove.bind(this)); + this.canvas.addEventListener('mouseup', this.handleMouseUp.bind(this)); + this.canvas.addEventListener('dblclick', this.handleDoubleClick.bind(this)); + this.canvas.addEventListener('contextmenu', this.handleRightClick.bind(this)); + window.addEventListener('resize', this.resizeCanvas.bind(this)); + } + + handleMouseDown(e) { + const rect = this.canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + for (let node of this.nodes) { + if (node.isPointInside(x, y)) { + this.selectedNode = node; + this.isDragging = true; + this.offsetX = x - node.x; + this.offsetY = y - node.y; + break; + } + } + } + + handleMouseMove(e) { + if (this.isDragging && this.selectedNode) { + const rect = this.canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + this.selectedNode.x = x - this.offsetX; + this.selectedNode.y = y - this.offsetY; + } + } + + handleMouseUp() { + this.isDragging = false; + this.selectedNode = null; + } + + handleDoubleClick(e) { + const rect = this.canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + for (let node of this.nodes) { + if (node.isPointInside(x, y)) { + this.editNode(node); + break; + } + } + } + + handleRightClick(e) { + e.preventDefault(); + const rect = this.canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + for (let i = this.nodes.length - 1; i >= 0; i--) { + if (this.nodes[i].isPointInside(x, y)) { + this.nodes.splice(i, 1); + break; + } + } + } + + editNode(node) { + const dialog = document.getElementById('editDialog'); + const textarea = document.getElementById('nodeContent'); + textarea.value = node.content; + + dialog.showModal(); + + dialog.querySelector('form').onsubmit = (e) => { + e.preventDefault(); + node.content = textarea.value; + dialog.close(); + }; + + document.getElementById('cancelEdit').onclick = () => dialog.close(); + } + + addNode() { + const x = this.canvas.width / 2 - 75; + const y = this.canvas.height / 2 - 50; + this.nodes.push(new Node(x, y)); + } + + resizeCanvas() { + this.canvas.width = window.innerWidth; + this.canvas.height = window.innerHeight; + } + + animate() { + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + + for (let node of this.nodes) { + node.draw(this.ctx); + } + + requestAnimationFrame(this.animate.bind(this)); + } +} + +// Initialize dashboard +const canvas = document.getElementById('dashboardCanvas'); +const dashboard = new Dashboard(canvas); + +// Add node button +document.getElementById('addNode').addEventListener('click', () => { + dashboard.addNode(); +}); \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..f288a2e --- /dev/null +++ b/style.css @@ -0,0 +1,102 @@ +:root { + --primary-color: #6366f1; + --secondary-color: #4f46e5; + --background: #1e1e2f; + --text-color: #f8fafc; + --node-color: #3b82f6; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + background-color: var(--background); + color: var(--text-color); + font-family: system-ui, -apple-system, sans-serif; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +.dashboard { + flex: 1; + position: relative; +} + +.canvas-container { + width: 100%; + height: 100vh; + overflow: hidden; +} + +canvas { + width: 100%; + height: 100%; + background: radial-gradient(circle at center, #2c2c44, #1e1e2f); +} + +.controls { + position: absolute; + bottom: 2rem; + right: 2rem; + z-index: 10; +} + +button { + background-color: var(--primary-color); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + cursor: pointer; + font-size: 1rem; + transition: background-color 0.2s; +} + +button:hover { + background-color: var(--secondary-color); +} + +#editDialog { + background-color: var(--background); + color: var(--text-color); + border: 1px solid #333; + border-radius: 0.5rem; + padding: 1.5rem; + max-width: 400px; +} + +#editDialog::backdrop { + background: rgba(0, 0, 0, 0.5); +} + +.dialog-buttons { + display: flex; + gap: 1rem; + margin-top: 1rem; +} + +textarea { + width: 100%; + padding: 0.5rem; + border-radius: 0.25rem; + border: 1px solid #333; + background-color: #2c2c44; + color: var(--text-color); + resize: vertical; +} + +@media (max-width: 768px) { + .controls { + bottom: 1rem; + right: 1rem; + } + + button { + padding: 0.5rem 1rem; + font-size: 0.9rem; + } +} \ No newline at end of file