Merge branch 'local_server' into staging_environment
This commit is contained in:
commit
a503148238
5 changed files with 66 additions and 19 deletions
|
|
@ -8,7 +8,6 @@ import {
|
|||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Theme,
|
||||
Typography
|
||||
} from "@mui/material";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
|
|
@ -19,10 +18,10 @@ import TagSettings from "common/TagSettings";
|
|||
import { Device, Tag } from "models";
|
||||
import { filterByTag } from "pbHelpers/Tag";
|
||||
import { useDeviceAPI, useSnackbar, useTagAPI } from "providers";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
|
||||
const useStyles = makeStyles((_theme: Theme) => {
|
||||
const useStyles = makeStyles(() => {
|
||||
return ({
|
||||
addIcon: {
|
||||
color: "var(--status-ok)"
|
||||
|
|
@ -45,19 +44,19 @@ function AddDeviceTag(props: AddDeviceTagProps) {
|
|||
const [searchValue, setSearchValue] = useState("");
|
||||
const [tags, setTags] = useState<Tag[]>([])
|
||||
|
||||
const loadTags = () => {
|
||||
const loadTags = useCallback(() => {
|
||||
tagAPI.listTags().then(resp => {
|
||||
let newTags: Tag[] = [];
|
||||
const newTags: Tag[] = [];
|
||||
resp.data.tags.forEach((tag: pond.Tag) => {
|
||||
newTags.push(Tag.create(tag))
|
||||
})
|
||||
setTags(newTags)
|
||||
})
|
||||
}
|
||||
}, [tagAPI])
|
||||
|
||||
useEffect(() => {
|
||||
loadTags()
|
||||
}, [])
|
||||
}, [loadTags])
|
||||
|
||||
const tagItems = tags
|
||||
.filter(tag => !deviceTags.some(tagSettings => tagSettings.key === tag.settings.key))
|
||||
|
|
@ -144,10 +143,10 @@ export default function DeviceTags(props: DeviceTagsProps) {
|
|||
const [deviceTags, setDeviceTags] = useState<pond.TagSettings[]>(device.status.tags);
|
||||
const previousDeviceRef = useRef(device);
|
||||
|
||||
const loadTags = () => {
|
||||
const loadTags = useCallback(() => {
|
||||
// setLoading(true)
|
||||
tagAPI.listTags().then(resp => {
|
||||
let newTags: Tag[] = [];
|
||||
const newTags: Tag[] = [];
|
||||
resp.data.tags.forEach((tag: pond.Tag) => {
|
||||
newTags.push(Tag.create(tag))
|
||||
})
|
||||
|
|
@ -155,7 +154,7 @@ export default function DeviceTags(props: DeviceTagsProps) {
|
|||
}).finally(() => {
|
||||
// setLoading(false)
|
||||
})
|
||||
}
|
||||
}, [tagAPI])
|
||||
|
||||
useEffect(() => {
|
||||
if (previousDeviceRef.current !== device) {
|
||||
|
|
@ -166,14 +165,16 @@ export default function DeviceTags(props: DeviceTagsProps) {
|
|||
|
||||
useEffect(() => {
|
||||
loadTags()
|
||||
}, [])
|
||||
}, [loadTags])
|
||||
|
||||
const addTag = (tag: Tag) => {
|
||||
if (!deviceTags.some(dt => dt.key === tag.settings.key)) {
|
||||
deviceAPI
|
||||
.tag(device.id(), tag.settings.key)
|
||||
.then(() => {
|
||||
setDeviceTags([...deviceTags, tag.settings]);
|
||||
setDeviceTags(current =>
|
||||
current.some(dt => dt.key === tag.settings.key) ? current : [...current, tag.settings]
|
||||
);
|
||||
})
|
||||
.catch(() => error("Failed to tag device as " + tag.name));
|
||||
}
|
||||
|
|
@ -184,7 +185,7 @@ export default function DeviceTags(props: DeviceTagsProps) {
|
|||
deviceAPI
|
||||
.untag(device.id(), tag.key())
|
||||
.then(() => {
|
||||
setDeviceTags(deviceTags.filter(t => tag.key() !== t.key));
|
||||
setDeviceTags(current => current.filter(t => tag.key() !== t.key));
|
||||
})
|
||||
.catch(() => error("Failed to remove tag " + tag.name + " from device"));
|
||||
}
|
||||
|
|
@ -197,7 +198,7 @@ export default function DeviceTags(props: DeviceTagsProps) {
|
|||
return (
|
||||
<React.Fragment>
|
||||
{deviceTags?.map(tagSettings => {
|
||||
let pondTag = pond.Tag.create({ settings: tagSettings })
|
||||
const pondTag = pond.Tag.create({ settings: tagSettings })
|
||||
return (
|
||||
<Grid key={"device-tags-"+tagSettings.key}>
|
||||
<DeviceTag tag={Tag.create(pondTag)} removeTagFromDevice={removeTagFromDevice} />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Container, SxProps, Theme } from "@mui/material";
|
||||
import { Container, SxProps, Theme, Typography } from "@mui/material";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import classNames from "classnames";
|
||||
// import { useMobile } from "hooks";
|
||||
|
|
@ -47,6 +47,23 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
},
|
||||
buildInfo: {
|
||||
position: "fixed" as const,
|
||||
bottom: 56,
|
||||
left: 8,
|
||||
fontSize: 10,
|
||||
lineHeight: 1.3,
|
||||
opacity: 0.35,
|
||||
color: theme.palette.text.secondary,
|
||||
pointerEvents: "none" as const,
|
||||
zIndex: 1,
|
||||
[theme.breakpoints.up("sm")]: {
|
||||
bottom: 8,
|
||||
},
|
||||
[theme.breakpoints.up("md")]: {
|
||||
left: `calc(${theme.spacing(9)} + 8px)`,
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
|
|
@ -78,8 +95,13 @@ export const PageContainer: React.FunctionComponent<Props> = (props: Props) => {
|
|||
}}
|
||||
disableGutters
|
||||
maxWidth={false}
|
||||
children={<>{children}</>}
|
||||
/>
|
||||
>
|
||||
{children}
|
||||
<Typography component="div" className={classes.buildInfo}>
|
||||
{new Date(__BUILD_DATE__).toLocaleDateString()}<br />
|
||||
{__GIT_HASH__}
|
||||
</Typography>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -700,8 +700,12 @@ export default function DeviceProvider(props: PropsWithChildren<Props>) {
|
|||
};
|
||||
|
||||
const setTags = (id: number, tags: string[]) => {
|
||||
const keys = getContextKeys()
|
||||
const types = getContextTypes()
|
||||
let url = "/devices/" + id + "/tags" + "?keys=" + keys + "&types=" + types
|
||||
if (as && !keys.includes(as)) url += "&as=" + as
|
||||
return new Promise<AxiosResponse>((resolve, reject) => {
|
||||
put(pondURL("/devices/" + id + "/tags"), { tags }).then(resp => {
|
||||
put(pondURL(url), { tags }).then(resp => {
|
||||
return resolve(resp)
|
||||
}).catch(err => {
|
||||
return reject(err)
|
||||
|
|
@ -746,8 +750,12 @@ export default function DeviceProvider(props: PropsWithChildren<Props>) {
|
|||
};
|
||||
|
||||
const untag = (id: number, tag: string) => {
|
||||
const keys = getContextKeys()
|
||||
const types = getContextTypes()
|
||||
let url = "/devices/" + id + "/tags/" + tag + "?keys=" + keys + "&types=" + types
|
||||
if (as && !keys.includes(as)) url += "&as=" + as
|
||||
return new Promise<AxiosResponse>((resolve, reject) => {
|
||||
del(pondURL("/devices/" + id + "/tags/" + tag)).then(resp => {
|
||||
del(pondURL(url)).then(resp => {
|
||||
return resolve(resp)
|
||||
}).catch(err => {
|
||||
return reject(err)
|
||||
|
|
|
|||
3
src/vite-env.d.ts
vendored
3
src/vite-env.d.ts
vendored
|
|
@ -1 +1,4 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
declare const __BUILD_DATE__: string
|
||||
declare const __GIT_HASH__: string
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { VitePWA } from 'vite-plugin-pwa';
|
|||
import * as path from 'path' // ✅ Import path module
|
||||
import { readFileSync, renameSync, existsSync, unlinkSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { execSync } from 'node:child_process'
|
||||
|
||||
const rootDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
|
|
@ -49,7 +50,19 @@ function emitLocalnetShellAsIndexHtml (mode: string): Plugin {
|
|||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ command, mode }): UserConfig => {
|
||||
const useLocalnetShell = mode === LOCALNET_MODE
|
||||
|
||||
let gitHash = 'unknown'
|
||||
try {
|
||||
gitHash = execSync('git rev-parse --short HEAD').toString().trim()
|
||||
} catch {}
|
||||
|
||||
const buildDate = new Date().toISOString()
|
||||
|
||||
return {
|
||||
define: {
|
||||
__BUILD_DATE__: JSON.stringify(buildDate),
|
||||
__GIT_HASH__: JSON.stringify(gitHash),
|
||||
},
|
||||
plugins: [
|
||||
useLocalnetShellHtml(mode, command),
|
||||
emitLocalnetShellAsIndexHtml(mode),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue