diff --git a/Makefile b/Makefile index c058ed0..9861398 100644 --- a/Makefile +++ b/Makefile @@ -17,9 +17,6 @@ build-server: build: build-ui build-server -generate-apiclient: - openapi-generator generate -i openapi.yml -g typescript-axios -o ${UI_DIR}/src/sebrauc-client -p "supportsES6=true" - clean: rm -f build/* rm -rf ${UI_DIR}/dist/** diff --git a/go.sum b/go.sum index 4188720..6bcb5c4 100644 --- a/go.sum +++ b/go.sum @@ -19,7 +19,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4 h1:ocK/D6lCgLji37Z2so4xhMl46se1ntReQQCUIU4BWI8= github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/openapi.yml b/openapi.yml index fe288c0..f55550d 100644 --- a/openapi.yml +++ b/openapi.yml @@ -118,10 +118,6 @@ components: SystemInfo: type: object properties: - hostname: - description: Hostname of the system - type: string - example: "raspberrypi3" os_name: description: Name of the os distribution type: string @@ -142,21 +138,21 @@ components: description: Compatible firmware variant type: string example: "rpi-prod" + rauc_booted: + description: Currently booted rootfs + type: string + example: "rootfs.0" + rauc_boot_primary: + description: Primary rootfs to boot from + type: string + example: "rootfs.1" rauc_rootfs: description: List of RAUC root filesystems type: object additionalProperties: - $ref: "#/components/schemas/Rootfs" - required: - - hostname - - os_name - - os_version - - uptime - - rauc_compatible - - rauc_variant - - rauc_rootfs + $ref: "#/components/schemas/RaucFS" - Rootfs: + RaucFS: type: object properties: device: @@ -167,6 +163,11 @@ components: description: Filesystem type: string example: ext4 + state: + description: Current state of filesystem + type: string + enum: [active, inactive, booted] + example: booted mountpoint: description: Mount path (null when not mounted) type: string @@ -175,19 +176,6 @@ components: bootable: description: "Is the filesystem bootable" type: boolean - booted: - description: "Is the filesystem booted" - type: boolean - primary: - description: "Is the filesystem the next boot target" - type: boolean - required: - - device - - type - - mountpoint - - bootable - - booted - - primary StatusMessage: type: object @@ -200,5 +188,4 @@ components: type: string example: Update started required: - - success - msg diff --git a/src/fixtures/rauc_mock/main.go b/src/fixtures/rauc_mock/main.go index 58986ff..4c9b884 100644 --- a/src/fixtures/rauc_mock/main.go +++ b/src/fixtures/rauc_mock/main.go @@ -41,34 +41,22 @@ LastError: Failed to check bundle identifier: Invalid identifier. ` + idle Installing ` + "/app/demo` failed" -const statusJson = `{"compatible":"TSGRain","variant":"dev","booted":"A",` + - `"boot_primary":"rootfs.0","slots":[{"rootfs.1":{"class":"rootfs",` + - `"device":"/dev/mmcblk0p3","type":"ext4","bootname":"B","state":"inactive",` + - `"parent":null,"mountpoint":null,"boot_status":"good"}},{"rootfs.0":` + - `{"class":"rootfs","device":"/dev/mmcblk0p2","type":"ext4","bootname":"A",` + - `"state":"booted","parent":null,"mountpoint":"/","boot_status":"good"}}]}` - -func printLinesWithDelay(lines string) { - for _, line := range strings.Split(lines, "\n") { - fmt.Println(line) - time.Sleep(500 * time.Millisecond) - } -} - func main() { arg := "" if len(os.Args) > 1 { arg = os.Args[1] } + var lines string switch arg { case "fail": - printLinesWithDelay(outputFailure) - case "install": - printLinesWithDelay(outputSuccess) - case "status": - fmt.Println(statusJson) + lines = outputFailure default: - os.Exit(1) + lines = outputSuccess + } + + for _, line := range strings.Split(lines, "\n") { + fmt.Println(line) + time.Sleep(500 * time.Millisecond) } } diff --git a/src/fixtures/testfiles/os-release b/src/fixtures/testfiles/os-release deleted file mode 100644 index 84a41a1..0000000 --- a/src/fixtures/testfiles/os-release +++ /dev/null @@ -1,5 +0,0 @@ -ID=tsgrain -NAME="TSGRain distro" -VERSION="0.0.1" -VERSION_ID=0.0.1 -PRETTY_NAME="TSGRain distro 0.0.1" diff --git a/src/rauc/rauc.go b/src/rauc/rauc.go index 3e021fe..7585285 100644 --- a/src/rauc/rauc.go +++ b/src/rauc/rauc.go @@ -70,7 +70,7 @@ func (r *Rauc) RunRauc(updateFile string) error { } r.broadcast <- r.GetStatusJson() - cmd := util.CommandFromString(fmt.Sprintf("%s install %s", util.RaucCmd, updateFile)) + cmd := util.CommandFromString(fmt.Sprintf("%s %s", util.UpdateCmd, updateFile)) readPipe, _ := cmd.StdoutPipe() cmd.Stderr = cmd.Stdout diff --git a/src/server/server.go b/src/server/server.go index 46522a3..b9ca070 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -8,7 +8,6 @@ import ( "time" "code.thetadev.de/TSGRain/SEBRAUC/src/rauc" - "code.thetadev.de/TSGRain/SEBRAUC/src/sysinfo" "code.thetadev.de/TSGRain/SEBRAUC/src/util" "code.thetadev.de/TSGRain/SEBRAUC/ui" "github.com/gofiber/fiber/v2" @@ -89,7 +88,6 @@ func (srv *SEBRAUCServer) Run() error { app.Get("/api/ws", websocket.New(srv.hub.Handler)) app.Post("/api/update", srv.controllerUpdate) app.Get("/api/status", srv.controllerStatus) - app.Get("/api/info", srv.controllerInfo) app.Post("/api/reboot", srv.controllerReboot) // Start messaging hub @@ -133,17 +131,6 @@ func (srv *SEBRAUCServer) controllerStatus(c *fiber.Ctx) error { return nil } -func (srv *SEBRAUCServer) controllerInfo(c *fiber.Ctx) error { - info, err := sysinfo.GetSysinfo() - if err != nil { - return err - } - - c.Context().SetStatusCode(200) - _ = c.JSON(info) - return nil -} - func (srv *SEBRAUCServer) controllerReboot(c *fiber.Ctx) error { go util.Reboot(5 * time.Second) diff --git a/src/sysinfo/sysinfo.go b/src/sysinfo/sysinfo.go deleted file mode 100644 index f00f389..0000000 --- a/src/sysinfo/sysinfo.go +++ /dev/null @@ -1,180 +0,0 @@ -package sysinfo - -import ( - "encoding/json" - "os" - "regexp" - "strconv" - "strings" - - "code.thetadev.de/TSGRain/SEBRAUC/src/util" -) - -type SystemInfo struct { - Hostname string `json:"hostname"` - OsName string `json:"os_name"` - OsVersion string `json:"os_version"` - Uptime int `json:"uptime"` - RaucCompatible string `json:"rauc_compatible"` - RaucVariant string `json:"rauc_variant"` - RaucRootfs map[string]Rootfs `json:"rauc_rootfs"` -} - -type Rootfs struct { - Device string `json:"device"` - Type string `json:"type"` - bootname string - Mountpoint *string `json:"mountpoint"` - Bootable bool `json:"bootable"` - Booted bool `json:"booted"` - Primary bool `json:"primary"` -} - -type raucInfo struct { - Compatible string `json:"compatible"` - Variant string `json:"variant"` - Booted string `json:"booted"` - BootPrimary string `json:"boot_primary"` - Slots []map[string]raucFS `json:"slots"` -} - -type raucFS struct { - Class string `json:"class"` - Device string `json:"device"` - Type string `json:"type"` - Bootname string `json:"bootname"` - State string `json:"state"` - Mountpoint *string `json:"mountpoint"` - BootStatus string `json:"boot_status"` -} - -type osRelease struct { - OsName string `json:"os_name"` - OsVersion string `json:"os_version"` -} - -var ( - rexpOsName = regexp.MustCompile(`(?m)^NAME="(.+)"`) - rexpOsVersion = regexp.MustCompile(`(?m)^VERSION="(.+)"`) - rexpUptime = regexp.MustCompile(`^\d+`) -) - -func parseRaucInfo(raucInfoJson []byte) (raucInfo, error) { - res := raucInfo{} - err := json.Unmarshal(raucInfoJson, &res) - return res, err -} - -func parseOsRelease(osReleaseFile string) (osRelease, error) { - osReleaseTxt, err := os.ReadFile(osReleaseFile) - if err != nil { - return osRelease{}, err - } - - nameMatch := rexpOsName.FindSubmatch(osReleaseTxt) - versionMatch := rexpOsVersion.FindSubmatch(osReleaseTxt) - - name := "" - if nameMatch != nil { - name = string(nameMatch[1]) - } - - version := "" - if versionMatch != nil { - version = string(versionMatch[1]) - } - - return osRelease{ - OsName: name, - OsVersion: version, - }, nil -} - -func mapRootfs(rinf raucInfo) map[string]Rootfs { - res := make(map[string]Rootfs) - - for _, slot := range rinf.Slots { - for name, fs := range slot { - if fs.Class == "rootfs" { - res[name] = Rootfs{ - Device: fs.Device, - Type: fs.Type, - bootname: fs.Bootname, - Mountpoint: fs.Mountpoint, - Bootable: fs.BootStatus == "good", - Booted: fs.State == "booted", - Primary: rinf.BootPrimary == name, - } - } - } - } - return res -} - -func getFSNameFromBootname(rfslist map[string]Rootfs, bootname string) string { - for name, rfs := range rfslist { - if rfs.bootname == bootname { - return name - } - } - return "n/a" -} - -func mapSysinfo(rinf raucInfo, osr osRelease, uptime int, hostname string) SystemInfo { - rfslist := mapRootfs(rinf) - - return SystemInfo{ - Hostname: hostname, - OsName: osr.OsName, - OsVersion: osr.OsVersion, - Uptime: uptime, - RaucCompatible: rinf.Compatible, - RaucVariant: rinf.Variant, - RaucRootfs: rfslist, - } -} - -func getUptime() (int, error) { - uptimeRaw, err := os.ReadFile("/proc/uptime") - if err != nil { - return 0, err - } - - uptimeChars := rexpUptime.Find(uptimeRaw) - return strconv.Atoi(string(uptimeChars)) -} - -func getHostname() string { - hostname, err := os.ReadFile("/etc/hostname") - if err != nil { - return "" - } - return strings.TrimSpace(string(hostname)) -} - -func GetSysinfo() (SystemInfo, error) { - cmd := util.CommandFromString(util.RaucCmd + " status") - rinfJson, err := cmd.Output() - if err != nil { - return SystemInfo{}, err - } - - rinf, err := parseRaucInfo(rinfJson) - if err != nil { - return SystemInfo{}, err - } - - osinf, err := parseOsRelease("/etc/os-release") - if err != nil { - return SystemInfo{}, err - } - - uptime, err := getUptime() - if err != nil { - return SystemInfo{}, err - } - - hostname := getHostname() - - return mapSysinfo(rinf, osinf, uptime, hostname), nil -} diff --git a/src/sysinfo/sysinfo_test.go b/src/sysinfo/sysinfo_test.go deleted file mode 100644 index 3628435..0000000 --- a/src/sysinfo/sysinfo_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package sysinfo - -import ( - "path/filepath" - "testing" - - "code.thetadev.de/TSGRain/SEBRAUC/src/fixtures" - "github.com/stretchr/testify/assert" -) - -const statusJson = `{"compatible":"TSGRain","variant":"dev","booted":"A",` + - `"boot_primary":"rootfs.0","slots":[{"rootfs.1":{"class":"rootfs",` + - `"device":"/dev/mmcblk0p3","type":"ext4","bootname":"B","state":"inactive",` + - `"parent":null,"mountpoint":null,"boot_status":"good"}},{"rootfs.0":` + - `{"class":"rootfs","device":"/dev/mmcblk0p2","type":"ext4","bootname":"A",` + - `"state":"booted","parent":null,"mountpoint":"/","boot_status":"good"}}]}` - -var mountRoot = "/" - -var expectedRaucInfo = raucInfo{ - Compatible: "TSGRain", - Variant: "dev", - Booted: "A", - BootPrimary: "rootfs.0", - Slots: []map[string]raucFS{ - { - "rootfs.1": { - Class: "rootfs", - Device: "/dev/mmcblk0p3", - Type: "ext4", - Bootname: "B", - State: "inactive", - Mountpoint: nil, - BootStatus: "good", - }, - }, - { - "rootfs.0": { - Class: "rootfs", - Device: "/dev/mmcblk0p2", - Type: "ext4", - Bootname: "A", - State: "booted", - Mountpoint: &mountRoot, - BootStatus: "good", - }, - }, - }, -} - -var expectedRootfsList = map[string]Rootfs{ - "rootfs.0": { - Device: "/dev/mmcblk0p2", - Type: "ext4", - bootname: "A", - Mountpoint: &mountRoot, - Bootable: true, - Booted: true, - Primary: true, - }, - "rootfs.1": { - Device: "/dev/mmcblk0p3", - Type: "ext4", - bootname: "B", - Mountpoint: nil, - Bootable: true, - Booted: false, - Primary: false, - }, -} - -func TestParseRaucInfo(t *testing.T) { - info, err := parseRaucInfo([]byte(statusJson)) - if err != nil { - panic(err) - } - - assert.Equal(t, expectedRaucInfo, info) -} - -func TestParseOsRelease(t *testing.T) { - testfiles := fixtures.GetTestfilesDir() - osReleaseFile := filepath.Join(testfiles, "os-release") - - osRel, err := parseOsRelease(osReleaseFile) - if err != nil { - panic(err) - } - - expected := osRelease{ - OsName: "TSGRain distro", - OsVersion: "0.0.1", - } - - assert.Equal(t, expected, osRel) -} - -func TestMapRootfsList(t *testing.T) { - rootfsList := mapRootfs(expectedRaucInfo) - - assert.Equal(t, expectedRootfsList, rootfsList) -} - -func TestGetFSNameFromBootname(t *testing.T) { - rootfsList := mapRootfs(expectedRaucInfo) - - assert.Equal(t, "rootfs.0", getFSNameFromBootname(rootfsList, "A")) - assert.Equal(t, "rootfs.1", getFSNameFromBootname(rootfsList, "B")) - assert.Equal(t, "n/a", getFSNameFromBootname(rootfsList, "C")) -} - -func TestGetSysinfo(t *testing.T) { - sysinfo, err := GetSysinfo() - if err != nil { - panic(err) - } - - assert.Greater(t, sysinfo.Uptime, 0) - assert.Equal(t, "TSGRain", sysinfo.RaucCompatible) - assert.Equal(t, "dev", sysinfo.RaucVariant) - assert.Equal(t, expectedRootfsList, sysinfo.RaucRootfs) -} diff --git a/src/util/commands.go b/src/util/commands.go index a157fa0..a17f2e6 100644 --- a/src/util/commands.go +++ b/src/util/commands.go @@ -5,7 +5,7 @@ package util const ( RebootCmd = "shutdown -r 0" - RaucCmd = "rauc" + UpdateCmd = "rauc install" TestMode = false ) diff --git a/src/util/commands_mock.go b/src/util/commands_mock.go index d4d1392..1790b46 100644 --- a/src/util/commands_mock.go +++ b/src/util/commands_mock.go @@ -5,7 +5,7 @@ package util const ( RebootCmd = "touch /tmp/sebrauc_reboot_test" - RaucCmd = "go run code.thetadev.de/TSGRain/SEBRAUC/src/fixtures/rauc_mock" + UpdateCmd = "go run code.thetadev.de/TSGRain/SEBRAUC/src/fixtures/rauc_mock" TestMode = true ) diff --git a/ui/src/components/Updater/Alert.tsx b/ui/src/components/Updater/Alert.tsx index 204a691..6eb16a9 100644 --- a/ui/src/components/Updater/Alert.tsx +++ b/ui/src/components/Updater/Alert.tsx @@ -1,7 +1,6 @@ import {Component} from "preact" import {mdiTriangleOutline} from "@mdi/js" import Icon from "../Icon/Icon" -import colors from "../../util/colors" type Props = { source?: string @@ -21,7 +20,7 @@ export default class Alert extends Component { return (
- + {msg}
diff --git a/ui/src/components/Updater/Reboot.tsx b/ui/src/components/Updater/Reboot.tsx index 49a0232..c53666e 100644 --- a/ui/src/components/Updater/Reboot.tsx +++ b/ui/src/components/Updater/Reboot.tsx @@ -1,6 +1,7 @@ import {mdiCheckCircleOutline, mdiRestore} from "@mdi/js" +import axios, {AxiosError, AxiosResponse} from "axios" import {Component} from "preact" -import {sebraucApi} from "../../util/apiUrls" +import {apiUrl} from "../../util/apiUrls" import Icon from "../Icon/Icon" export default class Reboot extends Component { @@ -8,9 +9,9 @@ export default class Reboot extends Component { const res = confirm("Reboot the system?") if (!res) return - sebraucApi - .startReboot() - .then((response) => { + axios + .post(apiUrl + "/reboot") + .then((response: AxiosResponse) => { const msg = response.data.msg if (msg !== undefined) { @@ -19,7 +20,7 @@ export default class Reboot extends Component { alert("No response") } }) - .catch((error) => { + .catch((error: AxiosError) => { if (error.response) { const msg = error.response.data.msg diff --git a/ui/src/components/Updater/SysinfoCard.tsx b/ui/src/components/Updater/SysinfoCard.tsx deleted file mode 100644 index 04bd51c..0000000 --- a/ui/src/components/Updater/SysinfoCard.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import {Component} from "preact" -import {SystemInfo} from "../../sebrauc-client" -import {sebraucApi} from "../../util/apiUrls" -import {secondsToString} from "../../util/functions" -import Icon from "../Icon/Icon" -import { - mdiAlphaVCircleOutline, - mdiCheckCircleOutline, - mdiCircleOutline, - mdiClockOutline, - mdiCloseCircleOutline, - mdiMonitor, - mdiPenguin, - mdiTagMultipleOutline, - mdiTagOutline, -} from "@mdi/js" -import colors from "../../util/colors" - -type Props = {} - -type State = { - sysinfo: SystemInfo -} - -export default class SysinfoCard extends Component { - constructor(props?: Props | undefined, context?: any) { - super(props, context) - this.fetchInfo() - } - - private fetchInfo = () => { - sebraucApi - .getInfo() - .then((response) => { - if (response.status == 200) { - this.setState({sysinfo: response.data}) - } else { - console.log("error fetching info", response.data) - console.log("error fetching info", response.data) - window.setTimeout(this.fetchInfo, 3000) - } - }) - .catch((reason) => { - console.log("error fetching info", reason) - window.setTimeout(this.fetchInfo, 3000) - }) - } - - private renderSysinfo() { - return ( -
-
-

System information

- - - - - - - - - - - - - - - - - - - - - - - - - -
- Hostname - {this.state.sysinfo.hostname}
- Operating system - {this.state.sysinfo.os_name}
- OS version - {this.state.sysinfo.os_version}
- Uptime - {secondsToString(this.state.sysinfo.uptime)}
- Compatible FW - {this.state.sysinfo.rauc_compatible}
- Compatible FW - variant - {this.state.sysinfo.rauc_variant}
-
- -
-

Rootfs slots

-
- - - - - - - - - - - {Object.keys(this.state.sysinfo.rauc_rootfs).map( - (k, i) => { - const rfs = this.state.sysinfo.rauc_rootfs[k] - let icon = mdiCircleOutline - let iconColor = colors.BLUE - - if (!rfs.bootable) { - icon = mdiCloseCircleOutline - iconColor = colors.RED - } else if (rfs.primary) { - icon = mdiCheckCircleOutline - iconColor = colors.GREEN - } - - return ( - - - - - - - ) - } - )} - -
NameDeviceMountpoint
- - {k}{rfs.device}{rfs.mountpoint}
-
-
-
- ) - } - - private renderLoadingAnimation() { - return ( -
-

loading sysinfo...

-
- ) - } - - render() { - if (this.state.sysinfo) { - return this.renderSysinfo() - } - return this.renderLoadingAnimation() - } -} diff --git a/ui/src/components/Updater/Updater.scss b/ui/src/components/Updater/Updater.scss index fe3ace9..90b798e 100644 --- a/ui/src/components/Updater/Updater.scss +++ b/ui/src/components/Updater/Updater.scss @@ -1,11 +1,11 @@ -.updater-view { +.uploader { display: flex; flex-direction: column; justify-content: center; align-items: center; margin: 0 auto; - max-width: 600px; + max-width: 500px; width: 90%; > * { @@ -18,8 +18,8 @@ justify-content: center; align-items: center; - margin-top: 25px; - margin-bottom: 8px; + padding: 15px 8px; + margin: 8px 0; text-align: center; @@ -29,14 +29,6 @@ .top { font-size: 1.5em; } - - &.pad { - padding: 15px 0; - } - - &:first-of-type { - margin-top: 8px; - } } .alert { @@ -50,9 +42,3 @@ } } } - -.button-top-right { - position: absolute; - top: 20px; - right: 20px; -} diff --git a/ui/src/components/Updater/UpdaterCard.tsx b/ui/src/components/Updater/Updater.tsx similarity index 90% rename from ui/src/components/Updater/UpdaterCard.tsx rename to ui/src/components/Updater/Updater.tsx index 6873897..772f837 100644 --- a/ui/src/components/Updater/UpdaterCard.tsx +++ b/ui/src/components/Updater/Updater.tsx @@ -5,10 +5,10 @@ import Dropzone from "../Dropzone/Dropzone" import ProgressCircle from "../ProgressCircle/ProgressCircle" import Icon from "../Icon/Icon" import "./Updater.scss" +import axios from "axios" import Alert from "./Alert" import Reboot from "./Reboot" -import {sebraucApi, wsUrl} from "../../util/apiUrls" -import colors from "../../util/colors" +import {apiUrl, wsUrl} from "../../util/apiUrls" class UploadStatus { uploading = false @@ -50,7 +50,7 @@ type State = { wsConnected: boolean } -export default class UpdaterCard extends Component { +export default class Updater extends Component { private dropzoneRef = createRef() private conn: WebSocket | undefined @@ -77,13 +77,19 @@ export default class UpdaterCard extends Component { if (files.length === 0) return const newFile = files[0] + const formData = new FormData() + formData.append("updateFile", newFile) + this.setState({ uploadStatus: new UploadStatus(true, newFile.size, 0), uploadFilename: newFile.name, }) - sebraucApi - .startUpdate(newFile, { + axios + .post(apiUrl + "/update", formData, { + headers: { + "Content-Type": "multipart/form-data", + }, onUploadProgress: (progressEvent: {loaded: number; total: number}) => { this.setState({ uploadStatus: UploadStatus.fromProgressEvent(progressEvent), @@ -126,6 +132,8 @@ export default class UpdaterCard extends Component { JSON.parse(messages[i]) ), }) + + console.log(this.state.raucStatus) } } } else { @@ -155,9 +163,9 @@ export default class UpdaterCard extends Component { } private circleColor(): string { - if (this.state.raucStatus.installing) return colors.RED - if (this.state.uploadStatus.uploading) return colors.GREEN - return colors.BLUE + if (this.state.raucStatus.installing) return "#FF0039" + if (this.state.uploadStatus.uploading) return "#148420" + return "#1f85de" } private circlePercentage(): number { @@ -187,13 +195,12 @@ export default class UpdaterCard extends Component { topText = "Updating firmware" bottomText = this.state.raucStatus.message } else { - topText = "Firmware update" - bottomText = "Upload *.raucb FW package" + topText = "Upload firmware package" } return ( -
-
+
+

{topText}

diff --git a/ui/src/components/Updater/UpdaterView.tsx b/ui/src/components/Updater/UpdaterView.tsx deleted file mode 100644 index faf96c4..0000000 --- a/ui/src/components/Updater/UpdaterView.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import {mdiInformation, mdiUpload} from "@mdi/js" -import {Component} from "preact" -import Icon from "../Icon/Icon" -import SysinfoCard from "./SysinfoCard" -import UpdaterCard from "./UpdaterCard" -import "./Updater.scss" - -type Props = {} - -type State = { - flipped: boolean -} - -export default class UpdaterView extends Component { - constructor(props?: Props | undefined, context?: any) { - super(props, context) - - this.state = { - flipped: false, - } - } - - private flipCard = () => { - this.setState({flipped: !this.state.flipped}) - } - - render() { - return ( -
- - -
- {!this.state.flipped ? : } -
-
- ) - } -} diff --git a/ui/src/components/app.tsx b/ui/src/components/app.tsx index b068bc3..4d0f547 100644 --- a/ui/src/components/app.tsx +++ b/ui/src/components/app.tsx @@ -1,5 +1,5 @@ import {Component} from "preact" -import UpdaterView from "./Updater/UpdaterView" +import Updater from "./Updater/Updater" import logo from "../assets/logo.svg" import {version} from "../util/version" @@ -9,7 +9,7 @@ export default class App extends Component {
SEBRAUC {version} - +
) } diff --git a/ui/src/sebrauc-client/.openapi-generator-ignore b/ui/src/sebrauc-client/.openapi-generator-ignore deleted file mode 100644 index 7e15242..0000000 --- a/ui/src/sebrauc-client/.openapi-generator-ignore +++ /dev/null @@ -1,27 +0,0 @@ -# OpenAPI Generator Ignore -# Generated by openapi-generator https://github.com/openapitools/openapi-generator - -# Use this file to prevent files from being overwritten by the generator. -# The patterns follow closely to .gitignore or .dockerignore. - -# As an example, the C# client generator defines ApiClient.cs. -# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: -#ApiClient.cs - -# You can match any string of characters against a directory, file or extension with a single asterisk (*): -#foo/*/qux -# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux - -# You can recursively match patterns against a directory, file or extension with a double asterisk (**): -#foo/**/qux -# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux - -# You can also negate patterns with an exclamation (!). -# For example, you can ignore all files in a docs folder with the file extension .md: -#docs/*.md -# Then explicitly reverse the ignore rule for a single file: -#!docs/README.md - -/.gitignore -/.npmignore -/git_push.sh diff --git a/ui/src/sebrauc-client/.openapi-generator/FILES b/ui/src/sebrauc-client/.openapi-generator/FILES deleted file mode 100644 index 53250c0..0000000 --- a/ui/src/sebrauc-client/.openapi-generator/FILES +++ /dev/null @@ -1,5 +0,0 @@ -api.ts -base.ts -common.ts -configuration.ts -index.ts diff --git a/ui/src/sebrauc-client/.openapi-generator/VERSION b/ui/src/sebrauc-client/.openapi-generator/VERSION deleted file mode 100644 index e230c83..0000000 --- a/ui/src/sebrauc-client/.openapi-generator/VERSION +++ /dev/null @@ -1 +0,0 @@ -5.3.0 \ No newline at end of file diff --git a/ui/src/sebrauc-client/api.ts b/ui/src/sebrauc-client/api.ts deleted file mode 100644 index 82abc3d..0000000 --- a/ui/src/sebrauc-client/api.ts +++ /dev/null @@ -1,539 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * SEBRAUC - * REST API for the SEBRAUC firmware updater - * - * The version of the OpenAPI document: 0.1.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import {Configuration} from "./configuration" -import globalAxios, {AxiosPromise, AxiosInstance, AxiosRequestConfig} from "axios" -// Some imports not used depending on template conditions -// @ts-ignore -import { - DUMMY_BASE_URL, - assertParamExists, - setApiKeyToObject, - setBasicAuthToObject, - setBearerAuthToObject, - setOAuthToObject, - setSearchParams, - serializeDataIfNeeded, - toPathString, - createRequestFunction, -} from "./common" -// @ts-ignore -import { - BASE_PATH, - COLLECTION_FORMATS, - RequestArgs, - BaseAPI, - RequiredError, -} from "./base" - -/** - * - * @export - * @interface RaucStatus - */ -export interface RaucStatus { - /** - * True if the installer is running - * @type {boolean} - * @memberof RaucStatus - */ - installing: boolean - /** - * Installation progress - * @type {number} - * @memberof RaucStatus - */ - percent: number - /** - * Current installation step - * @type {string} - * @memberof RaucStatus - */ - message: string - /** - * Installation error message - * @type {string} - * @memberof RaucStatus - */ - last_error: string - /** - * Full command line output of the current installation - * @type {string} - * @memberof RaucStatus - */ - log: string -} -/** - * - * @export - * @interface Rootfs - */ -export interface Rootfs { - /** - * Block device - * @type {string} - * @memberof Rootfs - */ - device: string - /** - * Filesystem - * @type {string} - * @memberof Rootfs - */ - type: string - /** - * Mount path (null when not mounted) - * @type {string} - * @memberof Rootfs - */ - mountpoint: string | null - /** - * Is the filesystem bootable - * @type {boolean} - * @memberof Rootfs - */ - bootable: boolean - /** - * Is the filesystem booted - * @type {boolean} - * @memberof Rootfs - */ - booted: boolean - /** - * Is the filesystem the next boot target - * @type {boolean} - * @memberof Rootfs - */ - primary: boolean -} -/** - * - * @export - * @interface StatusMessage - */ -export interface StatusMessage { - /** - * Is operation successful - * @type {boolean} - * @memberof StatusMessage - */ - success: boolean - /** - * Success message - * @type {string} - * @memberof StatusMessage - */ - msg: string -} -/** - * - * @export - * @interface SystemInfo - */ -export interface SystemInfo { - /** - * Hostname of the system - * @type {string} - * @memberof SystemInfo - */ - hostname: string - /** - * Name of the os distribution - * @type {string} - * @memberof SystemInfo - */ - os_name: string - /** - * Operating system version - * @type {string} - * @memberof SystemInfo - */ - os_version: string - /** - * System uptime in seconds - * @type {number} - * @memberof SystemInfo - */ - uptime: number - /** - * Compatible firmware name - * @type {string} - * @memberof SystemInfo - */ - rauc_compatible: string - /** - * Compatible firmware variant - * @type {string} - * @memberof SystemInfo - */ - rauc_variant: string - /** - * List of RAUC root filesystems - * @type {{ [key: string]: Rootfs; }} - * @memberof SystemInfo - */ - rauc_rootfs: {[key: string]: Rootfs} -} - -/** - * DefaultApi - axios parameter creator - * @export - */ -export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getInfo: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/info` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "GET", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getStatus: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/status` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "GET", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - startReboot: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/reboot` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "POST", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, - /** - * - * @param {any} [updateFile] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - startUpdate: async ( - updateFile?: any, - options: AxiosRequestConfig = {} - ): Promise => { - const localVarPath = `/update` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "POST", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - const localVarFormParams = new ((configuration && - configuration.formDataCtor) || - FormData)() - - if (updateFile !== undefined) { - localVarFormParams.append("updateFile", updateFile as any) - } - - localVarHeaderParameter["Content-Type"] = "multipart/form-data" - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - localVarRequestOptions.data = localVarFormParams - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, - } -} - -/** - * DefaultApi - functional programming interface - * @export - */ -export const DefaultApiFp = function (configuration?: Configuration) { - const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration) - return { - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getInfo( - options?: AxiosRequestConfig - ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise - > { - const localVarAxiosArgs = await localVarAxiosParamCreator.getInfo(options) - return createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration - ) - }, - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getStatus( - options?: AxiosRequestConfig - ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise - > { - const localVarAxiosArgs = await localVarAxiosParamCreator.getStatus(options) - return createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration - ) - }, - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async startReboot( - options?: AxiosRequestConfig - ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise - > { - const localVarAxiosArgs = await localVarAxiosParamCreator.startReboot( - options - ) - return createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration - ) - }, - /** - * - * @param {any} [updateFile] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async startUpdate( - updateFile?: any, - options?: AxiosRequestConfig - ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise - > { - const localVarAxiosArgs = await localVarAxiosParamCreator.startUpdate( - updateFile, - options - ) - return createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration - ) - }, - } -} - -/** - * DefaultApi - factory interface - * @export - */ -export const DefaultApiFactory = function ( - configuration?: Configuration, - basePath?: string, - axios?: AxiosInstance -) { - const localVarFp = DefaultApiFp(configuration) - return { - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getInfo(options?: any): AxiosPromise { - return localVarFp - .getInfo(options) - .then((request) => request(axios, basePath)) - }, - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getStatus(options?: any): AxiosPromise { - return localVarFp - .getStatus(options) - .then((request) => request(axios, basePath)) - }, - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - startReboot(options?: any): AxiosPromise { - return localVarFp - .startReboot(options) - .then((request) => request(axios, basePath)) - }, - /** - * - * @param {any} [updateFile] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - startUpdate(updateFile?: any, options?: any): AxiosPromise { - return localVarFp - .startUpdate(updateFile, options) - .then((request) => request(axios, basePath)) - }, - } -} - -/** - * DefaultApi - object-oriented interface - * @export - * @class DefaultApi - * @extends {BaseAPI} - */ -export class DefaultApi extends BaseAPI { - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public getInfo(options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration) - .getInfo(options) - .then((request) => request(this.axios, this.basePath)) - } - - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public getStatus(options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration) - .getStatus(options) - .then((request) => request(this.axios, this.basePath)) - } - - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public startReboot(options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration) - .startReboot(options) - .then((request) => request(this.axios, this.basePath)) - } - - /** - * - * @param {any} [updateFile] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public startUpdate(updateFile?: any, options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration) - .startUpdate(updateFile, options) - .then((request) => request(this.axios, this.basePath)) - } -} diff --git a/ui/src/sebrauc-client/base.ts b/ui/src/sebrauc-client/base.ts deleted file mode 100644 index 6248680..0000000 --- a/ui/src/sebrauc-client/base.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * SEBRAUC - * REST API for the SEBRAUC firmware updater - * - * The version of the OpenAPI document: 0.1.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import {Configuration} from "./configuration" -// Some imports not used depending on template conditions -// @ts-ignore -import globalAxios, {AxiosPromise, AxiosInstance, AxiosRequestConfig} from "axios" - -export const BASE_PATH = "http://localhost:8080/api".replace(/\/+$/, "") - -/** - * - * @export - */ -export const COLLECTION_FORMATS = { - csv: ",", - ssv: " ", - tsv: "\t", - pipes: "|", -} - -/** - * - * @export - * @interface RequestArgs - */ -export interface RequestArgs { - url: string - options: AxiosRequestConfig -} - -/** - * - * @export - * @class BaseAPI - */ -export class BaseAPI { - protected configuration: Configuration | undefined - - constructor( - configuration?: Configuration, - protected basePath: string = BASE_PATH, - protected axios: AxiosInstance = globalAxios - ) { - if (configuration) { - this.configuration = configuration - this.basePath = configuration.basePath || this.basePath - } - } -} - -/** - * - * @export - * @class RequiredError - * @extends {Error} - */ -export class RequiredError extends Error { - name: "RequiredError" = "RequiredError" - constructor(public field: string, msg?: string) { - super(msg) - } -} diff --git a/ui/src/sebrauc-client/common.ts b/ui/src/sebrauc-client/common.ts deleted file mode 100644 index 9942bb6..0000000 --- a/ui/src/sebrauc-client/common.ts +++ /dev/null @@ -1,181 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * SEBRAUC - * REST API for the SEBRAUC firmware updater - * - * The version of the OpenAPI document: 0.1.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import {Configuration} from "./configuration" -import {RequiredError, RequestArgs} from "./base" -import {AxiosInstance, AxiosResponse} from "axios" - -/** - * - * @export - */ -export const DUMMY_BASE_URL = "https://example.com" - -/** - * - * @throws {RequiredError} - * @export - */ -export const assertParamExists = function ( - functionName: string, - paramName: string, - paramValue: unknown -) { - if (paramValue === null || paramValue === undefined) { - throw new RequiredError( - paramName, - `Required parameter ${paramName} was null or undefined when calling ${functionName}.` - ) - } -} - -/** - * - * @export - */ -export const setApiKeyToObject = async function ( - object: any, - keyParamName: string, - configuration?: Configuration -) { - if (configuration && configuration.apiKey) { - const localVarApiKeyValue = - typeof configuration.apiKey === "function" - ? await configuration.apiKey(keyParamName) - : await configuration.apiKey - object[keyParamName] = localVarApiKeyValue - } -} - -/** - * - * @export - */ -export const setBasicAuthToObject = function ( - object: any, - configuration?: Configuration -) { - if (configuration && (configuration.username || configuration.password)) { - object["auth"] = { - username: configuration.username, - password: configuration.password, - } - } -} - -/** - * - * @export - */ -export const setBearerAuthToObject = async function ( - object: any, - configuration?: Configuration -) { - if (configuration && configuration.accessToken) { - const accessToken = - typeof configuration.accessToken === "function" - ? await configuration.accessToken() - : await configuration.accessToken - object["Authorization"] = "Bearer " + accessToken - } -} - -/** - * - * @export - */ -export const setOAuthToObject = async function ( - object: any, - name: string, - scopes: string[], - configuration?: Configuration -) { - if (configuration && configuration.accessToken) { - const localVarAccessTokenValue = - typeof configuration.accessToken === "function" - ? await configuration.accessToken(name, scopes) - : await configuration.accessToken - object["Authorization"] = "Bearer " + localVarAccessTokenValue - } -} - -/** - * - * @export - */ -export const setSearchParams = function (url: URL, ...objects: any[]) { - const searchParams = new URLSearchParams(url.search) - for (const object of objects) { - for (const key in object) { - if (Array.isArray(object[key])) { - searchParams.delete(key) - for (const item of object[key]) { - searchParams.append(key, item) - } - } else { - searchParams.set(key, object[key]) - } - } - } - url.search = searchParams.toString() -} - -/** - * - * @export - */ -export const serializeDataIfNeeded = function ( - value: any, - requestOptions: any, - configuration?: Configuration -) { - const nonString = typeof value !== "string" - const needsSerialization = - nonString && configuration && configuration.isJsonMime - ? configuration.isJsonMime(requestOptions.headers["Content-Type"]) - : nonString - return needsSerialization - ? JSON.stringify(value !== undefined ? value : {}) - : value || "" -} - -/** - * - * @export - */ -export const toPathString = function (url: URL) { - return url.pathname + url.search + url.hash -} - -/** - * - * @export - */ -export const createRequestFunction = function ( - axiosArgs: RequestArgs, - globalAxios: AxiosInstance, - BASE_PATH: string, - configuration?: Configuration -) { - return >( - axios: AxiosInstance = globalAxios, - basePath: string = BASE_PATH - ) => { - const axiosRequestArgs = { - ...axiosArgs.options, - url: (configuration?.basePath || basePath) + axiosArgs.url, - } - return axios.request(axiosRequestArgs) - } -} diff --git a/ui/src/sebrauc-client/configuration.ts b/ui/src/sebrauc-client/configuration.ts deleted file mode 100644 index 357fd9b..0000000 --- a/ui/src/sebrauc-client/configuration.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * SEBRAUC - * REST API for the SEBRAUC firmware updater - * - * The version of the OpenAPI document: 0.1.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -export interface ConfigurationParameters { - apiKey?: - | string - | Promise - | ((name: string) => string) - | ((name: string) => Promise) - username?: string - password?: string - accessToken?: - | string - | Promise - | ((name?: string, scopes?: string[]) => string) - | ((name?: string, scopes?: string[]) => Promise) - basePath?: string - baseOptions?: any - formDataCtor?: new () => any -} - -export class Configuration { - /** - * parameter for apiKey security - * @param name security name - * @memberof Configuration - */ - apiKey?: - | string - | Promise - | ((name: string) => string) - | ((name: string) => Promise) - /** - * parameter for basic security - * - * @type {string} - * @memberof Configuration - */ - username?: string - /** - * parameter for basic security - * - * @type {string} - * @memberof Configuration - */ - password?: string - /** - * parameter for oauth2 security - * @param name security name - * @param scopes oauth2 scope - * @memberof Configuration - */ - accessToken?: - | string - | Promise - | ((name?: string, scopes?: string[]) => string) - | ((name?: string, scopes?: string[]) => Promise) - /** - * override base path - * - * @type {string} - * @memberof Configuration - */ - basePath?: string - /** - * base options for axios calls - * - * @type {any} - * @memberof Configuration - */ - baseOptions?: any - /** - * The FormData constructor that will be used to create multipart form data - * requests. You can inject this here so that execution environments that - * do not support the FormData class can still run the generated client. - * - * @type {new () => FormData} - */ - formDataCtor?: new () => any - - constructor(param: ConfigurationParameters = {}) { - this.apiKey = param.apiKey - this.username = param.username - this.password = param.password - this.accessToken = param.accessToken - this.basePath = param.basePath - this.baseOptions = param.baseOptions - this.formDataCtor = param.formDataCtor - } - - /** - * Check if the given MIME is a JSON MIME. - * JSON MIME examples: - * application/json - * application/json; charset=UTF8 - * APPLICATION/JSON - * application/vnd.company+json - * @param mime - MIME (Multipurpose Internet Mail Extensions) - * @return True if the given MIME is JSON, false otherwise. - */ - public isJsonMime(mime: string): boolean { - const jsonMime: RegExp = new RegExp( - "^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$", - "i" - ) - return ( - mime !== null && - (jsonMime.test(mime) || - mime.toLowerCase() === "application/json-patch+json") - ) - } -} diff --git a/ui/src/sebrauc-client/index.ts b/ui/src/sebrauc-client/index.ts deleted file mode 100644 index a0c08f6..0000000 --- a/ui/src/sebrauc-client/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * SEBRAUC - * REST API for the SEBRAUC firmware updater - * - * The version of the OpenAPI document: 0.1.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -export * from "./api" -export * from "./configuration" diff --git a/ui/src/style/index.scss b/ui/src/style/index.scss index 1f333d4..5774a08 100644 --- a/ui/src/style/index.scss +++ b/ui/src/style/index.scss @@ -1,5 +1,3 @@ -@use "table"; - html, body { height: 100%; diff --git a/ui/src/style/table.scss b/ui/src/style/table.scss deleted file mode 100644 index c522f5d..0000000 --- a/ui/src/style/table.scss +++ /dev/null @@ -1,47 +0,0 @@ -.table-wrapper { - width: 100%; - overflow-x: auto; -} - -.table { - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; - border-collapse: collapse; - margin: 0; - padding: 0; - width: 100%; - - &.no-bottom-border { - &, - > tr:last-child, - :not(thead) tr:last-child { - border-bottom: none; - } - } -} - -.table caption { - font-size: 1.5em; - margin: 0.5em 0 0.75em; -} - -.table tr { - border-bottom: 1px solid #ddd; - padding: 0.35em; -} - -.table th, -.table td { - padding: 0.625em; - text-align: left; - - .icon { - color: #1f85de; - } -} - -.table th { - font-size: 0.85em; - letter-spacing: 0.085em; - text-transform: uppercase; -} diff --git a/ui/src/util/apiUrls.ts b/ui/src/util/apiUrls.ts index 724d52b..4a9d51b 100644 --- a/ui/src/util/apiUrls.ts +++ b/ui/src/util/apiUrls.ts @@ -1,5 +1,3 @@ -import {Configuration, DefaultApi} from "../sebrauc-client" - let apiHost = document.location.host const httpProto = document.location.protocol const wsProto = httpProto === "https:" ? "wss:" : "ws:" @@ -11,10 +9,4 @@ if (import.meta.env.VITE_API_HOST !== undefined) { const apiUrl = `${httpProto}//${apiHost}/api` const wsUrl = `${wsProto}//${apiHost}/api/ws` -let apicfg = new Configuration({ - basePath: apiUrl, -}) - -const sebraucApi = new DefaultApi(apicfg) - -export {apiUrl, wsUrl, sebraucApi} +export {apiUrl, wsUrl} diff --git a/ui/src/util/colors.ts b/ui/src/util/colors.ts deleted file mode 100644 index 3202366..0000000 --- a/ui/src/util/colors.ts +++ /dev/null @@ -1,7 +0,0 @@ -class colors { - static readonly RED = "#FF0039" - static readonly GREEN = "#148420" - static readonly BLUE = "#1f85de" -} - -export default colors diff --git a/ui/src/util/functions.ts b/ui/src/util/functions.ts deleted file mode 100644 index 18179e2..0000000 --- a/ui/src/util/functions.ts +++ /dev/null @@ -1,18 +0,0 @@ -function secondsToString(seconds: number): string { - const numyears = Math.floor(seconds / 31536000) - const numdays = Math.floor((seconds % 31536000) / 86400) - const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600) - const numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60) - const numseconds = (((seconds % 31536000) % 86400) % 3600) % 60 - - let res = [] - if (numyears > 0) res.push(numyears + "yr") - if (numdays > 0) res.push(numdays + "d") - if (numhours > 0) res.push(numhours + "h") - if (numminutes > 0) res.push(numminutes + "m") - if (seconds < 60) res.push(numseconds + "s") - - return res.join(" ") -} - -export {secondsToString}