LucaVivona commited on
Commit
7496675
β€’
1 Parent(s): 46e4902

default max_thread; Frontend Node Resizer πŸ‘‹

Browse files
backend/src/demo/demo.py CHANGED
@@ -4,7 +4,7 @@ import sys
4
  sys.path.insert(0, "../resources")
5
  from module import GradioModule, register, InterLauncher, tabularGradio
6
  sys.path.insert(0, "../example")
7
- from examples import Pictionary, FSD, stock_forecast
8
 
9
  import gradio as gr
10
 
@@ -43,9 +43,9 @@ elif args.examples == "load":
43
  demo = gr.Interface.load("models/EleutherAI/gpt-neo-1.3B", description=description, examples=examples)
44
  InterLauncher("Demo", demo) if args.listen == None else InterLauncher("Demo", demo, listen=args.listen)
45
 
46
- elif args.examples == "FSD": FSD().launch() if args.listen == None else FSD().launch(listen=args.listen)
47
 
48
- elif args.examples == "Stonk" : stock_forecast().launch() if args.listen == None else stock_forecast().launch(listen=args.listen)
49
 
50
- else:
51
- Pictionary("../example/data/labels.txt", "../example/data/pytorch_model.bin").launch(live=True) if args.listen == None else Pictionary("../example/data/labels.txt", "../example/data/pytorch_model.bin").launch(live=True, listen=args.listen)
 
4
  sys.path.insert(0, "../resources")
5
  from module import GradioModule, register, InterLauncher, tabularGradio
6
  sys.path.insert(0, "../example")
7
+ # from examples import Pictionary, FSD, stock_forecast
8
 
9
  import gradio as gr
10
 
 
43
  demo = gr.Interface.load("models/EleutherAI/gpt-neo-1.3B", description=description, examples=examples)
44
  InterLauncher("Demo", demo) if args.listen == None else InterLauncher("Demo", demo, listen=args.listen)
45
 
46
+ # elif args.examples == "FSD": FSD().launch() if args.listen == None else FSD().launch(listen=args.listen)
47
 
48
+ # elif args.examples == "Stonk" : stock_forecast().launch() if args.listen == None else stock_forecast().launch(listen=args.listen)
49
 
50
+ # else:
51
+ # Pictionary("../example/data/labels.txt", "../example/data/pytorch_model.bin").launch(live=True) if args.listen == None else Pictionary("../example/data/labels.txt", "../example/data/pytorch_model.bin").launch(live=True, listen=args.listen)
backend/src/resources/module.py CHANGED
@@ -78,7 +78,7 @@ def InterLauncher(name, interface, listen=2000, **kwargs):
78
  share=kwargs['share'] if "share" in kwargs else None,
79
  debug=kwargs['debug'] if "debug" in kwargs else False,
80
  enable_queue=kwargs['enable_queue'] if "enable_queue" in kwargs else None,
81
- max_threads=kwargs['max_threads'] if "max_threads" in kwargs else None,
82
  auth=kwargs['auth'] if "auth" in kwargs else None,
83
  auth_message=kwargs['auth_message'] if "auth_message" in kwargs else None,
84
  prevent_thread_lock=kwargs['prevent_thread_lock'] if "prevent_thread_lock" in kwargs else False,
@@ -131,7 +131,7 @@ def tabularGradio(funcs, names=[], name="Tabular Temp Name", **kwargs):
131
  share=kwargs['share'] if "share" in kwargs else None,
132
  debug=kwargs['debug'] if "debug" in kwargs else False,
133
  enable_queue=kwargs['enable_queue'] if "enable_queue" in kwargs else None,
134
- max_threads=kwargs['max_threads'] if "max_threads" in kwargs else None,
135
  auth=kwargs['auth'] if "auth" in kwargs else None,
136
  auth_message=kwargs['auth_message'] if "auth_message" in kwargs else None,
137
  prevent_thread_lock=kwargs['prevent_thread_lock'] if "prevent_thread_lock" in kwargs else False,
@@ -315,14 +315,14 @@ def GradioModule(cls):
315
  except Exception:
316
  print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πŸ›The listening api is either not up or you choose the wrong port.πŸ›")
317
  return
318
-
319
  self.interface.launch(server_port=port,
320
- server_name=f"{DOCKER_LOCAL_HOST}",
321
  inline= kwargs['inline'] if "inline" in kwargs else None,
322
  share=kwargs['share'] if "share" in kwargs else None,
323
  debug=kwargs['debug'] if "debug" in kwargs else False,
324
  enable_queue=kwargs['enable_queue'] if "enable_queue" in kwargs else None,
325
- max_threads=kwargs['max_threads'] if "max_threads" in kwargs else None,
326
  auth=kwargs['auth'] if "auth" in kwargs else None,
327
  auth_message=kwargs['auth_message'] if "auth_message" in kwargs else None,
328
  prevent_thread_lock=kwargs['prevent_thread_lock'] if "prevent_thread_lock" in kwargs else False,
 
78
  share=kwargs['share'] if "share" in kwargs else None,
79
  debug=kwargs['debug'] if "debug" in kwargs else False,
80
  enable_queue=kwargs['enable_queue'] if "enable_queue" in kwargs else None,
81
+ max_threads=kwargs['max_threads'] if "max_threads" in kwargs else 40,
82
  auth=kwargs['auth'] if "auth" in kwargs else None,
83
  auth_message=kwargs['auth_message'] if "auth_message" in kwargs else None,
84
  prevent_thread_lock=kwargs['prevent_thread_lock'] if "prevent_thread_lock" in kwargs else False,
 
131
  share=kwargs['share'] if "share" in kwargs else None,
132
  debug=kwargs['debug'] if "debug" in kwargs else False,
133
  enable_queue=kwargs['enable_queue'] if "enable_queue" in kwargs else None,
134
+ max_threads=kwargs['max_threads'] if "max_threads" in kwargs else 40,
135
  auth=kwargs['auth'] if "auth" in kwargs else None,
136
  auth_message=kwargs['auth_message'] if "auth_message" in kwargs else None,
137
  prevent_thread_lock=kwargs['prevent_thread_lock'] if "prevent_thread_lock" in kwargs else False,
 
315
  except Exception:
316
  print(f"**{bcolor.BOLD}{bcolor.FAIL}CONNECTION ERROR{bcolor.ENDC}** πŸ›The listening api is either not up or you choose the wrong port.πŸ›")
317
  return
318
+ print(port)
319
  self.interface.launch(server_port=port,
320
+ server_name=DOCKER_LOCAL_HOST,
321
  inline= kwargs['inline'] if "inline" in kwargs else None,
322
  share=kwargs['share'] if "share" in kwargs else None,
323
  debug=kwargs['debug'] if "debug" in kwargs else False,
324
  enable_queue=kwargs['enable_queue'] if "enable_queue" in kwargs else None,
325
+ max_threads=kwargs['max_threads'] if "max_threads" in kwargs else 40,
326
  auth=kwargs['auth'] if "auth" in kwargs else None,
327
  auth_message=kwargs['auth_message'] if "auth_message" in kwargs else None,
328
  prevent_thread_lock=kwargs['prevent_thread_lock'] if "prevent_thread_lock" in kwargs else False,
frontend/package-lock.json CHANGED
The diff for this file is too large to render. See raw diff
 
frontend/package.json CHANGED
@@ -10,12 +10,14 @@
10
  "@types/node": "^18.7.13",
11
  "@types/react": "^18.0.17",
12
  "@types/react-dom": "^18.0.6",
 
13
  "axios": "^0.27.2",
14
  "react": "^18.2.0",
15
  "react-dom": "^18.2.0",
16
  "react-flow-renderer": "^10.3.8",
17
  "react-icons": "^4.4.0",
18
  "react-scripts": "5.0.1",
 
19
  "semantic-ui-css": "^2.4.1",
20
  "semantic-ui-react": "^2.1.3",
21
  "typescript": "^4.8.2",
 
10
  "@types/node": "^18.7.13",
11
  "@types/react": "^18.0.17",
12
  "@types/react-dom": "^18.0.6",
13
+ "@use-gesture/react": "^10.2.20",
14
  "axios": "^0.27.2",
15
  "react": "^18.2.0",
16
  "react-dom": "^18.2.0",
17
  "react-flow-renderer": "^10.3.8",
18
  "react-icons": "^4.4.0",
19
  "react-scripts": "5.0.1",
20
+ "react-spring": "^9.5.5",
21
  "semantic-ui-css": "^2.4.1",
22
  "semantic-ui-react": "^2.1.3",
23
  "typescript": "^4.8.2",
frontend/src/components/Nodes/Custom.js CHANGED
@@ -1,206 +1,99 @@
1
- import React from "react"
2
- import { Handle, Position } from "react-flow-renderer"
3
  import {TbResize} from 'react-icons/tb'
4
  import {BiCube, BiRefresh} from 'react-icons/bi'
5
- import {BsTrash, BsArrowDownRightSquare} from 'react-icons/bs'
6
  import {CgLayoutGridSmall} from 'react-icons/cg'
 
 
 
7
  import '../../css/counter.css'
8
 
9
  const MINIMUM_HEIGHT = 600;
10
  const MINIMUM_WIDTH = 540;
11
- export default class CustomNodeIframe extends React.Component {
12
- constructor({id , data}){
13
- super()
14
- this.myRef = React.createRef()
15
- this.original_width = 0;
16
- this.original_height = 0;
17
- this.original_x = 0;
18
- this.original_y = 0;
19
- this.original_mouse_x = 0;
20
- this.original_mouse_y = 0;
21
- this.state = {
22
- id : id,
23
- reachable : this.isFetchable(data.host),
24
- selected : false,
25
- data : data,
26
- width : 540,
27
- height : 600,
28
- size : false,
29
- iframe : 0,
30
- }
31
-
32
- }
33
-
34
- handelSelected = () => {
35
- this.setState(prevState => ({'selected' : !prevState.selected, 'size' : false }))
36
- }
37
-
38
- handelSizeState = () => {
39
- this.setState(prevState => ({'size' : !prevState.size}))
40
- }
41
-
42
- isFetchable = async (host) => {
43
 
44
- fetch(host, {mode: 'no-cors'}).then((re) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  return true
46
  }).catch((err)=>{
47
  return false
48
  })
49
- return false
50
- }
51
-
52
-
53
- onNodeClick = (id) => {
54
- this.state.data.delete(id)
55
- }
56
-
57
- onRefresh(){
58
- if(!this.isFetchable(this.state.data.host)){
59
- this.onNodeClick(this.state.id)
60
- } else{
61
- this.setState(prevState => ({'iframe' : prevState.iframe + 1}))
62
- }
63
- }
64
-
65
- handelOnChange(evt, type){
66
- this.setState({[`${type}`] : parseInt(evt.target.value) })
67
- type === "width" ? this.myRef.current.style.width = `${parseInt(evt.target.value)}px` : this.myRef.current.style.height = `${parseInt(evt.target.value)}px`
68
- }
69
-
70
- handelSize(evt, increment, change){
71
- if (evt === "increment") {
72
- this.setState({[`${change}`] : change === "width" ? this.state.width + increment : this.state.height + increment })
73
- change === "width" ? this.myRef.current.style.width = `${this.state.width + increment}px` : this.myRef.current.style.height = `${this.state.height + increment}px`
74
- }
75
-
76
- }
77
-
78
- //resize nodes by dragging
79
- initial = (e) => {
80
- this.original_width = this.myRef.current.offsetWidth
81
- this.original_height = this.myRef.current.offsetHeight
82
-
83
- this.original_x = this.myRef.current.getBoundingClientRect().left;
84
- this.original_y = this.myRef.current.getBoundingClientRect().top;
85
-
86
- this.original_mouse_x = e.clientX
87
- this.original_mouse_y = e.clientY
88
- }
89
-
90
- resize = (e, point) => {
91
- var height = 0;
92
- var width = 0;
93
- // e.dataTransfer.setDragImage(new Image(), 0, 0)
94
- if (point === 'bottom-right'){
95
- width = this.original_width + (e.clientX - this.original_mouse_x);
96
- height = this.original_height + (e.clientY - this.original_mouse_y)
97
- if (width > MINIMUM_WIDTH) {
98
- this.myRef.current.style.width = `${width}px`
99
- this.setState({'width' : parseInt(width) , 'height' : parseInt(height)})
100
-
101
  }
102
- if (height > MINIMUM_HEIGHT) {
103
- this.myRef.current.style.height = `${height}px`
104
- this.setState({'width' : parseInt(width) , 'height' : parseInt(height)})
105
 
 
 
 
 
 
 
 
106
  }
107
- }
108
- }
109
-
110
- OnDragEnd = () => {
111
- this.setState({'width' : parseInt(this.myRef.current.offsetWidth), 'height' : parseInt(this.myRef.current.offsetHeight)})
112
- }
113
-
114
- Counter(focus, size){
115
- return (<div className="custom-number-input h-10 w-32 dark:text-white text-black ">
116
- <div className="flex flex-row h-10 w-full rounded-lg relative bg-transparent">
117
- <button data-action="decrement" className=" border-2 border-dotted border-Retro-dark-blue hover:border-rose-700 rounded-l-xl hover:animate-pulse h-full w-20 cursor-pointer outline-none " onClick={(e)=> {this.handelSize("increment", -5, focus)}}>
118
- <span className="m-auto text-2xl font-bold">βˆ’</span>
119
- </button>
120
- <input type="number" className="focus:outline-none border-Retro-dark-blue border-y-2 border-dotted text-center w-full font-semibold text-md focus:from-fuchsia-200 md:text-basecursor-default flex items-cente outline-none bg-transparent" name="input-number" value={size} onChange={(e) => this.handelOnChange(e, focus)} onKeyDown={(e) => {this.handelSize(e.key, size, focus)}}></input>
121
- <button data-action="increment" className="border-2 border-dotted border-Retro-dark-blue hover:border-green-400 rounded-r-xl hover:animate-pulse h-full w-20 cursor-pointer" onClick={(e)=> {this.handelSize("increment", 5, focus)}} >
122
- <span className="m-auto text-2xl font-bold">+</span>
123
- </button>
124
- </div>
125
- </div>)
126
- }
127
-
128
- render(){
129
- if (!this.state.reachable) {this.onNodeClick(this.state.id) }
130
- return (<>
131
- <div className=" flex w-full h-10 top-0 cursor-pointer" onClick={this.handelEvent}>
132
- <div title={this.state.selected ? "Collaspse Node" : "Expand Node"} className=" duration-300 cursor-pointer shadow-xl border-2 border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Blue rounded-xl" onClick={this.handelSelected}><CgLayoutGridSmall className="h-full w-full text-white p-1"/></div>
133
-
134
-
135
- <div className={` flex ${this.state.selected ? '' : 'w-0 hidden'}`}>
136
- <div title="Adjust Node Size" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Violet rounded-xl" onClick={this.handelSizeState}><TbResize className="h-full w-full text-white p-1"/></div>
137
- <a href={this.state.data.host} target="_blank" rel="noopener noreferrer"><div title="Gradio Host Site" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Pink rounded-xl"><BiCube className="h-full w-full text-white p-1"/></div></a>
138
- <div title="Delete Node" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Red rounded-xl" onClick={() => this.onNodeClick(this.state.id)}><BsTrash className="h-full w-full text-white p-1"/></div>
139
- <div title="Refresh Node" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Orange rounded-xl" onClick={() => this.onRefresh()}><BiRefresh className="h-full w-full text-white p-1"/></div>
140
-
141
- { this.state.size && <div className="duration-300 flex w-auto h-full mr-2 -mt-3 space-x-4">
142
- {this.Counter("width", this.state.width)}
143
- {this.Counter("height", this.state.height)}
144
- </div>}
145
- </div>
146
-
147
- </div>
148
-
149
- <div id={`draggable`} className={`relative overflow-hidden m-0 p-0 shadow-2xl ${this.state.selected ? "w-[540px] h-[600px]" : "hidden"} duration-200`} ref={this.myRef}>
150
-
151
- <div className={`absolute p-5 h-full w-full ${this.state.data.colour} shadow-2xl rounded-xl -z-20`}></div>
152
- <iframe
153
- id="iframe"
154
- key={this.state.iframe}
155
- src={this.state.data.host}
156
- title={this.state.data.label}
157
- frameBorder="0"
158
- className="p-2 -z-10 h-full w-full ml-auto mr-auto overflow-y-scroll"
159
- sandbox="allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"
160
- ></iframe>
161
- </div>
162
-
163
- {/*Input*/}
164
- <Handle type="target"
165
- id="input"
166
- position={Position.Left}
167
- style={!this.state.selected ?
168
- {"paddingRight" : "5px" , "marginTop" : "15px", "height" : "25px", "width" : "25px", "borderRadius" : "3px", "zIndex" : "10000", "background" : "white", "boxShadow" : "3px 3px #888888"}
169
- :{"paddingRight" : "5px" ,"height" : "25px", "width" : "25px", "borderRadius" : "3px", "zIndex" : "10000", "background" : "white", "boxShadow" : "3px 3px #888888"}}
170
- />
171
-
172
- {/*Output*/}
173
- <Handle type="source" id="output" position={Position.Right} style={ !this.state.selected ?
174
- {"paddingLeft" : "5px", "marginTop" : "15px" ,"height" : "25px", "width" : "25px", "borderRadius" : "3px", "zIndex" : "10000", "background" : "white", "boxShadow" : "3px 3px #888888"}
175
- : {"paddingLeft" : "5px", "marginTop" : "0px" ,"height" : "25px", "width" : "25px", "borderRadius" : "3px", "zIndex" : "10000", "background" : "white", "boxShadow" : "3px 3px #888888"}}/>
176
-
177
- {
178
- !this.state.selected &&
179
- <div
180
- id={`draggable`}
181
- className={` w-[340px] h-[140px] text-white text-md flex flex-col text-center items-center cursor-grab shadow-lg
182
- p-5 px-2 rounded-md hover:animate-pulse break-all -z-20 ${this.state.data.colour}`}>
183
-
184
- <div className="absolute text-6xl opacity-60 z-10 pt-8 ">{this.state.data.emoji}</div>
185
- <h2 className={`max-w-full font-sans text-blue-50 leading-tight font-bold text-3xl flex-1 z-20 pt-10`} style={{"textShadow" : "0px 1px 2px rgba(0, 0, 0, 0.25)"}} >{this.state.data.label}</h2>
186
- </div >
187
- }
188
- { this.state.size && !navigator.userAgent.match(/firefox|fxios/i) && <>
189
-
190
- <div id="remove-ghost" className={`absolute select-none -bottom-0 right-0 w-5 h-5border-2 shadow-2xl rounded-xl z-10 cursor-nwse-resize hover:opacity-50 `}
191
- style={{"userDrag": "none"}}
192
- draggable
193
- onDragStart={(e) => { this.initial(e) }}
194
- onDrag={(e) => { this.resize(e, 'bottom-right') }}
195
- onDragEnd={() => {this.OnDragEnd()}}
196
- >
197
- <BsArrowDownRightSquare className=" text-selected-text text-2xl bg-white"/>
198
- </div>
199
-
200
- </>
201
- }
202
-
203
-
204
- </>)
205
- }
206
- }
 
1
+ import React, { useCallback, useEffect, useRef, useState } from "react"
2
+ // import { Handle, Position } from "react-flow-renderer"
3
  import {TbResize} from 'react-icons/tb'
4
  import {BiCube, BiRefresh} from 'react-icons/bi'
5
+ import {BsTrash} from 'react-icons/bs'
6
  import {CgLayoutGridSmall} from 'react-icons/cg'
7
+ import {useDrag} from '@use-gesture/react'
8
+ import { useSpring, animated } from 'react-spring'
9
+
10
  import '../../css/counter.css'
11
 
12
  const MINIMUM_HEIGHT = 600;
13
  const MINIMUM_WIDTH = 540;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ export default function CustomNodeIframe({id, data}){
16
+ const [collapsed, setCollapsible] = useState(true)
17
+ const [{width, height}, api] = useSpring(() => ({width: MINIMUM_WIDTH, height: MINIMUM_HEIGHT }))
18
+ const [sizeAdjuster, setSizeAdjuster] = useState(false)
19
+ const [reachable ,setReachable] = useState(false)
20
+ const [refresh, setRefresh] = useState(0)
21
+ const dragElement = useRef()
22
+
23
+ const bind = useDrag((state) => {
24
+ const isResizing = (state?.event.target === dragElement.current);
25
+ if (isResizing) {
26
+ api.set({
27
+ width: state.offset[0],
28
+ height: state.offset[1],
29
+
30
+ });
31
+ }
32
+ }, {
33
+ from: (event) => {
34
+ const isResizing = (event.target === dragElement.current);
35
+ if (isResizing) {
36
+ return [width.get(), height.get()];
37
+ }
38
+ },
39
+ });
40
+
41
+ const isFetchable =useCallback(async () => {
42
+ return fetch(data.host, {mode: 'no-cors'}).then((res) => {
43
  return true
44
  }).catch((err)=>{
45
  return false
46
  })
47
+ }, [data.host])
48
+
49
+ useEffect(() => {
50
+ const fetched = setInterval(
51
+ async () => {
52
+ const fetch = await isFetchable()
53
+ if (fetch){
54
+ setReachable(true)
55
+ clearInterval(fetched)
56
+ }
57
+ },1000)
58
+ },[isFetchable])
59
+
60
+
61
+ return (
62
+ <div className="w-10 h-10">
63
+
64
+ <div id={'draggable'}className=" flex w-full h-10 top-0 cursor-pointer" onClick={() => {}}>
65
+ <div id={'draggable'} title={collapsed ? "Collaspse Node" : "Expand Node"} className=" flex-none duration-300 cursor-pointer shadow-xl border-2 border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Blue rounded-xl" onClick={() => {setCollapsible((clps) => !clps)}}><CgLayoutGridSmall className="h-full w-full text-white p-1"/></div>
66
+
67
+ <div className={` flex ${!collapsed ? '' : 'w-0 hidden'}`}>
68
+ <div title="Adjust Node Size" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Violet rounded-xl" onClick={() => {setSizeAdjuster((size) => !size)}}><TbResize className="h-full w-full text-white p-1"/></div>
69
+ <a href={data.host} target="_blank" rel="noopener noreferrer"><div title="Gradio Host Site" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Pink rounded-xl"><BiCube className="h-full w-full text-white p-1"/></div></a>
70
+ <div title="Delete Node" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Red rounded-xl" onClick={() => data.delete([{id : id}])}><BsTrash className="h-full w-full text-white p-1"/></div>
71
+ <div title="Refresh Node" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-white h-10 w-10 mr-2 -mt-3 bg-Warm-Orange rounded-xl" onClick={() => {setRefresh((old) => old++)}}><BiRefresh className="h-full w-full text-white p-1"/></div>
72
+ </div>
73
+ </div>
74
+
75
+ { !collapsed && reachable && <>
76
+ <animated.div className={`border-dashed ${sizeAdjuster ? 'border-4 border-white' : ''} relative top-0 left-0 z-[1000] touch-none shadow-lg rounded-xl`} style={{width, height }} {...bind()}>
77
+ <div id="draggable" className={`absolute h-full w-full ${data.colour} shadow-2xl rounded-xl -z-20`}></div>
78
+ <iframe id="iframe"
79
+ key={refresh}
80
+ src={data.host}
81
+ title={data.label}
82
+ frameBorder="0"
83
+ className=" p-[0.6rem] -z-10 h-full w-full ml-auto mr-auto overflow-y-scroll"/>
84
+ <div className={` ${sizeAdjuster ? '' : 'hidden'} rounded-full border-2 absolute -bottom-4 -right-4 w-7 h-7 bg-Blue-Royal cursor-nwse-resize touch-none shadow-lg`} ref={dragElement}>
85
+ </div>
86
+ </animated.div>
87
+ </>
 
 
 
 
 
 
 
 
 
 
 
88
  }
 
 
 
89
 
90
+ { collapsed &&
91
+ <div id={`draggable`}
92
+ className={` w-[340px] h-[140px] text-white text-md flex flex-col text-center items-center cursor-grab shadow-lg
93
+ p-5 px-2 rounded-md break-all -z-20 ${data.colour} hover:opacity-70 duration-300`} onClick={() => setCollapsible(collapsed => !collapsed)}>
94
+ <div className="absolute text-6xl opacity-60 z-10 pt-8 ">{data.emoji}</div>
95
+ <h2 className={`max-w-full font-sans text-blue-50 leading-tight font-bold text-3xl flex-1 z-20 pt-10`} style={{"textShadow" : "0px 1px 2px rgba(0, 0, 0, 0.25)"}} >{data.label}</h2>
96
+ </div >
97
  }
98
+ </div>)
99
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/src/css/dist/output.css CHANGED
@@ -606,8 +606,12 @@ video {
606
  top: 2.25rem;
607
  }
608
 
609
- .-bottom-0 {
610
- bottom: -0px;
 
 
 
 
611
  }
612
 
613
  .top-4 {
@@ -626,6 +630,10 @@ video {
626
  z-index: 10;
627
  }
628
 
 
 
 
 
629
  .-z-10 {
630
  z-index: -10;
631
  }
@@ -638,14 +646,6 @@ video {
638
  float: left;
639
  }
640
 
641
- .m-auto {
642
- margin: auto;
643
- }
644
-
645
- .m-0 {
646
- margin: 0px;
647
- }
648
-
649
  .mr-5 {
650
  margin-right: 1.25rem;
651
  }
@@ -742,8 +742,8 @@ video {
742
  height: auto;
743
  }
744
 
745
- .h-\[600px\] {
746
- height: 600px;
747
  }
748
 
749
  .h-\[140px\] {
@@ -782,30 +782,18 @@ video {
782
  width: 75%;
783
  }
784
 
785
- .w-32 {
786
- width: 8rem;
787
- }
788
-
789
  .w-0 {
790
  width: 0px;
791
  }
792
 
793
- .w-auto {
794
- width: auto;
795
- }
796
-
797
- .w-\[540px\] {
798
- width: 540px;
799
  }
800
 
801
  .w-\[340px\] {
802
  width: 340px;
803
  }
804
 
805
- .w-5 {
806
- width: 1.25rem;
807
- }
808
-
809
  .w-\[41px\] {
810
  width: 41px;
811
  }
@@ -822,6 +810,10 @@ video {
822
  flex: 1 1 0%;
823
  }
824
 
 
 
 
 
825
  .rotate-180 {
826
  --tw-rotate: 180deg;
827
  -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
@@ -850,19 +842,15 @@ video {
850
  cursor: default;
851
  }
852
 
 
 
 
 
853
  .select-none {
854
  -webkit-user-select: none;
855
  user-select: none;
856
  }
857
 
858
- .resize {
859
- resize: both;
860
- }
861
-
862
- .flex-row {
863
- flex-direction: row;
864
- }
865
-
866
  .flex-col {
867
  flex-direction: column;
868
  }
@@ -879,12 +867,6 @@ video {
879
  justify-content: center;
880
  }
881
 
882
- .space-x-4 > :not([hidden]) ~ :not([hidden]) {
883
- --tw-space-x-reverse: 0;
884
- margin-right: calc(1rem * var(--tw-space-x-reverse));
885
- margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
886
- }
887
-
888
  .overflow-auto {
889
  overflow: auto;
890
  }
@@ -926,16 +908,6 @@ video {
926
  border-top-right-radius: 0.5rem;
927
  }
928
 
929
- .rounded-l-xl {
930
- border-top-left-radius: 0.75rem;
931
- border-bottom-left-radius: 0.75rem;
932
- }
933
-
934
- .rounded-r-xl {
935
- border-top-right-radius: 0.75rem;
936
- border-bottom-right-radius: 0.75rem;
937
- }
938
-
939
  .rounded-tl-lg {
940
  border-top-left-radius: 0.5rem;
941
  }
@@ -948,9 +920,8 @@ video {
948
  border-width: 1px;
949
  }
950
 
951
- .border-y-2 {
952
- border-top-width: 2px;
953
- border-bottom-width: 2px;
954
  }
955
 
956
  .border-r-\[1px\] {
@@ -961,10 +932,6 @@ video {
961
  border-style: dashed;
962
  }
963
 
964
- .border-dotted {
965
- border-style: dotted;
966
- }
967
-
968
  .border-gray-200 {
969
  --tw-border-opacity: 1;
970
  border-color: rgb(229 231 235 / var(--tw-border-opacity));
@@ -985,11 +952,6 @@ video {
985
  border-color: rgb(220 38 38 / var(--tw-border-opacity));
986
  }
987
 
988
- .border-Retro-dark-blue {
989
- --tw-border-opacity: 1;
990
- border-color: rgb(3 94 232 / var(--tw-border-opacity));
991
- }
992
-
993
  .border-white {
994
  --tw-border-opacity: 1;
995
  border-color: rgb(255 255 255 / var(--tw-border-opacity));
@@ -1053,6 +1015,11 @@ video {
1053
  background-color: rgb(254 169 89 / var(--tw-bg-opacity));
1054
  }
1055
 
 
 
 
 
 
1056
  .bg-gradient-to-bl {
1057
  background-image: linear-gradient(to bottom left, var(--tw-gradient-stops));
1058
  }
@@ -1280,6 +1247,10 @@ video {
1280
  padding: 0.25rem;
1281
  }
1282
 
 
 
 
 
1283
  .px-6 {
1284
  padding-left: 1.5rem;
1285
  padding-right: 1.5rem;
@@ -1402,11 +1373,6 @@ video {
1402
  line-height: 2.25rem;
1403
  }
1404
 
1405
- .text-2xl {
1406
- font-size: 1.5rem;
1407
- line-height: 2rem;
1408
- }
1409
-
1410
  .text-6xl {
1411
  font-size: 3.75rem;
1412
  line-height: 1;
@@ -1420,10 +1386,6 @@ video {
1420
  font-weight: 700;
1421
  }
1422
 
1423
- .font-semibold {
1424
- font-weight: 600;
1425
- }
1426
-
1427
  .leading-tight {
1428
  line-height: 1.25;
1429
  }
@@ -1458,11 +1420,6 @@ video {
1458
  color: rgb(239 246 255 / var(--tw-text-opacity));
1459
  }
1460
 
1461
- .text-selected-text {
1462
- --tw-text-opacity: 1;
1463
- color: rgb(0 83 215 / var(--tw-text-opacity));
1464
- }
1465
-
1466
  .underline {
1467
  -webkit-text-decoration-line: underline;
1468
  text-decoration-line: underline;
@@ -1496,11 +1453,6 @@ video {
1496
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1497
  }
1498
 
1499
- .outline-none {
1500
- outline: 2px solid transparent;
1501
- outline-offset: 2px;
1502
- }
1503
-
1504
  .filter {
1505
  -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
1506
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
@@ -1572,16 +1524,6 @@ video {
1572
  border-color: rgb(151 0 204 / var(--tw-border-opacity));
1573
  }
1574
 
1575
- .hover\:border-rose-700:hover {
1576
- --tw-border-opacity: 1;
1577
- border-color: rgb(190 18 60 / var(--tw-border-opacity));
1578
- }
1579
-
1580
- .hover\:border-green-400:hover {
1581
- --tw-border-opacity: 1;
1582
- border-color: rgb(74 222 128 / var(--tw-border-opacity));
1583
- }
1584
-
1585
  .hover\:bg-gray-200:hover {
1586
  --tw-bg-opacity: 1;
1587
  background-color: rgb(229 231 235 / var(--tw-bg-opacity));
@@ -1601,10 +1543,6 @@ video {
1601
  opacity: 0.7;
1602
  }
1603
 
1604
- .hover\:opacity-50:hover {
1605
- opacity: 0.5;
1606
- }
1607
-
1608
  .hover\:shadow-lg:hover {
1609
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
1610
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
@@ -1621,12 +1559,6 @@ video {
1621
  background-color: rgb(55 65 81 / var(--tw-bg-opacity));
1622
  }
1623
 
1624
- .focus\:from-fuchsia-200:focus {
1625
- --tw-gradient-from: #f5d0fe;
1626
- --tw-gradient-to: rgb(245 208 254 / 0);
1627
- --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
1628
- }
1629
-
1630
  .focus\:shadow-xl:focus {
1631
  --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
1632
  --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
 
606
  top: 2.25rem;
607
  }
608
 
609
+ .-bottom-4 {
610
+ bottom: -1rem;
611
+ }
612
+
613
+ .-right-4 {
614
+ right: -1rem;
615
  }
616
 
617
  .top-4 {
 
630
  z-index: 10;
631
  }
632
 
633
+ .z-\[1000\] {
634
+ z-index: 1000;
635
+ }
636
+
637
  .-z-10 {
638
  z-index: -10;
639
  }
 
646
  float: left;
647
  }
648
 
 
 
 
 
 
 
 
 
649
  .mr-5 {
650
  margin-right: 1.25rem;
651
  }
 
742
  height: auto;
743
  }
744
 
745
+ .h-7 {
746
+ height: 1.75rem;
747
  }
748
 
749
  .h-\[140px\] {
 
782
  width: 75%;
783
  }
784
 
 
 
 
 
785
  .w-0 {
786
  width: 0px;
787
  }
788
 
789
+ .w-7 {
790
+ width: 1.75rem;
 
 
 
 
791
  }
792
 
793
  .w-\[340px\] {
794
  width: 340px;
795
  }
796
 
 
 
 
 
797
  .w-\[41px\] {
798
  width: 41px;
799
  }
 
810
  flex: 1 1 0%;
811
  }
812
 
813
+ .flex-none {
814
+ flex: none;
815
+ }
816
+
817
  .rotate-180 {
818
  --tw-rotate: 180deg;
819
  -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
 
842
  cursor: default;
843
  }
844
 
845
+ .touch-none {
846
+ touch-action: none;
847
+ }
848
+
849
  .select-none {
850
  -webkit-user-select: none;
851
  user-select: none;
852
  }
853
 
 
 
 
 
 
 
 
 
854
  .flex-col {
855
  flex-direction: column;
856
  }
 
867
  justify-content: center;
868
  }
869
 
 
 
 
 
 
 
870
  .overflow-auto {
871
  overflow: auto;
872
  }
 
908
  border-top-right-radius: 0.5rem;
909
  }
910
 
 
 
 
 
 
 
 
 
 
 
911
  .rounded-tl-lg {
912
  border-top-left-radius: 0.5rem;
913
  }
 
920
  border-width: 1px;
921
  }
922
 
923
+ .border-4 {
924
+ border-width: 4px;
 
925
  }
926
 
927
  .border-r-\[1px\] {
 
932
  border-style: dashed;
933
  }
934
 
 
 
 
 
935
  .border-gray-200 {
936
  --tw-border-opacity: 1;
937
  border-color: rgb(229 231 235 / var(--tw-border-opacity));
 
952
  border-color: rgb(220 38 38 / var(--tw-border-opacity));
953
  }
954
 
 
 
 
 
 
955
  .border-white {
956
  --tw-border-opacity: 1;
957
  border-color: rgb(255 255 255 / var(--tw-border-opacity));
 
1015
  background-color: rgb(254 169 89 / var(--tw-bg-opacity));
1016
  }
1017
 
1018
+ .bg-Blue-Royal {
1019
+ --tw-bg-opacity: 1;
1020
+ background-color: rgb(61 118 224 / var(--tw-bg-opacity));
1021
+ }
1022
+
1023
  .bg-gradient-to-bl {
1024
  background-image: linear-gradient(to bottom left, var(--tw-gradient-stops));
1025
  }
 
1247
  padding: 0.25rem;
1248
  }
1249
 
1250
+ .p-\[0\.6rem\] {
1251
+ padding: 0.6rem;
1252
+ }
1253
+
1254
  .px-6 {
1255
  padding-left: 1.5rem;
1256
  padding-right: 1.5rem;
 
1373
  line-height: 2.25rem;
1374
  }
1375
 
 
 
 
 
 
1376
  .text-6xl {
1377
  font-size: 3.75rem;
1378
  line-height: 1;
 
1386
  font-weight: 700;
1387
  }
1388
 
 
 
 
 
1389
  .leading-tight {
1390
  line-height: 1.25;
1391
  }
 
1420
  color: rgb(239 246 255 / var(--tw-text-opacity));
1421
  }
1422
 
 
 
 
 
 
1423
  .underline {
1424
  -webkit-text-decoration-line: underline;
1425
  text-decoration-line: underline;
 
1453
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1454
  }
1455
 
 
 
 
 
 
1456
  .filter {
1457
  -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
1458
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
 
1524
  border-color: rgb(151 0 204 / var(--tw-border-opacity));
1525
  }
1526
 
 
 
 
 
 
 
 
 
 
 
1527
  .hover\:bg-gray-200:hover {
1528
  --tw-bg-opacity: 1;
1529
  background-color: rgb(229 231 235 / var(--tw-bg-opacity));
 
1543
  opacity: 0.7;
1544
  }
1545
 
 
 
 
 
1546
  .hover\:shadow-lg:hover {
1547
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
1548
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
 
1559
  background-color: rgb(55 65 81 / var(--tw-bg-opacity));
1560
  }
1561
 
 
 
 
 
 
 
1562
  .focus\:shadow-xl:focus {
1563
  --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
1564
  --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);