import React, { Component } from "react"; import { Icon } from 'semantic-ui-react' import Import from '../Modal/importer' import { random_colour, random_emoji } from "../../helper/visual"; import "../../css/dist/output.css" import { BsArrowLeftShort } from 'react-icons/bs'; import { ReactComponent as ReactLogo } from '../../images/logo.svg' import chattyImage from '../../images/chatty.png'; export default class Navbar extends Component { constructor(props) { super(props) this.temp_host = 0 this.deleteNode = props.onDelete this.state = { open: true, menu: [], colour: props.colour || [], text: "", name: "", emoji: props.emoji || [], mode: false, modal: false, error: false } } componentDidMount() { this.fetch_classes() } /** * Asynchronously call the Flask api server every second to check if there exist a gradio application info * @return null */ fetch_classes = async () => { try { setInterval(async () => { await fetch("http://localhost:2000/api/open/ports", { method: 'GET', mode: 'cors', }) .then(response => response.json()) .then(data => { this.handelTabs(this.state.menu, data, data) this.setState({ menu: data }) }) .catch(error => { console.log(error) }) }, 1000); } catch (e) { console.log(e) } } /** * Append new node from the user */ appendStreamNode = async (type) => { const pattern = { local: new RegExp('^https?://(localhost)(:[0-9]+)?(/)?$'), share: new RegExp('^https?://(?:[a-zA-Z0-9]+\\.gradio\\.live)/?$'), huggingFace: new RegExp('^https?://([a-zA-Z0-9-]+\\.hf\\.space)/?$'), proxmoxVNC: new RegExp('^wss?://([a-zA-Z0-9-]+\\.yourdomain\\.com)/?$') // Regex pattern for Proxmox VNC URLs } if (this.state.name.length > 20 || this.state.text === "" || this.state.menu.findIndex(element => { return element.name.toLowerCase() === this.state.name.toLowerCase() || element.host.includes(this.state.text) }) !== -1 || this.state.text.includes(" ") || (!pattern.local.test(this.state.text) && !pattern.share.test(this.state.text) && !pattern.huggingFace.test(this.state.text) && !pattern.proxmoxVNC.test(this.state.text))) { this.setState({ 'text': '', 'name': '', 'error': true }) return } fetch(this.state.text, { method: "GET", mode: 'no-cors' }).then((re) => { 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 => { this.setState({ 'text': "", 'name': "", 'error': false, 'modal': false }) }).catch(() => this.setState({ 'text': '', 'name': '', 'error': true, })) }).catch((err) => this.setState({ 'text': '', 'name': '', 'error': true, })) } /** * Render a tab for the Proxmox VNC that can be dragged into React Flow */ renderProxmoxVncTab = () => { // Assuming the Proxmox VNC tab information is stored in the state const { proxmoxVncInfo } = this.state; if (!proxmoxVncInfo) return null; // If no Proxmox VNC info, don't render anything return (
  • this.onDragStart(event, 'proxmoxVNC', proxmoxVncInfo, -1)} 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" draggable>
    {random_emoji()}

    Proxmox VNC

  • ); } /** * error check the user input * @param {*} bool boolean of the current state of the modal */ handelModal = (bool) => { this.setState({ 'error': !bool ? false : this.state.error, 'modal': bool }) } /** * when dragged get all the information needed * @param {*} event * @param {*} nodeType string 'custom' node type * @param {*} item object information returned from the api * @param {*} index current index */ onDragStart = (event, nodeType, item, index) => { event.dataTransfer.setData('application/reactflow', nodeType); event.dataTransfer.setData('application/style', JSON.stringify({ colour: this.state.colour[index], emoji: this.state.emoji[index] })) event.dataTransfer.setData('application/item', JSON.stringify(item)) event.dataTransfer.effectAllowed = 'move'; }; /** * droped event that occurs when the user drops the Tab within the tash div. * The function just deletes all nodes within React-Flow enviorment related, * and remove it from the api. * @param {*} e drop event */ onDragDrop = (e) => { e.preventDefault(); var item = JSON.parse(e.dataTransfer.getData('application/item')); fetch("http://localhost:2000/api/remove/port", { method: "POST", mode: 'cors', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(item) }).then((re) => { this.deleteNode(item.name) }) } /** * update the tabs within the navbar * @param {*} e current menu * @param {*} d integer variable of the diffence between the current menu and new menu updated ment */ handelTabs = async (e, d) => { // if less then 0 we must remove colour's and emoji's // get index of the object // remove var c = [] var j = [] if (d.length - e.length === 0) return else if (d.length - e.length < 0) { var a = this.state.menu.filter(item => e.includes(item)) // get the items not in menu anymore c = this.state.colour j = this.state.emoji for (var k = 0; k < d.length; k++) { c.splice(this.state.menu.indexOf(a[k]), 1) j.splice(this.state.menu.indexOf(a[k]), 1) } this.setState({ 'colour': c, 'emoji': j }) } else { //append new colours for (var i = 0; i < d.length; i++) { c.push(random_colour(i === 0 ? null : c[i - 1])); j.push(random_emoji(i === 0 ? null : c[i - 1])); } const colour = [...this.state.colour] const emoji = [...this.state.emoji] this.setState({ 'colour': [...colour, ...c], 'emoji': [...emoji, ...j], }) } } handelError = (boolean) => { this.setState({ 'error': boolean }) } /** * handel navagation open and close function */ handelNavbar = () => { this.setState({ 'open': !this.state.open }) } /** * * @param {*} e : event type to get the target value of the current input * @param {*} type : text | name string that set the changed value of the input to the current value */ updateText = (e, type) => { this.setState({ [`${type}`]: e.target.value }) } /** * * @param {*} item : object infomation from the flask api * @param {*} index : current index with in the list * @returns div component that contians infomation of gradio */ subComponents(item, index) { return (<>
  • this.onDragStart(event, 'custom', item, index)} className={` text-white text-md flex flex-col text-center items-center cursor-grab shadow-lg 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>
    {`${this.state.emoji[index] === null ? "" : this.state.emoji[index]}`}

    {`${item.name}`}

  • ) } render() { return (
    Chat'nFace Logo {/* Display the image */}

    Chat-nFace

    Chat-nFace

    { this.handelModal(true) }}>
      {this.state.menu.map((menu, index) => { return this.subComponents(menu, index) })}
    { e.preventDefault() }} onDrop={(e) => { this.onDragDrop(e) }}>
    ) } }