added plugins, updated image paths
10
src/App.js
@@ -14,7 +14,9 @@ import Widget from './canvas/widgets/base'
|
||||
import { DraggableWidgetCard } from './components/cards'
|
||||
import { DragProvider } from './components/draggable/draggableContext'
|
||||
import { ActiveWidgetProvider } from './canvas/activeWidgetContext'
|
||||
import TkinterSidebar from './frameworks/tkinter/sidebarWidgets'
|
||||
import TkinterWidgets from './frameworks/tkinter/sidebarWidgets'
|
||||
import PluginsContainer from './sidebar/pluginsContainer'
|
||||
import TkinterPluginWidgets from './frameworks/tkinter/sidebarPlugins'
|
||||
|
||||
|
||||
function App() {
|
||||
@@ -31,7 +33,7 @@ function App() {
|
||||
|
||||
const [dropAnimation, setDropAnimation] = useState(null)
|
||||
|
||||
const [sidebarWidgets, setSidebarWidgets] = useState(TkinterSidebar || [])
|
||||
const [sidebarWidgets, setSidebarWidgets] = useState(TkinterWidgets || [])
|
||||
const [canvasWidgets, setCanvasWidgets] = useState([]) // contains the reference to the widgets inside the canvas
|
||||
|
||||
const [activeSidebarWidget, setActiveSidebarWidget] = useState(null) // helps with the dnd overlay
|
||||
@@ -44,12 +46,12 @@ function App() {
|
||||
{
|
||||
name: "Widgets",
|
||||
icon: <LayoutFilled />,
|
||||
content: <WidgetsContainer sidebarContent={TkinterSidebar} onWidgetsUpdate={(widgets) => setSidebarWidgets(widgets)}/>
|
||||
content: <WidgetsContainer sidebarContent={TkinterWidgets} onWidgetsUpdate={(widgets) => setSidebarWidgets(widgets)}/>
|
||||
},
|
||||
{
|
||||
name: "Plugins",
|
||||
icon: <ProductFilled />,
|
||||
content: <></>
|
||||
content: <PluginsContainer sidebarContent={TkinterPluginWidgets}/>
|
||||
},
|
||||
{
|
||||
name: "Uploads",
|
||||
|
||||
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
BIN
src/frameworks/tkinter/assets/widgets/plugins/clock.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
src/frameworks/tkinter/assets/widgets/plugins/map.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
src/frameworks/tkinter/assets/widgets/plugins/tables.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/frameworks/tkinter/assets/widgets/plugins/video.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
105
src/frameworks/tkinter/plugins/analogTimepicker.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import React from "react"
|
||||
|
||||
import { timePicker, timePickerInput } from 'analogue-time-picker'
|
||||
|
||||
import Widget from "../../../canvas/widgets/base"
|
||||
import Tools from "../../../canvas/constants/tools"
|
||||
import { removeKeyFromObject } from "../../../utils/common"
|
||||
|
||||
|
||||
class AnalogTimePicker extends Widget{
|
||||
|
||||
static widgetType = "analogue_timepicker"
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.droppableTags = null
|
||||
|
||||
const newAttrs = removeKeyFromObject("layout", this.state.attrs)
|
||||
|
||||
this.timePicker = null
|
||||
|
||||
this.timePickerRef = React.createRef()
|
||||
|
||||
this.state = {
|
||||
...this.state,
|
||||
size: { width: 'fit', height: 'fit' },
|
||||
attrs: {
|
||||
...newAttrs,
|
||||
styling: {
|
||||
...newAttrs.styling,
|
||||
foregroundColor: {
|
||||
label: "Foreground Color",
|
||||
tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string
|
||||
value: "#000",
|
||||
onChange: (value) => {
|
||||
this.setWidgetStyling("color", value)
|
||||
this.setAttrValue("styling.foregroundColor", value)
|
||||
}
|
||||
}
|
||||
},
|
||||
buttonLabel: {
|
||||
label: "Button Label",
|
||||
tool: Tools.INPUT, // the tool to display, can be either HTML ELement or a constant string
|
||||
toolProps: {placeholder: "Button label", maxLength: 100},
|
||||
value: "Button",
|
||||
onChange: (value) => this.setAttrValue("buttonLabel", value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
super.componentDidMount()
|
||||
this.setWidgetName("Time picker")
|
||||
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
|
||||
|
||||
this.timePicker = timePicker({
|
||||
element: this.timePickerRef.current,
|
||||
mode: "12"
|
||||
})
|
||||
|
||||
const timePickerBtns = this.timePickerRef.current.getElementsByClassName("atp-clock-btn")
|
||||
for (let i = 0; i < timePickerBtns.length; i++) {
|
||||
timePickerBtns[i].remove()
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
this.timePicker.dispose()
|
||||
}
|
||||
|
||||
getToolbarAttrs(){
|
||||
|
||||
const toolBarAttrs = super.getToolbarAttrs()
|
||||
|
||||
|
||||
return ({
|
||||
id: this.__id,
|
||||
widgetName: toolBarAttrs.widgetName,
|
||||
buttonLabel: this.state.attrs.buttonLabel,
|
||||
size: toolBarAttrs.size,
|
||||
|
||||
...this.state.attrs,
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
renderContent(){
|
||||
return (
|
||||
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md
|
||||
tw-border tw-border-solid tw-border-gray-400 tw-overflow-hidden">
|
||||
<div className="tw-p-2 tw-w-full tw-h-full tw-content-start tw-pointer-events-none"
|
||||
style={this.state.widgetStyling} ref={this.timePickerRef}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default AnalogTimePicker
|
||||
BIN
src/frameworks/tkinter/plugins/assets/map.png
Normal file
|
After Width: | Height: | Size: 241 KiB |
BIN
src/frameworks/tkinter/plugins/assets/video.jpg
Normal file
|
After Width: | Height: | Size: 60 KiB |
79
src/frameworks/tkinter/plugins/mapview.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import React from "react"
|
||||
|
||||
|
||||
import Widget from "../../../canvas/widgets/base"
|
||||
import Tools from "../../../canvas/constants/tools"
|
||||
import { removeKeyFromObject } from "../../../utils/common"
|
||||
|
||||
import MapImage from "./assets/map.png"
|
||||
import { MinusOutlined, PlayCircleFilled, PlusOutlined } from "@ant-design/icons"
|
||||
|
||||
|
||||
class MapView extends Widget{
|
||||
|
||||
static widgetType = "map_view"
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.droppableTags = null
|
||||
|
||||
const newAttrs = removeKeyFromObject("layout", this.state.attrs)
|
||||
|
||||
this.state = {
|
||||
...this.state,
|
||||
size: { width: 400, height: 250 },
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
super.componentDidMount()
|
||||
this.setWidgetName("Map viewer")
|
||||
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
|
||||
}
|
||||
|
||||
getToolbarAttrs(){
|
||||
|
||||
const toolBarAttrs = super.getToolbarAttrs()
|
||||
|
||||
|
||||
return ({
|
||||
id: this.__id,
|
||||
widgetName: toolBarAttrs.widgetName,
|
||||
size: toolBarAttrs.size,
|
||||
|
||||
...this.state.attrs,
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
renderContent(){
|
||||
return (
|
||||
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md
|
||||
tw-border tw-border-solid tw-border-gray-400 tw-overflow-hidden">
|
||||
<div className="tw-p-2 tw-w-full tw-h-full tw-content-start tw-pointer-events-none"
|
||||
style={this.state.widgetStyling}>
|
||||
<div className="tw-relative tw-w-full tw-h-full">
|
||||
<div className="tw-absolute tw-left-5 tw-top-3 tw-flex tw-flex-col tw-gap-2">
|
||||
<div className="tw-text-white tw-bg-black tw-text-center
|
||||
tw-p-[2px]
|
||||
tw-w-[25px] tw-h-[25px] tw-rounded-md">
|
||||
<PlusOutlined className="tw-text-xl"/>
|
||||
</div>
|
||||
<div className="tw-text-white tw-bg-black tw-text-center
|
||||
tw-p-1
|
||||
tw-w-[25px] tw-h-[25px] tw-rounded-md">
|
||||
<MinusOutlined className="tw-text-xl"/>
|
||||
</div>
|
||||
</div>
|
||||
<img src={MapImage} className="tw-w-full tw-h-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default MapView
|
||||
139
src/frameworks/tkinter/plugins/pandasTable.js
Normal file
@@ -0,0 +1,139 @@
|
||||
|
||||
|
||||
|
||||
|
||||
import React, { useEffect, useRef, useState } from "react"
|
||||
|
||||
import Widget from "../../../canvas/widgets/base"
|
||||
import { removeKeyFromObject } from "../../../utils/common"
|
||||
|
||||
import MapImage from "./assets/map.png"
|
||||
import { MinusOutlined, PlusOutlined } from "@ant-design/icons"
|
||||
|
||||
|
||||
const ResizableTable = ({minRows=5, minCols=5}) => {
|
||||
const [rows, setRows] = useState(minRows)
|
||||
const [cols, setCols] = useState(minCols)
|
||||
const containerRef = useRef(null)
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
for (let entry of entries) {
|
||||
const { width, height } = entry.contentRect
|
||||
|
||||
// Set number of columns and rows based on widget width and height
|
||||
const newCols = Math.max(minCols, Math.floor(width / 100)) // each column is 100px wide
|
||||
const newRows = Math.max(minRows, Math.floor(height / 50)) // each row is 50px high
|
||||
|
||||
setCols(newCols)
|
||||
setRows(newRows)
|
||||
}
|
||||
})
|
||||
|
||||
if (containerRef.current) {
|
||||
resizeObserver.observe(containerRef.current); // Start observing the widget
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (containerRef.current) {
|
||||
resizeObserver.unobserve(containerRef.current); // Stop observing when component unmounts
|
||||
}
|
||||
}
|
||||
}, [containerRef])
|
||||
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="tw-w-full tw-h-full tw-rounded-md tw-border tw-border-solid tw-overflow-hidden">
|
||||
<table className="tw-w-full tw-h-full">
|
||||
<tbody className="">
|
||||
{Array.from({ length: rows }).map((_, rowIndex) => (
|
||||
<tr key={rowIndex} className="">
|
||||
{Array.from({ length: cols }).map((_, colIndex) => (
|
||||
<td key={colIndex} className="tw-border tw-border-solid tw-border-gray-400 tw-p-2">
|
||||
{/* Row {rowIndex + 1}, Col {colIndex + 1} */}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
class PandasTable extends Widget{
|
||||
|
||||
static widgetType = "pandas_table"
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.droppableTags = null
|
||||
|
||||
const newAttrs = removeKeyFromObject("layout", this.state.attrs)
|
||||
|
||||
this.state = {
|
||||
...this.state,
|
||||
size: { width: 400, height: 250 },
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
super.componentDidMount()
|
||||
this.setWidgetName("Pandas Table")
|
||||
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
|
||||
}
|
||||
|
||||
getToolbarAttrs(){
|
||||
|
||||
const toolBarAttrs = super.getToolbarAttrs()
|
||||
|
||||
|
||||
return ({
|
||||
id: this.__id,
|
||||
widgetName: toolBarAttrs.widgetName,
|
||||
size: toolBarAttrs.size,
|
||||
|
||||
...this.state.attrs,
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
renderContent(){
|
||||
return (
|
||||
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md
|
||||
tw-border tw-border-solid tw-border-gray-400 tw-overflow-hidden">
|
||||
<div className="tw-p-2 tw-w-full tw-h-full tw-content-start tw-pointer-events-none"
|
||||
style={this.state.widgetStyling}>
|
||||
<ResizableTable />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default PandasTable
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* {'align': 'w',
|
||||
'cellbackgr': '#F4F4F3',
|
||||
'cellwidth': 80,
|
||||
'floatprecision': 2,
|
||||
'thousandseparator': '',
|
||||
'font': 'Arial',
|
||||
'fontsize': 12,
|
||||
'fontstyle': '',
|
||||
'grid_color': '#ABB1AD',
|
||||
'linewidth': 1,
|
||||
'rowheight': 22,
|
||||
'rowselectedcolor': '#E4DED4',
|
||||
'textcolor': 'black'}
|
||||
*/
|
||||
70
src/frameworks/tkinter/plugins/videoPlayer.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from "react"
|
||||
|
||||
import Widget from "../../../canvas/widgets/base"
|
||||
import Tools from "../../../canvas/constants/tools"
|
||||
import { removeKeyFromObject } from "../../../utils/common"
|
||||
|
||||
import VideoImage from "./assets/video.jpg"
|
||||
import { PlayCircleFilled } from "@ant-design/icons"
|
||||
|
||||
|
||||
class VideoPlayer extends Widget{
|
||||
|
||||
static widgetType = "video_player"
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.droppableTags = null
|
||||
|
||||
const newAttrs = removeKeyFromObject("layout", this.state.attrs)
|
||||
|
||||
this.state = {
|
||||
...this.state,
|
||||
size: { width: 'fit', height: 'fit' },
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
super.componentDidMount()
|
||||
this.setWidgetName("Video Player")
|
||||
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
|
||||
}
|
||||
|
||||
getToolbarAttrs(){
|
||||
|
||||
const toolBarAttrs = super.getToolbarAttrs()
|
||||
|
||||
|
||||
return ({
|
||||
id: this.__id,
|
||||
widgetName: toolBarAttrs.widgetName,
|
||||
size: toolBarAttrs.size,
|
||||
|
||||
...this.state.attrs,
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
renderContent(){
|
||||
return (
|
||||
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md
|
||||
tw-border tw-border-solid tw-border-gray-400 tw-overflow-hidden">
|
||||
<div className="tw-p-2 tw-w-full tw-h-full tw-content-start tw-pointer-events-none"
|
||||
style={this.state.widgetStyling}>
|
||||
<div className="tw-relative tw-w-full tw-h-full">
|
||||
<div className="tw-absolute tw-text-white tw-left-1/2 tw-top-1/2
|
||||
tw--translate-x-1/2 tw--translate-y-1/2">
|
||||
<PlayCircleFilled className="tw-text-4xl"/>
|
||||
</div>
|
||||
<img src={VideoImage} className="tw-w-full tw-h-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default VideoPlayer
|
||||
42
src/frameworks/tkinter/sidebarPlugins.js
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
import ClockImage from "./assets/widgets/plugins/clock.png"
|
||||
import VideoImage from "./assets/widgets/plugins/video.png"
|
||||
import MapImage from "./assets/widgets/plugins/map.png"
|
||||
import DataTableImage from "./assets/widgets/plugins/tables.png"
|
||||
|
||||
import AnalogTimePicker from "./plugins/analogTimepicker"
|
||||
import VideoPlayer from "./plugins/videoPlayer"
|
||||
import MapView from "./plugins/mapview"
|
||||
import PandasTable from "./plugins/pandasTable"
|
||||
|
||||
|
||||
const TkinterPluginWidgets = [
|
||||
{
|
||||
name: "Analog TimePicker",
|
||||
img: ClockImage,
|
||||
link: "https://github.com",
|
||||
widgetClass: AnalogTimePicker
|
||||
},
|
||||
{
|
||||
name: "Video Player",
|
||||
img: VideoImage,
|
||||
link: "https://github.com/PaulleDemon/tkVideoPlayer",
|
||||
widgetClass: VideoPlayer
|
||||
},
|
||||
{
|
||||
name: "Map viewer",
|
||||
img: MapImage,
|
||||
link: "https://github.com/TomSchimansky/TkinterMapView",
|
||||
widgetClass: MapView
|
||||
},
|
||||
{
|
||||
name: "Pandas Table",
|
||||
img: DataTableImage,
|
||||
link: "https://github.com/dmnfarrell/pandastable",
|
||||
widgetClass: PandasTable
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
|
||||
export default TkinterPluginWidgets
|
||||
@@ -1,31 +1,31 @@
|
||||
|
||||
|
||||
import { CheckBox, RadioButton } from "./widgets/ checkButton"
|
||||
import Button from "./widgets/button"
|
||||
import Frame from "./widgets/frame"
|
||||
import { Input, Text } from "./widgets/input"
|
||||
import Label from "./widgets/label"
|
||||
import MainWindow from "./widgets/mainWindow"
|
||||
import TopLevel from "./widgets/toplevel"
|
||||
import Frame from "./widgets/frame"
|
||||
import Label from "./widgets/label"
|
||||
import Button from "./widgets/button"
|
||||
import OptionMenu from "./widgets/optionMenu"
|
||||
import Slider from "./widgets/slider"
|
||||
import TopLevel from "./widgets/toplevel"
|
||||
import { CheckBox, RadioButton } from "./widgets/ checkButton"
|
||||
import { Input, Text } from "./widgets/input"
|
||||
import SpinBox from "./widgets/spinBox"
|
||||
|
||||
import MainWindowImage from "./assets/widgets/mainwindow.png"
|
||||
import TopLevelImage from "./assets/widgets/Toplevel.png"
|
||||
import FrameImage from "./assets/widgets/frame2.png"
|
||||
import LabelImage from "./assets/widgets/label.png"
|
||||
import ButtonImage from "./assets/widgets/button.png"
|
||||
import InputImage from "./assets/widgets/input.png"
|
||||
import TextAreaImage from "./assets/widgets/textarea.png"
|
||||
import SliderImage from "./assets/widgets/slider.png"
|
||||
import DropDownImage from "./assets/widgets/dropdown.png"
|
||||
import CheckButtonImage from "./assets/widgets/check.png"
|
||||
import RadioButtonImage from "./assets/widgets/radio.png"
|
||||
import SpinBoxImage from "./assets/widgets/spinbox.png"
|
||||
import MainWindowImage from "./assets/widgets/main/mainwindow.png"
|
||||
import TopLevelImage from "./assets/widgets/main/Toplevel.png"
|
||||
import FrameImage from "./assets/widgets/main/frame2.png"
|
||||
import LabelImage from "./assets/widgets/main/label.png"
|
||||
import ButtonImage from "./assets/widgets/main/button.png"
|
||||
import InputImage from "./assets/widgets/main/input.png"
|
||||
import TextAreaImage from "./assets/widgets/main/textarea.png"
|
||||
import SliderImage from "./assets/widgets/main/slider.png"
|
||||
import DropDownImage from "./assets/widgets/main/dropdown.png"
|
||||
import CheckButtonImage from "./assets/widgets/main/check.png"
|
||||
import RadioButtonImage from "./assets/widgets/main/radio.png"
|
||||
import SpinBoxImage from "./assets/widgets/main/spinbox.png"
|
||||
|
||||
|
||||
const TkinterSidebar = [
|
||||
const TkinterWidgets = [
|
||||
{
|
||||
name: "Main window",
|
||||
img: MainWindowImage,
|
||||
@@ -102,7 +102,7 @@ const TkinterSidebar = [
|
||||
]
|
||||
|
||||
|
||||
export default TkinterSidebar
|
||||
export default TkinterWidgets
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,12 +10,7 @@ class Button extends Widget{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
// TODO: disable drop
|
||||
|
||||
this.droppableTags = {
|
||||
// TODO: exclude all
|
||||
exclude: ["image", "video", "media", "main_window", "toplevel"]
|
||||
}
|
||||
this.droppableTags = null
|
||||
const newAttrs = removeKeyFromObject("layout", this.state.attrs)
|
||||
|
||||
this.state = {
|
||||
|
||||
90
src/sidebar/pluginsContainer.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
|
||||
import { CloseCircleFilled, SearchOutlined } from "@ant-design/icons"
|
||||
|
||||
import {SidebarWidgetCard} from "../components/cards"
|
||||
|
||||
import ButtonWidget from "../assets/widgets/button.png"
|
||||
|
||||
import { filterObjectListStartingWith } from "../utils/filter"
|
||||
import Widget from "../canvas/widgets/base"
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {function} onWidgetsUpdate - this is a callback that will be called once the sidebar is populated with widgets
|
||||
* @returns
|
||||
*/
|
||||
function PluginsContainer({sidebarContent, onWidgetsUpdate}){
|
||||
|
||||
|
||||
const [searchValue, setSearchValue] = useState("")
|
||||
const [widgetData, setWidgetData] = useState(sidebarContent)
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
setWidgetData(sidebarContent)
|
||||
// if (onWidgetsUpdate){
|
||||
// onWidgetsUpdate(widgets)
|
||||
// }
|
||||
|
||||
}, [sidebarContent])
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (searchValue.length > 0){
|
||||
const searchData = filterObjectListStartingWith(sidebarContent, "name", searchValue)
|
||||
setWidgetData(searchData)
|
||||
}else{
|
||||
setWidgetData(sidebarContent)
|
||||
}
|
||||
|
||||
}, [searchValue])
|
||||
|
||||
function onSearch(event){
|
||||
|
||||
setSearchValue(event.target.value)
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full tw-p-2 tw-gap-4 tw-flex tw-flex-col tw-overflow-x-hidden">
|
||||
|
||||
<div className="tw-flex tw-gap-2 input tw-place-items-center">
|
||||
<SearchOutlined />
|
||||
<input type="text" placeholder="Search" className="tw-outline-none tw-w-full tw-border-none"
|
||||
id="" onInput={onSearch} value={searchValue}/>
|
||||
<div className="">
|
||||
{
|
||||
searchValue.length > 0 &&
|
||||
<div className="tw-cursor-pointer tw-text-gray-600" onClick={() => setSearchValue("")}>
|
||||
<CloseCircleFilled />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-col tw-gap-2 tw-h-full tw-p-1">
|
||||
|
||||
{
|
||||
widgetData.map((widget, index) => {
|
||||
return (
|
||||
<SidebarWidgetCard key={widget.name}
|
||||
name={widget.name}
|
||||
img={widget.img}
|
||||
url={widget.link}
|
||||
widgetClass={widget.widgetClass}
|
||||
/>
|
||||
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default PluginsContainer
|
||||