diff --git a/ui/.prettierignore b/ui/.prettierignore new file mode 100644 index 00000000..b25984f0 --- /dev/null +++ b/ui/.prettierignore @@ -0,0 +1,2 @@ +build +node_modules \ No newline at end of file diff --git a/ui/.prettierrc.json b/ui/.prettierrc.json new file mode 100644 index 00000000..a3c88f0c --- /dev/null +++ b/ui/.prettierrc.json @@ -0,0 +1,13 @@ +{ + "trailingComma": "all", + "tabWidth": 2, + "endOfLine": "auto", + "semi": true, + "singleQuote": false, + "printWidth": 120, + "bracketSpacing": true, + "arrowParens": "avoid", + "jsxSingleQuote": false, + "quoteProps": "as-needed", + "jsxBracketSameLine": true +} diff --git a/ui/package.json b/ui/package.json index 1a571100..8d826b5e 100644 --- a/ui/package.json +++ b/ui/package.json @@ -44,7 +44,14 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "lint": "prettier --check .", + "format": "prettier --write . && git add -A ." + }, + "husky": { + "hooks": { + "pre-commit": "yarn format" + } }, "eslintConfig": { "extends": [ @@ -60,5 +67,9 @@ "not dead", "not op_mini all" ], - "proxy": "http://127.0.0.1:8080/" + "proxy": "http://127.0.0.1:8080/", + "devDependencies": { + "husky": "^7.0.4", + "prettier": "^2.6.2" + } } diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 4d8d0b29..349bc941 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { Router, Route, Switch } from "react-router-dom"; -import { Layout } from 'antd'; +import { Layout } from "antd"; import { User } from "@chirpstack/chirpstack-api-grpc-web/api/user_pb"; @@ -35,15 +35,12 @@ import SessionStore from "./stores/SessionStore"; import history from "./history"; - -interface IProps { -} +interface IProps {} interface IState { user?: User; } - class App extends Component { constructor(props: IProps) { super(props); @@ -66,13 +63,14 @@ class App extends Component { } render() { - return( - + return ( + - - - {this.state.user && + + + {this.state.user && ( +
@@ -80,7 +78,7 @@ class App extends Component { - + @@ -98,7 +96,8 @@ class App extends Component { - } + + )} diff --git a/ui/src/components/Admin.tsx b/ui/src/components/Admin.tsx index b31fe9f5..511fe034 100644 --- a/ui/src/components/Admin.tsx +++ b/ui/src/components/Admin.tsx @@ -2,7 +2,6 @@ import { Component } from "react"; import SessionStore from "../stores/SessionStore"; - interface IProps { tenantId?: string; isDeviceAdmin?: boolean; @@ -68,14 +67,14 @@ class Admin extends Component { }); } } - } + }; render() { if (this.state.admin) { - return(this.props.children); + return this.props.children; } - return(null); + return null; } } diff --git a/ui/src/components/AesKeyInput.tsx b/ui/src/components/AesKeyInput.tsx index 1c89b9fa..218382c8 100644 --- a/ui/src/components/AesKeyInput.tsx +++ b/ui/src/components/AesKeyInput.tsx @@ -4,9 +4,9 @@ import { Input, Select, Button, Space, Form } from "antd"; import { ReloadOutlined } from "@ant-design/icons"; interface IProps { - formRef: React.RefObject, - label: string, - name: string, + formRef: React.RefObject; + label: string; + name: string; required?: boolean; value?: string; disabled?: boolean; @@ -18,7 +18,6 @@ interface IState { value: string; } - class AesKeyInput extends Component { constructor(props: IProps) { super(props); @@ -39,7 +38,7 @@ class AesKeyInput extends Component { this.props.formRef.current.setFieldsValue({ [this.props.name]: value, }); - } + }; componentDidMount() { if (this.props.value) { @@ -51,7 +50,7 @@ class AesKeyInput extends Component { onChange = (e: React.ChangeEvent) => { let v = e.target.value; - const match = v.match(/[A-Fa-f0-9]/g); + const match = v.match(/[A-Fa-f0-9]/g); let value = ""; if (match) { @@ -62,10 +61,13 @@ class AesKeyInput extends Component { } } - this.setState({ - value: value, - }, this.updateField); - } + this.setState( + { + value: value, + }, + this.updateField, + ); + }; onByteOrderSelect = (v: string) => { if (v === this.state.byteOrder) { @@ -79,21 +81,27 @@ class AesKeyInput extends Component { const current = this.state.value; const bytes = current.match(/[A-Fa-f0-9]{2}/g) || []; - this.setState({ - value: bytes.reverse().join(""), - }, this.updateField); - } + this.setState( + { + value: bytes.reverse().join(""), + }, + this.updateField, + ); + }; generateRandom = () => { let cryptoObj = window.crypto || window.Crypto; let b = new Uint8Array(16); cryptoObj.getRandomValues(b); - let key = Buffer.from(b).toString('hex'); - this.setState({ - value: key, - }, this.updateField); - } + let key = Buffer.from(b).toString("hex"); + this.setState( + { + value: key, + }, + this.updateField, + ); + }; render() { const addon = ( @@ -102,23 +110,34 @@ class AesKeyInput extends Component { MSB LSB - + ); - return( + return ( - + ); } diff --git a/ui/src/components/Autocomplete.tsx b/ui/src/components/Autocomplete.tsx index ce798041..9bc92efe 100644 --- a/ui/src/components/Autocomplete.tsx +++ b/ui/src/components/Autocomplete.tsx @@ -2,24 +2,23 @@ import React, { Component } from "react"; import { Select } from "antd"; -export type OptionsCallbackFunc = (o: {label: string, value: string}[]) => void; -export type OptionCallbackFunc = (o: {label: string, value: string}) => void; +export type OptionsCallbackFunc = (o: { label: string; value: string }[]) => void; +export type OptionCallbackFunc = (o: { label: string; value: string }) => void; interface IProps { placeholder: string; className: string; - value?: string, - getOption: (s: string, fn: OptionCallbackFunc) => void, - getOptions: (s: string, fn: OptionsCallbackFunc) => void, - onSelect?: (s: string) => void, + value?: string; + getOption: (s: string, fn: OptionCallbackFunc) => void; + getOptions: (s: string, fn: OptionsCallbackFunc) => void; + onSelect?: (s: string) => void; } interface IState { - option?: {label: string, value: string}; - options: {label: string, value: string}[]; + option?: { label: string; value: string }; + options: { label: string; value: string }[]; } - class Autocomplete extends Component { constructor(props: IProps) { super(props); @@ -31,7 +30,7 @@ class Autocomplete extends Component { componentDidMount() { if (this.props.value && this.props.value !== "") { - this.props.getOption(this.props.value, (o: {label: string, value: string}) => { + this.props.getOption(this.props.value, (o: { label: string; value: string }) => { this.setState({ options: [o], }); @@ -45,7 +44,7 @@ class Autocomplete extends Component { } if (this.props.value && this.props.value !== "") { - this.props.getOption(this.props.value, (o: {label: string, value: string}) => { + this.props.getOption(this.props.value, (o: { label: string; value: string }) => { this.setState({ options: [o], }); @@ -54,7 +53,7 @@ class Autocomplete extends Component { } onFocus = () => { - this.props.getOptions("", (options) => { + this.props.getOptions("", options => { if (this.state.option !== undefined) { const selected = this.state.option.value; @@ -67,30 +66,30 @@ class Autocomplete extends Component { options: options, }); }); - } + }; onSearch = (value: string) => { - this.props.getOptions(value, (options) => { + this.props.getOptions(value, options => { this.setState({ options: options, }); }); - } + }; onSelect = (value: string, option: any) => { this.setState({ - option: {label: option.label, value: option.value}, + option: { label: option.label, value: option.value }, }); if (this.props.onSelect !== undefined) { this.props.onSelect(value); } - } + }; render() { const { getOption, getOptions, ...otherProps } = this.props; - return( + return ( - + + Enter '{this.props.confirm}' to confirm you want to delete this {this.props.typ}: + + + ); } } - class DeleteConfirm extends Component { render() { - return( - } trigger="click" placement="left"> + return ( + } trigger="click" placement="left"> {this.props.children} ); diff --git a/ui/src/components/DevAddrInput.tsx b/ui/src/components/DevAddrInput.tsx index b8479fff..9ccea74f 100644 --- a/ui/src/components/DevAddrInput.tsx +++ b/ui/src/components/DevAddrInput.tsx @@ -3,21 +3,15 @@ import React, { Component } from "react"; import { Input, Select, Button, Space, Form } from "antd"; import { ReloadOutlined } from "@ant-design/icons"; - -import { - GetRandomDevAddrRequest, - GetRandomDevAddrResponse, -} from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; - +import { GetRandomDevAddrRequest, GetRandomDevAddrResponse } from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; import DeviceStore from "../stores/DeviceStore"; - interface IProps { - formRef: React.RefObject, - label: string, - name: string, - devEui: string, + formRef: React.RefObject; + label: string; + name: string; + devEui: string; required?: boolean; value?: string; disabled?: boolean; @@ -28,7 +22,6 @@ interface IState { value: string; } - class DevAddrInput extends Component { constructor(props: IProps) { super(props); @@ -49,7 +42,7 @@ class DevAddrInput extends Component { this.props.formRef.current.setFieldsValue({ [this.props.name]: value, }); - } + }; componentDidMount() { if (this.props.value) { @@ -61,7 +54,7 @@ class DevAddrInput extends Component { onChange = (e: React.ChangeEvent) => { let v = e.target.value; - const match = v.match(/[A-Fa-f0-9]/g); + const match = v.match(/[A-Fa-f0-9]/g); let value = ""; if (match) { @@ -72,10 +65,13 @@ class DevAddrInput extends Component { } } - this.setState({ - value: value, - }, this.updateField); - } + this.setState( + { + value: value, + }, + this.updateField, + ); + }; onByteOrderSelect = (v: string) => { if (v === this.state.byteOrder) { @@ -89,21 +85,27 @@ class DevAddrInput extends Component { const current = this.state.value; const bytes = current.match(/[A-Fa-f0-9]{2}/g) || []; - this.setState({ - value: bytes.reverse().join(""), - }, this.updateField); - } + this.setState( + { + value: bytes.reverse().join(""), + }, + this.updateField, + ); + }; generateRandom = () => { let req = new GetRandomDevAddrRequest(); req.setDevEui(this.props.devEui); DeviceStore.getRandomDevAddr(req, (resp: GetRandomDevAddrResponse) => { - this.setState({ - value: resp.getDevAddr(), - }, this.updateField); + this.setState( + { + value: resp.getDevAddr(), + }, + this.updateField, + ); }); - } + }; render() { const addon = ( @@ -112,22 +114,33 @@ class DevAddrInput extends Component { MSB LSB - + ); - return( + return ( - + ); } diff --git a/ui/src/components/EuiInput.tsx b/ui/src/components/EuiInput.tsx index 54a73bf6..fe937e2b 100644 --- a/ui/src/components/EuiInput.tsx +++ b/ui/src/components/EuiInput.tsx @@ -4,9 +4,9 @@ import { Input, Select, Button, Space, Form } from "antd"; import { ReloadOutlined } from "@ant-design/icons"; interface IProps { - formRef: React.RefObject, - label: string, - name: string, + formRef: React.RefObject; + label: string; + name: string; required?: boolean; value?: string; disabled?: boolean; @@ -17,7 +17,6 @@ interface IState { value: string; } - class EuiInput extends Component { constructor(props: IProps) { super(props); @@ -38,7 +37,7 @@ class EuiInput extends Component { this.props.formRef.current.setFieldsValue({ [this.props.name]: value, }); - } + }; componentDidMount() { if (this.props.value) { @@ -50,7 +49,7 @@ class EuiInput extends Component { onChange = (e: React.ChangeEvent) => { let v = e.target.value; - const match = v.match(/[A-Fa-f0-9]/g); + const match = v.match(/[A-Fa-f0-9]/g); let value = ""; if (match) { @@ -61,10 +60,13 @@ class EuiInput extends Component { } } - this.setState({ - value: value, - }, this.updateField); - } + this.setState( + { + value: value, + }, + this.updateField, + ); + }; onByteOrderSelect = (v: string) => { if (v === this.state.byteOrder) { @@ -78,21 +80,27 @@ class EuiInput extends Component { const current = this.state.value; const bytes = current.match(/[A-Fa-f0-9]{2}/g) || []; - this.setState({ - value: bytes.reverse().join(""), - }, this.updateField); - } + this.setState( + { + value: bytes.reverse().join(""), + }, + this.updateField, + ); + }; generateRandom = () => { let cryptoObj = window.crypto || window.Crypto; let b = new Uint8Array(8); cryptoObj.getRandomValues(b); - let key = Buffer.from(b).toString('hex'); - this.setState({ - value: key, - }, this.updateField); - } + let key = Buffer.from(b).toString("hex"); + this.setState( + { + value: key, + }, + this.updateField, + ); + }; render() { const addon = ( @@ -101,22 +109,33 @@ class EuiInput extends Component { MSB LSB - + ); - return( + return ( - + ); } diff --git a/ui/src/components/Header.tsx b/ui/src/components/Header.tsx index b60eeeaa..e69d5b0f 100644 --- a/ui/src/components/Header.tsx +++ b/ui/src/components/Header.tsx @@ -13,27 +13,20 @@ import { import InternalStore from "../stores/InternalStore"; - interface IProps { user: User; } interface IState { searchResult?: GlobalSearchResponse; - settings?: SettingsResponse, + settings?: SettingsResponse; } -const renderTitle = (title: string) => ( - - {title} - -); +const renderTitle = (title: string) => {title}; const renderItem = (title: string, url: string) => ({ value: title, - label: ( - {title} - ), + label: {title}, }); class Header extends Component { @@ -65,7 +58,7 @@ class Header extends Component { searchResult: resp, }); }); - } + }; render() { if (this.state.settings === undefined) { @@ -76,9 +69,11 @@ class Header extends Component { const menu = ( - {!oidcEnabled && - Change password - } + {!oidcEnabled && ( + + Change password + + )} Logout @@ -90,19 +85,19 @@ class Header extends Component { options: any[]; }[] = [ { - label: renderTitle('Tenants'), + label: renderTitle("Tenants"), options: [], }, { - label: renderTitle('Gateways'), + label: renderTitle("Gateways"), options: [], }, { - label: renderTitle('Applications'), + label: renderTitle("Applications"), options: [], }, { - label: renderTitle('Devices'), + label: renderTitle("Devices"), options: [], }, ]; @@ -110,24 +105,36 @@ class Header extends Component { if (this.state.searchResult !== undefined) { for (const res of this.state.searchResult.getResultList()) { if (res.getKind() === "tenant") { - options[0].options.push(renderItem(res.getTenantName(), `/tenants/${res.getTenantId()}`)) + options[0].options.push(renderItem(res.getTenantName(), `/tenants/${res.getTenantId()}`)); } if (res.getKind() === "gateway") { - options[1].options.push(renderItem(res.getGatewayName(), `/tenants/${res.getTenantId()}/gateways/${res.getGatewayId()}`)) + options[1].options.push( + renderItem(res.getGatewayName(), `/tenants/${res.getTenantId()}/gateways/${res.getGatewayId()}`), + ); } if (res.getKind() === "application") { - options[2].options.push(renderItem(res.getApplicationName(), `/tenants/${res.getTenantId()}/applications/${res.getApplicationId()}`)) + options[2].options.push( + renderItem( + res.getApplicationName(), + `/tenants/${res.getTenantId()}/applications/${res.getApplicationId()}`, + ), + ); } if (res.getKind() === "device") { - options[3].options.push(renderItem(res.getDeviceName(), `/tenants/${res.getTenantId()}/applications/${res.getApplicationId()}/devices/${res.getDeviceDevEui()}`)); + options[3].options.push( + renderItem( + res.getDeviceName(), + `/tenants/${res.getTenantId()}/applications/${res.getApplicationId()}/devices/${res.getDeviceDevEui()}`, + ), + ); } } } - return( + return (
ChirpStack
@@ -138,15 +145,19 @@ class Header extends Component { options={options} onSearch={this.onSearch} > - +
- - + +
diff --git a/ui/src/components/Heatmap.tsx b/ui/src/components/Heatmap.tsx index 82e79860..f3075289 100644 --- a/ui/src/components/Heatmap.tsx +++ b/ui/src/components/Heatmap.tsx @@ -3,28 +3,25 @@ import React, { Component } from "react"; import { color } from "chart.js/helpers"; import { Chart } from "react-chartjs-2"; - interface HeatmapData { x: string; y: Array<[string, number]>; } - interface IProps { data: HeatmapData[]; fromColor: string; toColor: string; } - class Heatmap extends Component { render() { if (this.props.data.length === 0) { return null; } - let xSet: {[key: string]: any} = {}; - let ySet: {[key: string]: any} = {}; + let xSet: { [key: string]: any } = {}; + let ySet: { [key: string]: any } = {}; let dataData: { x: string; @@ -45,18 +42,22 @@ class Heatmap extends Component { fromColor: this.props.fromColor.match(/\d+/g)!.map(Number), toColor: this.props.toColor.match(/\d+/g)!.map(Number), backgroundColor: (ctx: any): string => { - if (ctx.dataset === undefined || ctx.dataset.data === undefined || ctx.dataset.data[ctx.dataIndex] === undefined) { - return color('white').rgbString(); + if ( + ctx.dataset === undefined || + ctx.dataset.data === undefined || + ctx.dataset.data[ctx.dataIndex] === undefined + ) { + return color("white").rgbString(); } const value = ctx.dataset.data[ctx.dataIndex].v; const steps = ctx.dataset.maxValue - ctx.dataset.minValue + 1; const step = value - ctx.dataset.minValue; - const factor = 1 / steps * step; + const factor = (1 / steps) * step; let result: [number, number, number] = ctx.dataset.fromColor.slice(); for (var i = 0; i < 3; i++) { - result[i] = Math.round(result[i] + factor * (ctx.dataset.toColor[i] - ctx.dataset.fromColor[i])); + result[i] = Math.round(result[i] + factor * (ctx.dataset.toColor[i] - ctx.dataset.fromColor[i])); } return color(result).rgbString(); @@ -94,19 +95,18 @@ class Heatmap extends Component { grid: { display: false, }, - }, }, plugins: { - legend: {display: false}, + legend: { display: false }, tooltip: { callbacks: { title: () => { - return ''; + return ""; }, label: (ctx: any) => { const v = ctx.dataset.data[ctx.dataIndex].v; - return 'Count: ' + v; + return "Count: " + v; }, }, }, @@ -136,9 +136,7 @@ class Heatmap extends Component { } } - return( - - ); + return ; } } diff --git a/ui/src/components/LogTable.tsx b/ui/src/components/LogTable.tsx index 6f6d285b..e5fcaf54 100644 --- a/ui/src/components/LogTable.tsx +++ b/ui/src/components/LogTable.tsx @@ -3,11 +3,10 @@ import moment from "moment"; import JSONTreeOriginal from "react-json-tree"; import { Tag, Drawer, Button, Table, Spin } from "antd"; -import { ZoomInOutlined } from '@ant-design/icons'; +import { ZoomInOutlined } from "@ant-design/icons"; import { LogItem } from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; - interface IProps { logs: LogItem[]; } @@ -15,8 +14,7 @@ interface IProps { interface IState { drawerOpen: boolean; body: any; -}; - +} class LogTable extends Component { constructor(props: IProps) { @@ -32,7 +30,7 @@ class LogTable extends Component { this.setState({ drawerOpen: false, }); - } + }; onDrawerOpen = (body: any) => { return () => { @@ -41,47 +39,59 @@ class LogTable extends Component { drawerOpen: true, }); }; - } + }; render() { let items = this.props.logs.map((l, i) => l.toObject()); let body = JSON.parse(this.state.body); const theme = { - scheme: 'google', - author: 'seth wright (http://sethawright.com)', - base00: '#000000', - base01: '#282a2e', - base02: '#373b41', - base03: '#969896', - base04: '#b4b7b4', - base05: '#c5c8c6', - base06: '#e0e0e0', - base07: '#ffffff', - base08: '#CC342B', - base09: '#F96A38', - base0A: '#FBA922', - base0B: '#198844', - base0C: '#3971ED', - base0D: '#3971ED', - base0E: '#A36AC7', - base0F: '#3971ED', + scheme: "google", + author: "seth wright (http://sethawright.com)", + base00: "#000000", + base01: "#282a2e", + base02: "#373b41", + base03: "#969896", + base04: "#b4b7b4", + base05: "#c5c8c6", + base06: "#e0e0e0", + base07: "#ffffff", + base08: "#CC342B", + base09: "#F96A38", + base0A: "#FBA922", + base0B: "#198844", + base0C: "#3971ED", + base0D: "#3971ED", + base0E: "#A36AC7", + base0F: "#3971ED", }; - return( + return (
- + {return true}} + shouldExpandNode={() => { + return true; + }} /> - {items.length !== 0 &&
} + {items.length !== 0 && ( +
+ +
+ )} { let ts = new Date(0); ts.setUTCSeconds(obj.time!.seconds); return moment(ts).format("YYYY-MM-DD HH:mm:ss"); - }, + }, }, { title: "Type", dataIndex: "description", key: "description", width: 200, - render: (text, obj) => , + render: (text, obj) => ( + + ), }, { title: "Properties", dataIndex: "properties", key: "properties", - render: (text, obj) => obj.propertiesMap.map((p, i) => { - if (p[1] !== "") { - return
{p[0]}: {p[1]}
- } + render: (text, obj) => + obj.propertiesMap.map((p, i) => { + if (p[1] !== "") { + return ( + +
+                          {p[0]}: {p[1]}
+                        
+
+ ); + } - return null; - }), + return null; + }), }, ]} /> diff --git a/ui/src/components/Map.tsx b/ui/src/components/Map.tsx index fa38baf1..d61bc2e6 100644 --- a/ui/src/components/Map.tsx +++ b/ui/src/components/Map.tsx @@ -3,8 +3,7 @@ import React, { Component } from "react"; import L, { LatLngTuple, FitBoundsOptions } from "leaflet"; import "leaflet.awesome-markers"; import { MarkerProps as LMarkerProps } from "react-leaflet"; -import { MapContainer, Marker as LMarker, TileLayer } from 'react-leaflet'; - +import { MapContainer, Marker as LMarker, TileLayer } from "react-leaflet"; interface IProps { height: number; @@ -17,7 +16,6 @@ interface IState { map?: L.Map; } - class Map extends Component { constructor(props: IProps) { super(props); @@ -25,22 +23,25 @@ class Map extends Component { } setMap = (map: L.Map) => { - this.setState({ - map: map, - }, () => { - // This is needed as setMap is called after the map has been created. - // There is a small amount of time where componentDidUpdate can't update - // the map with the new center because setMap hasn't been called yet. - // In such case, the map would never update to the new center. - if (this.props.center !== undefined) { - map.panTo(this.props.center); - } + this.setState( + { + map: map, + }, + () => { + // This is needed as setMap is called after the map has been created. + // There is a small amount of time where componentDidUpdate can't update + // the map with the new center because setMap hasn't been called yet. + // In such case, the map would never update to the new center. + if (this.props.center !== undefined) { + map.panTo(this.props.center); + } - if (this.props.bounds !== undefined) { - map.fitBounds(this.props.bounds, this.props.boundsOptions); - } - }); - } + if (this.props.bounds !== undefined) { + map.fitBounds(this.props.bounds, this.props.boundsOptions); + } + }, + ); + }; componentDidUpdate(oldProps: IProps) { if (this.props === oldProps) { @@ -63,7 +64,7 @@ class Map extends Component { height: this.props.height, }; - return( + return ( { } } -export type MarkerColor = "red" | "darkred" | "orange" | "green" | "darkgreen" | "blue" | "purple" | "darkpurple" | "cadetblue" | undefined; +export type MarkerColor = + | "red" + | "darkred" + | "orange" + | "green" + | "darkgreen" + | "blue" + | "purple" + | "darkpurple" + | "cadetblue" + | undefined; interface MarkerProps extends LMarkerProps { position: [number, number]; @@ -100,11 +111,12 @@ export class Marker extends Component { icon: faIcon, prefix: "fa", markerColor: color, - }); + }); - - return( - {this.props.children} + return ( + + {this.props.children} + ); } } diff --git a/ui/src/components/Menu.tsx b/ui/src/components/Menu.tsx index 2ad96204..887c52ea 100644 --- a/ui/src/components/Menu.tsx +++ b/ui/src/components/Menu.tsx @@ -2,9 +2,22 @@ import React, { Component } from "react"; import { withRouter, RouteComponentProps, Link } from "react-router-dom"; import { Menu, MenuProps } from "antd"; -import { CloudOutlined, HomeOutlined, UserOutlined, DashboardOutlined, KeyOutlined, WifiOutlined, ControlOutlined, AppstoreOutlined } from "@ant-design/icons"; +import { + CloudOutlined, + HomeOutlined, + UserOutlined, + DashboardOutlined, + KeyOutlined, + WifiOutlined, + ControlOutlined, + AppstoreOutlined, +} from "@ant-design/icons"; -import { GetTenantResponse, ListTenantsRequest, ListTenantsResponse } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; +import { + GetTenantResponse, + ListTenantsRequest, + ListTenantsResponse, +} from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import Autocomplete, { OptionCallbackFunc, OptionsCallbackFunc } from "../components/Autocomplete"; import TenantStore from "../stores/TenantStore"; @@ -48,7 +61,7 @@ class SideMenu extends Component { this.setState({ tenantId: SessionStore.getTenantId(), }); - } + }; getTenantOptions = (search: string, fn: OptionsCallbackFunc) => { let req = new ListTenantsRequest(); @@ -56,85 +69,86 @@ class SideMenu extends Component { req.setLimit(10); TenantStore.list(req, (resp: ListTenantsResponse) => { - const options = resp.getResultList().map((o, i) => {return {label: o.getName(), value: o.getId()}}); + const options = resp.getResultList().map((o, i) => { + return { label: o.getName(), value: o.getId() }; + }); fn(options); }); - } + }; getTenantOption = (id: string, fn: OptionCallbackFunc) => { TenantStore.get(id, (resp: GetTenantResponse) => { const tenant = resp.getTenant(); if (tenant) { - fn({label: tenant.getName(), value: tenant.getId()}); + fn({ label: tenant.getName(), value: tenant.getId() }); } }); - } + }; onTenantSelect = (value: string) => { SessionStore.setTenantId(value); this.props.history.push(`/tenants/${value}`); - } + }; parseLocation = () => { const path = this.props.history.location.pathname; const tenantRe = /\/tenants\/([\w-]{36})/g; const match = tenantRe.exec(path); - if (match !== null && (this.state.tenantId !== match[1])) { + if (match !== null && this.state.tenantId !== match[1]) { SessionStore.setTenantId(match[1]); } // ns dashboard if (path === "/dashboard") { - this.setState({selectedKey: "ns-dashboard"}); + this.setState({ selectedKey: "ns-dashboard" }); } // ns tenants if (/\/tenants(\/([\w-]{36}\/edit|create))?/g.exec(path)) { - this.setState({selectedKey: "ns-tenants"}); + this.setState({ selectedKey: "ns-tenants" }); } // ns tenants if (/\/users(\/([\w-]{36}\/edit|create))?/g.exec(path)) { - this.setState({selectedKey: "ns-users"}); + this.setState({ selectedKey: "ns-users" }); } // ns api keys if (/\/api-keys(\/([\w-]{36}\/edit|create))?/g.exec(path)) { - this.setState({selectedKey: "ns-api-keys"}); + this.setState({ selectedKey: "ns-api-keys" }); } - // tenant dashboard if (/\/tenants\/[\w-]{36}/g.exec(path)) { - this.setState({selectedKey: "tenant-dashboard"}); + this.setState({ selectedKey: "tenant-dashboard" }); } // tenant users if (/\/tenants\/[\w-]{36}\/users.*/g.exec(path)) { - this.setState({selectedKey: "tenant-users"}); + this.setState({ selectedKey: "tenant-users" }); } // tenant api-keys if (/\/tenants\/[\w-]{36}\/api-keys.*/g.exec(path)) { - this.setState({selectedKey: "tenant-api-keys"}); + this.setState({ selectedKey: "tenant-api-keys" }); } // tenant device-profiles if (/\/tenants\/[\w-]{36}\/device-profiles.*/g.exec(path)) { - this.setState({selectedKey: "tenant-device-profiles"}); + this.setState({ selectedKey: "tenant-device-profiles" }); } // tenant gateways if (/\/tenants\/[\w-]{36}\/gateways.*/g.exec(path)) { - this.setState({selectedKey: "tenant-gateways"}); + this.setState({ selectedKey: "tenant-gateways" }); } // tenant applications if (/\/tenants\/[\w-]{36}\/applications.*/g.exec(path)) { - this.setState({selectedKey: "tenant-applications"}); + this.setState({ selectedKey: "tenant-applications" }); } - } + }; render() { const tenantId = this.state.tenantId; @@ -170,13 +184,13 @@ class SideMenu extends Component { }); } - return( + return (
diff --git a/ui/src/history.ts b/ui/src/history.ts index 80690b81..68df10c0 100644 --- a/ui/src/history.ts +++ b/ui/src/history.ts @@ -1,2 +1,2 @@ -import { createHashHistory } from 'history'; +import { createHashHistory } from "history"; export default createHashHistory(); diff --git a/ui/src/index.css b/ui/src/index.css index 6c0f6e5e..0d771316 100644 --- a/ui/src/index.css +++ b/ui/src/index.css @@ -1,88 +1,88 @@ .layout { - margin-left: 300px; + margin-left: 300px; } .layout-header { - background: #ffffff; - box-shadow: 0px 0px 10px 0px #ccc; - z-index: 999; + background: #ffffff; + box-shadow: 0px 0px 10px 0px #ccc; + z-index: 999; - position: fixed; - width: 100%; + position: fixed; + width: 100%; } .layout-header .logo { - float: left; - margin-top: 16px; - height: 32px; + float: left; + margin-top: 16px; + height: 32px; } .layout-header .actions { - float: right; + float: right; } .layout-header .actions > div { - display: inline; - padding-left: 24px; + display: inline; + padding-left: 24px; } .layout-menu { - padding-top: 85px; + padding-top: 85px; - overflow: auto; - position: fixed; - height: 100vh; - left: 0; + overflow: auto; + position: fixed; + height: 100vh; + left: 0; } .layout-menu .organiation-select { - margin-left: 24px; - margin-bottom: 12px; - width: 252px; + margin-left: 24px; + margin-bottom: 12px; + width: 252px; } .layout-content { - margin-top: 65px; + margin-top: 65px; } .layout-content .content-header > * { - float: right; + float: right; } .layout-content .content-header h3 { - float: left; - display: inline; + float: left; + display: inline; } .layout-content .content { - background: #ffffff; + background: #ffffff; } .spinner { - text-align: center; + text-align: center; } pre { - margin: 0px; + margin: 0px; } .chart-doughtnut { - max-width: 350; - padding: 0; - margin: auto; - display: block; + max-width: 350; + padding: 0; + margin: auto; + display: block; } .dashboard-chart > .ant-card-body { - height: 300px; + height: 300px; } .integration-card { - margin-bottom: 24px; + margin-bottom: 24px; } .integration-card .ant-card-meta-description { - min-height: 75px; + min-height: 75px; } .search-dropdown .ant-select-dropdown-menu-item-group-title { diff --git a/ui/src/index.tsx b/ui/src/index.tsx index a52303d0..a7f1d607 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -3,7 +3,7 @@ import ReactDOM from "react-dom"; // import { Chart, ArcElement, Tooltip, Legend, CategoryScale, LinearScale, Title } from "chart.js"; import { Chart, registerables } from "chart.js"; -import { MatrixElement, MatrixController } from 'chartjs-chart-matrix'; +import { MatrixElement, MatrixController } from "chartjs-chart-matrix"; import "chartjs-adapter-moment"; import App from "./App"; @@ -23,7 +23,7 @@ ReactDOM.render( , - document.getElementById("root") + document.getElementById("root"), ); // If you want to start measuring performance in your app, pass a function diff --git a/ui/src/reportWebVitals.ts b/ui/src/reportWebVitals.ts index 49a2a16e..5fa3583b 100644 --- a/ui/src/reportWebVitals.ts +++ b/ui/src/reportWebVitals.ts @@ -1,8 +1,8 @@ -import { ReportHandler } from 'web-vitals'; +import { ReportHandler } from "web-vitals"; const reportWebVitals = (onPerfEntry?: ReportHandler) => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); getFID(onPerfEntry); getFCP(onPerfEntry); diff --git a/ui/src/setupTests.ts b/ui/src/setupTests.ts index 8f2609b7..1dd407a6 100644 --- a/ui/src/setupTests.ts +++ b/ui/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +import "@testing-library/jest-dom"; diff --git a/ui/src/stores/ApplicationStore.ts b/ui/src/stores/ApplicationStore.ts index 0220d7d5..2cdce963 100644 --- a/ui/src/stores/ApplicationStore.ts +++ b/ui/src/stores/ApplicationStore.ts @@ -64,7 +64,6 @@ import { import SessionStore from "./SessionStore"; import { HandleError } from "./helpers"; - class ApplicationStore extends EventEmitter { client: ApplicationServiceClient; @@ -87,7 +86,7 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; get = (req: GetApplicationRequest, callbackFunc: (resp: GetApplicationResponse) => void) => { this.client.get(req, SessionStore.getMetadata(), (err, resp) => { @@ -98,10 +97,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; update = (req: UpdateApplicationRequest, callbackFunc: () => void) => { - this.client.update(req, SessionStore.getMetadata(), (err) => { + this.client.update(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -114,10 +113,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; delete = (req: DeleteApplicationRequest, callbackFunc: () => void) => { - this.client.delete(req, SessionStore.getMetadata(), (err) => { + this.client.delete(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -130,7 +129,7 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; list = (req: ListApplicationsRequest, callbackFunc: (resp: ListApplicationsResponse) => void) => { this.client.list(req, SessionStore.getMetadata(), (err, resp) => { @@ -141,7 +140,7 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; listIntegrations = (req: ListIntegrationsRequest, callbackFunc: (resp: ListIntegrationsResponse) => void) => { this.client.listIntegrations(req, SessionStore.getMetadata(), (err, resp) => { @@ -151,11 +150,11 @@ class ApplicationStore extends EventEmitter { } callbackFunc(resp); - }) - } + }); + }; createHttpIntegration = (req: CreateHttpIntegrationRequest, callbackFunc: () => void) => { - this.client.createHttpIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createHttpIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -168,7 +167,7 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; getHttpIntegration = (req: GetHttpIntegrationRequest, callbackFunc: (resp: GetHttpIntegrationResponse) => void) => { this.client.getHttpIntegration(req, SessionStore.getMetadata(), (err, resp) => { @@ -179,10 +178,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateHttpIntegration = (req: UpdateHttpIntegrationRequest, callbackFunc: () => void) => { - this.client.updateHttpIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updateHttpIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -195,10 +194,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deleteHttpIntegration = (req: DeleteHttpIntegrationRequest, callbackFunc: () => void) => { - this.client.deleteHttpIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deleteHttpIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -212,10 +211,10 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; createAwsSnsIntegration = (req: CreateAwsSnsIntegrationRequest, callbackFunc: () => void) => { - this.client.createAwsSnsIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createAwsSnsIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -228,9 +227,12 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; - getAwsSnsIntegration = (req: GetAwsSnsIntegrationRequest, callbackFunc: (resp: GetAwsSnsIntegrationResponse) => void) => { + getAwsSnsIntegration = ( + req: GetAwsSnsIntegrationRequest, + callbackFunc: (resp: GetAwsSnsIntegrationResponse) => void, + ) => { this.client.getAwsSnsIntegration(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -239,10 +241,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateAwsSnsIntegration = (req: UpdateAwsSnsIntegrationRequest, callbackFunc: () => void) => { - this.client.updateAwsSnsIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updateAwsSnsIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -255,10 +257,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deleteAwsSnsIntegration = (req: DeleteAwsSnsIntegrationRequest, callbackFunc: () => void) => { - this.client.deleteAwsSnsIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deleteAwsSnsIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -272,10 +274,10 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; createAzureServiceBusIntegration = (req: CreateAzureServiceBusIntegrationRequest, callbackFunc: () => void) => { - this.client.createAzureServiceBusIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createAzureServiceBusIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -288,9 +290,12 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; - getAzureServiceBusIntegration = (req: GetAzureServiceBusIntegrationRequest, callbackFunc: (resp: GetAzureServiceBusIntegrationResponse) => void) => { + getAzureServiceBusIntegration = ( + req: GetAzureServiceBusIntegrationRequest, + callbackFunc: (resp: GetAzureServiceBusIntegrationResponse) => void, + ) => { this.client.getAzureServiceBusIntegration(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -299,10 +304,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateAzureServiceBusIntegration = (req: UpdateAzureServiceBusIntegrationRequest, callbackFunc: () => void) => { - this.client.updateAzureServiceBusIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updateAzureServiceBusIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -315,10 +320,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deleteAzureServiceBusIntegration = (req: DeleteAzureServiceBusIntegrationRequest, callbackFunc: () => void) => { - this.client.deleteAzureServiceBusIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deleteAzureServiceBusIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -332,10 +337,10 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; createGcpPubSubIntegration = (req: CreateGcpPubSubIntegrationRequest, callbackFunc: () => void) => { - this.client.createGcpPubSubIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createGcpPubSubIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -348,9 +353,12 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; - getGcpPubSubIntegration = (req: GetGcpPubSubIntegrationRequest, callbackFunc: (resp: GetGcpPubSubIntegrationResponse) => void) => { + getGcpPubSubIntegration = ( + req: GetGcpPubSubIntegrationRequest, + callbackFunc: (resp: GetGcpPubSubIntegrationResponse) => void, + ) => { this.client.getGcpPubSubIntegration(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -359,10 +367,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateGcpPubSubIntegration = (req: UpdateGcpPubSubIntegrationRequest, callbackFunc: () => void) => { - this.client.updateGcpPubSubIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updateGcpPubSubIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -375,10 +383,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deleteGcpPubSubIntegration = (req: DeleteGcpPubSubIntegrationRequest, callbackFunc: () => void) => { - this.client.deleteGcpPubSubIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deleteGcpPubSubIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -392,10 +400,10 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; createInfluxDbIntegration = (req: CreateInfluxDbIntegrationRequest, callbackFunc: () => void) => { - this.client.createInfluxDbIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createInfluxDbIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -408,9 +416,12 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; - getInfluxDbIntegration = (req: GetInfluxDbIntegrationRequest, callbackFunc: (resp: GetInfluxDbIntegrationResponse) => void) => { + getInfluxDbIntegration = ( + req: GetInfluxDbIntegrationRequest, + callbackFunc: (resp: GetInfluxDbIntegrationResponse) => void, + ) => { this.client.getInfluxDbIntegration(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -419,10 +430,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateInfluxDbIntegration = (req: UpdateInfluxDbIntegrationRequest, callbackFunc: () => void) => { - this.client.updateInfluxDbIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updateInfluxDbIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -435,10 +446,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deleteInfluxDbIntegration = (req: DeleteInfluxDbIntegrationRequest, callbackFunc: () => void) => { - this.client.deleteInfluxDbIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deleteInfluxDbIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -452,10 +463,10 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; createMyDevicesIntegration = (req: CreateMyDevicesIntegrationRequest, callbackFunc: () => void) => { - this.client.createMyDevicesIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createMyDevicesIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -468,9 +479,12 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; - getMyDevicesIntegration = (req: GetMyDevicesIntegrationRequest, callbackFunc: (resp: GetMyDevicesIntegrationResponse) => void) => { + getMyDevicesIntegration = ( + req: GetMyDevicesIntegrationRequest, + callbackFunc: (resp: GetMyDevicesIntegrationResponse) => void, + ) => { this.client.getMyDevicesIntegration(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -479,10 +493,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateMyDevicesIntegration = (req: UpdateMyDevicesIntegrationRequest, callbackFunc: () => void) => { - this.client.updateMyDevicesIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updateMyDevicesIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -495,10 +509,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deleteMyDevicesIntegration = (req: DeleteMyDevicesIntegrationRequest, callbackFunc: () => void) => { - this.client.deleteMyDevicesIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deleteMyDevicesIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -512,10 +526,10 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; createPilotThingsIntegration = (req: CreatePilotThingsIntegrationRequest, callbackFunc: () => void) => { - this.client.createPilotThingsIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createPilotThingsIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -528,9 +542,12 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; - getPilotThingsIntegration = (req: GetPilotThingsIntegrationRequest, callbackFunc: (resp: GetPilotThingsIntegrationResponse) => void) => { + getPilotThingsIntegration = ( + req: GetPilotThingsIntegrationRequest, + callbackFunc: (resp: GetPilotThingsIntegrationResponse) => void, + ) => { this.client.getPilotThingsIntegration(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -539,10 +556,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updatePilotThingsIntegration = (req: UpdatePilotThingsIntegrationRequest, callbackFunc: () => void) => { - this.client.updatePilotThingsIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updatePilotThingsIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -555,10 +572,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deletePilotThingsIntegration = (req: DeletePilotThingsIntegrationRequest, callbackFunc: () => void) => { - this.client.deletePilotThingsIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deletePilotThingsIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -572,10 +589,10 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; createLoraCloudIntegration = (req: CreateLoraCloudIntegrationRequest, callbackFunc: () => void) => { - this.client.createLoraCloudIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createLoraCloudIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -588,9 +605,12 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; - getLoraCloudIntegration = (req: GetLoraCloudIntegrationRequest, callbackFunc: (resp: GetLoraCloudIntegrationResponse) => void) => { + getLoraCloudIntegration = ( + req: GetLoraCloudIntegrationRequest, + callbackFunc: (resp: GetLoraCloudIntegrationResponse) => void, + ) => { this.client.getLoraCloudIntegration(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -599,10 +619,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateLoraCloudIntegration = (req: UpdateLoraCloudIntegrationRequest, callbackFunc: () => void) => { - this.client.updateLoraCloudIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updateLoraCloudIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -615,10 +635,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deleteLoraCloudIntegration = (req: DeleteLoraCloudIntegrationRequest, callbackFunc: () => void) => { - this.client.deleteLoraCloudIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deleteLoraCloudIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -632,10 +652,10 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; createThingsBoardIntegration = (req: CreateThingsBoardIntegrationRequest, callbackFunc: () => void) => { - this.client.createThingsBoardIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.createThingsBoardIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -648,9 +668,12 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; - getThingsBoardIntegration = (req: GetThingsBoardIntegrationRequest, callbackFunc: (resp: GetThingsBoardIntegrationResponse) => void) => { + getThingsBoardIntegration = ( + req: GetThingsBoardIntegrationRequest, + callbackFunc: (resp: GetThingsBoardIntegrationResponse) => void, + ) => { this.client.getThingsBoardIntegration(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -659,10 +682,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateThingsBoardIntegration = (req: UpdateThingsBoardIntegrationRequest, callbackFunc: () => void) => { - this.client.updateThingsBoardIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.updateThingsBoardIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -675,10 +698,10 @@ class ApplicationStore extends EventEmitter { callbackFunc(); }); - } + }; deleteThingsBoardIntegration = (req: DeleteThingsBoardIntegrationRequest, callbackFunc: () => void) => { - this.client.deleteThingsBoardIntegration(req, SessionStore.getMetadata(), (err) => { + this.client.deleteThingsBoardIntegration(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -692,9 +715,12 @@ class ApplicationStore extends EventEmitter { this.emit("integration.delete"); callbackFunc(); }); - } + }; - generateMqttIntegrationClientCertificate = (req: GenerateMqttIntegrationClientCertificateRequest, callbackFunc: (resp: GenerateMqttIntegrationClientCertificateResponse) => void) => { + generateMqttIntegrationClientCertificate = ( + req: GenerateMqttIntegrationClientCertificateRequest, + callbackFunc: (resp: GenerateMqttIntegrationClientCertificateResponse) => void, + ) => { this.client.generateMqttIntegrationClientCertificate(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -703,7 +729,7 @@ class ApplicationStore extends EventEmitter { callbackFunc(resp); }); - } + }; } const applicationStore = new ApplicationStore(); diff --git a/ui/src/stores/DeviceProfileStore.ts b/ui/src/stores/DeviceProfileStore.ts index a38bd045..6f1630a8 100644 --- a/ui/src/stores/DeviceProfileStore.ts +++ b/ui/src/stores/DeviceProfileStore.ts @@ -17,7 +17,6 @@ import { import SessionStore from "./SessionStore"; import { HandleError } from "./helpers"; - class DeviceProfileStore extends EventEmitter { client: DeviceProfileServiceClient; @@ -40,7 +39,7 @@ class DeviceProfileStore extends EventEmitter { callbackFunc(resp); }); - } + }; get = (req: GetDeviceProfileRequest, callbackFunc: (resp: GetDeviceProfileResponse) => void) => { this.client.get(req, SessionStore.getMetadata(), (err, resp) => { @@ -51,10 +50,10 @@ class DeviceProfileStore extends EventEmitter { callbackFunc(resp); }); - } + }; update = (req: UpdateDeviceProfileRequest, callbackFunc: () => void) => { - this.client.update(req, SessionStore.getMetadata(), (err) => { + this.client.update(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -67,10 +66,10 @@ class DeviceProfileStore extends EventEmitter { callbackFunc(); }); - } + }; delete = (req: DeleteDeviceProfileRequest, callbackFunc: () => void) => { - this.client.delete(req, SessionStore.getMetadata(), (err) => { + this.client.delete(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -83,7 +82,7 @@ class DeviceProfileStore extends EventEmitter { callbackFunc(); }); - } + }; list = (req: ListDeviceProfilesRequest, callbackFunc: (resp: ListDeviceProfilesResponse) => void) => { this.client.list(req, SessionStore.getMetadata(), (err, resp) => { @@ -93,8 +92,8 @@ class DeviceProfileStore extends EventEmitter { } callbackFunc(resp); - }) - } + }); + }; listAdrAlgorithms = (callbackFunc: (resp: ListDeviceProfileAdrAlgorithmsResponse) => void) => { this.client.listAdrAlgorithms(new google_protobuf_empty_pb.Empty(), SessionStore.getMetadata(), (err, resp) => { @@ -105,7 +104,7 @@ class DeviceProfileStore extends EventEmitter { callbackFunc(resp); }); - } + }; } const deviceProfileStore = new DeviceProfileStore(); diff --git a/ui/src/stores/DeviceStore.ts b/ui/src/stores/DeviceStore.ts index 3fc14607..887ec5c1 100644 --- a/ui/src/stores/DeviceStore.ts +++ b/ui/src/stores/DeviceStore.ts @@ -33,7 +33,6 @@ import { import SessionStore from "./SessionStore"; import { HandleError } from "./helpers"; - class DeviceStore extends EventEmitter { client: DeviceServiceClient; @@ -43,7 +42,7 @@ class DeviceStore extends EventEmitter { } create = (req: CreateDeviceRequest, callbackFunc: () => void) => { - this.client.create(req, SessionStore.getMetadata(), (err) => { + this.client.create(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -56,7 +55,7 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; get = (req: GetDeviceRequest, callbackFunc: (resp: GetDeviceResponse) => void) => { this.client.get(req, SessionStore.getMetadata(), (err, resp) => { @@ -67,10 +66,10 @@ class DeviceStore extends EventEmitter { callbackFunc(resp); }); - } + }; update = (req: UpdateDeviceRequest, callbackFunc: () => void) => { - this.client.update(req, SessionStore.getMetadata(), (err) => { + this.client.update(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -83,10 +82,10 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; delete = (req: DeleteDeviceRequest, callbackFunc: () => void) => { - this.client.delete(req, SessionStore.getMetadata(), (err) => { + this.client.delete(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -99,7 +98,7 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; list = (req: ListDevicesRequest, callbackFunc: (resp: ListDevicesResponse) => void) => { this.client.list(req, SessionStore.getMetadata(), (err, resp) => { @@ -110,10 +109,10 @@ class DeviceStore extends EventEmitter { callbackFunc(resp); }); - } + }; createKeys = (req: CreateDeviceKeysRequest, callbackFunc: () => void) => { - this.client.createKeys(req, SessionStore.getMetadata(), (err) => { + this.client.createKeys(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -126,7 +125,7 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; getKeys = (req: GetDeviceKeysRequest, callbackFunc: (resp?: GetDeviceKeysResponse) => void) => { this.client.getKeys(req, SessionStore.getMetadata(), (err, resp) => { @@ -139,10 +138,10 @@ class DeviceStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateKeys = (req: UpdateDeviceKeysRequest, callbackFunc: () => void) => { - this.client.updateKeys(req, SessionStore.getMetadata(), (err) => { + this.client.updateKeys(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -155,10 +154,10 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; deleteKeys = (req: DeleteDeviceKeysRequest, callbackFunc: () => void) => { - this.client.deleteKeys(req, SessionStore.getMetadata(), (err) => { + this.client.deleteKeys(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -171,7 +170,7 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; getStats = (req: GetDeviceStatsRequest, callbackFunc: (resp: GetDeviceStatsResponse) => void) => { this.client.getStats(req, SessionStore.getMetadata(), (err, resp) => { @@ -182,7 +181,7 @@ class DeviceStore extends EventEmitter { callbackFunc(resp); }); - } + }; enqueue = (req: EnqueueDeviceQueueItemRequest, callbackFunc: (resp: EnqueueDeviceQueueItemResponse) => void) => { this.client.enqueue(req, SessionStore.getMetadata(), (err, resp) => { @@ -193,10 +192,10 @@ class DeviceStore extends EventEmitter { callbackFunc(resp); }); - } + }; flushQueue = (req: FlushDeviceQueueRequest, callbackFunc: () => void) => { - this.client.flushQueue(req, SessionStore.getMetadata(), (err) => { + this.client.flushQueue(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -204,10 +203,10 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; flushDevNonces = (req: FlushDevNoncesRequest, callbackFunc: () => void) => { - this.client.flushDevNonces(req, SessionStore.getMetadata(), (err) => { + this.client.flushDevNonces(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -220,7 +219,7 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; getQueue = (req: GetDeviceQueueItemsRequest, callbackFunc: (resp: GetDeviceQueueItemsResponse) => void) => { this.client.getQueue(req, SessionStore.getMetadata(), (err, resp) => { @@ -231,10 +230,10 @@ class DeviceStore extends EventEmitter { callbackFunc(resp); }); - } + }; activate = (req: ActivateDeviceRequest, callbackFunc: () => void) => { - this.client.activate(req, SessionStore.getMetadata(), (err) => { + this.client.activate(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -247,7 +246,7 @@ class DeviceStore extends EventEmitter { callbackFunc(); }); - } + }; getActivation = (req: GetDeviceActivationRequest, callbackFunc: (resp: GetDeviceActivationResponse) => void) => { this.client.getActivation(req, SessionStore.getMetadata(), (err, resp) => { @@ -258,7 +257,7 @@ class DeviceStore extends EventEmitter { callbackFunc(resp); }); - } + }; getRandomDevAddr = (req: GetRandomDevAddrRequest, callbackFunc: (resp: GetRandomDevAddrResponse) => void) => { this.client.getRandomDevAddr(req, SessionStore.getMetadata(), (err, resp) => { @@ -269,7 +268,7 @@ class DeviceStore extends EventEmitter { callbackFunc(resp); }); - } + }; } const deviceStore = new DeviceStore(); diff --git a/ui/src/stores/GatewayStore.ts b/ui/src/stores/GatewayStore.ts index 8d8e1ea6..78b23b8c 100644 --- a/ui/src/stores/GatewayStore.ts +++ b/ui/src/stores/GatewayStore.ts @@ -18,7 +18,6 @@ import { import SessionStore from "./SessionStore"; import { HandleError } from "./helpers"; - class GatewayStore extends EventEmitter { client: GatewayServiceClient; @@ -28,7 +27,7 @@ class GatewayStore extends EventEmitter { } create = (req: CreateGatewayRequest, callbackFunc: () => void) => { - this.client.create(req, SessionStore.getMetadata(), (err) => { + this.client.create(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -41,7 +40,7 @@ class GatewayStore extends EventEmitter { callbackFunc(); }); - } + }; get = (req: GetGatewayRequest, callbackFunc: (resp: GetGatewayResponse) => void) => { this.client.get(req, SessionStore.getMetadata(), (err, resp) => { @@ -52,10 +51,10 @@ class GatewayStore extends EventEmitter { callbackFunc(resp); }); - } + }; update = (req: UpdateGatewayRequest, callbackFunc: () => void) => { - this.client.update(req, SessionStore.getMetadata(), (err) => { + this.client.update(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -68,10 +67,10 @@ class GatewayStore extends EventEmitter { callbackFunc(); }); - } + }; delete = (req: DeleteGatewayRequest, callbackFunc: () => void) => { - this.client.delete(req, SessionStore.getMetadata(), (err) => { + this.client.delete(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -84,7 +83,7 @@ class GatewayStore extends EventEmitter { callbackFunc(); }); - } + }; list = (req: ListGatewaysRequest, callbackFunc: (resp: ListGatewaysResponse) => void) => { this.client.list(req, SessionStore.getMetadata(), (err, resp) => { @@ -95,7 +94,7 @@ class GatewayStore extends EventEmitter { callbackFunc(resp); }); - } + }; getStats = (req: GetGatewayStatsRequest, callbackFunc: (resp: GetGatewayStatsResponse) => void) => { this.client.getStats(req, SessionStore.getMetadata(), (err, resp) => { @@ -106,9 +105,12 @@ class GatewayStore extends EventEmitter { callbackFunc(resp); }); - } + }; - generateClientCertificate = (req: GenerateGatewayClientCertificateRequest, callbackFunc: (resp: GenerateGatewayClientCertificateResponse) => void) => { + generateClientCertificate = ( + req: GenerateGatewayClientCertificateRequest, + callbackFunc: (resp: GenerateGatewayClientCertificateResponse) => void, + ) => { this.client.generateClientCertificate(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); @@ -117,7 +119,7 @@ class GatewayStore extends EventEmitter { callbackFunc(resp); }); - } + }; } const gatewayStore = new GatewayStore(); diff --git a/ui/src/stores/InternalStore.ts b/ui/src/stores/InternalStore.ts index a43d59fa..52341d11 100644 --- a/ui/src/stores/InternalStore.ts +++ b/ui/src/stores/InternalStore.ts @@ -1,4 +1,4 @@ -import * as grpcWeb from 'grpc-web'; +import * as grpcWeb from "grpc-web"; import google_protobuf_empty_pb from "google-protobuf/google/protobuf/empty_pb"; import { notification } from "antd"; @@ -26,7 +26,6 @@ import { import SessionStore from "./SessionStore"; import { HandleError } from "./helpers"; - class InternalStore extends EventEmitter { client: InternalServiceClient; @@ -49,7 +48,7 @@ class InternalStore extends EventEmitter { callbackFunc(resp); }); - } + }; deleteApiKey = (req: DeleteApiKeyRequest, callbackFunc: () => void) => { this.client.deleteApiKey(req, SessionStore.getMetadata(), (err, resp) => { @@ -65,7 +64,7 @@ class InternalStore extends EventEmitter { callbackFunc(); }); - } + }; listApiKeys = (req: ListApiKeysRequest, callbackFunc: (resp: ListApiKeysResponse) => void) => { this.client.listApiKeys(req, SessionStore.getMetadata(), (err, resp) => { @@ -76,26 +75,25 @@ class InternalStore extends EventEmitter { callbackFunc(resp); }); - } + }; - streamGatewayFrames = (req: StreamGatewayFramesRequest, callbackFunc: (resp: LogItem) => void): () => void => { + streamGatewayFrames = (req: StreamGatewayFramesRequest, callbackFunc: (resp: LogItem) => void): (() => void) => { var stream: grpcWeb.ClientReadableStream | undefined = undefined; let setup = () => { console.log("Setting up gRPC stream"); stream = this.client.streamGatewayFrames(req, SessionStore.getMetadata()); - stream = stream.on("data", (resp) => { + stream = stream.on("data", resp => { callbackFunc(resp); }); - stream = stream.on('end', function() { + stream = stream.on("end", function () { console.log("gRPC stream end, reconnecting"); setTimeout(setup, 1000); }); }; - setup(); return () => { @@ -103,26 +101,25 @@ class InternalStore extends EventEmitter { stream.cancel(); } }; - } + }; - streamDeviceFrames = (req: StreamDeviceFramesRequest, callbackFunc: (resp: LogItem) => void): () => void => { + streamDeviceFrames = (req: StreamDeviceFramesRequest, callbackFunc: (resp: LogItem) => void): (() => void) => { var stream: grpcWeb.ClientReadableStream | undefined = undefined; let setup = () => { console.log("Setting up gRPC stream"); stream = this.client.streamDeviceFrames(req, SessionStore.getMetadata()); - stream = stream.on("data", (resp) => { + stream = stream.on("data", resp => { callbackFunc(resp); }); - stream = stream.on('end', function() { + stream = stream.on("end", function () { console.log("gRPC stream end, reconnecting"); setTimeout(setup, 1000); }); }; - setup(); return () => { @@ -130,20 +127,20 @@ class InternalStore extends EventEmitter { stream.cancel(); } }; - } + }; - streamDeviceEvents = (req: StreamDeviceEventsRequest, callbackFunc: (resp: LogItem) => void): () => void => { + streamDeviceEvents = (req: StreamDeviceEventsRequest, callbackFunc: (resp: LogItem) => void): (() => void) => { var stream: grpcWeb.ClientReadableStream | undefined = undefined; let setup = () => { console.log("Setting up gRPC stream"); stream = this.client.streamDeviceEvents(req, SessionStore.getMetadata()); - stream = stream.on("data", (resp) => { + stream = stream.on("data", resp => { callbackFunc(resp); }); - stream = stream.on('end', function() { + stream = stream.on("end", function () { console.log("gRPC stream end, reconnecting"); setTimeout(setup, 1000); }); @@ -156,7 +153,7 @@ class InternalStore extends EventEmitter { stream.cancel(); } }; - } + }; getGatewaysSummary = (req: GetGatewaysSummaryRequest, callbackFunc: (resp: GetGatewaysSummaryResponse) => void) => { this.client.getGatewaysSummary(req, SessionStore.getMetadata(), (err, resp) => { @@ -167,7 +164,7 @@ class InternalStore extends EventEmitter { callbackFunc(resp); }); - } + }; getDevicesSummary = (req: GetDevicesSummaryRequest, callbackFunc: (resp: GetDevicesSummaryResponse) => void) => { this.client.getDevicesSummary(req, SessionStore.getMetadata(), (err, resp) => { @@ -178,7 +175,7 @@ class InternalStore extends EventEmitter { callbackFunc(resp); }); - } + }; settings = (callbackFunc: (resp: SettingsResponse) => void) => { this.client.settings(new google_protobuf_empty_pb.Empty(), {}, (err, resp) => { @@ -189,7 +186,7 @@ class InternalStore extends EventEmitter { callbackFunc(resp); }); - } + }; globalSearch = (req: GlobalSearchRequest, callbackFunc: (resp: GlobalSearchResponse) => void) => { this.client.globalSearch(req, SessionStore.getMetadata(), (err, resp) => { @@ -200,7 +197,7 @@ class InternalStore extends EventEmitter { callbackFunc(resp); }); - } + }; } const internalStore = new InternalStore(); diff --git a/ui/src/stores/LocationStore.ts b/ui/src/stores/LocationStore.ts index 2ff1519d..ed93cb3b 100644 --- a/ui/src/stores/LocationStore.ts +++ b/ui/src/stores/LocationStore.ts @@ -11,17 +11,21 @@ class LocationStore extends EventEmitter { return; } - navigator.geolocation.getCurrentPosition((p: GeolocationPosition) => { - callbackFunc([p.coords.latitude, p.coords.longitude]); - }, (e: GeolocationPositionError) => { - notification.error({ - message: e.message, - duration: 3, - }); - }, { - timeout: 3000, - }); - } + navigator.geolocation.getCurrentPosition( + (p: GeolocationPosition) => { + callbackFunc([p.coords.latitude, p.coords.longitude]); + }, + (e: GeolocationPositionError) => { + notification.error({ + message: e.message, + duration: 3, + }); + }, + { + timeout: 3000, + }, + ); + }; } const locationStore = new LocationStore(); diff --git a/ui/src/stores/MulticastGroupStore.ts b/ui/src/stores/MulticastGroupStore.ts index e369654e..44d1647d 100644 --- a/ui/src/stores/MulticastGroupStore.ts +++ b/ui/src/stores/MulticastGroupStore.ts @@ -20,7 +20,6 @@ import { import SessionStore from "./SessionStore"; import { HandleError } from "./helpers"; - class MulticastGroupStore extends EventEmitter { client: MulticastGroupServiceClient; @@ -43,7 +42,7 @@ class MulticastGroupStore extends EventEmitter { callbackFunc(resp); }); - } + }; get = (req: GetMulticastGroupRequest, callbackFunc: (resp: GetMulticastGroupResponse) => void) => { this.client.get(req, SessionStore.getMetadata(), (err, resp) => { @@ -54,10 +53,10 @@ class MulticastGroupStore extends EventEmitter { callbackFunc(resp); }); - } - + }; + update = (req: UpdateMulticastGroupRequest, callbackFunc: () => void) => { - this.client.update(req, SessionStore.getMetadata(), (err) => { + this.client.update(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -70,10 +69,10 @@ class MulticastGroupStore extends EventEmitter { callbackFunc(); }); - } + }; delete = (req: DeleteMulticastGroupRequest, callbackFunc: () => void) => { - this.client.delete(req, SessionStore.getMetadata(), (err) => { + this.client.delete(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -86,7 +85,7 @@ class MulticastGroupStore extends EventEmitter { callbackFunc(); }); - } + }; list = (req: ListMulticastGroupsRequest, callbackFunc: (resp: ListMulticastGroupsResponse) => void) => { this.client.list(req, SessionStore.getMetadata(), (err, resp) => { @@ -97,10 +96,10 @@ class MulticastGroupStore extends EventEmitter { callbackFunc(resp); }); - } + }; addDevice = (req: AddDeviceToMulticastGroupRequest, callbackFunc: () => void) => { - this.client.addDevice(req, SessionStore.getMetadata(), (err) => { + this.client.addDevice(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -113,10 +112,10 @@ class MulticastGroupStore extends EventEmitter { callbackFunc(); }); - } + }; removeDevice = (req: RemoveDeviceFromMulticastGroupRequest, callbackFunc: () => void) => { - this.client.removeDevice(req, SessionStore.getMetadata(), (err) => { + this.client.removeDevice(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -124,7 +123,7 @@ class MulticastGroupStore extends EventEmitter { callbackFunc(); }); - } + }; listQueue = (req: ListMulticastGroupQueueRequest, callbackFunc: (resp: ListMulticastGroupQueueResponse) => void) => { this.client.listQueue(req, SessionStore.getMetadata(), (err, resp) => { @@ -135,7 +134,7 @@ class MulticastGroupStore extends EventEmitter { callbackFunc(resp); }); - } + }; } const multicastGroupStore = new MulticastGroupStore(); diff --git a/ui/src/stores/SessionStore.ts b/ui/src/stores/SessionStore.ts index 0797ee3a..a688d17c 100644 --- a/ui/src/stores/SessionStore.ts +++ b/ui/src/stores/SessionStore.ts @@ -3,7 +3,11 @@ import { Metadata } from "grpc-web"; import { EventEmitter } from "events"; import { InternalServiceClient } from "@chirpstack/chirpstack-api-grpc-web/api/internal_grpc_web_pb"; -import { LoginRequest, UserTenantLink, OpenIdConnectLoginRequest } from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; +import { + LoginRequest, + UserTenantLink, + OpenIdConnectLoginRequest, +} from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; import { User } from "@chirpstack/chirpstack-api-grpc-web/api/user_pb"; import { HandleError, HandleLoginError } from "./helpers"; @@ -30,12 +34,12 @@ class SessionStore extends EventEmitter { if (err !== null) { HandleLoginError(err); return; - } + } this.setToken(resp.getJwt()); this.fetchProfile(callbackFunc); }); - } + }; openIdConnectLogin = (req: OpenIdConnectLoginRequest, callbackFunc: any) => { this.client.openIdConnectLogin(req, {}, (err, resp) => { @@ -47,7 +51,7 @@ class SessionStore extends EventEmitter { this.setToken(resp.getToken()); this.fetchProfile(callbackFunc); }); - } + }; logout = (emit: boolean, callbackFunc: () => void) => { localStorage.clear(); @@ -59,11 +63,11 @@ class SessionStore extends EventEmitter { } callbackFunc(); - } + }; setToken = (s: string) => { localStorage.setItem("token", s); - } + }; getToken = (): string => { let token = localStorage.getItem("token"); @@ -71,25 +75,25 @@ class SessionStore extends EventEmitter { return ""; } return token; - } + }; getTenantId = (): string => { return localStorage.getItem("tenantId") || ""; - } + }; setTenantId = (id: string) => { console.log("tenantId set to", id); localStorage.setItem("tenantId", id); this.emit("tenant.change"); - } + }; getRowsPerPage = (): number => { return parseInt(localStorage.getItem("rowsPerPage") || "10", 10); - } + }; setRowsPerPage = (count: number) => { localStorage.setItem("rowsPerPage", count.toString()); - } + }; getMetadata = (): Metadata => { if (this.getToken() === "") { @@ -99,7 +103,7 @@ class SessionStore extends EventEmitter { return { authorization: "Bearer " + this.getToken(), }; - } + }; fetchProfile = (callbackFunc: any) => { if (this.getToken() === "") { @@ -118,19 +122,19 @@ class SessionStore extends EventEmitter { callbackFunc(); }); - } + }; getUser = (): User | undefined => { return this.user; - } + }; isAdmin = (): boolean => { - if(!this.user) { + if (!this.user) { return false; } return this.user.getIsAdmin(); - } + }; isTenantAdmin = (tenantId: string): boolean => { for (const t of this.tenants) { @@ -140,7 +144,7 @@ class SessionStore extends EventEmitter { } return false; - } + }; isTenantDeviceAdmin = (tenantId: string): boolean => { for (const t of this.tenants) { @@ -150,7 +154,7 @@ class SessionStore extends EventEmitter { } return false; - } + }; isTenantGatewayAdmin = (tenantId: string): boolean => { for (const t of this.tenants) { @@ -158,7 +162,7 @@ class SessionStore extends EventEmitter { } return false; - } + }; } const sessionStore = new SessionStore(); diff --git a/ui/src/stores/TenantStore.ts b/ui/src/stores/TenantStore.ts index c3fb11ad..508c599a 100644 --- a/ui/src/stores/TenantStore.ts +++ b/ui/src/stores/TenantStore.ts @@ -22,7 +22,6 @@ import { import SessionStore from "./SessionStore"; import { HandleError } from "./helpers"; - class TenantStore extends EventEmitter { client: TenantServiceClient; @@ -45,7 +44,7 @@ class TenantStore extends EventEmitter { callbackFunc(resp); }); - } + }; get = (id: string, callbackFunc: (resp: GetTenantResponse) => void) => { let req = new GetTenantRequest(); @@ -59,14 +58,14 @@ class TenantStore extends EventEmitter { callbackFunc(resp); }); - } + }; update = (req: UpdateTenantRequest, callbackFunc: () => void) => { this.client.update(req, SessionStore.getMetadata(), (err, resp) => { if (err !== null) { HandleError(err); return; - } + } notification.success({ message: "Tenant updated", @@ -77,7 +76,7 @@ class TenantStore extends EventEmitter { callbackFunc(); }); - } + }; delete = (req: DeleteTenantRequest, callbackFunc: () => void) => { this.client.delete(req, SessionStore.getMetadata(), (err, resp) => { @@ -93,7 +92,7 @@ class TenantStore extends EventEmitter { callbackFunc(); }); - } + }; list = (req: ListTenantsRequest, callbackFunc: (resp: ListTenantsResponse) => void) => { this.client.list(req, SessionStore.getMetadata(), (err, resp) => { @@ -104,10 +103,10 @@ class TenantStore extends EventEmitter { callbackFunc(resp); }); - } + }; addUser = (req: AddTenantUserRequest, callbackFunc: () => void) => { - this.client.addUser(req, SessionStore.getMetadata(), (err) => { + this.client.addUser(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -131,10 +130,10 @@ class TenantStore extends EventEmitter { callbackFunc(resp); }); - } + }; updateUser = (req: UpdateTenantUserRequest, callbackFunc: () => void) => { - this.client.updateUser(req, SessionStore.getMetadata(), (err) => { + this.client.updateUser(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -147,10 +146,10 @@ class TenantStore extends EventEmitter { callbackFunc(); }); - } + }; deleteUser = (req: DeleteTenantUserRequest, callbackFunc: () => void) => { - this.client.deleteUser(req, SessionStore.getMetadata(), (err) => { + this.client.deleteUser(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -163,7 +162,7 @@ class TenantStore extends EventEmitter { callbackFunc(); }); - } + }; listUsers = (req: ListTenantUsersRequest, callbackFunc: (resp: ListTenantUsersResponse) => void) => { this.client.listUsers(req, SessionStore.getMetadata(), (err, resp) => { @@ -174,7 +173,7 @@ class TenantStore extends EventEmitter { callbackFunc(resp); }); - } + }; } const tenantStore = new TenantStore(); diff --git a/ui/src/stores/UserStore.ts b/ui/src/stores/UserStore.ts index f355d330..677a312a 100644 --- a/ui/src/stores/UserStore.ts +++ b/ui/src/stores/UserStore.ts @@ -16,7 +16,6 @@ import { import SessionStore from "./SessionStore"; import { HandleError } from "./helpers"; - class UserStore extends EventEmitter { client: UserServiceClient; @@ -39,7 +38,7 @@ class UserStore extends EventEmitter { callbackFunc(resp); }); - } + }; get = (req: GetUserRequest, callbackFunc: (resp: GetUserResponse) => void) => { this.client.get(req, SessionStore.getMetadata(), (err, resp) => { @@ -50,7 +49,7 @@ class UserStore extends EventEmitter { callbackFunc(resp); }); - } + }; update = (req: UpdateUserRequest, callbackFunc: () => void) => { this.client.update(req, SessionStore.getMetadata(), (err, resp) => { @@ -66,7 +65,7 @@ class UserStore extends EventEmitter { callbackFunc(); }); - } + }; delete = (req: DeleteUserRequest, callbackFunc: () => void) => { this.client.delete(req, SessionStore.getMetadata(), (err, resp) => { @@ -82,7 +81,7 @@ class UserStore extends EventEmitter { callbackFunc(); }); - } + }; list = (req: ListUsersRequest, callbackFunc: (resp: ListUsersResponse) => void) => { this.client.list(req, SessionStore.getMetadata(), (err, resp) => { @@ -93,10 +92,10 @@ class UserStore extends EventEmitter { callbackFunc(resp); }); - } + }; updatePassword = (req: UpdateUserPasswordRequest, callbackFunc: () => void) => { - this.client.updatePassword(req, SessionStore.getMetadata(), (err) => { + this.client.updatePassword(req, SessionStore.getMetadata(), err => { if (err !== null) { HandleError(err); return; @@ -109,7 +108,7 @@ class UserStore extends EventEmitter { callbackFunc(); }); - } + }; } const userStore = new UserStore(); diff --git a/ui/src/stores/helpers.ts b/ui/src/stores/helpers.ts index 93b29aa5..134c1900 100644 --- a/ui/src/stores/helpers.ts +++ b/ui/src/stores/helpers.ts @@ -6,7 +6,7 @@ import history from "../history"; export function HandleError(e: Error) { console.log("API error: ", e); - if (e.code === 16 || e.code === 2) { + if (e.code === 16 || e.code === 2) { history.push("/login"); return; } diff --git a/ui/src/views/api-keys/ApiKeyForm.tsx b/ui/src/views/api-keys/ApiKeyForm.tsx index a12924ee..f5726815 100644 --- a/ui/src/views/api-keys/ApiKeyForm.tsx +++ b/ui/src/views/api-keys/ApiKeyForm.tsx @@ -4,7 +4,6 @@ import { Form, Input, Button } from "antd"; import { ApiKey } from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; - interface IProps { initialValues: ApiKey; onFinish: (obj: ApiKey) => void; @@ -17,20 +16,18 @@ class ApiKeyForm extends Component { let apiKey = new ApiKey(); apiKey.setName(values.name); this.props.onFinish(apiKey); - } + }; render() { - return( + return (
- + - + ); diff --git a/ui/src/views/api-keys/ApiKeyToken.tsx b/ui/src/views/api-keys/ApiKeyToken.tsx index 5a97e181..b50163c8 100644 --- a/ui/src/views/api-keys/ApiKeyToken.tsx +++ b/ui/src/views/api-keys/ApiKeyToken.tsx @@ -1,31 +1,28 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Input, Typography, Button, Space } from 'antd'; +import { Input, Typography, Button, Space } from "antd"; import { CreateApiKeyResponse } from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; - interface IProps { createApiKeyResponse: CreateApiKeyResponse; } - class ApiKeyToken extends Component { - - render() { return ( - Use the following API token when making API requests. This token can - be revoked at any time by deleting it. Please note that this token can - only be retrieved once: + Use the following API token when making API requests. This token can be revoked at any time by deleting it. + Please note that this token can only be retrieved once: - + ); } diff --git a/ui/src/views/api-keys/CreateAdminApiKey.tsx b/ui/src/views/api-keys/CreateAdminApiKey.tsx index 7a2b37f7..0572a597 100644 --- a/ui/src/views/api-keys/CreateAdminApiKey.tsx +++ b/ui/src/views/api-keys/CreateAdminApiKey.tsx @@ -9,14 +9,12 @@ import ApiKeyForm from "./ApiKeyForm"; import ApiKeyToken from "./ApiKeyToken"; import InternalStore from "../../stores/InternalStore"; - interface IProps {} interface IState { createApiKeyResponse?: CreateApiKeyResponse; } - class CreateAdminApiKey extends Component { constructor(props: IProps) { super(props); @@ -34,26 +32,30 @@ class CreateAdminApiKey extends Component { createApiKeyResponse: resp, }); }); - } + }; render() { const apiKey = new ApiKey(); - return( + return ( + breadcrumbRender={() => ( + Network-server - API keys + + API keys + Add - } + + )} /> {!this.state.createApiKeyResponse && } diff --git a/ui/src/views/api-keys/CreateTenantApiKey.tsx b/ui/src/views/api-keys/CreateTenantApiKey.tsx index 8dacd189..f250660b 100644 --- a/ui/src/views/api-keys/CreateTenantApiKey.tsx +++ b/ui/src/views/api-keys/CreateTenantApiKey.tsx @@ -10,7 +10,6 @@ import ApiKeyForm from "./ApiKeyForm"; import ApiKeyToken from "./ApiKeyToken"; import InternalStore from "../../stores/InternalStore"; - interface IState { createApiKeyResponse?: CreateApiKeyResponse; } @@ -19,7 +18,6 @@ interface IProps { tenant: Tenant; } - class CreateTenantApiKey extends Component { constructor(props: IProps) { super(props); @@ -37,28 +35,34 @@ class CreateTenantApiKey extends Component { createApiKeyResponse: resp, }); }); - } + }; render() { const apiKey = new ApiKey(); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - API Keys + + API Keys + Add - } + + )} title="Add API key" /> diff --git a/ui/src/views/api-keys/ListAdminApiKeys.tsx b/ui/src/views/api-keys/ListAdminApiKeys.tsx index 1395b52b..f4cd43e8 100644 --- a/ui/src/views/api-keys/ListAdminApiKeys.tsx +++ b/ui/src/views/api-keys/ListAdminApiKeys.tsx @@ -6,20 +6,23 @@ import { DeleteOutlined } from "@ant-design/icons"; import { Space, Breadcrumb, Button, PageHeader } from "antd"; import { ColumnsType } from "antd/es/table"; -import { ListApiKeysRequest, ListApiKeysResponse, DeleteApiKeyRequest, ApiKey } from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; +import { + ListApiKeysRequest, + ListApiKeysResponse, + DeleteApiKeyRequest, + ApiKey, +} from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import InternalStore from "../../stores/InternalStore"; import DeleteConfirm from "../../components/DeleteConfirm"; - interface IProps {} interface IState { refreshKey: number; } - class ListAdminApiKeys extends Component { constructor(props: IProps) { super(props); @@ -47,19 +50,15 @@ class ListAdminApiKeys extends Component { key: "action", width: 100, render: (text, record) => ( - + + , ]} /> - + ); } diff --git a/ui/src/views/api-keys/ListTenantApiKeys.tsx b/ui/src/views/api-keys/ListTenantApiKeys.tsx index e4cfa6d0..1dd13a8a 100644 --- a/ui/src/views/api-keys/ListTenantApiKeys.tsx +++ b/ui/src/views/api-keys/ListTenantApiKeys.tsx @@ -5,7 +5,12 @@ import { DeleteOutlined } from "@ant-design/icons"; import { Space, Breadcrumb, Button, PageHeader } from "antd"; import { ColumnsType } from "antd/es/table"; -import { ListApiKeysRequest, ListApiKeysResponse, DeleteApiKeyRequest, ApiKey } from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; +import { + ListApiKeysRequest, + ListApiKeysResponse, + DeleteApiKeyRequest, + ApiKey, +} from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; @@ -13,7 +18,6 @@ import InternalStore from "../../stores/InternalStore"; import DeleteConfirm from "../../components/DeleteConfirm"; import Admin from "../../components/Admin"; - interface IProps { tenant: Tenant; isAdmin: boolean; @@ -23,13 +27,12 @@ interface IState { refreshKey: number; } - class ListTenantApiKeys extends Component { constructor(props: IProps) { super(props); this.state = { refreshKey: 1, - } + }; } columns = (): ColumnsType => { @@ -52,20 +55,16 @@ class ListTenantApiKeys extends Component { width: 100, render: (text, record) => ( - + - + + , ]} /> - + ); } diff --git a/ui/src/views/applications/ApplicationForm.tsx b/ui/src/views/applications/ApplicationForm.tsx index 4d52a9d3..b4eab948 100644 --- a/ui/src/views/applications/ApplicationForm.tsx +++ b/ui/src/views/applications/ApplicationForm.tsx @@ -3,7 +3,6 @@ import React, { Component } from "react"; import { Application } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import { Form, Input, Button } from "antd"; - interface IProps { initialValues: Application; onFinish: (obj: Application) => void; @@ -21,26 +20,21 @@ class ApplicationForm extends Component { app.setDescription(v.description); this.props.onFinish(app); - } + }; render() { - return( + return (
- + - + - + ); diff --git a/ui/src/views/applications/ApplicationLayout.tsx b/ui/src/views/applications/ApplicationLayout.tsx index 4c5d4d8d..1e9a2fa3 100644 --- a/ui/src/views/applications/ApplicationLayout.tsx +++ b/ui/src/views/applications/ApplicationLayout.tsx @@ -35,13 +35,11 @@ import CreateThingsBoardIntegration from "./integrations/CreateThingsBoardIntegr import EditThingsBoardIntegration from "./integrations/EditThingsBoardIntegration"; import GenerateMqttCertificate from "./integrations/GenerateMqttCertificate"; - interface IProps extends RouteComponentProps { tenant: Tenant; application: Application; } - class ApplicationLayout extends Component { deleteApplication = () => { let req = new DeleteApplicationRequest(); @@ -50,7 +48,7 @@ class ApplicationLayout extends Component { ApplicationStore.delete(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications`); }); - } + }; render() { const tenant = this.props.tenant; @@ -73,73 +71,180 @@ class ApplicationLayout extends Component { tab = "integrations"; } - const showIntegrations = SessionStore.isAdmin() || SessionStore.isTenantAdmin(tenant.getId()) || SessionStore.isTenantDeviceAdmin(tenant.getId()); + const showIntegrations = + SessionStore.isAdmin() || + SessionStore.isTenantAdmin(tenant.getId()) || + SessionStore.isTenantDeviceAdmin(tenant.getId()); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Applications + + Applications + {app.getName()} - } + + )} title={app.getName()} subTitle={`application id: ${app.getId()}`} extra={[ - - + + - + , ]} /> - - - Devices - Multicast groups - Application configuration - {showIntegrations && Integrations } - - - } /> - } /> - } /> - } /> + + + + Devices + + + + Multicast groups + + + + Application configuration + + {showIntegrations && ( + + Integrations + + )} + + + } /> + } + /> + } + /> + } + /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + + ); } diff --git a/ui/src/views/applications/ApplicationLoader.tsx b/ui/src/views/applications/ApplicationLoader.tsx index d481a5fe..c0630dab 100644 --- a/ui/src/views/applications/ApplicationLoader.tsx +++ b/ui/src/views/applications/ApplicationLoader.tsx @@ -2,7 +2,11 @@ import React, { Component } from "react"; import { Route, Switch, RouteComponentProps } from "react-router-dom"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; -import { Application, GetApplicationRequest, GetApplicationResponse } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { + Application, + GetApplicationRequest, + GetApplicationResponse, +} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationStore from "../../stores/ApplicationStore"; import ApplicationLayout from "./ApplicationLayout"; @@ -11,7 +15,6 @@ import DeviceLayout from "../devices/DeviceLayout"; import MulticastGroupLayout from "../multicast-groups/MulticastGroupLayout"; import CreateMulticastGroup from "../multicast-groups/CreateMulticastGroup"; - interface MatchParams { applicationId: string; } @@ -24,7 +27,6 @@ interface IState { application?: Application; } - class ApplicationLoader extends Component { constructor(props: IProps) { super(props); @@ -44,7 +46,7 @@ class ApplicationLoader extends Component { application: resp.getApplication(), }); }); - } + }; render() { const app = this.state.application; @@ -55,13 +57,26 @@ class ApplicationLoader extends Component { const path = this.props.match.path; const tenant = this.props.tenant; - - return( + return ( - } /> - } /> - } /> - } /> + } + /> + } + /> + } + /> + } + /> } /> ); diff --git a/ui/src/views/applications/CreateApplication.tsx b/ui/src/views/applications/CreateApplication.tsx index a400c032..e9dd0abc 100644 --- a/ui/src/views/applications/CreateApplication.tsx +++ b/ui/src/views/applications/CreateApplication.tsx @@ -4,17 +4,19 @@ import { Link, RouteComponentProps } from "react-router-dom"; import { Space, Breadcrumb, Card, PageHeader } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; -import { Application, CreateApplicationRequest, CreateApplicationResponse } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { + Application, + CreateApplicationRequest, + CreateApplicationResponse, +} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationForm from "./ApplicationForm"; import ApplicationStore from "../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { tenant: Tenant; } - class CreateApplication extends Component { onFinish = (obj: Application) => { obj.setTenantId(this.props.tenant.getId()); @@ -25,28 +27,34 @@ class CreateApplication extends Component { ApplicationStore.create(req, (resp: CreateApplicationResponse) => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${resp.getId()}`); }); - } + }; render() { const app = new Application(); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Applications + + Applications + Add - } + + )} title="Add application" /> diff --git a/ui/src/views/applications/EditApplication.tsx b/ui/src/views/applications/EditApplication.tsx index 5609b236..1f3dbf66 100644 --- a/ui/src/views/applications/EditApplication.tsx +++ b/ui/src/views/applications/EditApplication.tsx @@ -7,28 +7,30 @@ import ApplicationStore from "../../stores/ApplicationStore"; import ApplicationForm from "./ApplicationForm"; import SessionStore from "../../stores/SessionStore"; - interface IProps extends RouteComponentProps { - application: Application, + application: Application; } - class EditApplication extends Component { onFinish = (obj: Application) => { let req = new UpdateApplicationRequest(); req.setApplication(obj); ApplicationStore.update(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}`, + ); }); - } + }; render() { - const disabled = !(SessionStore.isAdmin() || SessionStore.isTenantAdmin(this.props.application.getTenantId()) || SessionStore.isTenantDeviceAdmin(this.props.application.getTenantId())); - - return( - + const disabled = !( + SessionStore.isAdmin() || + SessionStore.isTenantAdmin(this.props.application.getTenantId()) || + SessionStore.isTenantDeviceAdmin(this.props.application.getTenantId()) ); + + return ; } } diff --git a/ui/src/views/applications/ListApplications.tsx b/ui/src/views/applications/ListApplications.tsx index 2f67eeea..ca422b63 100644 --- a/ui/src/views/applications/ListApplications.tsx +++ b/ui/src/views/applications/ListApplications.tsx @@ -4,19 +4,21 @@ import { Link } from "react-router-dom"; import { Space, Breadcrumb, Button, PageHeader } from "antd"; import { ColumnsType } from "antd/es/table"; -import { ListApplicationsRequest, ListApplicationsResponse, ApplicationListItem } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { + ListApplicationsRequest, + ListApplicationsResponse, + ApplicationListItem, +} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import ApplicationStore from "../../stores/ApplicationStore"; import Admin from "../../components/Admin"; - interface IProps { tenant: Tenant; } - class ListApplications extends Component { columns = (): ColumnsType => { return [ @@ -35,7 +37,7 @@ class ListApplications extends Component { key: "description", }, ]; - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListApplicationsRequest(); @@ -47,35 +49,37 @@ class ListApplications extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } + }; render() { - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + Applications - } + + )} title="Applications" extra={[ - - + + , ]} /> - + ); } diff --git a/ui/src/views/applications/ListIntegrations.tsx b/ui/src/views/applications/ListIntegrations.tsx index f206183b..8b74f9d7 100644 --- a/ui/src/views/applications/ListIntegrations.tsx +++ b/ui/src/views/applications/ListIntegrations.tsx @@ -22,7 +22,6 @@ import PilotThingsCard from "./integrations/PilotThingsCard"; import LoRaCloudCard from "./integrations/LoRaCloudCard"; import ThingsBoardCard from "./integrations/ThingsBoardCard"; - interface IProps { application: Application; } @@ -32,7 +31,6 @@ interface IState { available: any[]; } - class ListIntegrations extends Component { constructor(props: IProps) { super(props); @@ -70,83 +68,82 @@ class ListIntegrations extends Component { }; // AWS SNS - if(includes(resp.getResultList(), IntegrationKind.AWS_SNS)) { + if (includes(resp.getResultList(), IntegrationKind.AWS_SNS)) { configured.push(); } else { available.push(); } // Azure Service-Bus - if(includes(resp.getResultList(), IntegrationKind.AZURE_SERVICE_BUS)) { + if (includes(resp.getResultList(), IntegrationKind.AZURE_SERVICE_BUS)) { configured.push(); } else { available.push(); } // GCP Pub/Sub - if(includes(resp.getResultList(), IntegrationKind.GCP_PUB_SUB)) { + if (includes(resp.getResultList(), IntegrationKind.GCP_PUB_SUB)) { configured.push(); } else { available.push(); } // HTTP - if(includes(resp.getResultList(), IntegrationKind.HTTP)) { + if (includes(resp.getResultList(), IntegrationKind.HTTP)) { configured.push(); } else { available.push(); } // InfluxDB - if(includes(resp.getResultList(), IntegrationKind.INFLUX_DB)) { + if (includes(resp.getResultList(), IntegrationKind.INFLUX_DB)) { configured.push(); } else { available.push(); } // MQTT - if(includes(resp.getResultList(), IntegrationKind.MQTT_GLOBAL)) { + if (includes(resp.getResultList(), IntegrationKind.MQTT_GLOBAL)) { configured.push(); } // myDevices - if(includes(resp.getResultList(), IntegrationKind.MY_DEVICES)) { + if (includes(resp.getResultList(), IntegrationKind.MY_DEVICES)) { configured.push(); } else { available.push(); } // Pilot Things - if(includes(resp.getResultList(), IntegrationKind.PILOT_THINGS)) { + if (includes(resp.getResultList(), IntegrationKind.PILOT_THINGS)) { configured.push(); } else { available.push(); } // Semtech LoRa Cloud - if(includes(resp.getResultList(), IntegrationKind.LORA_CLOUD)) { + if (includes(resp.getResultList(), IntegrationKind.LORA_CLOUD)) { configured.push(); } else { available.push(); } // ThingsBoard - if(includes(resp.getResultList(), IntegrationKind.THINGS_BOARD)) { + if (includes(resp.getResultList(), IntegrationKind.THINGS_BOARD)) { configured.push(); } else { available.push(); } - this.setState({ configured: configured, available: available, }); }); - } + }; render() { - return( + return ( {this.state.configured} {this.state.available} diff --git a/ui/src/views/applications/integrations/AwsSnsCard.tsx b/ui/src/views/applications/integrations/AwsSnsCard.tsx index bd5d3dc5..84e68c1a 100644 --- a/ui/src/views/applications/integrations/AwsSnsCard.tsx +++ b/ui/src/views/applications/integrations/AwsSnsCard.tsx @@ -1,45 +1,41 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; -import { - Application, - DeleteAwsSnsIntegrationRequest, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { Application, DeleteAwsSnsIntegrationRequest } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class AwsSns extends Component { onDelete = () => { let req = new DeleteAwsSnsIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deleteAwsSnsIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -50,12 +46,10 @@ class AwsSns extends Component { } + cover={AWS SNS} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/AwsSnsIntegrationForm.tsx b/ui/src/views/applications/integrations/AwsSnsIntegrationForm.tsx index a2781ca1..9e049344 100644 --- a/ui/src/views/applications/integrations/AwsSnsIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/AwsSnsIntegrationForm.tsx @@ -2,11 +2,7 @@ import React, { Component } from "react"; import { Form, Input, Button, Select } from "antd"; -import { - AwsSnsIntegration, - Encoding, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - +import { AwsSnsIntegration, Encoding } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; interface IProps { initialValues: AwsSnsIntegration; @@ -26,51 +22,49 @@ class AwsSnsIntegrationForm extends Component { i.setTopicArn(v.topicArn); this.props.onFinish(i); - } + }; render() { - return( -
+ return ( + - + - + ); diff --git a/ui/src/views/applications/integrations/AzureServiceBusCard.tsx b/ui/src/views/applications/integrations/AzureServiceBusCard.tsx index 4177262c..be4d30f7 100644 --- a/ui/src/views/applications/integrations/AzureServiceBusCard.tsx +++ b/ui/src/views/applications/integrations/AzureServiceBusCard.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; import { @@ -11,34 +11,33 @@ import { import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class AzureServiceBusCard extends Component { onDelete = () => { let req = new DeleteAzureServiceBusIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deleteAzureServiceBusIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -49,12 +48,10 @@ class AzureServiceBusCard extends Component { } + cover={Azure Service-Bus} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/AzureServiceBusIntegrationForm.tsx b/ui/src/views/applications/integrations/AzureServiceBusIntegrationForm.tsx index 6be727ff..aa0ccc99 100644 --- a/ui/src/views/applications/integrations/AzureServiceBusIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/AzureServiceBusIntegrationForm.tsx @@ -2,18 +2,13 @@ import React, { Component } from "react"; import { Form, Input, Button, Select } from "antd"; -import { - AzureServiceBusIntegration, - Encoding, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - +import { AzureServiceBusIntegration, Encoding } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; interface IProps { initialValues: AzureServiceBusIntegration; onFinish: (obj: AzureServiceBusIntegration) => void; } - class AzureServiceBusIntegrationForm extends Component { onFinish = (values: AzureServiceBusIntegration.AsObject) => { const v = Object.assign(this.props.initialValues.toObject(), values); @@ -25,15 +20,15 @@ class AzureServiceBusIntegrationForm extends Component { i.setPublishName(v.publishName); this.props.onFinish(i); - } + }; render() { - return( -
+ return ( + - + ); diff --git a/ui/src/views/applications/integrations/CreateAwsSnsIntegration.tsx b/ui/src/views/applications/integrations/CreateAwsSnsIntegration.tsx index abbb4d7f..f96ff64e 100644 --- a/ui/src/views/applications/integrations/CreateAwsSnsIntegration.tsx +++ b/ui/src/views/applications/integrations/CreateAwsSnsIntegration.tsx @@ -24,14 +24,16 @@ class CreateAwsSnsIntegration extends Component { req.setIntegration(obj); ApplicationStore.createAwsSnsIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { const i = new AwsSnsIntegration(); - return( + return ( diff --git a/ui/src/views/applications/integrations/CreateAzureServiceBusIntegration.tsx b/ui/src/views/applications/integrations/CreateAzureServiceBusIntegration.tsx index bb4aa279..4e7e38af 100644 --- a/ui/src/views/applications/integrations/CreateAzureServiceBusIntegration.tsx +++ b/ui/src/views/applications/integrations/CreateAzureServiceBusIntegration.tsx @@ -12,12 +12,10 @@ import { import AzureServiceBusIntegrationForm from "./AzureServiceBusIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - class CreateAzureServiceBusIntegration extends Component { onFinish = (obj: AzureServiceBusIntegration) => { obj.setApplicationId(this.props.application.getId()); @@ -26,14 +24,16 @@ class CreateAzureServiceBusIntegration extends Component { req.setIntegration(obj); ApplicationStore.createAzureServiceBusIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { const i = new AzureServiceBusIntegration(); - return( + return ( diff --git a/ui/src/views/applications/integrations/CreateGcpPubSubIntegration.tsx b/ui/src/views/applications/integrations/CreateGcpPubSubIntegration.tsx index 2a49341b..8c513065 100644 --- a/ui/src/views/applications/integrations/CreateGcpPubSubIntegration.tsx +++ b/ui/src/views/applications/integrations/CreateGcpPubSubIntegration.tsx @@ -12,12 +12,10 @@ import { import GcpPubSubIntegrationForm from "./GcpPubSubIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - class CreateGcpPubSubIntegration extends Component { onFinish = (obj: GcpPubSubIntegration) => { obj.setApplicationId(this.props.application.getId()); @@ -26,14 +24,16 @@ class CreateGcpPubSubIntegration extends Component { req.setIntegration(obj); ApplicationStore.createGcpPubSubIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { const i = new GcpPubSubIntegration(); - return( + return ( diff --git a/ui/src/views/applications/integrations/CreateHttpIntegration.tsx b/ui/src/views/applications/integrations/CreateHttpIntegration.tsx index 4e0a81e8..ffabf643 100644 --- a/ui/src/views/applications/integrations/CreateHttpIntegration.tsx +++ b/ui/src/views/applications/integrations/CreateHttpIntegration.tsx @@ -12,7 +12,6 @@ import { import HttpIntegrationForm from "./HttpIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } @@ -25,14 +24,16 @@ class CreateHttpIntegration extends Component { req.setIntegration(obj); ApplicationStore.createHttpIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { const i = new HttpIntegration(); - return( + return ( diff --git a/ui/src/views/applications/integrations/CreateInfluxDbIntegration.tsx b/ui/src/views/applications/integrations/CreateInfluxDbIntegration.tsx index 3b93c5f8..3470c663 100644 --- a/ui/src/views/applications/integrations/CreateInfluxDbIntegration.tsx +++ b/ui/src/views/applications/integrations/CreateInfluxDbIntegration.tsx @@ -12,12 +12,10 @@ import { import InfluxDbIntegrationForm from "./InfluxDbIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - class CreateInfluxDbIntegration extends Component { onFinish = (obj: InfluxDbIntegration) => { obj.setApplicationId(this.props.application.getId()); @@ -26,14 +24,16 @@ class CreateInfluxDbIntegration extends Component { req.setIntegration(obj); ApplicationStore.createInfluxDbIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { const i = new InfluxDbIntegration(); - return( + return ( diff --git a/ui/src/views/applications/integrations/CreateLoRaCloudIntegration.tsx b/ui/src/views/applications/integrations/CreateLoRaCloudIntegration.tsx index c4af6656..10516e51 100644 --- a/ui/src/views/applications/integrations/CreateLoRaCloudIntegration.tsx +++ b/ui/src/views/applications/integrations/CreateLoRaCloudIntegration.tsx @@ -10,16 +10,13 @@ import { CreateLoraCloudIntegrationRequest, } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - import LoRaCloudIntegrationForm from "./LoRaCloudIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - class CreateLoRaCloudIntegration extends Component { onFinish = (obj: LoraCloudIntegration) => { obj.setApplicationId(this.props.application.getId()); @@ -28,9 +25,11 @@ class CreateLoRaCloudIntegration extends Component { req.setIntegration(obj); ApplicationStore.createLoraCloudIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { let i = new LoraCloudIntegration(); @@ -41,8 +40,7 @@ class CreateLoRaCloudIntegration extends Component { i.setModemGeolocationServices(mgs); - - return( + return ( diff --git a/ui/src/views/applications/integrations/CreateMyDevicesIntegration.tsx b/ui/src/views/applications/integrations/CreateMyDevicesIntegration.tsx index 6e80f4eb..e91ae81b 100644 --- a/ui/src/views/applications/integrations/CreateMyDevicesIntegration.tsx +++ b/ui/src/views/applications/integrations/CreateMyDevicesIntegration.tsx @@ -12,12 +12,10 @@ import { import MyDevicesIntegrationForm from "./MyDevicesIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - class CreateMyDevicesIntegration extends Component { onFinish = (obj: MyDevicesIntegration) => { obj.setApplicationId(this.props.application.getId()); @@ -26,14 +24,16 @@ class CreateMyDevicesIntegration extends Component { req.setIntegration(obj); ApplicationStore.createMyDevicesIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { const i = new MyDevicesIntegration(); - return( + return ( diff --git a/ui/src/views/applications/integrations/CreatePilotThingsIntegration.tsx b/ui/src/views/applications/integrations/CreatePilotThingsIntegration.tsx index d6629952..989d5e0c 100644 --- a/ui/src/views/applications/integrations/CreatePilotThingsIntegration.tsx +++ b/ui/src/views/applications/integrations/CreatePilotThingsIntegration.tsx @@ -12,12 +12,10 @@ import { import PilotThingsIntegrationForm from "./PilotThingsIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - class CreatePilotThingsIntegration extends Component { onFinish = (obj: PilotThingsIntegration) => { obj.setApplicationId(this.props.application.getId()); @@ -26,14 +24,16 @@ class CreatePilotThingsIntegration extends Component { req.setIntegration(obj); ApplicationStore.createPilotThingsIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { const i = new PilotThingsIntegration(); - return( + return ( diff --git a/ui/src/views/applications/integrations/CreateThingsBoardIntegration.tsx b/ui/src/views/applications/integrations/CreateThingsBoardIntegration.tsx index 4f4a6d3e..a4fcabe9 100644 --- a/ui/src/views/applications/integrations/CreateThingsBoardIntegration.tsx +++ b/ui/src/views/applications/integrations/CreateThingsBoardIntegration.tsx @@ -12,12 +12,10 @@ import { import ThingsBoardIntegrationForm from "./ThingsBoardIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - class CreateThingsBoardIntegration extends Component { onFinish = (obj: ThingsBoardIntegration) => { obj.setApplicationId(this.props.application.getId()); @@ -26,14 +24,16 @@ class CreateThingsBoardIntegration extends Component { req.setIntegration(obj); ApplicationStore.createThingsBoardIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { const i = new ThingsBoardIntegration(); - return( + return ( diff --git a/ui/src/views/applications/integrations/EditAwsSnsIntegration.tsx b/ui/src/views/applications/integrations/EditAwsSnsIntegration.tsx index 842a7182..d616cfc6 100644 --- a/ui/src/views/applications/integrations/EditAwsSnsIntegration.tsx +++ b/ui/src/views/applications/integrations/EditAwsSnsIntegration.tsx @@ -22,7 +22,6 @@ interface IState { integration?: AwsSnsIntegration; } - class EditAwsSnsIntegration extends Component { constructor(props: IProps) { super(props); @@ -45,16 +44,18 @@ class EditAwsSnsIntegration extends Component { req.setIntegration(obj); ApplicationStore.updateAwsSnsIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { if (this.state.integration === undefined) { return null; } - return( + return ( diff --git a/ui/src/views/applications/integrations/EditAzureServiceBusIntegration.tsx b/ui/src/views/applications/integrations/EditAzureServiceBusIntegration.tsx index 4ba02c1a..4b40cf24 100644 --- a/ui/src/views/applications/integrations/EditAzureServiceBusIntegration.tsx +++ b/ui/src/views/applications/integrations/EditAzureServiceBusIntegration.tsx @@ -14,17 +14,14 @@ import { import AzureServiceBusIntegrationForm from "./AzureServiceBusIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - interface IState { integration?: AzureServiceBusIntegration; } - class EditAzureServiceBusIntegration extends Component { constructor(props: IProps) { super(props); @@ -47,16 +44,18 @@ class EditAzureServiceBusIntegration extends Component { req.setIntegration(obj); ApplicationStore.updateAzureServiceBusIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { if (this.state.integration === undefined) { return null; } - return( + return ( diff --git a/ui/src/views/applications/integrations/EditGcpPubSubIntegration.tsx b/ui/src/views/applications/integrations/EditGcpPubSubIntegration.tsx index f75f82fb..4f316866 100644 --- a/ui/src/views/applications/integrations/EditGcpPubSubIntegration.tsx +++ b/ui/src/views/applications/integrations/EditGcpPubSubIntegration.tsx @@ -14,23 +14,20 @@ import { import GcpPubSubIntegrationForm from "./GcpPubSubIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - interface IState { integration?: GcpPubSubIntegration; } - class EditGcpPubSubIntegration extends Component { constructor(props: IProps) { super(props); this.state = {}; } - + componentDidMount() { let req = new GetGcpPubSubIntegrationRequest(); req.setApplicationId(this.props.application.getId()); @@ -47,19 +44,21 @@ class EditGcpPubSubIntegration extends Component { req.setIntegration(obj); ApplicationStore.updateGcpPubSubIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { if (this.state.integration === undefined) { return null; } - return( - - - + return ( + + + ); } } diff --git a/ui/src/views/applications/integrations/EditHttpIntegration.tsx b/ui/src/views/applications/integrations/EditHttpIntegration.tsx index 2f1eff90..2ff58391 100644 --- a/ui/src/views/applications/integrations/EditHttpIntegration.tsx +++ b/ui/src/views/applications/integrations/EditHttpIntegration.tsx @@ -14,7 +14,6 @@ import { import HttpIntegrationForm from "./HttpIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } @@ -45,16 +44,18 @@ class EditHttpIntegration extends Component { req.setIntegration(obj); ApplicationStore.updateHttpIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { if (this.state.integration === undefined) { return null; } - return( + return ( diff --git a/ui/src/views/applications/integrations/EditInfluxDbIntegration.tsx b/ui/src/views/applications/integrations/EditInfluxDbIntegration.tsx index dd84faea..004ae9c5 100644 --- a/ui/src/views/applications/integrations/EditInfluxDbIntegration.tsx +++ b/ui/src/views/applications/integrations/EditInfluxDbIntegration.tsx @@ -14,17 +14,14 @@ import { import InfluxDbIntegrationForm from "./InfluxDbIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - interface IState { integration?: InfluxDbIntegration; } - class EditInfluxDbIntegration extends Component { constructor(props: IProps) { super(props); @@ -47,17 +44,18 @@ class EditInfluxDbIntegration extends Component { req.setIntegration(obj); ApplicationStore.updateInfluxDbIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - - } + }; render() { if (this.state.integration === undefined) { return null; } - return( + return ( diff --git a/ui/src/views/applications/integrations/EditLoRaCloudIntegration.tsx b/ui/src/views/applications/integrations/EditLoRaCloudIntegration.tsx index b764401e..56b8c174 100644 --- a/ui/src/views/applications/integrations/EditLoRaCloudIntegration.tsx +++ b/ui/src/views/applications/integrations/EditLoRaCloudIntegration.tsx @@ -14,17 +14,14 @@ import { import LoRaCloudIntegrationForm from "./LoRaCloudIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - interface IState { integration?: LoraCloudIntegration; } - class EditLoRaCloudIntegration extends Component { constructor(props: IProps) { super(props); @@ -47,16 +44,18 @@ class EditLoRaCloudIntegration extends Component { req.setIntegration(obj); ApplicationStore.updateLoraCloudIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { if (this.state.integration === undefined) { return null; } - return( + return ( diff --git a/ui/src/views/applications/integrations/EditMyDevicesIntegration.tsx b/ui/src/views/applications/integrations/EditMyDevicesIntegration.tsx index 645176f5..e78b77b1 100644 --- a/ui/src/views/applications/integrations/EditMyDevicesIntegration.tsx +++ b/ui/src/views/applications/integrations/EditMyDevicesIntegration.tsx @@ -14,7 +14,6 @@ import { import MyDevicesIntegrationForm from "./MyDevicesIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } @@ -23,7 +22,6 @@ interface IState { integration?: MyDevicesIntegration; } - class EditMyDevicesIntegration extends Component { constructor(props: IProps) { super(props); @@ -46,16 +44,18 @@ class EditMyDevicesIntegration extends Component { req.setIntegration(obj); ApplicationStore.updateMyDevicesIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { if (this.state.integration === undefined) { return null; } - return( + return ( diff --git a/ui/src/views/applications/integrations/EditPilotThingsIntegration.tsx b/ui/src/views/applications/integrations/EditPilotThingsIntegration.tsx index f13c0730..40dd6da3 100644 --- a/ui/src/views/applications/integrations/EditPilotThingsIntegration.tsx +++ b/ui/src/views/applications/integrations/EditPilotThingsIntegration.tsx @@ -14,17 +14,14 @@ import { import PilotThingsIntegrationForm from "./PilotThingsIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } - interface IState { integration?: PilotThingsIntegration; } - class EditPilotThingsIntegration extends Component { constructor(props: IProps) { super(props); @@ -47,16 +44,18 @@ class EditPilotThingsIntegration extends Component { req.setIntegration(obj); ApplicationStore.updatePilotThingsIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { if (this.state.integration === undefined) { return null; } - return( + return ( diff --git a/ui/src/views/applications/integrations/EditThingsBoardIntegration.tsx b/ui/src/views/applications/integrations/EditThingsBoardIntegration.tsx index 06588845..71b46359 100644 --- a/ui/src/views/applications/integrations/EditThingsBoardIntegration.tsx +++ b/ui/src/views/applications/integrations/EditThingsBoardIntegration.tsx @@ -14,7 +14,6 @@ import { import ThingsBoardIntegrationForm from "./ThingsBoardIntegrationForm"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps extends RouteComponentProps { application: Application; } @@ -23,7 +22,6 @@ interface IState { integration?: ThingsBoardIntegration; } - class EditThingsBoardIntegration extends Component { constructor(props: IProps) { super(props); @@ -46,16 +44,18 @@ class EditThingsBoardIntegration extends Component { req.setIntegration(obj); ApplicationStore.updateThingsBoardIntegration(req, () => { - this.props.history.push(`/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`); + this.props.history.push( + `/tenants/${this.props.application.getTenantId()}/applications/${this.props.application.getId()}/integrations`, + ); }); - } + }; render() { if (this.state.integration === undefined) { return null; } - return( + return ( diff --git a/ui/src/views/applications/integrations/GcpPubSubCard.tsx b/ui/src/views/applications/integrations/GcpPubSubCard.tsx index b24fd365..dfb65030 100644 --- a/ui/src/views/applications/integrations/GcpPubSubCard.tsx +++ b/ui/src/views/applications/integrations/GcpPubSubCard.tsx @@ -1,44 +1,40 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; -import { - Application, - DeleteGcpPubSubIntegrationRequest, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { Application, DeleteGcpPubSubIntegrationRequest } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class GcpPubSubCard extends Component { onDelete = () => { let req = new DeleteGcpPubSubIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deleteGcpPubSubIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -49,12 +45,10 @@ class GcpPubSubCard extends Component { } + cover={GCP Pub/Sub} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/GcpPubSubIntegrationForm.tsx b/ui/src/views/applications/integrations/GcpPubSubIntegrationForm.tsx index 9ba97313..7e8ffcaf 100644 --- a/ui/src/views/applications/integrations/GcpPubSubIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/GcpPubSubIntegrationForm.tsx @@ -2,18 +2,13 @@ import React, { Component } from "react"; import { Form, Input, Button, Select } from "antd"; -import { - GcpPubSubIntegration, - Encoding, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - +import { GcpPubSubIntegration, Encoding } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; interface IProps { initialValues: GcpPubSubIntegration; onFinish: (obj: GcpPubSubIntegration) => void; } - class GcpPubSubIntegrationForm extends Component { onFinish = (values: GcpPubSubIntegration.AsObject) => { const v = Object.assign(this.props.initialValues.toObject(), values); @@ -26,15 +21,15 @@ class GcpPubSubIntegrationForm extends Component { i.setCredentialsFile(v.credentialsFile); this.props.onFinish(i); - } + }; render() { - return( -
+ return ( + @@ -59,12 +54,14 @@ class GcpPubSubIntegrationForm extends Component { label="GCP Service account credentials file" name="credentialsFile" tooltip="Under IAM create a Service account with 'Pub/Sub Publisher' role, then put the content of the JSON key in this field." - rules={[{required: true, message: "Please enter a GCP Service account credentials file!"}]} + rules={[{ required: true, message: "Please enter a GCP Service account credentials file!" }]} >
- + ); diff --git a/ui/src/views/applications/integrations/GenerateMqttCertificate.tsx b/ui/src/views/applications/integrations/GenerateMqttCertificate.tsx index 40ed7eb5..13a32693 100644 --- a/ui/src/views/applications/integrations/GenerateMqttCertificate.tsx +++ b/ui/src/views/applications/integrations/GenerateMqttCertificate.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import moment from "moment"; -import { Card, Button, Form, Input } from 'antd'; +import { Card, Button, Form, Input } from "antd"; import { Application, @@ -11,18 +11,15 @@ import { import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { application: Application; } - interface IState { certificate?: GenerateMqttIntegrationClientCertificateResponse; buttonDisabled: boolean; } - class GenerateMqttCertificate extends Component { constructor(props: IProps) { super(props); @@ -40,28 +37,35 @@ class GenerateMqttCertificate extends Component { let req = new GenerateMqttIntegrationClientCertificateRequest(); req.setApplicationId(this.props.application.getId()); - ApplicationStore.generateMqttIntegrationClientCertificate(req, (resp: GenerateMqttIntegrationClientCertificateResponse) => { - this.setState({ - certificate: resp, - }); - }); - } + ApplicationStore.generateMqttIntegrationClientCertificate( + req, + (resp: GenerateMqttIntegrationClientCertificateResponse) => { + this.setState({ + certificate: resp, + }); + }, + ); + }; renderRequest = () => { - return( + return (

- If required by the network, the MQTT client needs to be configured with a client certificate - in order to connect to the MQTT broker to receive device data. The generated certificate is - application specific. - Please note the expiration of the certificate and make sure to renew the certificate on time! + If required by the network, the MQTT client needs to be configured with a client certificate in order to + connect to the MQTT broker to receive device data. The generated certificate is application specific. + + {" "} + Please note the expiration of the certificate and make sure to renew the certificate on time! +

- +

); - } + }; renderResponse = () => { const certificate = this.state.certificate!; @@ -73,52 +77,40 @@ class GenerateMqttCertificate extends Component { tlsKey: certificate.getTlsKey(), }; - return( + return (
- + - + - - + + - - + + ); - } + }; render() { let content = this.renderRequest(); if (this.state.certificate !== undefined) { content = this.renderResponse(); - } + } - return( - - {content} - - ); + return {content}; } } diff --git a/ui/src/views/applications/integrations/HttpCard.tsx b/ui/src/views/applications/integrations/HttpCard.tsx index 386457bd..e78ee6b2 100644 --- a/ui/src/views/applications/integrations/HttpCard.tsx +++ b/ui/src/views/applications/integrations/HttpCard.tsx @@ -1,44 +1,40 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; -import { - Application, - DeleteHttpIntegrationRequest, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { Application, DeleteHttpIntegrationRequest } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class HttpCard extends Component { onDelete = () => { let req = new DeleteHttpIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deleteHttpIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -49,12 +45,10 @@ class HttpCard extends Component { } + cover={HTTP} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/HttpIntegrationForm.tsx b/ui/src/views/applications/integrations/HttpIntegrationForm.tsx index 6ce3c700..24a5af9d 100644 --- a/ui/src/views/applications/integrations/HttpIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/HttpIntegrationForm.tsx @@ -1,13 +1,9 @@ import React, { Component } from "react"; import { Form, Input, Button, Select, Row, Col, Typography, Space } from "antd"; -import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; - -import { - HttpIntegration, - Encoding, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons"; +import { HttpIntegration, Encoding } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; interface IProps { initialValues: HttpIntegration; @@ -29,15 +25,15 @@ class HttpIntegrationForm extends Component { } this.props.onFinish(i); - } + }; render() { - return( -
+ return ( + - + Headers - {(fields, { add, remove }) => ( + {(fields, { add, remove }) => ( <> {fields.map(( {key, name, ...restField} ) => ( @@ -64,7 +60,7 @@ class HttpIntegrationForm extends Component { {...restField} name={[name, 0]} fieldKey={[name, 0]} - rules={[{ required: true, message: 'Please enter a key!' }]} + rules={[{ required: true, message: "Please enter a key!" }]} >
@@ -74,14 +70,14 @@ class HttpIntegrationForm extends Component { {...restField} name={[name, 1]} fieldKey={[name, 1]} - rules={[{ required: true, message: 'Please enter a value!' }]} + rules={[{ required: true, message: "Please enter a value!" }]} >
-
- remove(name)} /> - + + remove(name)} /> + ))} @@ -94,7 +90,9 @@ class HttpIntegrationForm extends Component { - + ); diff --git a/ui/src/views/applications/integrations/InfluxDbIntegrationForm.tsx b/ui/src/views/applications/integrations/InfluxDbIntegrationForm.tsx index f8160488..91eef013 100644 --- a/ui/src/views/applications/integrations/InfluxDbIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/InfluxDbIntegrationForm.tsx @@ -8,18 +8,15 @@ import { InfluxDbVersion, } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - interface IProps { initialValues: InfluxDbIntegration; onFinish: (obj: InfluxDbIntegration) => void; } - interface IState { selectedVersion: InfluxDbVersion; } - class InfluxDbIntegrationForm extends Component { constructor(props: IProps) { super(props); @@ -45,21 +42,21 @@ class InfluxDbIntegrationForm extends Component { i.setToken(v.token); this.props.onFinish(i); - } + }; onVersionChange = (version: InfluxDbVersion) => { this.setState({ selectedVersion: version, }); - } + }; render() { - return( -
+ return ( + + - {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && - - } - {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && - - } - {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && - - } - {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && - - } - {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && - - } - {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_2 && - - } - {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_2 && - - } - {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_2 && - - } + {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && ( + + + + )} + {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && ( + + + + )} + {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && ( + + + + )} + {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && ( + + + + )} + {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_1 && ( + + + + )} + {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_2 && ( + + + + )} + {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_2 && ( + + + + )} + {this.state.selectedVersion === InfluxDbVersion.INFLUXDB_2 && ( + + + + )} - + ); diff --git a/ui/src/views/applications/integrations/InfluxdbCard.tsx b/ui/src/views/applications/integrations/InfluxdbCard.tsx index 780c16fa..088605f9 100644 --- a/ui/src/views/applications/integrations/InfluxdbCard.tsx +++ b/ui/src/views/applications/integrations/InfluxdbCard.tsx @@ -1,44 +1,40 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; -import { - Application, - DeleteInfluxDbIntegrationRequest, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { Application, DeleteInfluxDbIntegrationRequest } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class InfluxdbCard extends Component { onDelete = () => { let req = new DeleteInfluxDbIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deleteInfluxDbIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -49,12 +45,10 @@ class InfluxdbCard extends Component { } + cover={InfluxDB} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/LoRaCloudCard.tsx b/ui/src/views/applications/integrations/LoRaCloudCard.tsx index 5cb047cb..53ee0496 100644 --- a/ui/src/views/applications/integrations/LoRaCloudCard.tsx +++ b/ui/src/views/applications/integrations/LoRaCloudCard.tsx @@ -1,44 +1,40 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; -import { - Application, - DeleteLoraCloudIntegrationRequest, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { Application, DeleteLoraCloudIntegrationRequest } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class LoRaCloudCard extends Component { onDelete = () => { let req = new DeleteLoraCloudIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deleteLoraCloudIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -49,12 +45,10 @@ class LoRaCloudCard extends Component { } + cover={Semtech LoRa Cloud} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/LoRaCloudIntegrationForm.tsx b/ui/src/views/applications/integrations/LoRaCloudIntegrationForm.tsx index 9beebe82..42b331a1 100644 --- a/ui/src/views/applications/integrations/LoRaCloudIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/LoRaCloudIntegrationForm.tsx @@ -7,13 +7,11 @@ import { LoraCloudModemGeolocationServices, } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - interface IProps { initialValues: LoraCloudIntegration; onFinish: (obj: LoraCloudIntegration) => void; } - interface IState { modemEnabled: boolean; geolocationTdoa: boolean; @@ -22,7 +20,6 @@ interface IState { geolocationGnss: boolean; } - class LoRaCloudIntegrationForm extends Component { constructor(props: IProps) { super(props); @@ -56,7 +53,6 @@ class LoRaCloudIntegrationForm extends Component { let mgs = new LoraCloudModemGeolocationServices(); - if (mgsv !== undefined) { mgs.setToken(mgsv.token); mgs.setModemEnabled(mgsv.modemEnabled); @@ -80,48 +76,48 @@ class LoRaCloudIntegrationForm extends Component { i.setModemGeolocationServices(mgs); this.props.onFinish(i); - } + }; onModemEnabledChange = (v: boolean) => { this.setState({ modemEnabled: v, }); - } + }; onGeolocationTdoaChange = (v: boolean) => { this.setState({ geolocationTdoa: v, }); - } + }; onGeolocationRssiChange = (v: boolean) => { this.setState({ geolocationRssi: v, }); - } + }; onGeolocationWifiChange = (v: boolean) => { this.setState({ geolocationWifi: v, }); - } + }; onGeolocationGnssChange = (v: boolean) => { this.setState({ geolocationGnss: v, }); - } + }; render() { - return( -
+ return ( + @@ -132,39 +128,47 @@ class LoRaCloudIntegrationForm extends Component { >
- {this.state.modemEnabled && - - } - {this.state.modemEnabled && - - } - {this.state.modemEnabled && - - } - {this.state.modemEnabled && - - } - + {this.state.modemEnabled && ( + + + + )} + {this.state.modemEnabled && ( + + + + )} + {this.state.modemEnabled && ( + + + + )} + {this.state.modemEnabled && ( + + + + )} + { > - {(this.state.geolocationTdoa || this.state.geolocationRssi) && - - } - {(this.state.geolocationTdoa || this.state.geolocationRssi) && - - } - {this.state.geolocationWifi && - - } - {this.state.geolocationGnss && - - } - {this.state.geolocationGnss && - - } + {(this.state.geolocationTdoa || this.state.geolocationRssi) && ( + + + + )} + {(this.state.geolocationTdoa || this.state.geolocationRssi) && ( + + + + )} + {this.state.geolocationWifi && ( + + + + )} + {this.state.geolocationGnss && ( + + + + )} + {this.state.geolocationGnss && ( + + + + )} - + ); diff --git a/ui/src/views/applications/integrations/MqttCard.tsx b/ui/src/views/applications/integrations/MqttCard.tsx index d64d4254..ec6d0c62 100644 --- a/ui/src/views/applications/integrations/MqttCard.tsx +++ b/ui/src/views/applications/integrations/MqttCard.tsx @@ -1,35 +1,27 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card } from 'antd'; - -import { - Application, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { Col, Card } from "antd"; +import { Application } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; interface IProps { - application: Application, + application: Application; } - class HttpCard extends Component { render() { - let actions: any[] = [ - Get certificate - ]; + let actions: any[] = [Get certificate]; return (
} + cover={MQTT} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/MyDevicesCard.tsx b/ui/src/views/applications/integrations/MyDevicesCard.tsx index f34fdd68..9102dc67 100644 --- a/ui/src/views/applications/integrations/MyDevicesCard.tsx +++ b/ui/src/views/applications/integrations/MyDevicesCard.tsx @@ -1,44 +1,40 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; -import { - Application, - DeleteMyDevicesIntegrationRequest, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; +import { Application, DeleteMyDevicesIntegrationRequest } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class MyDevicesCard extends Component { onDelete = () => { let req = new DeleteMyDevicesIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deleteMyDevicesIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -49,12 +45,10 @@ class MyDevicesCard extends Component { } + cover={myDevices} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/MyDevicesIntegrationForm.tsx b/ui/src/views/applications/integrations/MyDevicesIntegrationForm.tsx index 5f53204c..99c46a98 100644 --- a/ui/src/views/applications/integrations/MyDevicesIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/MyDevicesIntegrationForm.tsx @@ -2,23 +2,18 @@ import React, { Component } from "react"; import { Form, Input, Button, Select } from "antd"; -import { - MyDevicesIntegration, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - +import { MyDevicesIntegration } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; interface IProps { initialValues: MyDevicesIntegration; onFinish: (obj: MyDevicesIntegration) => void; } - interface IState { selectedEndpoint: string; customEndpoint: string; } - class MyDevicesIntegrationForm extends Component { constructor(props: IProps) { super(props); @@ -40,43 +35,49 @@ class MyDevicesIntegrationForm extends Component { } this.props.onFinish(i); - } + }; onEndpointChange = (v: string) => { this.setState({ selectedEndpoint: v, }); - } + }; onCustomEndpointChange = (e: React.ChangeEvent) => { this.setState({ customEndpoint: e.target.value, }); - } + }; render() { - return( -
+ return ( + - {this.state.selectedEndpoint === "custom" && - - } + {this.state.selectedEndpoint === "custom" && ( + + + + )} - + ); diff --git a/ui/src/views/applications/integrations/PilotThingsCard.tsx b/ui/src/views/applications/integrations/PilotThingsCard.tsx index 927f85cc..ba0fd694 100644 --- a/ui/src/views/applications/integrations/PilotThingsCard.tsx +++ b/ui/src/views/applications/integrations/PilotThingsCard.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; import { @@ -11,34 +11,33 @@ import { import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class PilotThingsCard extends Component { onDelete = () => { let req = new DeletePilotThingsIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deletePilotThingsIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -49,12 +48,10 @@ class PilotThingsCard extends Component { } + cover={Pilot Things} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/PilotThingsIntegrationForm.tsx b/ui/src/views/applications/integrations/PilotThingsIntegrationForm.tsx index e8825e9e..5550a459 100644 --- a/ui/src/views/applications/integrations/PilotThingsIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/PilotThingsIntegrationForm.tsx @@ -2,18 +2,13 @@ import React, { Component } from "react"; import { Form, Input, Button } from "antd"; -import { - PilotThingsIntegration, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - - +import { PilotThingsIntegration } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; interface IProps { initialValues: PilotThingsIntegration; onFinish: (obj: PilotThingsIntegration) => void; } - class PilotThingsIntegrationForm extends Component { onFinish = (values: PilotThingsIntegration.AsObject) => { const v = Object.assign(this.props.initialValues.toObject(), values); @@ -24,27 +19,29 @@ class PilotThingsIntegrationForm extends Component { i.setToken(v.token); this.props.onFinish(i); - } + }; render() { - return( -
+ return ( + - + ); diff --git a/ui/src/views/applications/integrations/ThingsBoardCard.tsx b/ui/src/views/applications/integrations/ThingsBoardCard.tsx index 277d5728..aac2f41a 100644 --- a/ui/src/views/applications/integrations/ThingsBoardCard.tsx +++ b/ui/src/views/applications/integrations/ThingsBoardCard.tsx @@ -1,44 +1,43 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Col, Card, Popconfirm } from 'antd'; +import { Col, Card, Popconfirm } from "antd"; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons"; import { Application, - DeleteThingsBoardIntegrationRequest + DeleteThingsBoardIntegrationRequest, } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import ApplicationStore from "../../../stores/ApplicationStore"; - interface IProps { - application: Application, + application: Application; add?: boolean; } - class ThingsBoardCard extends Component { onDelete = () => { let req = new DeleteThingsBoardIntegrationRequest(); req.setApplicationId(this.props.application.getId()); ApplicationStore.deleteThingsBoardIntegration(req, () => {}); - } + }; render() { let actions: any[] = []; if (!!this.props.add) { actions = [ - + + + , ]; } else { actions = [ - , - + + + , + , ]; @@ -49,12 +48,10 @@ class ThingsBoardCard extends Component { } + cover={ThingsBoard} actions={actions} > - + ); diff --git a/ui/src/views/applications/integrations/ThingsBoardIntegrationForm.tsx b/ui/src/views/applications/integrations/ThingsBoardIntegrationForm.tsx index 777d77f4..90018644 100644 --- a/ui/src/views/applications/integrations/ThingsBoardIntegrationForm.tsx +++ b/ui/src/views/applications/integrations/ThingsBoardIntegrationForm.tsx @@ -2,17 +2,13 @@ import React, { Component } from "react"; import { Form, Input, Button, Typography } from "antd"; -import { - ThingsBoardIntegration, -} from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; - +import { ThingsBoardIntegration } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; interface IProps { initialValues: ThingsBoardIntegration; onFinish: (obj: ThingsBoardIntegration) => void; } - class ThingsBoardIntegrationForm extends Component { onFinish = (values: ThingsBoardIntegration.AsObject) => { const v = Object.assign(this.props.initialValues.toObject(), values); @@ -22,25 +18,28 @@ class ThingsBoardIntegrationForm extends Component { i.setServer(v.server); this.props.onFinish(i); - } + }; render() { - return( -
+ return ( + - Each device must have a 'ThingsBoardAccessToken' variable assigned. This access-token is generated by ThingsBoard. + Each device must have a 'ThingsBoardAccessToken' variable assigned. This access-token is generated by + ThingsBoard. - + ); diff --git a/ui/src/views/dashboard/Dashboard.tsx b/ui/src/views/dashboard/Dashboard.tsx index fafa1266..fb14efec 100644 --- a/ui/src/views/dashboard/Dashboard.tsx +++ b/ui/src/views/dashboard/Dashboard.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { presetPalettes } from '@ant-design/colors'; +import { presetPalettes } from "@ant-design/colors"; import { Space, Breadcrumb, Card, Row, Col, PageHeader, Empty } from "antd"; import moment from "moment"; @@ -30,7 +30,7 @@ interface GatewaysMapState { items: GatewayListItem[]; } -class GatewaysMap extends Component<{},GatewaysMapState> { +class GatewaysMap extends Component<{}, GatewaysMapState> { constructor(props: {}) { super(props); @@ -51,17 +51,15 @@ class GatewaysMap extends Component<{},GatewaysMapState> { items: resp.getResultList(), }); }); - } + }; render() { if (this.state.items.length === 0) { - return( - - ); + return ; } const boundsOptions: { - padding: PointTuple, + padding: PointTuple; } = { padding: [50, 50], }; @@ -79,7 +77,7 @@ class GatewaysMap extends Component<{},GatewaysMapState> { if (item.getLastSeenAt() !== undefined) { let ts = moment(item.getLastSeenAt()!.toDate()); lastSeen = ts.fromNow(); - if (ts.isBefore(moment().subtract(5, 'minutes'))) { + if (ts.isBefore(moment().subtract(5, "minutes"))) { color = "red"; } else { color = "green"; @@ -89,15 +87,18 @@ class GatewaysMap extends Component<{},GatewaysMapState> { markers.push( - {item.getName()}
- {item.getGatewayId()}

+ {item.getName()} +
+ {item.getGatewayId()} +
+
{lastSeen}
-
+ , ); } - return( + return ( {markers} @@ -105,18 +106,18 @@ class GatewaysMap extends Component<{},GatewaysMapState> { } } - interface GatewayProps { summary?: GetGatewaysSummaryResponse; } class GatewaysActiveInactive extends Component { render() { - if (this.props.summary === undefined || ( - this.props.summary.getNeverSeenCount() === 0 && - this.props.summary.getInactiveCount() === 0 && - this.props.summary.getActiveCount() === 0 - )) { + if ( + this.props.summary === undefined || + (this.props.summary.getNeverSeenCount() === 0 && + this.props.summary.getInactiveCount() === 0 && + this.props.summary.getActiveCount() === 0) + ) { return ; } @@ -124,13 +125,13 @@ class GatewaysActiveInactive extends Component { labels: ["Never seen", "Inactive", "Active"], datasets: [ { - data: [this.props.summary.getNeverSeenCount(), this.props.summary.getInactiveCount(), this.props.summary.getActiveCount()], - backgroundColor: [ - presetPalettes.orange.primary, - presetPalettes.red.primary, - presetPalettes.green.primary, + data: [ + this.props.summary.getNeverSeenCount(), + this.props.summary.getInactiveCount(), + this.props.summary.getActiveCount(), ], - } + backgroundColor: [presetPalettes.orange.primary, presetPalettes.red.primary, presetPalettes.green.primary], + }, ], }; @@ -139,25 +140,23 @@ class GatewaysActiveInactive extends Component { } = { animation: false, }; - - return( - - ); + + return ; } } - interface DeviceProps { summary?: GetDevicesSummaryResponse; } class DevicesActiveInactive extends Component { render() { - if (this.props.summary === undefined || ( - this.props.summary.getNeverSeenCount() === 0 && - this.props.summary.getInactiveCount() === 0 && - this.props.summary.getActiveCount() === 0 - )) { + if ( + this.props.summary === undefined || + (this.props.summary.getNeverSeenCount() === 0 && + this.props.summary.getInactiveCount() === 0 && + this.props.summary.getActiveCount() === 0) + ) { return ; } @@ -165,13 +164,13 @@ class DevicesActiveInactive extends Component { labels: ["Never seen", "Inactive", "Active"], datasets: [ { - data: [this.props.summary.getNeverSeenCount(), this.props.summary.getInactiveCount(), this.props.summary.getActiveCount()], - backgroundColor: [ - presetPalettes.orange.primary, - presetPalettes.red.primary, - presetPalettes.green.primary, + data: [ + this.props.summary.getNeverSeenCount(), + this.props.summary.getInactiveCount(), + this.props.summary.getActiveCount(), ], - } + backgroundColor: [presetPalettes.orange.primary, presetPalettes.red.primary, presetPalettes.green.primary], + }, ], }; @@ -180,19 +179,31 @@ class DevicesActiveInactive extends Component { } = { animation: false, }; - - - return( - - ); + + return ; } } - class DevicesDataRates extends Component { getColor = (dr: number) => { - return ['#ff5722', '#ff9800', '#ffc107', '#ffeb3b', '#cddc39', '#8bc34a', '#4caf50', '#009688', '#00bcd4', '#03a9f4', '#2196f3', '#3f51b5', '#673ab7', '#9c27b0', '#e91e63'][dr]; - } + return [ + "#ff5722", + "#ff9800", + "#ffc107", + "#ffeb3b", + "#cddc39", + "#8bc34a", + "#4caf50", + "#009688", + "#00bcd4", + "#03a9f4", + "#2196f3", + "#3f51b5", + "#673ab7", + "#9c27b0", + "#e91e63", + ][dr]; + }; render() { if (this.props.summary === undefined || this.props.summary.getDrCountMap().toArray().length === 0) { @@ -200,17 +211,19 @@ class DevicesDataRates extends Component { } let data: { - labels: string[], + labels: string[]; datasets: { - data: number[], - backgroundColor: string[], - }[], + data: number[]; + backgroundColor: string[]; + }[]; } = { labels: [], - datasets: [{ - data: [], - backgroundColor: [], - }], + datasets: [ + { + data: [], + backgroundColor: [], + }, + ], }; for (const elm of this.props.summary.getDrCountMap().toArray()) { @@ -225,14 +238,11 @@ class DevicesDataRates extends Component { animation: false, }; - return( - - ); + return ; } } - -interface IProps{} +interface IProps {} interface IState { gatewaysSummary?: GetGatewaysSummaryResponse; @@ -260,17 +270,19 @@ class Dashboard extends Component { } render() { - return( - + return ( + + breadcrumbRender={() => ( + Network Server Dashboard - } + + )} title="Dashboard" /> @@ -290,7 +302,9 @@ class Dashboard extends Component { - + + + ); } diff --git a/ui/src/views/device-profiles/CreateDeviceProfile.tsx b/ui/src/views/device-profiles/CreateDeviceProfile.tsx index ba8b1b5d..a1f8db7b 100644 --- a/ui/src/views/device-profiles/CreateDeviceProfile.tsx +++ b/ui/src/views/device-profiles/CreateDeviceProfile.tsx @@ -4,18 +4,21 @@ import { Link, RouteComponentProps } from "react-router-dom"; import { Space, Breadcrumb, Card, PageHeader } from "antd"; import { MacVersion, RegParamsRevision } from "@chirpstack/chirpstack-api-grpc-web/common/common_pb"; -import { DeviceProfile, CreateDeviceProfileRequest, CreateDeviceProfileResponse } from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; +import { + DeviceProfile, + CreateDeviceProfileRequest, + CreateDeviceProfileResponse, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; + import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import DeviceProfileForm from "./DeviceProfileForm"; import DeviceProfileStore from "../../stores/DeviceProfileStore"; - interface IProps extends RouteComponentProps { - tenant: Tenant, + tenant: Tenant; } - class CreateDeviceProfile extends Component { onFinish = (obj: DeviceProfile) => { obj.setTenantId(this.props.tenant.getId()); @@ -26,7 +29,7 @@ class CreateDeviceProfile extends Component { DeviceProfileStore.create(req, (_resp: CreateDeviceProfileResponse) => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/device-profiles`); }); - } + }; render() { const codecScript = `// Decode uplink function. @@ -71,23 +74,29 @@ function encodeDownlink(input) { deviceProfile.setRegParamsRevision(RegParamsRevision.A); deviceProfile.setFlushQueueOnActivate(true); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Device profiles + + Device profiles + Add - } + + )} title="Add device profile" /> diff --git a/ui/src/views/device-profiles/DeviceProfileForm.tsx b/ui/src/views/device-profiles/DeviceProfileForm.tsx index 4edf8c62..0df8957d 100644 --- a/ui/src/views/device-profiles/DeviceProfileForm.tsx +++ b/ui/src/views/device-profiles/DeviceProfileForm.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { Form, Input, Select, InputNumber, Switch, Row, Col, Button, Tabs } from "antd"; -import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; +import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons"; import { DeviceProfile, CodecRuntime } from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; import { Region, MacVersion, RegParamsRevision } from "@chirpstack/chirpstack-api-grpc-web/common/common_pb"; @@ -9,7 +9,6 @@ import { ListDeviceProfileAdrAlgorithmsResponse } from "@chirpstack/chirpstack-a import DeviceProfileStore from "../../stores/DeviceProfileStore"; import CodeEditor from "../../components/CodeEditor"; - interface IProps { initialValues: DeviceProfile; onFinish: (obj: DeviceProfile) => void; @@ -24,7 +23,6 @@ interface IState { adrAlgorithms: [string, string][]; } - class DeviceProfileForm extends Component { formRef = React.createRef(); @@ -101,51 +99,48 @@ class DeviceProfileForm extends Component { } this.props.onFinish(dp); - } + }; onSupportsOtaaChange = (checked: boolean) => { this.setState({ supportsOtaa: checked, }); - } + }; onSupportsClassBChnage = (checked: boolean) => { this.setState({ supportsClassB: checked, }); - } + }; onSupportsClassCChange = (checked: boolean) => { this.setState({ supportsClassC: checked, }); - } + }; onPayloadCodecRuntimeChange = (value: CodecRuntime) => { this.setState({ payloadCodecRuntime: value, }); - } + }; render() { - const adrOptions = this.state.adrAlgorithms.map((v) => {v[1]}); + const adrOptions = this.state.adrAlgorithms.map(v => {v[1]}); - return( -
+ return ( + - + - + LoRaWAN 1.0.0 @@ -185,7 +180,7 @@ class DeviceProfileForm extends Component { label="Regional parameters revision" tooltip="Revision of the Regional Parameters specification supported by the device." name="regParamsRevision" - rules={[{required: true, message: "Please select a regional parameters revision!"}]} + rules={[{ required: true, message: "Please select a regional parameters revision!" }]} > - {adrOptions} - +
@@ -241,19 +234,16 @@ class DeviceProfileForm extends Component { - + - {!this.state.supportsOtaa && + {!this.state.supportsOtaa && ( + @@ -263,19 +253,21 @@ class DeviceProfileForm extends Component { label="RX1 data-rate offset" tooltip="Please refer the LoRaWAN Regional Parameters specification for valid values." name="abpRx1DrOffset" - rules={[{required: true, message: "Please enter a RX1 data-rate offset!"}]} + rules={[{ required: true, message: "Please enter a RX1 data-rate offset!" }]} > - } - {!this.state.supportsOtaa && + + )} + {!this.state.supportsOtaa && ( + @@ -284,46 +276,43 @@ class DeviceProfileForm extends Component { - + - } + + )} - + - {this.state.supportsClassB && - - } + {this.state.supportsClassB && ( + + + + )} - + - {this.state.supportsClassC && - - } + {this.state.supportsClassC && ( + + + + )} { - {(fields, { add, remove }) => ( + {(fields, { add, remove }) => ( <> {fields.map(( {key, name, ...restField} ) => ( @@ -355,7 +344,7 @@ class DeviceProfileForm extends Component { {...restField} name={[name, 0]} fieldKey={[name, 0]} - rules={[{ required: true, message: 'Please enter a key!' }]} + rules={[{ required: true, message: "Please enter a key!" }]} > @@ -365,18 +354,24 @@ class DeviceProfileForm extends Component { {...restField} name={[name, 1]} fieldKey={[name, 1]} - rules={[{ required: true, message: 'Please enter a value!' }]} + rules={[{ required: true, message: "Please enter a value!" }]} > - - remove(name)} /> - + + remove(name)} /> + ))} - @@ -386,7 +381,9 @@ class DeviceProfileForm extends Component { - + ); diff --git a/ui/src/views/device-profiles/EditDeviceProfile.tsx b/ui/src/views/device-profiles/EditDeviceProfile.tsx index d13a0233..aee367c0 100644 --- a/ui/src/views/device-profiles/EditDeviceProfile.tsx +++ b/ui/src/views/device-profiles/EditDeviceProfile.tsx @@ -4,7 +4,13 @@ import { RouteComponentProps, Link } from "react-router-dom"; import { Space, Breadcrumb, Card, Button, PageHeader } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; -import { DeviceProfile, GetDeviceProfileRequest, GetDeviceProfileResponse, UpdateDeviceProfileRequest, DeleteDeviceProfileRequest } from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; +import { + DeviceProfile, + GetDeviceProfileRequest, + GetDeviceProfileResponse, + UpdateDeviceProfileRequest, + DeleteDeviceProfileRequest, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; import DeviceProfileForm from "./DeviceProfileForm"; import DeviceProfileStore from "../../stores/DeviceProfileStore"; @@ -12,7 +18,6 @@ import SessionStore from "../../stores/SessionStore"; import DeleteConfirm from "../../components/DeleteConfirm"; import Admin from "../../components/Admin"; - interface IState { deviceProfile?: DeviceProfile; } @@ -25,7 +30,6 @@ interface IProps extends RouteComponentProps { tenant: Tenant; } - class EditDeviceProfile extends Component { constructor(props: IProps) { super(props); @@ -46,7 +50,7 @@ class EditDeviceProfile extends Component { deviceProfile: resp.getDeviceProfile(), }); }); - } + }; onFinish = (obj: DeviceProfile) => { let req = new UpdateDeviceProfileRequest(); @@ -55,7 +59,7 @@ class EditDeviceProfile extends Component { DeviceProfileStore.update(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/device-profiles`); }); - } + }; deleteDeviceProfile = () => { let req = new DeleteDeviceProfileRequest(); @@ -64,7 +68,7 @@ class EditDeviceProfile extends Component { DeviceProfileStore.delete(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/device-profiles`); }); - } + }; render() { const dp = this.state.deviceProfile; @@ -73,42 +77,50 @@ class EditDeviceProfile extends Component { return null; } - const disabled = !(SessionStore.isAdmin() || SessionStore.isTenantAdmin(this.props.tenant.getId()) || SessionStore.isTenantDeviceAdmin(this.props.tenant.getId())); + const disabled = !( + SessionStore.isAdmin() || + SessionStore.isTenantAdmin(this.props.tenant.getId()) || + SessionStore.isTenantDeviceAdmin(this.props.tenant.getId()) + ); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Device profiles + + Device profiles + {dp.getName()} - } + + )} title={dp.getName()} subTitle={`device profile id: ${dp.getId()}`} extra={[ - - + + - + , ]} /> - - - + + + ); } diff --git a/ui/src/views/device-profiles/ListDeviceProfiles.tsx b/ui/src/views/device-profiles/ListDeviceProfiles.tsx index 48edf2ab..5ada24e1 100644 --- a/ui/src/views/device-profiles/ListDeviceProfiles.tsx +++ b/ui/src/views/device-profiles/ListDeviceProfiles.tsx @@ -4,7 +4,11 @@ import { Link } from "react-router-dom"; import { Space, Breadcrumb, Button, PageHeader } from "antd"; import { ColumnsType } from "antd/es/table"; -import { ListDeviceProfilesRequest, ListDeviceProfilesResponse, DeviceProfileListItem } from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; +import { + ListDeviceProfilesRequest, + ListDeviceProfilesResponse, + DeviceProfileListItem, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import { Region } from "@chirpstack/chirpstack-api-grpc-web/common/common_pb"; @@ -13,12 +17,10 @@ import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import DeviceProfileStore from "../../stores/DeviceProfileStore"; import Admin from "../../components/Admin"; - interface IProps { tenant: Tenant; } - class ListDeviceProfiles extends Component { columns = (): ColumnsType => { return [ @@ -97,7 +99,7 @@ class ListDeviceProfiles extends Component { }, }, ]; - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListDeviceProfilesRequest(); @@ -109,35 +111,37 @@ class ListDeviceProfiles extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } + }; render() { - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + Device profiles - } + + )} title="Device profiles" extra={[ - - + + , ]} /> - + ); } diff --git a/ui/src/views/devices/CreateDevice.tsx b/ui/src/views/devices/CreateDevice.tsx index 8f05f9da..46db75bb 100644 --- a/ui/src/views/devices/CreateDevice.tsx +++ b/ui/src/views/devices/CreateDevice.tsx @@ -6,19 +6,20 @@ import { Space, Breadcrumb, Card, PageHeader } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import { Application } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; import { CreateDeviceRequest, Device } from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; -import { GetDeviceProfileRequest, GetDeviceProfileResponse } from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; +import { + GetDeviceProfileRequest, + GetDeviceProfileResponse, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; import DeviceForm from "./DeviceForm"; import DeviceStore from "../../stores/DeviceStore"; import DeviceProfileStore from "../../stores/DeviceProfileStore"; - interface IProps extends RouteComponentProps { tenant: Tenant; application: Application; } - class CreateDevice extends Component { onFinish = (obj: Device) => { obj.setApplicationId(this.props.application.getId()); @@ -33,38 +34,52 @@ class CreateDevice extends Component { DeviceProfileStore.get(req, (resp: GetDeviceProfileResponse) => { let dp = resp.getDeviceProfile()!; if (dp.getSupportsOtaa()) { - this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${obj.getDevEui()}/keys`); + this.props.history.push( + `/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${obj.getDevEui()}/keys`, + ); } else { - this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${obj.getDevEui()}`); + this.props.history.push( + `/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${obj.getDevEui()}`, + ); } }); }); - } + }; render() { let device = new Device(); device.setApplicationId(this.props.application.getId()); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Applications + + Applications + - {this.props.application.getName()} + + + {this.props.application.getName()} + + Add device - } + + )} title="Add device" /> diff --git a/ui/src/views/devices/DeviceActivation.tsx b/ui/src/views/devices/DeviceActivation.tsx index 605cf81c..c640a4af 100644 --- a/ui/src/views/devices/DeviceActivation.tsx +++ b/ui/src/views/devices/DeviceActivation.tsx @@ -5,7 +5,7 @@ import { Space, Form, Button, Row, Col, InputNumber } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import { Application } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; -import { +import { Device, GetDeviceActivationRequest, GetDeviceActivationResponse, @@ -19,14 +19,12 @@ import AesKeyInput from "../../components/AesKeyInput"; import DevAddrInput from "../../components/DevAddrInput"; import DeviceStore from "../../stores/DeviceStore"; - interface FormProps { initialValues: DeviceActivationPb; device: Device; onFinish: (obj: DeviceActivationPb) => void; } - class LW10DeviceActivationForm extends Component { formRef = React.createRef(); @@ -44,12 +42,17 @@ class LW10DeviceActivationForm extends Component { da.setNFCntDown(v.nFCntDown); this.props.onFinish(da); - } + }; render() { - return( -
- + { formRef={this.formRef} required /> - - { />
- + - + - + ); } } - class LW11DeviceActivationForm extends Component { formRef = React.createRef(); @@ -115,12 +113,17 @@ class LW11DeviceActivationForm extends Component { da.setNFCntDown(v.nFCntDown); this.props.onFinish(da); - } + }; render() { - return( -
- + { formRef={this.formRef} required /> - - - - { />
- + - + - + - + ); } } - interface IProps extends RouteComponentProps { tenant: Tenant; application: Application; @@ -198,13 +193,11 @@ interface IProps extends RouteComponentProps { deviceProfile: DeviceProfile; } - interface IState { deviceActivation?: DeviceActivationPb; deviceActivationRequested: boolean; } - class DeviceActivation extends Component { constructor(props: IProps) { super(props); @@ -231,9 +224,11 @@ class DeviceActivation extends Component { req.setDeviceActivation(obj); DeviceStore.activate(req, () => { - this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${this.props.device.getDevEui()}`); + this.props.history.push( + `/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${this.props.device.getDevEui()}`, + ); }); - } + }; render() { if (!this.state.deviceActivationRequested) { @@ -248,10 +243,14 @@ class DeviceActivation extends Component { initialValues = this.state.deviceActivation; } - return( - - {!lw11 && } - {lw11 && } + return ( + + {!lw11 && ( + + )} + {lw11 && ( + + )} ); } diff --git a/ui/src/views/devices/DeviceDashboard.tsx b/ui/src/views/devices/DeviceDashboard.tsx index c3f81e0e..31b00af0 100644 --- a/ui/src/views/devices/DeviceDashboard.tsx +++ b/ui/src/views/devices/DeviceDashboard.tsx @@ -7,19 +7,16 @@ import { TimeUnit } from "chart.js"; import { Line, Bar } from "react-chartjs-2"; import { Timestamp } from "google-protobuf/google/protobuf/timestamp_pb"; -import { +import { Device, GetDeviceStatsRequest, GetDeviceStatsResponse, } from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; -import { - DeviceProfile, -} from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; +import { DeviceProfile } from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; import DeviceStore from "../../stores/DeviceStore"; import Heatmap from "../../components/Heatmap"; - interface IProps { device: Device; deviceProfile: DeviceProfile; @@ -32,7 +29,7 @@ interface IState { statsUpFreq: HeatmapStats[]; statsUpDr?: any; statsGwRssi?: any; - statsGwSnr?: any, + statsGwSnr?: any; } interface HeatmapStats { @@ -78,7 +75,7 @@ class DeviceDashboard extends Component { lineTension: number; pointBackgroundColor: string; data: number[]; - }[], + }[]; } = { labels: [], datasets: [ @@ -129,28 +126,32 @@ class DeviceDashboard extends Component { let statsGwRssiData: (number | null)[] = []; let statsGwRssi = { labels: statsGwRssiLabels, - datasets: [{ - label: "rssi (reported by gateways)", - borderColor: "rgba(33, 150, 243, 1)", - backgroundColor: "rgba(0, 0, 0, 0)", - lineTension: 0, - pointBackgroundColor: "rgba(33, 150, 243, 1)", - data: statsGwRssiData, - }], + datasets: [ + { + label: "rssi (reported by gateways)", + borderColor: "rgba(33, 150, 243, 1)", + backgroundColor: "rgba(0, 0, 0, 0)", + lineTension: 0, + pointBackgroundColor: "rgba(33, 150, 243, 1)", + data: statsGwRssiData, + }, + ], }; let statsGwSnrLabels: string[] = []; let statsGwSnrData: (number | null)[] = []; let statsGwSnr = { labels: statsGwSnrLabels, - datasets: [{ - label: "rssi (reported by gateways)", - borderColor: "rgba(33, 150, 243, 1)", - backgroundColor: "rgba(0, 0, 0, 0)", - lineTension: 0, - pointBackgroundColor: "rgba(33, 150, 243, 1)", - data: statsGwSnrData, - }], + datasets: [ + { + label: "rssi (reported by gateways)", + borderColor: "rgba(33, 150, 243, 1)", + backgroundColor: "rgba(0, 0, 0, 0)", + lineTension: 0, + pointBackgroundColor: "rgba(33, 150, 243, 1)", + data: statsGwSnrData, + }, + ], }; let statsUpFreq: HeatmapStats[] = []; @@ -160,7 +161,10 @@ class DeviceDashboard extends Component { statsUpFreq.push({ x: moment(row.getTime()!.toDate()).format("YYYY-MM-DD"), - y: row.getRxPacketsPerFrequencyMap().toObject().map(v => [v[0].toString(), v[1]]), + y: row + .getRxPacketsPerFrequencyMap() + .toObject() + .map(v => [v[0].toString(), v[1]]), }); statsErrors.labels.push(moment(row.getTime()!.toDate()).format("YYYY-MM-DD")); @@ -187,7 +191,6 @@ class DeviceDashboard extends Component { } statsErrorsSet[v[0]].push(v[1]); - } for (const v of row.getRxPacketsPerDrMap().toObject()) { @@ -204,7 +207,23 @@ class DeviceDashboard extends Component { } } - let backgroundColors = ['#8bc34a', '#ff5722', '#ff9800', '#ffc107', '#ffeb3b', '#cddc39', '#4caf50', '#009688', '#00bcd4', '#03a9f4', '#2196f3', '#3f51b5', '#673ab7', '#9c27b0', '#e91e63']; + let backgroundColors = [ + "#8bc34a", + "#ff5722", + "#ff9800", + "#ffc107", + "#ffeb3b", + "#cddc39", + "#4caf50", + "#009688", + "#00bcd4", + "#03a9f4", + "#2196f3", + "#3f51b5", + "#673ab7", + "#9c27b0", + "#e91e63", + ]; Object.entries(statsErrorsSet).forEach(([k, v]) => { statsErrors.datasets.push({ label: k, @@ -213,7 +232,23 @@ class DeviceDashboard extends Component { }); }); - backgroundColors = ['#8bc34a', '#ff5722', '#ff9800', '#ffc107', '#ffeb3b', '#cddc39', '#4caf50', '#009688', '#00bcd4', '#03a9f4', '#2196f3', '#3f51b5', '#673ab7', '#9c27b0', '#e91e63']; + backgroundColors = [ + "#8bc34a", + "#ff5722", + "#ff9800", + "#ffc107", + "#ffeb3b", + "#cddc39", + "#4caf50", + "#009688", + "#00bcd4", + "#03a9f4", + "#2196f3", + "#3f51b5", + "#673ab7", + "#9c27b0", + "#e91e63", + ]; Object.entries(statsUpDrSet).forEach(([k, v]) => { statsUpDr.datasets.push({ label: k, @@ -231,8 +266,7 @@ class DeviceDashboard extends Component { statsGwSnr: statsGwSnr, }); }); - } - + }; render() { const animation: false = false; @@ -287,15 +321,21 @@ class DeviceDashboard extends Component { lastSeenAt = moment(this.props.lastSeenAt).format("YYYY-MM-DD HH:mm:ss"); } - return( - + return ( + - - {lastSeenAt} - {this.props.deviceProfile.getName()} - {this.props.device.getIsDisabled() ? "no" : "yes"} - {this.props.device.getDescription()} - + + {lastSeenAt} + + + {this.props.deviceProfile.getName()} + + + {this.props.device.getIsDisabled() ? "no" : "yes"} + {this.props.device.getDescription()} + diff --git a/ui/src/views/devices/DeviceEvents.tsx b/ui/src/views/devices/DeviceEvents.tsx index be150221..8c16582f 100644 --- a/ui/src/views/devices/DeviceEvents.tsx +++ b/ui/src/views/devices/DeviceEvents.tsx @@ -6,14 +6,13 @@ import { StreamDeviceEventsRequest, LogItem } from "@chirpstack/chirpstack-api-g import InternalStore from "../../stores/InternalStore"; import LogTable from "../../components/LogTable"; - interface IProps { device: Device; } interface IState { events: LogItem[]; - cancelFunc?: () => void, + cancelFunc?: () => void; } class DeviceEvents extends Component { @@ -44,7 +43,7 @@ class DeviceEvents extends Component { this.setState({ cancelFunc: cancelFunc, }); - } + }; onMessage = (l: LogItem) => { let events = this.state.events; @@ -55,10 +54,10 @@ class DeviceEvents extends Component { events: events, }); } - } + }; render() { - return(); + return ; } } diff --git a/ui/src/views/devices/DeviceForm.tsx b/ui/src/views/devices/DeviceForm.tsx index e1842f46..b3f9006b 100644 --- a/ui/src/views/devices/DeviceForm.tsx +++ b/ui/src/views/devices/DeviceForm.tsx @@ -1,18 +1,22 @@ import React, { Component } from "react"; import { Form, Input, Row, Col, Button, Tabs } from "antd"; -import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; +import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import { Device } from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; -import { ListDeviceProfilesRequest, ListDeviceProfilesResponse, GetDeviceProfileRequest, GetDeviceProfileResponse } from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; +import { + ListDeviceProfilesRequest, + ListDeviceProfilesResponse, + GetDeviceProfileRequest, + GetDeviceProfileResponse, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; import EuiInput from "../../components/EuiInput"; -import{ OptionsCallbackFunc, OptionCallbackFunc } from "../../components/Autocomplete"; +import { OptionsCallbackFunc, OptionCallbackFunc } from "../../components/Autocomplete"; import AutocompleteInput from "../../components/AutocompleteInput"; import DeviceProfileStore from "../../stores/DeviceProfileStore"; - interface IProps { tenant: Tenant; initialValues: Device; @@ -20,7 +24,6 @@ interface IProps { update?: boolean; } - class DeviceForm extends Component { formRef = React.createRef(); @@ -45,7 +48,7 @@ class DeviceForm extends Component { } this.props.onFinish(d); - } + }; getDeviceProfileOptions = (search: string, fn: OptionsCallbackFunc) => { let req = new ListDeviceProfilesRequest(); @@ -54,10 +57,12 @@ class DeviceForm extends Component { req.setLimit(10); DeviceProfileStore.list(req, (resp: ListDeviceProfilesResponse) => { - const options = resp.getResultList().map((o, i) => {return {label: o.getName(), value: o.getId()}}); + const options = resp.getResultList().map((o, i) => { + return { label: o.getName(), value: o.getId() }; + }); fn(options); }); - } + }; getDeviceProfileOption = (id: string, fn: OptionCallbackFunc) => { let req = new GetDeviceProfileRequest(); @@ -66,30 +71,28 @@ class DeviceForm extends Component { DeviceProfileStore.get(req, (resp: GetDeviceProfileResponse) => { const dp = resp.getDeviceProfile(); if (dp) { - fn({label: dp.getName(), value: dp.getId()}); + fn({ label: dp.getName(), value: dp.getId() }); } }); - } + }; render() { - return( -
+ return ( + - + - + - { - {(fields, { add, remove }) => ( + {(fields, { add, remove }) => ( <> {fields.map(( {key, name, ...restField} ) => ( @@ -117,7 +120,7 @@ class DeviceForm extends Component { {...restField} name={[name, 0]} fieldKey={[name, 0]} - rules={[{ required: true, message: 'Please enter a key!' }]} + rules={[{ required: true, message: "Please enter a key!" }]} > @@ -127,14 +130,14 @@ class DeviceForm extends Component { {...restField} name={[name, 1]} fieldKey={[name, 1]} - rules={[{ required: true, message: 'Please enter a value!' }]} + rules={[{ required: true, message: "Please enter a value!" }]} > -
- remove(name)} /> - + + remove(name)} /> + ))} @@ -148,7 +151,7 @@ class DeviceForm extends Component { - {(fields, { add, remove }) => ( + {(fields, { add, remove }) => ( <> {fields.map(( {key, name, ...restField} ) => ( @@ -157,7 +160,7 @@ class DeviceForm extends Component { {...restField} name={[name, 0]} fieldKey={[name, 0]} - rules={[{ required: true, message: 'Please enter a key!' }]} + rules={[{ required: true, message: "Please enter a key!" }]} > @@ -167,14 +170,14 @@ class DeviceForm extends Component { {...restField} name={[name, 1]} fieldKey={[name, 1]} - rules={[{ required: true, message: 'Please enter a value!' }]} + rules={[{ required: true, message: "Please enter a value!" }]} > - - remove(name)} /> - + + remove(name)} /> + ))} @@ -188,7 +191,9 @@ class DeviceForm extends Component { - + ); diff --git a/ui/src/views/devices/DeviceFrames.tsx b/ui/src/views/devices/DeviceFrames.tsx index caa9d2e3..91652a34 100644 --- a/ui/src/views/devices/DeviceFrames.tsx +++ b/ui/src/views/devices/DeviceFrames.tsx @@ -6,14 +6,13 @@ import { StreamDeviceFramesRequest, LogItem } from "@chirpstack/chirpstack-api-g import InternalStore from "../../stores/InternalStore"; import LogTable from "../../components/LogTable"; - interface IProps { device: Device; } interface IState { frames: LogItem[]; - cancelFunc?: () => void, + cancelFunc?: () => void; } class DeviceFrames extends Component { @@ -44,7 +43,7 @@ class DeviceFrames extends Component { this.setState({ cancelFunc: cancelFunc, }); - } + }; onMessage = (l: LogItem) => { let frames = this.state.frames; @@ -55,10 +54,10 @@ class DeviceFrames extends Component { frames: frames, }); } - } + }; render() { - return(); + return ; } } diff --git a/ui/src/views/devices/DeviceLayout.tsx b/ui/src/views/devices/DeviceLayout.tsx index 941b3904..765f3e1f 100644 --- a/ui/src/views/devices/DeviceLayout.tsx +++ b/ui/src/views/devices/DeviceLayout.tsx @@ -5,8 +5,17 @@ import { Space, Breadcrumb, Card, Button, PageHeader, Menu } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import { Application } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; -import { DeviceProfile, GetDeviceProfileRequest, GetDeviceProfileResponse } from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; -import { Device, GetDeviceRequest, GetDeviceResponse, DeleteDeviceRequest } from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; +import { + DeviceProfile, + GetDeviceProfileRequest, + GetDeviceProfileResponse, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_profile_pb"; +import { + Device, + GetDeviceRequest, + GetDeviceResponse, + DeleteDeviceRequest, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; import DeviceStore from "../../stores/DeviceStore"; import DeviceProfileStore from "../../stores/DeviceProfileStore"; @@ -20,12 +29,11 @@ import DeviceEvents from "./DeviceEvents"; import DeviceQueue from "./DeviceQueue"; import DeviceActivation from "./DeviceActivation"; - interface MatchParams { devEui: string; } -interface IProps extends RouteComponentProps{ +interface IProps extends RouteComponentProps { tenant: Tenant; application: Application; } @@ -36,7 +44,6 @@ interface IState { lastSeenAt?: Date; } - class DeviceLayout extends Component { constructor(props: IProps) { super(props); @@ -52,9 +59,12 @@ class DeviceLayout extends Component { req.setDevEui(this.props.match.params.devEui); DeviceStore.get(req, (resp: GetDeviceResponse) => { - this.setState({ - device: resp.getDevice(), - }, cb); + this.setState( + { + device: resp.getDevice(), + }, + cb, + ); if (resp.getLastSeenAt() !== undefined) { this.setState({ @@ -62,7 +72,7 @@ class DeviceLayout extends Component { }); } }); - } + }; getDeviceProfile = () => { let req = new GetDeviceProfileRequest(); @@ -73,7 +83,7 @@ class DeviceLayout extends Component { deviceProfile: resp.getDeviceProfile(), }); }); - } + }; deleteDevice = () => { let req = new DeleteDeviceRequest(); @@ -82,7 +92,7 @@ class DeviceLayout extends Component { DeviceStore.delete(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}`); }); - } + }; render() { const device = this.state.device; @@ -116,61 +126,137 @@ class DeviceLayout extends Component { tab = "frames"; } - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Applications + + Applications + - {this.props.application.getName()} + + + {this.props.application.getName()} + + - Devices + + + Devices + + {device.getName()} - } + + )} title={device.getName()} subTitle={`device eui: ${device.getDevEui()}`} extra={[ - - - + + + , ]} /> - - - Dashboard - Configuration - OTAA keys - Activation - Queue - Events - LoRaWAN frames - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - + + + + + Dashboard + + + + + Configuration + + + + + OTAA keys + + + + + Activation + + + + + Queue + + + + + Events + + + + + LoRaWAN frames + + + + + ( + + )} + /> + } + /> + ( + + )} + /> + } + /> + } + /> + } + /> + ( + + )} + /> + + ); } diff --git a/ui/src/views/devices/DeviceQueue.tsx b/ui/src/views/devices/DeviceQueue.tsx index 8af1660e..8917c088 100644 --- a/ui/src/views/devices/DeviceQueue.tsx +++ b/ui/src/views/devices/DeviceQueue.tsx @@ -13,13 +13,13 @@ import { GetDeviceQueueItemsRequest, GetDeviceQueueItemsResponse, FlushDeviceQueueRequest, - DeviceQueueItem } from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; + DeviceQueueItem, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import DeviceStore from "../../stores/DeviceStore"; import CodeEditor from "../../components/CodeEditor"; - interface IProps { device: Device; } @@ -28,7 +28,6 @@ interface IState { refreshCounter: number; } - class DeviceQueue extends Component { formRef = React.createRef(); @@ -97,11 +96,11 @@ class DeviceQueue extends Component { dataIndex: "data", key: "data", render: (text, record) => { - return Buffer.from(record.data as string, 'base64').toString('hex'); + return Buffer.from(record.data as string, "base64").toString("hex"); }, }, - ] - } + ]; + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new GetDeviceQueueItemsRequest(); @@ -111,13 +110,13 @@ class DeviceQueue extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } + }; refreshQueue = () => { this.setState({ refreshCounter: this.state.refreshCounter + 1, }); - } + }; flushQueue = () => { let req = new FlushDeviceQueueRequest(); @@ -125,7 +124,7 @@ class DeviceQueue extends Component { DeviceStore.flushQueue(req, () => { this.refreshQueue(); }); - } + }; onEnqueue = (values: any) => { let req = new EnqueueDeviceQueueItemRequest(); @@ -136,11 +135,11 @@ class DeviceQueue extends Component { item.setConfirmed(values.confirmed); if (values.hex !== undefined) { - item.setData(Buffer.from(values.hex, 'hex')); + item.setData(Buffer.from(values.hex, "hex")); } if (values.base64 !== undefined) { - item.setData(Buffer.from(values.base64, 'base64')); + item.setData(Buffer.from(values.base64, "base64")); } if (values.json !== undefined) { @@ -149,7 +148,7 @@ class DeviceQueue extends Component { let struct = Struct.fromJavaScript(obj); item.setObject(struct); - } catch(err) { + } catch (err) { if (err instanceof Error) { notification.error({ message: "Error", @@ -162,19 +161,19 @@ class DeviceQueue extends Component { req.setItem(item); - DeviceStore.enqueue(req, (_) => { + DeviceStore.enqueue(req, _ => { this.formRef.current.resetFields(); this.refreshQueue(); }); - } + }; render() { return ( - + -
+ - + @@ -195,24 +194,20 @@ class DeviceQueue extends Component {
- + - + - - + + diff --git a/ui/src/views/devices/EditDevice.tsx b/ui/src/views/devices/EditDevice.tsx index f900b03f..97668522 100644 --- a/ui/src/views/devices/EditDevice.tsx +++ b/ui/src/views/devices/EditDevice.tsx @@ -14,21 +14,20 @@ interface IProps extends RouteComponentProps { device: Device; } - class EditDevice extends Component { onFinish = (obj: Device) => { let req = new UpdateDeviceRequest(); req.setDevice(obj); DeviceStore.update(req, () => { - this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${obj.getDevEui()}`); + this.props.history.push( + `/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${obj.getDevEui()}`, + ); }); - } + }; render() { - return( - - ); + return ; } } diff --git a/ui/src/views/devices/ListDevices.tsx b/ui/src/views/devices/ListDevices.tsx index 94f974e0..98fdd732 100644 --- a/ui/src/views/devices/ListDevices.tsx +++ b/ui/src/views/devices/ListDevices.tsx @@ -5,13 +5,23 @@ import moment from "moment"; import { Space, Button, Dropdown, Menu, Modal, Select } from "antd"; import { ColumnsType } from "antd/es/table"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faPlug, faBatteryFull, faBatteryQuarter, faBatteryHalf, faBatteryThreeQuarters } from '@fortawesome/free-solid-svg-icons' +import { + faPlug, + faBatteryFull, + faBatteryQuarter, + faBatteryHalf, + faBatteryThreeQuarters, +} from "@fortawesome/free-solid-svg-icons"; import { Application } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; -import { ListDevicesRequest, ListDevicesResponse, DeviceListItem } from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; -import { - ListMulticastGroupsRequest, - ListMulticastGroupsResponse, +import { + ListDevicesRequest, + ListDevicesResponse, + DeviceListItem, +} from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; +import { + ListMulticastGroupsRequest, + ListMulticastGroupsResponse, MulticastGroupListItem, AddDeviceToMulticastGroupRequest, } from "@chirpstack/chirpstack-api-grpc-web/api/multicast_group_pb"; @@ -21,20 +31,17 @@ import DeviceStore from "../../stores/DeviceStore"; import MulticastGroupStore from "../../stores/MulticastGroupStore"; import Admin from "../../components/Admin"; - interface IProps { application: Application; } - interface IState { selectedRowIds: string[]; multicastGroups: MulticastGroupListItem[]; mgModalVisible: boolean; - mgSelected: string, + mgSelected: string; } - class ListDevices extends Component { constructor(props: IProps) { super(props); @@ -71,7 +78,7 @@ class ListDevices extends Component { ts.setUTCSeconds(record.lastSeenAt.seconds); return moment(ts).format("YYYY-MM-DD HH:mm:ss"); } - return "Never"; + return "Never"; }, }, { @@ -80,7 +87,13 @@ class ListDevices extends Component { key: "devEui", width: 250, render: (text, record) => ( - {text} + + {text} + ), }, { @@ -92,8 +105,10 @@ class ListDevices extends Component { title: "Device profile", dataIndex: "deviceProfileName", key: "deviceProfileName", - render: (text, record) => ( - {text} + render: (text, record) => ( + + {text} + ), }, { @@ -119,7 +134,7 @@ class ListDevices extends Component { }, }, ]; - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListDevicesRequest(); @@ -131,31 +146,31 @@ class ListDevices extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } + }; onRowsSelectChange = (ids: string[]) => { this.setState({ selectedRowIds: ids, }); - } + }; showMgModal = () => { this.setState({ mgModalVisible: true, }); - } + }; hideMgModal = () => { this.setState({ mgModalVisible: false, }); - } + }; onMgSelected = (value: string) => { this.setState({ mgSelected: value, }); - } + }; handleMgModalOk = () => { for (let devEui of this.state.selectedRowIds) { @@ -164,12 +179,12 @@ class ListDevices extends Component { req.setDevEui(devEui); MulticastGroupStore.addDevice(req, () => {}); - } + } this.setState({ mgModalVisible: false, }); - } + }; render() { const menu = ( @@ -178,21 +193,42 @@ class ListDevices extends Component { ); - const mgOptions = this.state.multicastGroups.map((mg, i) => {mg.getName()}); + const mgOptions = this.state.multicastGroups.map((mg, i) => ( + {mg.getName()} + )); - return( - - - - {mgOptions} - - - + + + + + { } } -export default ListDevices; \ No newline at end of file +export default ListDevices; diff --git a/ui/src/views/devices/SetDeviceKeys.tsx b/ui/src/views/devices/SetDeviceKeys.tsx index b8c419a6..44e1d20e 100644 --- a/ui/src/views/devices/SetDeviceKeys.tsx +++ b/ui/src/views/devices/SetDeviceKeys.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { RouteComponentProps } from "react-router-dom"; -import { Form, Button, Space, Popconfirm} from "antd"; +import { Form, Button, Space, Popconfirm } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import { Application } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; @@ -20,13 +20,11 @@ import { MacVersion } from "@chirpstack/chirpstack-api-grpc-web/common/common_pb import AesKeyInput from "../../components/AesKeyInput"; import DeviceStore from "../../stores/DeviceStore"; - interface FormProps { initialValues: DeviceKeys; onFinish: (obj: DeviceKeys) => void; } - class LW10DeviceKeysForm extends Component { formRef = React.createRef(); @@ -40,11 +38,16 @@ class LW10DeviceKeysForm extends Component { dk.setNwkKey(v.nwkKey); this.props.onFinish(dk); - } + }; render() { - return( -
+ return ( + { required /> - + ); } } - class LW11DeviceKeysForm extends Component { formRef = React.createRef(); @@ -74,11 +78,16 @@ class LW11DeviceKeysForm extends Component { dk.setNwkKey(v.nwkKey); this.props.onFinish(dk); - } + }; render() { - return( -
+ return ( + { required /> - + ); } } - interface IProps extends RouteComponentProps { tenant: Tenant; application: Application; @@ -123,7 +133,7 @@ class SetDeviceKeys extends Component { deviceKeysRequested: false, }; } - + componentDidMount() { this.getDeviceKeys(); } @@ -144,7 +154,7 @@ class SetDeviceKeys extends Component { }); } }); - } + }; onFinish = (obj: DeviceKeys) => { if (this.state.deviceKeys) { @@ -153,9 +163,10 @@ class SetDeviceKeys extends Component { req.setDeviceKeys(obj); DeviceStore.updateKeys(req, () => { - this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${this.props.device.getDevEui()}`); + this.props.history.push( + `/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${this.props.device.getDevEui()}`, + ); }); - } else { // this is a create let req = new CreateDeviceKeysRequest(); @@ -163,16 +174,18 @@ class SetDeviceKeys extends Component { req.setDeviceKeys(obj); DeviceStore.createKeys(req, () => { - this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${this.props.device.getDevEui()}`); + this.props.history.push( + `/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/devices/${this.props.device.getDevEui()}`, + ); }); } - } + }; flushDevNonces = () => { let req = new FlushDevNoncesRequest(); req.setDevEui(this.props.device.getDevEui()); DeviceStore.flushDevNonces(req, () => {}); - } + }; render() { if (!this.state.deviceKeysRequested) { @@ -187,17 +200,19 @@ class SetDeviceKeys extends Component { initialValues = this.state.deviceKeys; } - return( - - {this.state.deviceKeys &&
- - - -
} + return ( + + {this.state.deviceKeys && ( +
+ + + +
+ )} {!lw11 && } {lw11 && }
diff --git a/ui/src/views/gateways/CreateGateway.tsx b/ui/src/views/gateways/CreateGateway.tsx index 9617dda8..63648380 100644 --- a/ui/src/views/gateways/CreateGateway.tsx +++ b/ui/src/views/gateways/CreateGateway.tsx @@ -9,12 +9,10 @@ import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import GatewayForm from "./GatewayForm"; import GatewayStore from "../../stores/GatewayStore"; - interface IProps extends RouteComponentProps { tenant: Tenant; } - class CreateGateway extends Component { onFinish = (obj: Gateway) => { obj.setTenantId(this.props.tenant.getId()); @@ -25,29 +23,35 @@ class CreateGateway extends Component { GatewayStore.create(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/gateways/${obj.getGatewayId()}`); }); - } + }; render() { const gateway = new Gateway(); - return( - - + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Gateways + + Gateways + Add - } + + )} /> diff --git a/ui/src/views/gateways/EditGateway.tsx b/ui/src/views/gateways/EditGateway.tsx index 6837f349..c3b2b189 100644 --- a/ui/src/views/gateways/EditGateway.tsx +++ b/ui/src/views/gateways/EditGateway.tsx @@ -3,18 +3,16 @@ import { RouteComponentProps } from "react-router-dom"; import { Gateway, UpdateGatewayRequest } from "@chirpstack/chirpstack-api-grpc-web/api/gateway_pb"; -import GatewayForm from "./GatewayForm"; +import GatewayForm from "./GatewayForm"; import GatewayStore from "../../stores/GatewayStore"; import SessionStore from "../../stores/SessionStore"; - interface IProps extends RouteComponentProps { gateway: Gateway; } interface IState {} - class EditGateway extends Component { onFinish = (obj: Gateway) => { let req = new UpdateGatewayRequest(); @@ -23,13 +21,15 @@ class EditGateway extends Component { GatewayStore.update(req, () => { this.props.history.push(`/tenants/${obj.getTenantId()}/gateways/${obj.getGatewayId()}`); }); - } + }; render() { - const disabled = !(SessionStore.isAdmin() || SessionStore.isTenantAdmin(this.props.gateway.getTenantId()) || SessionStore.isTenantGatewayAdmin(this.props.gateway.getTenantId())); - return( - + const disabled = !( + SessionStore.isAdmin() || + SessionStore.isTenantAdmin(this.props.gateway.getTenantId()) || + SessionStore.isTenantGatewayAdmin(this.props.gateway.getTenantId()) ); + return ; } } diff --git a/ui/src/views/gateways/GatewayCertificate.tsx b/ui/src/views/gateways/GatewayCertificate.tsx index 93e02867..256da974 100644 --- a/ui/src/views/gateways/GatewayCertificate.tsx +++ b/ui/src/views/gateways/GatewayCertificate.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import moment from "moment"; -import { Card, Button, Form, Input } from 'antd'; +import { Card, Button, Form, Input } from "antd"; import { Gateway, @@ -10,17 +10,15 @@ import { } from "@chirpstack/chirpstack-api-grpc-web/api/gateway_pb"; import GatewayStore from "../../stores/GatewayStore"; - interface IProps { gateway: Gateway; } interface IState { - certificate?: GenerateGatewayClientCertificateResponse, + certificate?: GenerateGatewayClientCertificateResponse; buttonDisabled: boolean; } - class GatewayCertificate extends Component { constructor(props: IProps) { super(props); @@ -43,23 +41,29 @@ class GatewayCertificate extends Component { certificate: resp, }); }); - } + }; renderRequest = () => { - return( + return (

- The gateway client-certificate can be used to connect the gateway in case a client-certificate is required for authentication. - Please note that this feature might not be available in case it has not been configured in the server configuration. - After the certificate has been generated, store the content of the files on your gateway. - Please note the expiration of the certificate and make sure to renew the certificate on time! + The gateway client-certificate can be used to connect the gateway in case a client-certificate is required for + authentication. Please note that this feature might not be available in case it has not been configured in the + server configuration. After the certificate has been generated, store the content of the files on your + gateway. + + {" "} + Please note the expiration of the certificate and make sure to renew the certificate on time! +

- +

); - } + }; renderResponse = () => { const certificate = this.state.certificate!; @@ -71,44 +75,44 @@ class GatewayCertificate extends Component { tlsKey: certificate.getTlsKey(), }; - return( + return (
- + - + - + - + ); - } + }; render() { if (this.state.certificate !== undefined) { return this.renderResponse(); - } + } return this.renderRequest(); } diff --git a/ui/src/views/gateways/GatewayDashboard.tsx b/ui/src/views/gateways/GatewayDashboard.tsx index bb111223..f990184c 100644 --- a/ui/src/views/gateways/GatewayDashboard.tsx +++ b/ui/src/views/gateways/GatewayDashboard.tsx @@ -16,7 +16,6 @@ import GatewayStore from "../../stores/GatewayStore"; import Map, { Marker } from "../../components/Map"; import Heatmap from "../../components/Heatmap"; - interface HeatmapStats { x: string; y: Array<[string, number]>; @@ -37,7 +36,6 @@ interface IState { statsDownStatus?: any; } - class GatewayDashboard extends Component { constructor(props: IProps) { super(props); @@ -149,22 +147,34 @@ class GatewayDashboard extends Component { statsUpFreq.push({ x: moment(row.getTime()!.toDate()).format("YYYY-MM-DD"), - y: row.getRxPacketsPerFrequencyMap().toObject().map(v => [v[0].toString(), v[1]]), + y: row + .getRxPacketsPerFrequencyMap() + .toObject() + .map(v => [v[0].toString(), v[1]]), }); statsDownFreq.push({ x: moment(row.getTime()!.toDate()).format("YYYY-MM-DD"), - y: row.getTxPacketsPerFrequencyMap().toObject().map(v => [v[0].toString(), v[1]]), + y: row + .getTxPacketsPerFrequencyMap() + .toObject() + .map(v => [v[0].toString(), v[1]]), }); statsUpDr.push({ x: moment(row.getTime()!.toDate()).format("YYYY-MM-DD"), - y: row.getRxPacketsPerDrMap().toObject().map(v => [v[0].toString(), v[1]]), + y: row + .getRxPacketsPerDrMap() + .toObject() + .map(v => [v[0].toString(), v[1]]), }); statsDownDr.push({ x: moment(row.getTime()!.toDate()).format("YYYY-MM-DD"), - y: row.getTxPacketsPerDrMap().toObject().map(v => [v[0].toString(), v[1]]), + y: row + .getTxPacketsPerDrMap() + .toObject() + .map(v => [v[0].toString(), v[1]]), }); for (const v of row.getTxPacketsPerStatusMap().toObject()) { @@ -179,7 +189,23 @@ class GatewayDashboard extends Component { } } - let backgroundColors = ['#8bc34a', '#ff5722', '#ff9800', '#ffc107', '#ffeb3b', '#cddc39', '#4caf50', '#009688', '#00bcd4', '#03a9f4', '#2196f3', '#3f51b5', '#673ab7', '#9c27b0', '#e91e63']; + let backgroundColors = [ + "#8bc34a", + "#ff5722", + "#ff9800", + "#ffc107", + "#ffeb3b", + "#cddc39", + "#4caf50", + "#009688", + "#00bcd4", + "#03a9f4", + "#2196f3", + "#3f51b5", + "#673ab7", + "#9c27b0", + "#e91e63", + ]; Object.entries(statsDownStatusSet).forEach(([k, v]) => { statsDownStatus.datasets.push({ label: k, @@ -198,13 +224,11 @@ class GatewayDashboard extends Component { statsDownStatus: statsDownStatus, }); }); - } + }; render() { const loc = this.props.gateway.getLocation()!; - const location: [number, number] = [ - loc.getLatitude(), loc.getLongitude() - ]; + const location: [number, number] = [loc.getLatitude(), loc.getLongitude()]; const animation: false = false; const unit: TimeUnit = "day"; @@ -258,67 +282,71 @@ class GatewayDashboard extends Component { lastSeenAt = moment(this.props.lastSeenAt).format("YYYY-MM-DD HH:mm:ss"); } - return( - - - - {lastSeenAt} - {this.props.gateway.getPropertiesMap().get("region_name")} - {this.props.gateway.getPropertiesMap().get("region_common_name")} - {this.props.gateway.getDescription()} - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + return ( + + + + {lastSeenAt} + + {this.props.gateway.getPropertiesMap().get("region_name")} + + + {this.props.gateway.getPropertiesMap().get("region_common_name")} + + {this.props.gateway.getDescription()} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); } } diff --git a/ui/src/views/gateways/GatewayForm.tsx b/ui/src/views/gateways/GatewayForm.tsx index 69cf4ea6..050809b3 100644 --- a/ui/src/views/gateways/GatewayForm.tsx +++ b/ui/src/views/gateways/GatewayForm.tsx @@ -1,8 +1,7 @@ import React, { Component } from "react"; import { Form, Input, Row, Col, Button, Tabs } from "antd"; -import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; - +import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons"; import { Location } from "@chirpstack/chirpstack-api-grpc-web/common/common_pb"; import { Gateway } from "@chirpstack/chirpstack-api-grpc-web/api/gateway_pb"; @@ -11,7 +10,6 @@ import EuiInput from "../../components/EuiInput"; import Map, { Marker } from "../../components/Map"; import LocationStore from "../../stores/LocationStore"; - interface IProps { initialValues: Gateway; onFinish: (obj: Gateway) => void; @@ -24,7 +22,6 @@ interface IState { lonValue: number; } - class GatewayForm extends Component { formRef = React.createRef(); @@ -39,10 +36,13 @@ class GatewayForm extends Component { componentDidMount() { if (!this.props.update) { LocationStore.getLocation((loc: [number, number]) => { - this.setState({ - latValue: loc[0], - lonValue: loc[1], - }, this.setLocationFields); + this.setState( + { + latValue: loc[0], + lonValue: loc[1], + }, + this.setLocationFields, + ); }); } else { const loc = this.props.initialValues.getLocation(); @@ -65,7 +65,6 @@ class GatewayForm extends Component { loc.setLongitude(v.location.longitude); } - gw.setTenantId(v.tenantId); gw.setName(v.name); gw.setDescription(v.description); @@ -78,16 +77,19 @@ class GatewayForm extends Component { } this.props.onFinish(gw); - } + }; updateLocation = (e: any) => { const loc = e.target.getLatLng(); - this.setState({ - latValue: loc.lat, - lonValue: loc.lng, - }, this.setLocationFields); - } + this.setState( + { + latValue: loc.lat, + lonValue: loc.lng, + }, + this.setLocationFields, + ); + }; setLocationFields = () => { this.formRef.current.setFieldsValue({ @@ -96,26 +98,24 @@ class GatewayForm extends Component { longitude: this.state.lonValue, }, }); - } + }; render() { const location: [number, number] = [this.state.latValue, this.state.lonValue]; - return( -
+ return ( + - + - + { disabled={this.props.update || this.props.disabled} required /> - - - + + + + + + + - + - {(fields, { add, remove }) => ( + {(fields, { add, remove }) => ( <> {fields.map(( {key, name, ...restField} ) => ( @@ -147,7 +155,7 @@ class GatewayForm extends Component { {...restField} name={[name, 0]} fieldKey={[name, 0]} - rules={[{ required: true, message: 'Please enter a key!' }]} + rules={[{ required: true, message: "Please enter a key!" }]} > @@ -157,18 +165,24 @@ class GatewayForm extends Component { {...restField} name={[name, 1]} fieldKey={[name, 1]} - rules={[{ required: true, message: 'Please enter a value!' }]} + rules={[{ required: true, message: "Please enter a value!" }]} > -
- remove(name)} disabled={this.props.disabled} /> - + + remove(name)} disabled={this.props.disabled} /> + ))} - @@ -178,7 +192,9 @@ class GatewayForm extends Component { - + ); diff --git a/ui/src/views/gateways/GatewayFrames.tsx b/ui/src/views/gateways/GatewayFrames.tsx index dba303ad..26bb76f4 100644 --- a/ui/src/views/gateways/GatewayFrames.tsx +++ b/ui/src/views/gateways/GatewayFrames.tsx @@ -6,14 +6,13 @@ import { StreamGatewayFramesRequest, LogItem } from "@chirpstack/chirpstack-api- import InternalStore from "../../stores/InternalStore"; import LogTable from "../../components/LogTable"; - interface IProps { gateway: Gateway; } interface IState { frames: LogItem[]; - cancelFunc?: () => void, + cancelFunc?: () => void; } class GatewayFrames extends Component { @@ -44,7 +43,7 @@ class GatewayFrames extends Component { this.setState({ cancelFunc: cancelFunc, }); - } + }; onMessage = (l: LogItem) => { let frames = this.state.frames; @@ -55,10 +54,10 @@ class GatewayFrames extends Component { frames: frames, }); } - } + }; render() { - return(); + return ; } } diff --git a/ui/src/views/gateways/GatewayLayout.tsx b/ui/src/views/gateways/GatewayLayout.tsx index ffe5cf4b..5c771dd6 100644 --- a/ui/src/views/gateways/GatewayLayout.tsx +++ b/ui/src/views/gateways/GatewayLayout.tsx @@ -4,7 +4,12 @@ import { Route, Switch, RouteComponentProps, Link } from "react-router-dom"; import { Space, Breadcrumb, Card, Button, PageHeader, Menu } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; -import { Gateway, GetGatewayRequest, GetGatewayResponse, DeleteGatewayRequest } from "@chirpstack/chirpstack-api-grpc-web/api/gateway_pb"; +import { + Gateway, + GetGatewayRequest, + GetGatewayResponse, + DeleteGatewayRequest, +} from "@chirpstack/chirpstack-api-grpc-web/api/gateway_pb"; import GatewayStore from "../../stores/GatewayStore"; import DeleteConfirm from "../../components/DeleteConfirm"; @@ -16,7 +21,6 @@ import GatewayCertificate from "./GatewayCertificate"; import Admin from "../../components/Admin"; import SessionStore from "../../stores/SessionStore"; - interface MatchParams { gatewayId: string; } @@ -30,7 +34,6 @@ interface IState { lastSeenAt?: Date; } - class GatewayLayout extends Component { constructor(props: IProps) { super(props); @@ -56,7 +59,7 @@ class GatewayLayout extends Component { }); } }); - } + }; deleteGateway = () => { let req = new DeleteGatewayRequest(); @@ -65,7 +68,7 @@ class GatewayLayout extends Component { GatewayStore.delete(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/gateways`); }); - } + }; render() { const tenant = this.props.tenant; @@ -87,53 +90,86 @@ class GatewayLayout extends Component { tab = "frames"; } - let isGatewayAdmin = SessionStore.isAdmin() || SessionStore.isTenantAdmin(this.props.tenant.getId()) || SessionStore.isTenantGatewayAdmin(this.props.tenant.getId()); + let isGatewayAdmin = + SessionStore.isAdmin() || + SessionStore.isTenantAdmin(this.props.tenant.getId()) || + SessionStore.isTenantGatewayAdmin(this.props.tenant.getId()); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Gateways + + Gateways + {gw.getName()} - } + + )} title={gw.getName()} subTitle={`gateway id: ${gw.getGatewayId()}`} extra={[ - - + + - + , ]} /> - - - Dashboard - Configuration - {isGatewayAdmin &&TLS certificate} - LoRaWAN frames - - - } /> - } /> - } /> - } /> - - + + + + Dashboard + + + Configuration + + {isGatewayAdmin && ( + + TLS certificate + + )} + + LoRaWAN frames + + + + } + /> + } + /> + } + /> + } + /> + + ); } diff --git a/ui/src/views/gateways/ListGateways.tsx b/ui/src/views/gateways/ListGateways.tsx index 5c6f6691..54d2edc6 100644 --- a/ui/src/views/gateways/ListGateways.tsx +++ b/ui/src/views/gateways/ListGateways.tsx @@ -5,19 +5,21 @@ import moment from "moment"; import { Space, Breadcrumb, Button, PageHeader } from "antd"; import { ColumnsType } from "antd/es/table"; -import { ListGatewaysRequest, ListGatewaysResponse, GatewayListItem } from "@chirpstack/chirpstack-api-grpc-web/api/gateway_pb"; +import { + ListGatewaysRequest, + ListGatewaysResponse, + GatewayListItem, +} from "@chirpstack/chirpstack-api-grpc-web/api/gateway_pb"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import GatewayStore from "../../stores/GatewayStore"; import Admin from "../../components/Admin"; - interface IProps { tenant: Tenant; } - class ListGateways extends Component { columns = (): ColumnsType => { return [ @@ -32,8 +34,8 @@ class ListGateways extends Component { ts.setUTCSeconds(record.lastSeenAt.seconds); return moment(ts).format("YYYY-MM-DD HH:mm:ss"); } - return "Never"; - } + return "Never"; + }, }, { title: "Gateway ID", @@ -80,7 +82,7 @@ class ListGateways extends Component { }, }, ]; - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListGatewaysRequest(); @@ -92,38 +94,40 @@ class ListGateways extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } + }; render() { - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + Gateways - } - extra={[ - - - - ]} - /> - + )} + extra={[ + + + , + ]} /> + ); } } -export default ListGateways; \ No newline at end of file +export default ListGateways; diff --git a/ui/src/views/helpers.ts b/ui/src/views/helpers.ts index 1b89a088..1ce9e164 100644 --- a/ui/src/views/helpers.ts +++ b/ui/src/views/helpers.ts @@ -1,7 +1,7 @@ import { MacVersion, RegParamsRevision } from "@chirpstack/chirpstack-api-grpc-web/common/common_pb"; export function formatMacVersion(m: MacVersion) { - switch(m) { + switch (m) { case MacVersion.LORAWAN_1_0_0: return "LoRaWAN 1.0.0"; case MacVersion.LORAWAN_1_0_1: @@ -20,7 +20,7 @@ export function formatMacVersion(m: MacVersion) { } export function formatRegParamsRevision(r: RegParamsRevision) { - switch(r) { + switch (r) { case RegParamsRevision.A: return "A"; case RegParamsRevision.B: @@ -38,8 +38,7 @@ export function formatRegParamsRevision(r: RegParamsRevision) { return ""; } - -export function getEnumName(enums: {[key: number]: string}, index: number) { +export function getEnumName(enums: { [key: number]: string }, index: number) { for (const [k, v] of Object.entries(enums)) { // This is weird. 'typeof v' returns 'number', but 'v === 0' errors // that v (string) can't be compared to number. diff --git a/ui/src/views/multicast-groups/CreateMulticastGroup.tsx b/ui/src/views/multicast-groups/CreateMulticastGroup.tsx index 5dfaa385..920703a2 100644 --- a/ui/src/views/multicast-groups/CreateMulticastGroup.tsx +++ b/ui/src/views/multicast-groups/CreateMulticastGroup.tsx @@ -5,18 +5,20 @@ import { Space, Breadcrumb, Card, PageHeader } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import { Application } from "@chirpstack/chirpstack-api-grpc-web/api/application_pb"; -import { CreateMulticastGroupRequest, CreateMulticastGroupResponse, MulticastGroup } from "@chirpstack/chirpstack-api-grpc-web/api/multicast_group_pb"; +import { + CreateMulticastGroupRequest, + CreateMulticastGroupResponse, + MulticastGroup, +} from "@chirpstack/chirpstack-api-grpc-web/api/multicast_group_pb"; import MulticastGroupForm from "./MulticastGroupForm"; import MulticastGroupStore from "../../stores/MulticastGroupStore"; - interface IProps extends RouteComponentProps { tenant: Tenant; application: Application; } - class CreateMulticastGroup extends Component { onFinish = (obj: MulticastGroup) => { obj.setApplicationId(this.props.application.getId()); @@ -25,34 +27,46 @@ class CreateMulticastGroup extends Component { req.setMulticastGroup(obj); MulticastGroupStore.create(req, (resp: CreateMulticastGroupResponse) => { - this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/multicast-groups`); + this.props.history.push( + `/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/multicast-groups`, + ); }); - } + }; render() { let multicastGroup = new MulticastGroup(); multicastGroup.setApplicationId(this.props.application.getId()); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Applications + + Applications + - {this.props.application.getName()} + + + {this.props.application.getName()} + + Add multicast-group - } + + )} title="Add multicast-group" /> diff --git a/ui/src/views/multicast-groups/EditMulticastGroup.tsx b/ui/src/views/multicast-groups/EditMulticastGroup.tsx index 9a0ffaa5..1b9ad32f 100644 --- a/ui/src/views/multicast-groups/EditMulticastGroup.tsx +++ b/ui/src/views/multicast-groups/EditMulticastGroup.tsx @@ -11,13 +11,11 @@ import MulticastGroupStore from "../../stores/MulticastGroupStore"; import MulticastGroupForm from "./MulticastGroupForm"; import SessionStore from "../../stores/SessionStore"; - interface IProps extends RouteComponentProps { multicastGroup: MulticastGroup; application: Application; } - class EditMulticastGroup extends Component { onFinish = (obj: MulticastGroup) => { let req = new UpdateMulticastGroupRequest(); @@ -26,12 +24,16 @@ class EditMulticastGroup extends Component { MulticastGroupStore.update(req, () => { this.props.history.push(`../${this.props.multicastGroup.getId()}`); }); - } + }; render() { - let disabled = !(SessionStore.isAdmin() || SessionStore.isTenantAdmin(this.props.application.getTenantId()) || SessionStore.isTenantDeviceAdmin(this.props.application.getTenantId())); + let disabled = !( + SessionStore.isAdmin() || + SessionStore.isTenantAdmin(this.props.application.getTenantId()) || + SessionStore.isTenantDeviceAdmin(this.props.application.getTenantId()) + ); - return( + return ( ); } diff --git a/ui/src/views/multicast-groups/ListMulticastGroupDevices.tsx b/ui/src/views/multicast-groups/ListMulticastGroupDevices.tsx index c20e192c..3a8bd889 100644 --- a/ui/src/views/multicast-groups/ListMulticastGroupDevices.tsx +++ b/ui/src/views/multicast-groups/ListMulticastGroupDevices.tsx @@ -9,7 +9,7 @@ import { DeviceListItem, } from "@chirpstack/chirpstack-api-grpc-web/api/device_pb"; -import { +import { MulticastGroup, RemoveDeviceFromMulticastGroupRequest, } from "@chirpstack/chirpstack-api-grpc-web/api/multicast_group_pb"; @@ -18,7 +18,6 @@ import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import DeviceStore from "../../stores/DeviceStore"; import MulticastGroupStore from "../../stores/MulticastGroupStore"; - interface IProps { multicastGroup: MulticastGroup; } @@ -28,7 +27,6 @@ interface IState { refreshKey: number; } - class ListMulticastGroupDevices extends Component { columns = (): ColumnsType => { return [ @@ -44,7 +42,7 @@ class ListMulticastGroupDevices extends Component { width: 250, }, ]; - } + }; constructor(props: IProps) { super(props); @@ -59,7 +57,7 @@ class ListMulticastGroupDevices extends Component { this.setState({ selectedRowIds: ids, }); - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListDevicesRequest(); @@ -72,10 +70,10 @@ class ListMulticastGroupDevices extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } + }; removeDevicesFromMulticastGroup = () => { - if(!window.confirm("Are you sure you want to remove the selected devices from the multicast-group?")) { + if (!window.confirm("Are you sure you want to remove the selected devices from the multicast-group?")) { return; } @@ -101,13 +99,15 @@ class ListMulticastGroupDevices extends Component { MulticastGroupStore.removeDevice(req, cbFunc(count)); } - } + }; render() { - return( - - - + return ( + + + { columns = (): ColumnsType => { return [ @@ -33,8 +30,14 @@ class ListMulticastGroups extends Component { dataIndex: "name", key: "name", render: (text, record) => ( - {text} - ) + + {text} + + ), }, { title: "Region", @@ -55,7 +58,7 @@ class ListMulticastGroups extends Component { }, }, ]; - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListMulticastGroupsRequest(); @@ -67,21 +70,21 @@ class ListMulticastGroups extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } + }; render() { - return( - + return ( + - - + ); } diff --git a/ui/src/views/multicast-groups/MulticastGroupForm.tsx b/ui/src/views/multicast-groups/MulticastGroupForm.tsx index 617c0f60..207146b9 100644 --- a/ui/src/views/multicast-groups/MulticastGroupForm.tsx +++ b/ui/src/views/multicast-groups/MulticastGroupForm.tsx @@ -7,7 +7,6 @@ import { MulticastGroup, MulticastGroupType } from "@chirpstack/chirpstack-api-g import AesKeyInput from "../../components/AesKeyInput"; import DevAddrInput from "../../components/DevAddrInput"; - interface IProps { initialValues: MulticastGroup; onFinish: (obj: MulticastGroup) => void; @@ -18,7 +17,6 @@ interface IState { selectPingSlotPeriod: boolean; } - class MulticastGroupForm extends Component { formRef = React.createRef(); @@ -46,27 +44,32 @@ class MulticastGroupForm extends Component { mg.setClassBPingSlotPeriod(v.classBPingSlotPeriod); this.props.onFinish(mg); - } + }; onGroupTypeChange = (groupType: MulticastGroupType) => { this.setState({ selectPingSlotPeriod: groupType === MulticastGroupType.CLASS_B, }); - } + }; render() { - return( -
+ return ( + - + { - +
@@ -114,9 +117,9 @@ class MulticastGroupForm extends Component { label="Frequency (Hz)" name="frequency" tooltip="The frequency to use when transmitting the multicast frames. Please refer to the LoRaWAN Regional Parameters specification for valid values." - rules={[{required: true, message: "Please enter a frequency!"}]} + rules={[{ required: true, message: "Please enter a frequency!" }]} > - + @@ -126,7 +129,7 @@ class MulticastGroupForm extends Component { label="Group type" name="groupType" tooltip="The multicast-group type defines the way how multicast frames are scheduled by the network-server." - rules={[{required: true, message: "Please select a group-type!"}]} + rules={[{ required: true, message: "Please select a group-type!" }]} > Every second Every 2 seconds @@ -153,7 +153,9 @@ class MulticastGroupForm extends Component { - + ); diff --git a/ui/src/views/multicast-groups/MulticastGroupLayout.tsx b/ui/src/views/multicast-groups/MulticastGroupLayout.tsx index 00b9e4bb..e0d866b9 100644 --- a/ui/src/views/multicast-groups/MulticastGroupLayout.tsx +++ b/ui/src/views/multicast-groups/MulticastGroupLayout.tsx @@ -18,23 +18,19 @@ import ListMulticastGroupDevices from "./ListMulticastGroupDevices"; import EditMulticastGroup from "./EditMulticastGroup"; import Admin from "../../components/Admin"; - interface MatchParams { multicastGroupId: string; } - interface IProps extends RouteComponentProps { tenant: Tenant; application: Application; } - interface IState { multicastGroup?: MulticastGroup; } - class MulticastGroupLayout extends Component { constructor(props: IProps) { super(props); @@ -50,16 +46,18 @@ class MulticastGroupLayout extends Component { multicastGroup: resp.getMulticastGroup(), }); }); - } + } deleteMulticastGroup = () => { let req = new DeleteMulticastGroupRequest(); req.setId(this.props.match.params.multicastGroupId); MulticastGroupStore.delete(req, () => { - this.props.history.push(`/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/multicast-groups`); + this.props.history.push( + `/tenants/${this.props.tenant.getId()}/applications/${this.props.application.getId()}/multicast-groups`, + ); }); - } + }; render() { const tenant = this.props.tenant; @@ -77,52 +75,76 @@ class MulticastGroupLayout extends Component { tab = "edit"; } - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Applications + + Applications + - {app.getName()} + + {app.getName()} + - Multicast-groups + + + Multicast-groups + + - - {mg.getName()} - - } + {mg.getName()} + + )} title={app.getName()} subTitle={`multicast-group id: ${mg.getId()}`} extra={[ - - + + - + , ]} /> - - Devices - Configuration - - - } /> - } /> - + + + + Devices + + + + + Configuration + + + + + } + /> + } + /> + ); diff --git a/ui/src/views/tenants/CreateTenant.tsx b/ui/src/views/tenants/CreateTenant.tsx index 19579912..1bbfa23d 100644 --- a/ui/src/views/tenants/CreateTenant.tsx +++ b/ui/src/views/tenants/CreateTenant.tsx @@ -8,7 +8,6 @@ import { Tenant, CreateTenantRequest, CreateTenantResponse } from "@chirpstack/c import TenantForm from "./TenantForm"; import TenantStore from "../../stores/TenantStore"; - class CreateTenant extends Component { onFinish = (obj: Tenant) => { let req = new CreateTenantRequest(); @@ -17,25 +16,29 @@ class CreateTenant extends Component { TenantStore.create(req, (resp: CreateTenantResponse) => { this.props.history.push("/tenants/" + resp.getId()); }); - } + }; render() { const tenant = new Tenant(); - return( + return ( + breadcrumbRender={() => ( + Network-server - Tenants + + Tenants + Add - } + + )} title="Add tenant" /> diff --git a/ui/src/views/tenants/CreateTenantUser.tsx b/ui/src/views/tenants/CreateTenantUser.tsx index 0c8a543e..c841958a 100644 --- a/ui/src/views/tenants/CreateTenantUser.tsx +++ b/ui/src/views/tenants/CreateTenantUser.tsx @@ -8,12 +8,10 @@ import { Tenant, TenantUser, AddTenantUserRequest } from "@chirpstack/chirpstack import TenantUserForm from "./TenantUserForm"; import TenantStore from "../../stores/TenantStore"; - interface IProps extends RouteComponentProps { tenant: Tenant; } - class CreateTenantUser extends Component { onFinish = (obj: TenantUser) => { obj.setTenantId(this.props.tenant.getId()); @@ -24,28 +22,34 @@ class CreateTenantUser extends Component { TenantStore.addUser(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/users`); }); - } + }; render() { const tu = new TenantUser(); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Tenant users + + Tenant users + Add - } + + )} title="Add tenant user" /> diff --git a/ui/src/views/tenants/EditTenant.tsx b/ui/src/views/tenants/EditTenant.tsx index 04c81b7d..41af71a4 100644 --- a/ui/src/views/tenants/EditTenant.tsx +++ b/ui/src/views/tenants/EditTenant.tsx @@ -7,30 +7,26 @@ import TenantStore from "../../stores/TenantStore"; import TenantForm from "./TenantForm"; import SessionStore from "../../stores/SessionStore"; - interface IProps extends RouteComponentProps { tenant: Tenant; } interface IState {} - class EditTenant extends Component { onFinish = (obj: Tenant) => { let req = new UpdateTenantRequest(); req.setTenant(obj); TenantStore.update(req, () => { - this.props.history.push("/tenants/"+ obj.getId()); + this.props.history.push("/tenants/" + obj.getId()); }); - } + }; render() { const disabled = !SessionStore.isAdmin(); - return( - - ); + return ; } } diff --git a/ui/src/views/tenants/EditTenantUser.tsx b/ui/src/views/tenants/EditTenantUser.tsx index 1e2b5e32..cce9ee71 100644 --- a/ui/src/views/tenants/EditTenantUser.tsx +++ b/ui/src/views/tenants/EditTenantUser.tsx @@ -3,7 +3,14 @@ import { RouteComponentProps, Link } from "react-router-dom"; import { Space, Breadcrumb, Card, Button, PageHeader } from "antd"; -import { Tenant, TenantUser, GetTenantUserRequest, GetTenantUserResponse, UpdateTenantUserRequest, DeleteTenantUserRequest } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; +import { + Tenant, + TenantUser, + GetTenantUserRequest, + GetTenantUserResponse, + UpdateTenantUserRequest, + DeleteTenantUserRequest, +} from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import TenantUserForm from "./TenantUserForm"; import TenantStore from "../../stores/TenantStore"; @@ -11,7 +18,6 @@ import SessionStore from "../../stores/SessionStore"; import DeleteConfirm from "../../components/DeleteConfirm"; import Admin from "../../components/Admin"; - interface IState { tenantUser?: TenantUser; } @@ -24,7 +30,6 @@ interface IProps extends RouteComponentProps { tenant: Tenant; } - class EditTenantUser extends Component { constructor(props: IProps) { super(props); @@ -46,7 +51,7 @@ class EditTenantUser extends Component { tenantUser: resp.getTenantUser(), }); }); - } + }; onFinish = (obj: TenantUser) => { let req = new UpdateTenantUserRequest(); @@ -55,7 +60,7 @@ class EditTenantUser extends Component { TenantStore.updateUser(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/users`); }); - } + }; deleteTenantUser = () => { let req = new DeleteTenantUserRequest(); @@ -65,7 +70,7 @@ class EditTenantUser extends Component { TenantStore.deleteUser(req, () => { this.props.history.push(`/tenants/${this.props.tenant.getId()}/users`); }); - } + }; render() { const tu = this.state.tenantUser; @@ -76,35 +81,39 @@ class EditTenantUser extends Component { const disabled = !(SessionStore.isAdmin() || SessionStore.isTenantAdmin(this.props.tenant.getId())); - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + - Tenant users + + Tenant users + {tu.getEmail()} - } + + )} title={tu.getEmail()} subTitle={`user id: ${tu.getUserId()}`} extra={[ - - + + - + , ]} /> diff --git a/ui/src/views/tenants/ListTenantUsers.tsx b/ui/src/views/tenants/ListTenantUsers.tsx index ef14ab8d..fec3c0e5 100644 --- a/ui/src/views/tenants/ListTenantUsers.tsx +++ b/ui/src/views/tenants/ListTenantUsers.tsx @@ -4,21 +4,23 @@ import { Link } from "react-router-dom"; import { Space, Breadcrumb, Button, PageHeader } from "antd"; import { ColumnsType } from "antd/es/table"; -import { ListTenantUsersRequest, ListTenantUsersResponse, TenantUserListItem } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; +import { + ListTenantUsersRequest, + ListTenantUsersResponse, + TenantUserListItem, +} from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import TenantStore from "../../stores/TenantStore"; import Admin from "../../components/Admin"; - interface IProps { tenant: Tenant; } interface IState {} - class ListTenantUsers extends Component { columns = (): ColumnsType => { return [ @@ -67,7 +69,7 @@ class ListTenantUsers extends Component { }, }, ]; - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListTenantUsersRequest(); @@ -79,35 +81,37 @@ class ListTenantUsers extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } + }; render() { - return( - + return ( + + breadcrumbRender={() => ( + Tenants - {this.props.tenant.getName()} + + {this.props.tenant.getName()} + Tenant users - } + + )} title="Tenant users" extra={[ - - + + , ]} /> - + ); } diff --git a/ui/src/views/tenants/ListTenants.tsx b/ui/src/views/tenants/ListTenants.tsx index a1c2a8cb..b76c3ed5 100644 --- a/ui/src/views/tenants/ListTenants.tsx +++ b/ui/src/views/tenants/ListTenants.tsx @@ -5,22 +5,23 @@ import { Link } from "react-router-dom"; import { Space, Breadcrumb, Button, PageHeader } from "antd"; import { ColumnsType } from "antd/es/table"; -import { ListTenantsRequest, ListTenantsResponse, TenantListItem } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; +import { + ListTenantsRequest, + ListTenantsResponse, + TenantListItem, +} from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import TenantStore from "../../stores/TenantStore"; - class ListTenants extends Component { columns = (): ColumnsType => { - return[ + return [ { title: "Name", dataIndex: "name", key: "name", - render: (text, record) => ( - {text} - ), + render: (text, record) => {text}, }, { title: "Can have gateways", @@ -79,7 +80,7 @@ class ListTenants extends Component { }, }, ]; - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListTenantsRequest(); @@ -88,32 +89,32 @@ class ListTenants extends Component { TenantStore.list(req, (resp: ListTenantsResponse) => { const obj = resp.toObject(); - callbackFunc(obj.totalCount, obj.resultList); + callbackFunc(obj.totalCount, obj.resultList); }); - } + }; render() { - return( + return ( + breadcrumbRender={() => ( + Network-server Tenants - } + + )} title="Tenants" extra={[ - + , ]} /> - + ); } diff --git a/ui/src/views/tenants/TenantDashboard.tsx b/ui/src/views/tenants/TenantDashboard.tsx index 8c9fc750..f92d8af9 100644 --- a/ui/src/views/tenants/TenantDashboard.tsx +++ b/ui/src/views/tenants/TenantDashboard.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { presetPalettes } from '@ant-design/colors'; +import { presetPalettes } from "@ant-design/colors"; import { Card, Col, Row, Space, Empty } from "antd"; import moment from "moment"; @@ -24,12 +24,10 @@ import { GatewayListItem, } from "@chirpstack/chirpstack-api-grpc-web/api/gateway_pb"; - import InternalStore from "../../stores/InternalStore"; import GatewayStore from "../../stores/GatewayStore"; import Map, { Marker, MarkerColor } from "../../components/Map"; - interface GatewaysMapProps { items: GatewayListItem[]; } @@ -37,13 +35,11 @@ interface GatewaysMapProps { class GatewaysMap extends Component { render() { if (this.props.items.length === 0) { - return( - - ); + return ; } const boundsOptions: { - padding: PointTuple, + padding: PointTuple; } = { padding: [50, 50], }; @@ -65,7 +61,7 @@ class GatewaysMap extends Component { if (item.getLastSeenAt() !== undefined) { let ts = moment(item.getLastSeenAt()!.toDate()); lastSeen = ts.fromNow(); - if (ts.isBefore(moment().subtract(5, 'minutes'))) { + if (ts.isBefore(moment().subtract(5, "minutes"))) { color = "red"; } else { color = "green"; @@ -75,15 +71,18 @@ class GatewaysMap extends Component { markers.push( - {item.getName()}
- {item.getGatewayId()}

+ {item.getName()} +
+ {item.getGatewayId()} +
+
{lastSeen}
-
+ , ); } - return( + return ( {markers} @@ -91,17 +90,18 @@ class GatewaysMap extends Component { } } - interface GatewayProps { summary?: GetGatewaysSummaryResponse; } class GatewaysActiveInactive extends Component { render() { - if (this.props.summary === undefined || ( - this.props.summary.getNeverSeenCount() === 0 && - this.props.summary.getInactiveCount() === 0 && - this.props.summary.getActiveCount() === 0)) { + if ( + this.props.summary === undefined || + (this.props.summary.getNeverSeenCount() === 0 && + this.props.summary.getInactiveCount() === 0 && + this.props.summary.getActiveCount() === 0) + ) { return ; } @@ -109,13 +109,13 @@ class GatewaysActiveInactive extends Component { labels: ["Never seen", "Inactive", "Active"], datasets: [ { - data: [this.props.summary.getNeverSeenCount(), this.props.summary.getInactiveCount(), this.props.summary.getActiveCount()], - backgroundColor: [ - presetPalettes.orange.primary, - presetPalettes.red.primary, - presetPalettes.green.primary, + data: [ + this.props.summary.getNeverSeenCount(), + this.props.summary.getInactiveCount(), + this.props.summary.getActiveCount(), ], - } + backgroundColor: [presetPalettes.orange.primary, presetPalettes.red.primary, presetPalettes.green.primary], + }, ], }; @@ -125,24 +125,22 @@ class GatewaysActiveInactive extends Component { animation: false, }; - return( - - ); + return ; } } - interface DeviceProps { summary?: GetDevicesSummaryResponse; } class DevicesActiveInactive extends Component { render() { - if (this.props.summary === undefined || ( - this.props.summary.getNeverSeenCount() === 0 && - this.props.summary.getInactiveCount() === 0 && - this.props.summary.getActiveCount() === 0 - )) { + if ( + this.props.summary === undefined || + (this.props.summary.getNeverSeenCount() === 0 && + this.props.summary.getInactiveCount() === 0 && + this.props.summary.getActiveCount() === 0) + ) { return ; } @@ -150,13 +148,13 @@ class DevicesActiveInactive extends Component { labels: ["Never seen", "Inactive", "Active"], datasets: [ { - data: [this.props.summary.getNeverSeenCount(), this.props.summary.getInactiveCount(), this.props.summary.getActiveCount()], - backgroundColor: [ - presetPalettes.orange.primary, - presetPalettes.red.primary, - presetPalettes.green.primary, + data: [ + this.props.summary.getNeverSeenCount(), + this.props.summary.getInactiveCount(), + this.props.summary.getActiveCount(), ], - } + backgroundColor: [presetPalettes.orange.primary, presetPalettes.red.primary, presetPalettes.green.primary], + }, ], }; @@ -165,17 +163,31 @@ class DevicesActiveInactive extends Component { } = { animation: false, }; - - return( - - ); + + return ; } } class DevicesDataRates extends Component { getColor = (dr: number) => { - return ['#ff5722', '#ff9800', '#ffc107', '#ffeb3b', '#cddc39', '#8bc34a', '#4caf50', '#009688', '#00bcd4', '#03a9f4', '#2196f3', '#3f51b5', '#673ab7', '#9c27b0', '#e91e63'][dr]; - } + return [ + "#ff5722", + "#ff9800", + "#ffc107", + "#ffeb3b", + "#cddc39", + "#8bc34a", + "#4caf50", + "#009688", + "#00bcd4", + "#03a9f4", + "#2196f3", + "#3f51b5", + "#673ab7", + "#9c27b0", + "#e91e63", + ][dr]; + }; render() { if (this.props.summary === undefined || this.props.summary.getDrCountMap().toArray().length === 0) { @@ -183,17 +195,19 @@ class DevicesDataRates extends Component { } let data: { - labels: string[], + labels: string[]; datasets: { - data: number[], - backgroundColor: string[], - }[], + data: number[]; + backgroundColor: string[]; + }[]; } = { labels: [], - datasets: [{ - data: [], - backgroundColor: [], - }], + datasets: [ + { + data: [], + backgroundColor: [], + }, + ], }; for (const elm of this.props.summary.getDrCountMap().toArray()) { @@ -208,13 +222,10 @@ class DevicesDataRates extends Component { animation: false, }; - return( - - ); + return ; } } - interface IProps { tenant: Tenant; } @@ -279,11 +290,11 @@ class TenantDashboard extends Component { }); }); } - } + }; render() { - return( - + return ( +
@@ -301,7 +312,9 @@ class TenantDashboard extends Component { - + + + ); } diff --git a/ui/src/views/tenants/TenantForm.tsx b/ui/src/views/tenants/TenantForm.tsx index d748a463..597b666f 100644 --- a/ui/src/views/tenants/TenantForm.tsx +++ b/ui/src/views/tenants/TenantForm.tsx @@ -4,7 +4,6 @@ import { Form, Input, InputNumber, Switch, Row, Col, Button } from "antd"; import { Tenant } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; - interface IProps { initialValues: Tenant; onFinish: (obj: Tenant) => void; @@ -27,22 +26,15 @@ class TenantForm extends Component { tenant.setPrivateGateways(values.privateGateways); this.props.onFinish(tenant); - } + }; render() { - return( + return (
- + - + @@ -89,7 +81,9 @@ class TenantForm extends Component { - + ); diff --git a/ui/src/views/tenants/TenantLayout.tsx b/ui/src/views/tenants/TenantLayout.tsx index 421abe99..5139f1dc 100644 --- a/ui/src/views/tenants/TenantLayout.tsx +++ b/ui/src/views/tenants/TenantLayout.tsx @@ -11,14 +11,12 @@ import Admin from "../../components/Admin"; import TenantDashboard from "./TenantDashboard"; import EditTenant from "./EditTenant"; - interface IState {} interface IProps extends RouteComponentProps { tenant: Tenant; } - class TenantLayout extends Component { deleteTenant = () => { let req = new DeleteTenantRequest(); @@ -27,7 +25,7 @@ class TenantLayout extends Component { TenantStore.delete(req, () => { this.props.history.push("/tenants"); }); - } + }; render() { const tenant = this.props.tenant; @@ -39,40 +37,52 @@ class TenantLayout extends Component { tab = "edit"; } - return( - + return ( + + breadcrumbRender={() => ( + Tenants {tenant.getName()} - } + + )} title={tenant.getName()} subTitle={`tenant id: ${tenant.getId()}`} extra={[ - - + + - + , ]} /> - - Dashboard - Configuration + + + Dashboard + + + Configuration + - } /> - } /> + } + /> + } + /> diff --git a/ui/src/views/tenants/TenantLoader.tsx b/ui/src/views/tenants/TenantLoader.tsx index caae5b05..1194c177 100644 --- a/ui/src/views/tenants/TenantLoader.tsx +++ b/ui/src/views/tenants/TenantLoader.tsx @@ -22,7 +22,6 @@ import ListApplications from "../applications/ListApplications"; import CreateApplication from "../applications/CreateApplication"; import ApplicationLoader from "../applications/ApplicationLoader"; - interface IState { tenant?: Tenant; isAdmin: boolean; @@ -37,7 +36,6 @@ interface MatchParams { interface IProps extends RouteComponentProps {} - class TenantLoader extends Component { constructor(props: IProps) { super(props); @@ -79,7 +77,7 @@ class TenantLoader extends Component { tenant: resp.getTenant(), }); }); - } + }; setIsAdmin = () => { const tenantId = this.props.match.params.tenantId; @@ -87,10 +85,12 @@ class TenantLoader extends Component { this.setState({ isAdmin: SessionStore.isAdmin(), isTenantAdmin: SessionStore.isAdmin() || SessionStore.isTenantAdmin(tenantId), - isDeviceAdmin: SessionStore.isAdmin() || SessionStore.isTenantAdmin(tenantId) || SessionStore.isTenantDeviceAdmin(tenantId), - isGatewayAdmin: SessionStore.isAdmin() || SessionStore.isTenantAdmin(tenantId) || SessionStore.isTenantGatewayAdmin(tenantId), + isDeviceAdmin: + SessionStore.isAdmin() || SessionStore.isTenantAdmin(tenantId) || SessionStore.isTenantDeviceAdmin(tenantId), + isGatewayAdmin: + SessionStore.isAdmin() || SessionStore.isTenantAdmin(tenantId) || SessionStore.isTenantGatewayAdmin(tenantId), }); - } + }; render() { if (this.state.tenant === undefined) { @@ -98,24 +98,58 @@ class TenantLoader extends Component { } const path = this.props.match.path; - const tenant:Tenant = this.state.tenant!; + const tenant: Tenant = this.state.tenant!; return ( - } /> - } /> - } /> - } /> - } /> + } + /> + } + /> + } + /> + } + /> + } + /> } /> } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> + } + /> + } /> + } /> + } + /> + } /> + } + /> + } + /> } /> ); diff --git a/ui/src/views/tenants/TenantRedirect.tsx b/ui/src/views/tenants/TenantRedirect.tsx index 2d522a4e..c684db3c 100644 --- a/ui/src/views/tenants/TenantRedirect.tsx +++ b/ui/src/views/tenants/TenantRedirect.tsx @@ -6,7 +6,6 @@ import { ListTenantsRequest, ListTenantsResponse } from "@chirpstack/chirpstack- import TenantStore from "../../stores/TenantStore"; import SessionStore from "../../stores/SessionStore"; - class TenantRedirect extends Component { componentDidMount() { const tenantId = SessionStore.getTenantId(); @@ -25,7 +24,7 @@ class TenantRedirect extends Component { } render() { - return(null); + return null; } } diff --git a/ui/src/views/tenants/TenantUserForm.tsx b/ui/src/views/tenants/TenantUserForm.tsx index a4c14e4e..f535af29 100644 --- a/ui/src/views/tenants/TenantUserForm.tsx +++ b/ui/src/views/tenants/TenantUserForm.tsx @@ -4,7 +4,6 @@ import { Form, Input, Switch, Row, Col, Button } from "antd"; import { TenantUser } from "@chirpstack/chirpstack-api-grpc-web/api/tenant_pb"; - interface IProps { initialValues: TenantUser; onFinish: (obj: TenantUser) => void; @@ -16,7 +15,6 @@ interface IState { isAdmin: boolean; } - class TenantUserForm extends Component { constructor(props: IProps) { super(props); @@ -45,22 +43,22 @@ class TenantUserForm extends Component { tu.setTenantId(v.tenantId); this.props.onFinish(tu); - } + }; onIsAdminChange = (checked: boolean) => { this.setState({ isAdmin: checked, }); - } + }; render() { - return( + return (
@@ -72,30 +70,34 @@ class TenantUserForm extends Component { > - {!this.state.isAdmin && -
- - - - - - - - - - } + {!this.state.isAdmin && ( + + + + + + + + + + + + + )} - + ); diff --git a/ui/src/views/users/ChangeUserPassword.tsx b/ui/src/views/users/ChangeUserPassword.tsx index cb127afb..faa2b985 100644 --- a/ui/src/views/users/ChangeUserPassword.tsx +++ b/ui/src/views/users/ChangeUserPassword.tsx @@ -3,11 +3,15 @@ import { RouteComponentProps } from "react-router-dom"; import { Space, Breadcrumb, Card, PageHeader } from "antd"; -import { User, GetUserRequest, GetUserResponse, UpdateUserPasswordRequest } from "@chirpstack/chirpstack-api-grpc-web/api/user_pb"; +import { + User, + GetUserRequest, + GetUserResponse, + UpdateUserPasswordRequest, +} from "@chirpstack/chirpstack-api-grpc-web/api/user_pb"; import UserStore from "../../stores/UserStore"; import PasswordForm from "./PasswordForm"; - interface MatchParams { userId: string; } @@ -16,7 +20,6 @@ interface IState { user?: User; } - class ChangeUserPassword extends Component, IState> { constructor(props: RouteComponentProps) { super(props); @@ -42,7 +45,7 @@ class ChangeUserPassword extends Component, ISt UserStore.updatePassword(req, () => { this.props.history.push("/"); }); - } + }; render() { const user = this.state.user; @@ -50,10 +53,11 @@ class ChangeUserPassword extends Component, ISt return null; } - return( - + return ( + + breadcrumbRender={() => ( + Users @@ -63,7 +67,8 @@ class ChangeUserPassword extends Component, ISt Change password - } + + )} title={user.getEmail()} subTitle={`user id: ${user.getId()}`} /> diff --git a/ui/src/views/users/CreateUser.tsx b/ui/src/views/users/CreateUser.tsx index 645d0d0d..eb7ea6da 100644 --- a/ui/src/views/users/CreateUser.tsx +++ b/ui/src/views/users/CreateUser.tsx @@ -8,7 +8,6 @@ import { User, CreateUserRequest, CreateUserResponse } from "@chirpstack/chirpst import UserForm from "./UserForm"; import UserStore from "../../stores/UserStore"; - class CreateUser extends Component { onFinish = (obj: User, password: string) => { let req = new CreateUserRequest(); @@ -18,25 +17,29 @@ class CreateUser extends Component { UserStore.create(req, (resp: CreateUserResponse) => { this.props.history.push("/users"); }); - } + }; render() { const user = new User(); - return( + return ( + breadcrumbRender={() => ( + Network-server - Users + + Users + Add - } + + )} title="Add user" /> diff --git a/ui/src/views/users/EditUser.tsx b/ui/src/views/users/EditUser.tsx index 92ce9796..6ed33fa7 100644 --- a/ui/src/views/users/EditUser.tsx +++ b/ui/src/views/users/EditUser.tsx @@ -3,13 +3,18 @@ import { RouteComponentProps, Link } from "react-router-dom"; import { Space, Breadcrumb, Card, Button, PageHeader } from "antd"; -import { User, GetUserRequest, GetUserResponse, UpdateUserRequest, DeleteUserRequest } from "@chirpstack/chirpstack-api-grpc-web/api/user_pb"; +import { + User, + GetUserRequest, + GetUserResponse, + UpdateUserRequest, + DeleteUserRequest, +} from "@chirpstack/chirpstack-api-grpc-web/api/user_pb"; import UserForm from "./UserForm"; import UserStore from "../../stores/UserStore"; import DeleteConfirm from "../../components/DeleteConfirm"; - interface IState { user?: User; } @@ -18,7 +23,6 @@ interface MatchParams { userId: string; } - class EditUser extends Component, IState> { constructor(props: RouteComponentProps) { super(props); @@ -38,7 +42,7 @@ class EditUser extends Component, IState> { user: resp.getUser(), }); }); - } + }; onFinish = (obj: User, password: string) => { let req = new UpdateUserRequest(); @@ -47,7 +51,7 @@ class EditUser extends Component, IState> { UserStore.update(req, () => { this.props.history.push("/users"); }); - } + }; deleteUser = () => { if (!this.state.user) { @@ -60,7 +64,7 @@ class EditUser extends Component, IState> { UserStore.delete(req, () => { this.props.history.push("/users"); }); - } + }; render() { const user = this.state.user; @@ -68,31 +72,35 @@ class EditUser extends Component, IState> { return null; } - return( - + return ( + + breadcrumbRender={() => ( + Network-server - Users + + Users + {user.getEmail()} - } + + )} title={user.getEmail()} subTitle={`user id: ${user.getId()}`} extra={[ - , - - - + , + + + , ]} /> diff --git a/ui/src/views/users/ListUsers.tsx b/ui/src/views/users/ListUsers.tsx index 88c601d7..653c125d 100644 --- a/ui/src/views/users/ListUsers.tsx +++ b/ui/src/views/users/ListUsers.tsx @@ -11,7 +11,6 @@ import DataTable, { GetPageCallbackFunc } from "../../components/DataTable"; import UserStore from "../../stores/UserStore"; - class ListUsers extends Component { columns = (): ColumnsType => { return [ @@ -19,9 +18,7 @@ class ListUsers extends Component { title: "Email", dataIndex: "email", key: "email", - render: (text, record) => ( - {text} - ), + render: (text, record) => {text}, }, { title: "Is admin", @@ -50,7 +47,7 @@ class ListUsers extends Component { }, }, ]; - } + }; getPage = (limit: number, offset: number, callbackFunc: GetPageCallbackFunc) => { let req = new ListUsersRequest(); @@ -61,31 +58,30 @@ class ListUsers extends Component { const obj = resp.toObject(); callbackFunc(obj.totalCount, obj.resultList); }); - } - + }; render() { - return( - + return ( + + breadcrumbRender={() => ( + Network-server Users - } + + )} title="Users" extra={[ - + , ]} /> - + ); } diff --git a/ui/src/views/users/Login.tsx b/ui/src/views/users/Login.tsx index 6d0bab7c..7612311d 100644 --- a/ui/src/views/users/Login.tsx +++ b/ui/src/views/users/Login.tsx @@ -5,11 +5,7 @@ import { Form, Input, Button } from "antd"; import SessionStore from "../../stores/SessionStore"; import InternalStore from "../../stores/InternalStore"; -import { - SettingsResponse, - OpenIdConnectLoginRequest, -} from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; - +import { SettingsResponse, OpenIdConnectLoginRequest } from "@chirpstack/chirpstack-api-grpc-web/api/internal_pb"; const layout = { labelCol: { @@ -27,31 +23,26 @@ const tailLayout = { }, }; -interface LoginFormState {}; +interface LoginFormState {} interface LoginFormValues { email: string; password: string; -}; +} class LoginForm extends Component { onFinish = (values: LoginFormValues) => { SessionStore.login(values.email, values.password, () => { this.props.history.push("/"); }); - } + }; render() { return ( - + - -
+ + { - + @@ -93,22 +82,20 @@ class LoginForm extends Component { } } - interface OidcLoginProps { - loginUrl: string, - loginLabel: string, + loginUrl: string; + loginLabel: string; } - class OidcLogin extends Component { render() { - return( - + return ( +
- - + + + + @@ -116,7 +103,6 @@ class OidcLogin extends Component { } } - interface LoginState { loaded: boolean; oidcEnabled: boolean; @@ -167,9 +153,9 @@ class Login extends Component { } if (this.state.oidcEnabled) { - return + return ; } else { - return + return ; } } } diff --git a/ui/src/views/users/PasswordForm.tsx b/ui/src/views/users/PasswordForm.tsx index 3d83217c..b7018947 100644 --- a/ui/src/views/users/PasswordForm.tsx +++ b/ui/src/views/users/PasswordForm.tsx @@ -2,18 +2,15 @@ import React, { Component } from "react"; import { Form, Input, Button, notification } from "antd"; - interface FormValues { password: string; passwordConfirm: string; } - interface IProps { onFinish: (pw: string) => void; } - class PasswordForm extends Component { onFinish = (v: FormValues) => { if (v.password !== v.passwordConfirm) { @@ -24,27 +21,25 @@ class PasswordForm extends Component { } else { this.props.onFinish(v.password); } - } + }; render() { - return( + return ( - + - + ); diff --git a/ui/src/views/users/UserForm.tsx b/ui/src/views/users/UserForm.tsx index bc3b0152..cef18477 100644 --- a/ui/src/views/users/UserForm.tsx +++ b/ui/src/views/users/UserForm.tsx @@ -4,7 +4,6 @@ import { Form, Input, Switch, Row, Col, Button } from "antd"; import { User } from "@chirpstack/chirpstack-api-grpc-web/api/user_pb"; - interface IProps { initialValues: User; onFinish: (obj: User, password: string) => void; @@ -17,7 +16,6 @@ interface UserWithPassword extends User.AsObject { password: string; } - class UserForm extends Component { onFinish = (v: UserWithPassword) => { const values = Object.assign(this.props.initialValues.toObject(), v); @@ -30,53 +28,38 @@ class UserForm extends Component { user.setIsAdmin(values.isAdmin); this.props.onFinish(user, v.password); - } + }; render() { - return( + return (
- + - + - {this.props.password && - - } + {this.props.password && ( + + + + )}
- + - + - + ); diff --git a/ui/tsconfig.json b/ui/tsconfig.json index a273b0cf..9d379a3c 100644 --- a/ui/tsconfig.json +++ b/ui/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, @@ -20,7 +16,5 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": [ - "src" - ] + "include": ["src"] } diff --git a/ui/yarn.lock b/ui/yarn.lock index 529a34f4..720ce4d6 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -6013,6 +6013,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +husky@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" + integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -8476,6 +8481,16 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prepend-http@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prettier@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== + pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" @@ -8490,7 +8505,7 @@ pretty-error@^4.0.0: renderkid "^3.0.0" pretty-format@^26.0.0, pretty-format@^26.6.2: - version "26.6.2" + version "26.6.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== dependencies: