Spaces:
Configuration error
Configuration error
zack commited on
Commit ·
61accb8
1
Parent(s): 3fde1d6
🔧 Update navbar and ReactFlowEnv components, 📸 Add new chatty image
Browse files
frontend/src/components/Navagation/navbar.js
CHANGED
|
@@ -5,31 +5,31 @@ import { random_colour, random_emoji } from "../../helper/visual";
|
|
| 5 |
|
| 6 |
import "../../css/dist/output.css"
|
| 7 |
|
| 8 |
-
import {
|
| 9 |
-
import {
|
| 10 |
-
import chattyImage from '../../images/chatty.png';
|
| 11 |
|
| 12 |
-
export default class Navbar extends Component
|
| 13 |
-
constructor(props)
|
| 14 |
-
super(props)
|
| 15 |
this.temp_host = 0
|
| 16 |
this.deleteNode = props.onDelete
|
| 17 |
this.state = {
|
| 18 |
-
open: true,
|
| 19 |
-
menu: [],
|
| 20 |
-
colour: props.colour || [],
|
| 21 |
-
text: "",
|
| 22 |
-
name: "",
|
| 23 |
-
emoji: props.emoji || [],
|
| 24 |
-
mode: false,
|
| 25 |
-
modal: false,
|
| 26 |
-
error: false
|
| 27 |
-
|
| 28 |
-
|
| 29 |
}
|
| 30 |
|
| 31 |
-
componentDidMount()
|
| 32 |
-
this.fetch_classes()
|
| 33 |
|
| 34 |
}
|
| 35 |
|
|
@@ -39,17 +39,17 @@ export default class Navbar extends Component {
|
|
| 39 |
*/
|
| 40 |
fetch_classes = async () => {
|
| 41 |
try {
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
}
|
| 53 |
console.log(e)
|
| 54 |
}
|
| 55 |
}
|
|
@@ -59,34 +59,33 @@ export default class Navbar extends Component {
|
|
| 59 |
*/
|
| 60 |
appendStreamNode = async (type) => {
|
| 61 |
const pattern = {
|
| 62 |
-
local: new RegExp('^https?://(localhost)(:[0-9]+)?(/)?$'),
|
| 63 |
-
share: new RegExp('^https?://(?:[a-zA-Z0-9]+\\.gradio\\.live)/?$'),
|
| 64 |
huggingFace: new RegExp('^https?://([a-zA-Z0-9-]+\\.hf\\.space)/?$'),
|
| 65 |
proxmoxVNC: new RegExp('^wss?://([a-zA-Z0-9-]+\\.yourdomain\\.com)/?$') // Regex pattern for Proxmox VNC URLs
|
| 66 |
-
}
|
| 67 |
|
| 68 |
if (this.state.name.length > 20 ||
|
| 69 |
-
this.state.text === ""
|
| 70 |
-
this.state.menu.findIndex(element => {
|
| 71 |
-
this.state.text.includes(" ") ||
|
| 72 |
(!pattern.local.test(this.state.text) &&
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
}
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
}).catch((err) => this.setState({ 'text': '', 'name': '', 'error': true, }))
|
| 90 |
}
|
| 91 |
|
| 92 |
/**
|
|
@@ -98,11 +97,11 @@ export default class Navbar extends Component {
|
|
| 98 |
if (!proxmoxVncInfo) return null; // If no Proxmox VNC info, don't render anything
|
| 99 |
|
| 100 |
return (
|
| 101 |
-
<li onDragStart={(event) => this.onDragStart(event, 'proxmoxVNC', proxmoxVncInfo, -1)}
|
| 102 |
className="text-white text-md flex flex-col text-center items-center cursor-grab shadow-lg p-5 px-2 mt-4 rounded-md hover:animate-pulse"
|
| 103 |
draggable>
|
| 104 |
<div className="absolute -mt-2 text-4xl opacity-60 z-10">{random_emoji()}</div>
|
| 105 |
-
<h4 className="max-w-full font-sans text-blue-50 leading-tight font-bold text-xl flex-1 z-20" style={{
|
| 106 |
Proxmox VNC
|
| 107 |
</h4>
|
| 108 |
</li>
|
|
@@ -114,10 +113,8 @@ export default class Navbar extends Component {
|
|
| 114 |
* @param {*} bool boolean of the current state of the modal
|
| 115 |
*/
|
| 116 |
handelModal = (bool) => {
|
| 117 |
-
this.setState({
|
| 118 |
-
|
| 119 |
-
'modal': bool
|
| 120 |
-
})
|
| 121 |
}
|
| 122 |
|
| 123 |
/**
|
|
@@ -129,10 +126,10 @@ export default class Navbar extends Component {
|
|
| 129 |
*/
|
| 130 |
onDragStart = (event, nodeType, item, index) => {
|
| 131 |
event.dataTransfer.setData('application/reactflow', nodeType);
|
| 132 |
-
event.dataTransfer.setData('application/style', JSON.stringify({
|
| 133 |
-
event.dataTransfer.setData('application/item',
|
| 134 |
event.dataTransfer.effectAllowed = 'move';
|
| 135 |
-
|
| 136 |
|
| 137 |
/**
|
| 138 |
* droped event that occurs when the user drops the Tab within the tash div.
|
|
@@ -142,11 +139,11 @@ export default class Navbar extends Component {
|
|
| 142 |
*/
|
| 143 |
onDragDrop = (e) => {
|
| 144 |
e.preventDefault();
|
| 145 |
-
var item
|
| 146 |
-
fetch("http://localhost:2000/api/remove/port", {
|
| 147 |
this.deleteNode(item.name)
|
| 148 |
})
|
| 149 |
-
|
| 150 |
}
|
| 151 |
|
| 152 |
/**
|
|
@@ -161,37 +158,37 @@ export default class Navbar extends Component {
|
|
| 161 |
var c = []
|
| 162 |
var j = []
|
| 163 |
if (d.length - e.length === 0) return
|
| 164 |
-
else if
|
| 165 |
var a = this.state.menu.filter(item => e.includes(item)) // get the items not in menu anymore
|
| 166 |
c = this.state.colour
|
| 167 |
j = this.state.emoji
|
| 168 |
-
for
|
| 169 |
c.splice(this.state.menu.indexOf(a[k]), 1)
|
| 170 |
j.splice(this.state.menu.indexOf(a[k]), 1)
|
| 171 |
}
|
| 172 |
-
this.setState({
|
| 173 |
-
}
|
| 174 |
//append new colours
|
| 175 |
-
for
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
}
|
| 180 |
const colour = [...this.state.colour]
|
| 181 |
-
const emoji
|
| 182 |
-
this.setState({
|
| 183 |
}
|
| 184 |
}
|
| 185 |
|
| 186 |
handelError = (boolean) => {
|
| 187 |
-
this.setState({
|
| 188 |
}
|
| 189 |
|
| 190 |
/**
|
| 191 |
* handel navagation open and close function
|
| 192 |
*/
|
| 193 |
handelNavbar = () => {
|
| 194 |
-
this.setState({
|
| 195 |
}
|
| 196 |
|
| 197 |
/**
|
|
@@ -200,7 +197,7 @@ export default class Navbar extends Component {
|
|
| 200 |
* @param {*} type : text | name string that set the changed value of the input to the current value
|
| 201 |
*/
|
| 202 |
updateText = (e, type) => {
|
| 203 |
-
this.setState({
|
| 204 |
}
|
| 205 |
|
| 206 |
/**
|
|
@@ -209,62 +206,59 @@ export default class Navbar extends Component {
|
|
| 209 |
* @param {*} index : current index with in the list
|
| 210 |
* @returns div component that contians infomation of gradio
|
| 211 |
*/
|
| 212 |
-
subComponents(item, index)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
className={` text-white text-md flex flex-col text-center items-center cursor-grab shadow-lg
|
| 217 |
-
p-5 px-2 mt-4 rounded-md ${this.state.open ? `hover:animate-pulse ${this.state.colour[index] === null ? "" : this.state.colour[index]} ` : `hidden`} break-all -z-20`} draggable>
|
| 218 |
|
| 219 |
-
<
|
| 220 |
-
<h4 key={`${index}-h4`} className={` max-w-full font-sans text-blue-50 leading-tight font-bold text-xl flex-1 z-20 ${this.state.open ? "" : "hidden"}`} style={{ "textShadow": "0px 1px 2px rgba(0, 0, 0, 0.25)" }} >{`${item.name}`} </h4>
|
| 221 |
-
|
| 222 |
-
</li >
|
| 223 |
|
| 224 |
</>)
|
| 225 |
}
|
| 226 |
|
| 227 |
|
| 228 |
-
render()
|
| 229 |
-
|
| 230 |
return (<div>
|
| 231 |
-
|
| 232 |
<div className={`z-10 flex-1 float-left bg-white dark:bg-stone-900 h-screen p-5 pt-8 ${this.state.open ? "lg:w-72 md:64 sm:w-60" : "w-10"} duration-300 absolute shadow-2xl border-black border-r-[1px] dark:border-white dark:text-white`} >
|
| 233 |
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
<img src={chattyImage} alt="Chat'nFace Logo" className={`h-12 w-auto ${this.state.open ? "visible" : "hidden"}`} /> {/* Display the image */}
|
| 237 |
-
<h1 className={`font-sans font-bold text-lg ${this.state.open ? "" : "hidden"} duration-500 ml-auto mr-auto`}>Chat-nFace</h1>
|
| 238 |
-
</div>
|
| 239 |
<div className="inline-flex w-full">
|
| 240 |
<h1 className={`font-sans font-bold text-lg ${this.state.open ? "" : "hidden"} duration-500 ml-auto mr-auto`}>Chat-nFace</h1>
|
| 241 |
</div>
|
| 242 |
|
| 243 |
-
<div className={`rounded-md text-center ${this.state.open ? "" : "px-0"} py-3`} onClick={() => {
|
| 244 |
<div className={` text-center bg-transparent w-full h-10 border border-slate-300 hover:border-Retro-purple hover:animate-pulse border-dashed rounded-md py-2 pl-5 ${this.state.open ? "pr-3" : "hidden"} shadow-sm sm:text-sm`}>
|
| 245 |
-
<Icon className=" block mr-auto ml-auto" name="plus"
|
| 246 |
</div>
|
| 247 |
</div>
|
| 248 |
-
<Import open={this.state.modal}
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
<div className=" relative z-10 h-auto overflow-auto pt-4">
|
| 256 |
<ul className="pt-2">
|
| 257 |
-
|
| 258 |
</ul>
|
| 259 |
</div>
|
| 260 |
|
| 261 |
-
<div className={`${this.state.open ? "" : "hidden"} absolute bottom-0 left-0 w-full text-center p-5`} onDragOver={(e)
|
| 262 |
<div className={` text-center bg-transparent w-full h-10 border border-red-600 border-dashed rounded-md py-2 pl-5 p-4 ${this.state.open ? "pr-3" : "hidden"} shadow-sm sm:text-sm`}>
|
| 263 |
-
<Icon name='trash alternate' />
|
| 264 |
</div>
|
| 265 |
</div>
|
| 266 |
</div>
|
| 267 |
-
|
| 268 |
</div>)
|
| 269 |
}
|
| 270 |
}
|
|
|
|
| 5 |
|
| 6 |
import "../../css/dist/output.css"
|
| 7 |
|
| 8 |
+
import {BsArrowLeftShort} from 'react-icons/bs';
|
| 9 |
+
import {ReactComponent as ReactLogo} from '../../images/logo.svg'
|
| 10 |
+
import chattyImage from '../../images/chatty.png'; // Import the image
|
| 11 |
|
| 12 |
+
export default class Navbar extends Component{
|
| 13 |
+
constructor(props){
|
| 14 |
+
super(props)
|
| 15 |
this.temp_host = 0
|
| 16 |
this.deleteNode = props.onDelete
|
| 17 |
this.state = {
|
| 18 |
+
open : true,
|
| 19 |
+
menu : [],
|
| 20 |
+
colour : props.colour || [],
|
| 21 |
+
text : "",
|
| 22 |
+
name : "",
|
| 23 |
+
emoji : props.emoji || [],
|
| 24 |
+
mode : false,
|
| 25 |
+
modal : false,
|
| 26 |
+
error : false
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
}
|
| 30 |
|
| 31 |
+
componentDidMount(){
|
| 32 |
+
this.fetch_classes()
|
| 33 |
|
| 34 |
}
|
| 35 |
|
|
|
|
| 39 |
*/
|
| 40 |
fetch_classes = async () => {
|
| 41 |
try {
|
| 42 |
+
setInterval( async () => {
|
| 43 |
+
await fetch("http://localhost:2000/api/open/ports", { method: 'GET', mode : 'cors',})
|
| 44 |
+
.then(response => response.json())
|
| 45 |
+
.then(data => {
|
| 46 |
+
this.handelTabs(this.state.menu,data, data)
|
| 47 |
+
this.setState({menu : data})
|
| 48 |
+
})
|
| 49 |
+
.catch(error => {console.log(error)})
|
| 50 |
+
|
| 51 |
+
},1000);
|
| 52 |
+
}catch(e){
|
| 53 |
console.log(e)
|
| 54 |
}
|
| 55 |
}
|
|
|
|
| 59 |
*/
|
| 60 |
appendStreamNode = async (type) => {
|
| 61 |
const pattern = {
|
| 62 |
+
local : new RegExp('^https?://(localhost)(:[0-9]+)?(/)?$'),
|
| 63 |
+
share : new RegExp('^https?://(?:[a-zA-Z0-9]+\\.gradio\\.live)/?$'),
|
| 64 |
huggingFace: new RegExp('^https?://([a-zA-Z0-9-]+\\.hf\\.space)/?$'),
|
| 65 |
proxmoxVNC: new RegExp('^wss?://([a-zA-Z0-9-]+\\.yourdomain\\.com)/?$') // Regex pattern for Proxmox VNC URLs
|
| 66 |
+
}
|
| 67 |
|
| 68 |
if (this.state.name.length > 20 ||
|
| 69 |
+
this.state.text === ""||
|
| 70 |
+
this.state.menu.findIndex(element => {return element.name.toLowerCase() === this.state.name.toLowerCase() || element.host.includes(this.state.text) }) !== -1 ||
|
| 71 |
+
this.state.text.includes(" ") ||
|
| 72 |
(!pattern.local.test(this.state.text) &&
|
| 73 |
+
!pattern.share.test(this.state.text) &&
|
| 74 |
+
!pattern.huggingFace.test(this.state.text) &&
|
| 75 |
+
!pattern.proxmoxVNC.test(this.state.text))){
|
| 76 |
+
|
| 77 |
+
this.setState({
|
| 78 |
+
'text': '',
|
| 79 |
+
'name': '',
|
| 80 |
+
'error': true})
|
| 81 |
+
return
|
| 82 |
+
}
|
| 83 |
+
fetch(this.state.text, {method: "GET", mode: 'no-cors'}).then((re) => {
|
| 84 |
+
fetch("http://localhost:2000/api/append/port", {method: 'POST', mode : 'cors', headers : { 'Content-Type' : 'application/json' }, body: JSON.stringify({file : "", kwargs : { type : type }, name : this.state.name === "" ?`temp_class_${this.temp_host++}` : `${this.state.name}`, port: 0 , host : this.state.text}) }).then(resp => {
|
| 85 |
+
this.setState({'text': "",'name' : "",'error' : false,'modal' : false })
|
| 86 |
+
|
| 87 |
+
}).catch(() => this.setState({'text': '', 'name' : '', 'error' : true, }))
|
| 88 |
+
}).catch((err)=> this.setState({'text': '','name' : '', 'error' : true,}))
|
|
|
|
| 89 |
}
|
| 90 |
|
| 91 |
/**
|
|
|
|
| 97 |
if (!proxmoxVncInfo) return null; // If no Proxmox VNC info, don't render anything
|
| 98 |
|
| 99 |
return (
|
| 100 |
+
<li onDragStart={(event) => this.onDragStart(event, 'proxmoxVNC', proxmoxVncInfo, -1)}
|
| 101 |
className="text-white text-md flex flex-col text-center items-center cursor-grab shadow-lg p-5 px-2 mt-4 rounded-md hover:animate-pulse"
|
| 102 |
draggable>
|
| 103 |
<div className="absolute -mt-2 text-4xl opacity-60 z-10">{random_emoji()}</div>
|
| 104 |
+
<h4 className="max-w-full font-sans text-blue-50 leading-tight font-bold text-xl flex-1 z-20" style={{"textShadow": "0px 1px 2px rgba(0, 0, 0, 0.25)"}}>
|
| 105 |
Proxmox VNC
|
| 106 |
</h4>
|
| 107 |
</li>
|
|
|
|
| 113 |
* @param {*} bool boolean of the current state of the modal
|
| 114 |
*/
|
| 115 |
handelModal = (bool) => {
|
| 116 |
+
this.setState({'error' : !bool ? false : this.state.error ,
|
| 117 |
+
'modal' : bool})
|
|
|
|
|
|
|
| 118 |
}
|
| 119 |
|
| 120 |
/**
|
|
|
|
| 126 |
*/
|
| 127 |
onDragStart = (event, nodeType, item, index) => {
|
| 128 |
event.dataTransfer.setData('application/reactflow', nodeType);
|
| 129 |
+
event.dataTransfer.setData('application/style', JSON.stringify({colour : this.state.colour[index], emoji : this.state.emoji[index] }))
|
| 130 |
+
event.dataTransfer.setData('application/item', JSON.stringify(item))
|
| 131 |
event.dataTransfer.effectAllowed = 'move';
|
| 132 |
+
};
|
| 133 |
|
| 134 |
/**
|
| 135 |
* droped event that occurs when the user drops the Tab within the tash div.
|
|
|
|
| 139 |
*/
|
| 140 |
onDragDrop = (e) => {
|
| 141 |
e.preventDefault();
|
| 142 |
+
var item = JSON.parse(e.dataTransfer.getData('application/item'));
|
| 143 |
+
fetch("http://localhost:2000/api/remove/port", {method : "POST", mode: 'cors', headers : { 'Content-Type' : 'application/json' }, body: JSON.stringify(item) }).then((re)=>{
|
| 144 |
this.deleteNode(item.name)
|
| 145 |
})
|
| 146 |
+
|
| 147 |
}
|
| 148 |
|
| 149 |
/**
|
|
|
|
| 158 |
var c = []
|
| 159 |
var j = []
|
| 160 |
if (d.length - e.length === 0) return
|
| 161 |
+
else if(d.length - e.length < 0){
|
| 162 |
var a = this.state.menu.filter(item => e.includes(item)) // get the items not in menu anymore
|
| 163 |
c = this.state.colour
|
| 164 |
j = this.state.emoji
|
| 165 |
+
for(var k=0; k < d.length; k++){
|
| 166 |
c.splice(this.state.menu.indexOf(a[k]), 1)
|
| 167 |
j.splice(this.state.menu.indexOf(a[k]), 1)
|
| 168 |
}
|
| 169 |
+
this.setState({'colour' : c, 'emoji' : j})
|
| 170 |
+
}else{
|
| 171 |
//append new colours
|
| 172 |
+
for(var i =0; i < d.length; i++){
|
| 173 |
+
c.push(random_colour(i === 0 ? null : c[i-1]));
|
| 174 |
+
j.push(random_emoji(i === 0 ? null : c[i-1]));
|
| 175 |
+
|
| 176 |
}
|
| 177 |
const colour = [...this.state.colour]
|
| 178 |
+
const emoji = [...this.state.emoji]
|
| 179 |
+
this.setState({'colour' : [...colour, ...c], 'emoji' : [...emoji, ...j],})
|
| 180 |
}
|
| 181 |
}
|
| 182 |
|
| 183 |
handelError = (boolean) => {
|
| 184 |
+
this.setState({'error' : boolean})
|
| 185 |
}
|
| 186 |
|
| 187 |
/**
|
| 188 |
* handel navagation open and close function
|
| 189 |
*/
|
| 190 |
handelNavbar = () => {
|
| 191 |
+
this.setState({'open' : !this.state.open})
|
| 192 |
}
|
| 193 |
|
| 194 |
/**
|
|
|
|
| 197 |
* @param {*} type : text | name string that set the changed value of the input to the current value
|
| 198 |
*/
|
| 199 |
updateText = (e, type) => {
|
| 200 |
+
this.setState({[`${type}`] : e.target.value })
|
| 201 |
}
|
| 202 |
|
| 203 |
/**
|
|
|
|
| 206 |
* @param {*} index : current index with in the list
|
| 207 |
* @returns div component that contians infomation of gradio
|
| 208 |
*/
|
| 209 |
+
subComponents(item, index){
|
| 210 |
+
|
| 211 |
+
return(<>
|
| 212 |
+
<li key={`${index}-li`} onDragStart={(event) => this.onDragStart(event, 'custom', item, index)}
|
| 213 |
+
className={` text-white text-md flex flex-col text-center items-center cursor-grab shadow-lg
|
| 214 |
+
p-5 px-2 mt-4 rounded-md ${ this.state.open ? `hover:animate-pulse ${this.state.colour[index] === null ? "" : this.state.colour[index]} ` : `hidden`} break-all -z-20`} draggable>
|
| 215 |
|
| 216 |
+
<div key={`${index}-div`} className=" absolute -mt-2 text-4xl opacity-60 z-10 ">{`${this.state.emoji[index] === null ? "" : this.state.emoji[index]}`}</div>
|
| 217 |
+
<h4 key={`${index}-h4`} className={` max-w-full font-sans text-blue-50 leading-tight font-bold text-xl flex-1 z-20 ${this.state.open ? "" : "hidden"}`} style={{"textShadow" : "0px 1px 2px rgba(0, 0, 0, 0.25)"}} >{`${item.name}`} </h4>
|
|
|
|
|
|
|
| 218 |
|
| 219 |
+
</li >
|
|
|
|
|
|
|
|
|
|
| 220 |
|
| 221 |
</>)
|
| 222 |
}
|
| 223 |
|
| 224 |
|
| 225 |
+
render(){
|
| 226 |
+
|
| 227 |
return (<div>
|
| 228 |
+
|
| 229 |
<div className={`z-10 flex-1 float-left bg-white dark:bg-stone-900 h-screen p-5 pt-8 ${this.state.open ? "lg:w-72 md:64 sm:w-60" : "w-10"} duration-300 absolute shadow-2xl border-black border-r-[1px] dark:border-white dark:text-white`} >
|
| 230 |
|
| 231 |
+
<BsArrowLeftShort onClick={this.handelNavbar} className={` bg-white text-Retro-darl-blue text-3xl rounded-full absolute -right-3 top-9 border border-black cursor-pointer ${!this.state.open && 'rotate-180'} dark:border-white duration-300 dark:text-white dark:bg-stone-900 `}/>
|
| 232 |
+
|
|
|
|
|
|
|
|
|
|
| 233 |
<div className="inline-flex w-full">
|
| 234 |
<h1 className={`font-sans font-bold text-lg ${this.state.open ? "" : "hidden"} duration-500 ml-auto mr-auto`}>Chat-nFace</h1>
|
| 235 |
</div>
|
| 236 |
|
| 237 |
+
<div className={`rounded-md text-center ${this.state.open ? "" : "px-0"} py-3`} onClick={() => {this.handelModal(true)}}>
|
| 238 |
<div className={` text-center bg-transparent w-full h-10 border border-slate-300 hover:border-Retro-purple hover:animate-pulse border-dashed rounded-md py-2 pl-5 ${this.state.open ? "pr-3" : "hidden"} shadow-sm sm:text-sm`}>
|
| 239 |
+
<Icon className=" block mr-auto ml-auto" name="plus"/>
|
| 240 |
</div>
|
| 241 |
</div>
|
| 242 |
+
<Import open={this.state.modal}
|
| 243 |
+
quitHandeler={this.handelModal}
|
| 244 |
+
textHandler={this.updateText}
|
| 245 |
+
appendHandler={this.appendStreamNode}
|
| 246 |
+
handelError={this.handelError}
|
| 247 |
+
catch={this.state.error}/>
|
| 248 |
+
|
| 249 |
<div className=" relative z-10 h-auto overflow-auto pt-4">
|
| 250 |
<ul className="pt-2">
|
| 251 |
+
{this.state.menu.map((menu, index) => {return this.subComponents(menu, index)})}
|
| 252 |
</ul>
|
| 253 |
</div>
|
| 254 |
|
| 255 |
+
<div className={`${this.state.open ? "" : "hidden"} absolute bottom-0 left-0 w-full text-center p-5`} onDragOver={(e)=> {e.preventDefault()}} onDrop={(e)=>{this.onDragDrop(e)}}>
|
| 256 |
<div className={` text-center bg-transparent w-full h-10 border border-red-600 border-dashed rounded-md py-2 pl-5 p-4 ${this.state.open ? "pr-3" : "hidden"} shadow-sm sm:text-sm`}>
|
| 257 |
+
<Icon name='trash alternate' />
|
| 258 |
</div>
|
| 259 |
</div>
|
| 260 |
</div>
|
| 261 |
+
|
| 262 |
</div>)
|
| 263 |
}
|
| 264 |
}
|
frontend/src/components/ReactFlow/ReactFlowEnv.js
CHANGED
|
@@ -57,33 +57,33 @@ export default function ReactEnviorment() {
|
|
| 57 |
restore();
|
| 58 |
},[deleteNode, deleteEdge]);
|
| 59 |
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
const handleAddEmbed = useCallback((embedData) => {
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
}, [nodes, reactFlowInstance]);
|
| 87 |
|
| 88 |
const onNodesChange = useCallback(
|
| 89 |
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
|
|
@@ -197,16 +197,16 @@ export default function ReactEnviorment() {
|
|
| 197 |
},
|
| 198 |
[reactFlowInstance, nodes, deleteNode]);
|
| 199 |
|
| 200 |
-
const addProxmoxVMNode = (vmAddress) => {
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
};
|
| 210 |
|
| 211 |
return (
|
| 212 |
<div className={`${theme ? "dark" : ""}`}>
|
|
@@ -216,7 +216,6 @@ export default function ReactEnviorment() {
|
|
| 216 |
<FaRegSave title="Save" className={`mt-6 text-black dark:text-white ${tool ? "visible" : " invisible"} ml-auto mr-auto `} onClick={() => onSave()}/>
|
| 217 |
<BsFillEraserFill title="Erase" className={`mt-6 text-black dark:text-white ml-auto mr-auto ${tool ? "visible" : " invisible"} `} onClick={() => onErase()}/>
|
| 218 |
</div>
|
| 219 |
-
<button onClick={() => setShowProxmoxForm(true)} className="absolute top-10 right-10 z-50 p-2 bg-green-500 text-white">Add Proxmox VM</button>
|
| 220 |
<div className={`flex h-screen w-screen ${theme ? "dark" : ""} transition-all`}>
|
| 221 |
<ReactFlowProvider>
|
| 222 |
<Navbar onDelete={deleteNodeContains} colour={JSON.parse(localStorage.getItem('colour'))} emoji={JSON.parse(localStorage.getItem('emoji'))} nodes={nodes}/>
|
|
@@ -231,3 +230,4 @@ export default function ReactEnviorment() {
|
|
| 231 |
</div>
|
| 232 |
);
|
| 233 |
}
|
|
|
|
|
|
| 57 |
restore();
|
| 58 |
},[deleteNode, deleteEdge]);
|
| 59 |
|
| 60 |
+
// const handleAddProxmoxVnc = async ({ vmid, node }) => {
|
| 61 |
+
// const response = await fetch('http://localhost:5000/api/proxmox/vnc', {
|
| 62 |
+
// method: 'POST',
|
| 63 |
+
// headers: { 'Content-Type': 'application/json' },
|
| 64 |
+
// body: JSON.stringify({ vmid, node }),
|
| 65 |
+
// });
|
| 66 |
+
// const data = await response.json();
|
| 67 |
+
// // Use data.iframe_src to create a new node in React Flow
|
| 68 |
+
// const newNode = {
|
| 69 |
+
// id: `proxmox-vnc-${nodes.length + 1}`,
|
| 70 |
+
// type: 'custom',
|
| 71 |
+
// position: reactFlowInstance.project({ x: 0, y: 0 }),
|
| 72 |
+
// data: { label: `Proxmox VM ${vmid}`, url: data.iframe_src },
|
| 73 |
+
// };
|
| 74 |
+
// setNodes((nds) => nds.concat(newNode));
|
| 75 |
+
// };
|
| 76 |
+
|
| 77 |
+
// const handleAddEmbed = useCallback((embedData) => {
|
| 78 |
+
// const newNode = {
|
| 79 |
+
// id: `embed-${nodes.length + 1}`,
|
| 80 |
+
// type: 'embed',
|
| 81 |
+
// position: reactFlowInstance.project({ x: 0, y: 0 }), // Adjust position as needed
|
| 82 |
+
// data: { url: embedData.url, width: embedData.width || '100%', height: embedData.height || '400px' },
|
| 83 |
+
// };
|
| 84 |
+
// setNodes((nds) => nds.concat(newNode));
|
| 85 |
+
// console.log(`Adding embed with URL: ${embedData.url} and Label: ${embedData.label}`);
|
| 86 |
+
// }, [nodes, reactFlowInstance]);
|
| 87 |
|
| 88 |
const onNodesChange = useCallback(
|
| 89 |
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
|
|
|
|
| 197 |
},
|
| 198 |
[reactFlowInstance, nodes, deleteNode]);
|
| 199 |
|
| 200 |
+
// const addProxmoxVMNode = (vmAddress) => {
|
| 201 |
+
// const newNode = {
|
| 202 |
+
// id: `proxmox-vm-${nodes.length + 1}`,
|
| 203 |
+
// type: 'proxmoxVM',
|
| 204 |
+
// position: { x: Math.random() * window.innerWidth, y: Math.random() * window.innerHeight },
|
| 205 |
+
// data: { vmAddress },
|
| 206 |
+
// };
|
| 207 |
+
// setNodes((nds) => nds.concat(newNode));
|
| 208 |
+
// setShowProxmoxForm(false);
|
| 209 |
+
// };
|
| 210 |
|
| 211 |
return (
|
| 212 |
<div className={`${theme ? "dark" : ""}`}>
|
|
|
|
| 216 |
<FaRegSave title="Save" className={`mt-6 text-black dark:text-white ${tool ? "visible" : " invisible"} ml-auto mr-auto `} onClick={() => onSave()}/>
|
| 217 |
<BsFillEraserFill title="Erase" className={`mt-6 text-black dark:text-white ml-auto mr-auto ${tool ? "visible" : " invisible"} `} onClick={() => onErase()}/>
|
| 218 |
</div>
|
|
|
|
| 219 |
<div className={`flex h-screen w-screen ${theme ? "dark" : ""} transition-all`}>
|
| 220 |
<ReactFlowProvider>
|
| 221 |
<Navbar onDelete={deleteNodeContains} colour={JSON.parse(localStorage.getItem('colour'))} emoji={JSON.parse(localStorage.getItem('emoji'))} nodes={nodes}/>
|
|
|
|
| 230 |
</div>
|
| 231 |
);
|
| 232 |
}
|
| 233 |
+
|
{images → frontend/src/images}/chatty.png
RENAMED
|
File without changes
|