diff --git a/.air.toml b/.air.toml new file mode 100644 index 0000000..58fff2a --- /dev/null +++ b/.air.toml @@ -0,0 +1,51 @@ +root = "." +testdata_dir = "testdata" +tmp_dir = "tmp" + +[build] + args_bin = [] + bin = "./tmp/main" + cmd = "go build -o ./tmp/main ." + delay = 1000 + exclude_dir = ["assets", "tmp", "vendor", "testdata"] + exclude_file = [] + exclude_regex = ["_test.go"] + exclude_unchanged = false + follow_symlink = false + full_bin = "" + include_dir = [] + include_ext = ["go", "tpl", "tmpl", "html"] + include_file = [] + kill_delay = "0s" + log = "build-errors.log" + poll = false + poll_interval = 0 + post_cmd = [] + pre_cmd = [] + rerun = false + rerun_delay = 500 + send_interrupt = false + stop_on_error = false + +[color] + app = "" + build = "yellow" + main = "magenta" + runner = "green" + watcher = "cyan" + +[log] + main_only = false + time = false + +[misc] + clean_on_exit = false + +[proxy] + app_port = 0 + enabled = false + proxy_port = 0 + +[screen] + clear_on_rebuild = false + keep_scroll = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cad2309 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/tmp \ No newline at end of file diff --git a/api.go b/api.go index c83a1be..8e092c1 100644 --- a/api.go +++ b/api.go @@ -40,6 +40,99 @@ func ListDatacenters(c echo.Context) error { return c.JSON(200, dataCenters) } +func ListRows(c echo.Context) error { + rows := make([]*Row, 0) + + var errs []error + action := func(path string) { + if !strings.Contains(path, "row_") { + return + } + data, err := GetObjectFullPath(path) + row := new(Row) + err = json.Unmarshal(data, row) + if err != nil { + errs = append(errs, err) + return + } + rows = append(rows, row) + } + + err := GetObjects(basePath, action) + if err != nil { + return c.JSON(500, err) + } + + if len(errs) != 0 { + return c.JSON(500, errs) + } + + return c.JSON(200, rows) +} + +func ListRowsByDatacenter(c echo.Context) error { + dcId := c.Param("id") + + dcIdInt, err := strconv.Atoi(dcId) + if err != nil { + return c.JSON(400, err) + } + + rows := make([]*Row, 0) + + var errs []error + action := func(path string) { + if !strings.Contains(path, "row_") { + return + } + data, err := GetObjectFullPath(path) + row := new(Row) + + err = json.Unmarshal(data, row) + if err != nil { + errs = append(errs, err) + return + } + + if row.DCID == dcIdInt { + rows = append(rows, row) + } + } + + err = GetObjects(basePath, action) + if err != nil { + return c.JSON(500, err) + } + + if len(errs) != 0 { + return c.JSON(500, errs) + } + + return c.JSON(200, rows) + +} + +func FindRow(c echo.Context) error { + id := c.Param("id") + idInt, err := strconv.Atoi(id) + if err != nil { + return c.JSON(400, err) + } + + data, err := GetObject(RowsPath, RowFile, idInt) + if err != nil { + return c.JSON(500, err) + } + + row := new(Row) + err = json.Unmarshal(data, row) + if err != nil { + return c.JSON(500, err) + } + + return c.JSON(200, row) +} + func FindDatacenter(c echo.Context) error { id := c.Param("id") idInt, err := strconv.Atoi(id) @@ -75,4 +168,4 @@ func UserConfigRecieveHandler(c echo.Context) error { SetConnectedSocket(key, &ConnectedSocket{Config: config}) fmt.Println(globalSocketsM["exampleKey"].Config.Datapoints[0].Axis) return c.JSON(http.StatusOK, map[string]string{"status": "success"}) -} \ No newline at end of file +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3e0d676..29834ba 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,6 +11,7 @@ "@radix-ui/react-tabs": "^1.0.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "ky": "^1.3.0", "lucide-react": "^0.395.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3153,6 +3154,17 @@ "json-buffer": "3.0.1" } }, + "node_modules/ky": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.3.0.tgz", + "integrity": "sha512-QUViPXlgP6NKA57IAPff/aZSmRA6qs9wKxlEpayBorwRZG+x2LG7jD4kXh8lnH3q/gkUr64NyZ7kwErUEZJmlw==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 0475b31..10ab4f3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "@radix-ui/react-tabs": "^1.0.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "ky": "^1.3.0", "lucide-react": "^0.395.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6d1f804..fc58fac 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,47 +1,54 @@ -import React, { useEffect, useState } from 'react'; +import ky from 'ky'; +import { useEffect, useState } from 'react'; +import { API_URL, DatacenterType } from './config/config'; +import DatacenterComponent from './components/Datacenter'; const WS_URL = 'ws://localhost:1323/v1/json/dynamic'; function App() { - const [message, setMessage] = useState(''); - const [socket, setSocket] = useState(null); - - useEffect(() => { - const socket = new WebSocket(WS_URL); - setSocket(socket); - - socket.addEventListener('open', () => { - console.log('Connected to server'); - socket.send('{"disk":0,"cpu":10,"memory":50,"sub":{"key1":1377}}'); - }); - - socket.addEventListener('message', (event) => { - console.log('Message from server ', event.data); - setMessage(event.data); - }); - - socket.addEventListener('error', (error) => { - console.error('WebSocket error: ', error); - }); - - return () => { - socket.close(); - }; - }, []); - - const sendMessage = () => { - if (socket && socket.readyState === WebSocket.OPEN) { - socket.send('Hello World!'); - } - }; - - return ( -
-

WebSocket Example

-

Message from server: {message}

- -
- ); + const [socket, setSocket] = useState(null); + + useEffect(() => { + const socket = new WebSocket(WS_URL); + setSocket(socket); + + socket.addEventListener('open', () => { + console.log('Connected to server'); + socket.send('{"disk":0,"cpu":10,"memory":50,"sub":{"key1":1377}}'); + }); + + socket.addEventListener('message', (event) => { + console.log('Message from server ', event.data); + }); + + socket.addEventListener('error', (error) => { + console.error('WebSocket error: ', error); + }); + + return () => { + socket.close(); + }; + }, []); + + const [dataCenters, setDataCenters] = useState>(); + + useEffect(() => { + const fetchData = async () => { + const json = await ky.get(`${API_URL}/datacenters`).json(); + setDataCenters(json as Array); + }; + console.log(dataCenters); + fetchData(); + }, []); + + return ( +
+

Name?? Dashboard Stats Logo??

+
+ {dataCenters?.map((item) => )} +
+
+ ); } export default App; diff --git a/frontend/src/components/Datacenter.tsx b/frontend/src/components/Datacenter.tsx new file mode 100644 index 0000000..0767fce --- /dev/null +++ b/frontend/src/components/Datacenter.tsx @@ -0,0 +1,30 @@ +import { API_URL, DatacenterType, RowType } from '@/config/config'; +import ky from 'ky'; +import { useEffect, useState } from 'react'; +import Row from './Row'; + +const Datacenter = ({ dataCenter }: { dataCenter: DatacenterType }) => { + const [rows, setRows] = useState(); + + useEffect(() => { + const getRows = async () => { + const json = await ky + .get(`${API_URL}/rows/datacenter/${dataCenter.ID}`) + .json(); + setRows(json as RowType[]); + console.log(json); + }; + getRows(); + }, []); + + return ( +
+ Datacenter {dataCenter.Tag}/{dataCenter.ID} +
+ {rows?.map((row) => )} +
+
+ ); +}; + +export default Datacenter; diff --git a/frontend/src/components/Row.tsx b/frontend/src/components/Row.tsx new file mode 100644 index 0000000..a052fe2 --- /dev/null +++ b/frontend/src/components/Row.tsx @@ -0,0 +1,12 @@ +import { RowType } from '@/config/config'; + +const Row = ({ Row }: { Row: RowType }) => { + return ( +
+ Row {Row.Tag}/{Row.ID} +
+
+ ); +}; + +export default Row; diff --git a/frontend/src/config/config.ts b/frontend/src/config/config.ts new file mode 100644 index 0000000..3866957 --- /dev/null +++ b/frontend/src/config/config.ts @@ -0,0 +1,14 @@ +export const API_URL = 'http://localhost:1323/v1/api'; + +export interface DatacenterType { + ID: number; + Tag: string; + Info: string; +} + +export interface RowType { + ID: number; + Tag: string; + Info: string; + DatacenterID: number; +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index ea752dc..11ccadf 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -13,17 +13,16 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", + "noImplicitAny": true, /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, + "noFallthroughCasesInSwitch": true, "baseUrl": ".", "paths": { - "@/*": [ - "./src/*" - ] + "@/*": ["./src/*"] } }, "include": ["src"], diff --git a/main.go b/main.go index b4ccbe4..1cbdcf0 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ func main() { e := echo.New() e.Use(middleware.Logger()) e.Use(middleware.Recover()) + e.Use(middleware.CORSWithConfig(middleware.DefaultCORSConfig)) wsV1 := e.Group("/v1/ws") apiV1 := e.Group("/v1/api") @@ -24,6 +25,10 @@ func main() { apiV1.GET("/datacenters", ListDatacenters) apiV1.GET("/datacenters/:id", FindDatacenter) + apiV1.GET("/rows", ListRows) + apiV1.GET("/rows/:id", FindRow) + apiV1.GET("/rows/datacenter/:id", ListRowsByDatacenter) + // ws upgrader for react upgrader := gws.NewUpgrader(&WebSocketHandler{}, &gws.ServerOption{ ParallelEnabled: true, @@ -63,7 +68,7 @@ func main() { }) // user config - e.POST("/v1/user/config", UserConfigRecieveHandler); + e.POST("/v1/user/config", UserConfigRecieveHandler) e.Logger.Fatal(e.Start(":1323")) } diff --git a/mdata/datacenters/datacenter_0.json b/mdata/datacenters/datacenter_0.json index 05462a3..3a16aa7 100755 --- a/mdata/datacenters/datacenter_0.json +++ b/mdata/datacenters/datacenter_0.json @@ -1,5 +1,5 @@ { "Tag": "DC01", - "ID": 1, + "ID": 0, "Info": "my favourite datacenter" } diff --git a/mdata/datacenters/datacenter_1.json b/mdata/datacenters/datacenter_1.json index 05462a3..dc265a8 100755 --- a/mdata/datacenters/datacenter_1.json +++ b/mdata/datacenters/datacenter_1.json @@ -1,5 +1,5 @@ { - "Tag": "DC01", + "Tag": "DC02", "ID": 1, "Info": "my favourite datacenter" } diff --git a/mdata/datacenters/datacenter_2.json b/mdata/datacenters/datacenter_2.json index 05462a3..4be983d 100755 --- a/mdata/datacenters/datacenter_2.json +++ b/mdata/datacenters/datacenter_2.json @@ -1,5 +1,5 @@ { - "Tag": "DC01", - "ID": 1, + "Tag": "DC03", + "ID": 2, "Info": "my favourite datacenter" } diff --git a/mdata/rows/row_0.json b/mdata/rows/row_0.json index fc8ef2d..ece21c4 100755 --- a/mdata/rows/row_0.json +++ b/mdata/rows/row_0.json @@ -1 +1,6 @@ -{"Data":"./mdata/rows/row_0.json"} \ No newline at end of file +{ + "Tag": "RW00", + "ID": 0, + "Info": "iron man row", + "DatacenterID": 1 +} diff --git a/mdata/rows/row_1.json b/mdata/rows/row_1.json new file mode 100644 index 0000000..501e0a0 --- /dev/null +++ b/mdata/rows/row_1.json @@ -0,0 +1,6 @@ +{ + "Tag": "RW01", + "ID": 1, + "Info": "some row", + "DatacenterID": 2 +} diff --git a/mdata/rows/row_2.json b/mdata/rows/row_2.json new file mode 100644 index 0000000..0123cff --- /dev/null +++ b/mdata/rows/row_2.json @@ -0,0 +1,6 @@ +{ + "Tag": "RW02", + "ID": 2, + "Info": "some row", + "DatacenterID": 0 +} diff --git a/mdata/rows/row_3.json b/mdata/rows/row_3.json new file mode 100644 index 0000000..7ef9dd7 --- /dev/null +++ b/mdata/rows/row_3.json @@ -0,0 +1,6 @@ +{ + "Tag": "RW03", + "ID": 3, + "Info": "some row", + "DatacenterID": 2 +} diff --git a/mdata/rows/row_4.json b/mdata/rows/row_4.json new file mode 100644 index 0000000..6215a69 --- /dev/null +++ b/mdata/rows/row_4.json @@ -0,0 +1,6 @@ +{ + "Tag": "RW04", + "ID": 4, + "Info": "some row", + "DatacenterID": 2 +}