-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e0eca25
commit 1b1cf96
Showing
62 changed files
with
11,715 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
name: Client Checks | ||
|
||
on: [push, pull_request] | ||
|
||
jobs: | ||
setup: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
- name: Setup Node.js | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: '20' | ||
- name: Install dependencies | ||
run: npm install | ||
working-directory: ./client | ||
|
||
build: | ||
needs: setup | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Build | ||
run: npm run build | ||
working-directory: ./client | ||
|
||
lint: | ||
needs: setup | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Lint | ||
run: npm run lint | ||
working-directory: ./client | ||
|
||
test: | ||
needs: setup | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Test | ||
run: npm run test | ||
working-directory: ./client |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"extends": ["next/core-web-vitals", "airbnb", "airbnb-typescript"], | ||
"rules": { | ||
"import/extensions": "off", | ||
"react/react-in-jsx-scope": "off", | ||
"react/require-default-props": "off", | ||
"react/jsx-props-no-spreading": "off", | ||
"react-hooks/exhaustive-deps": "off" | ||
}, | ||
"parserOptions": { | ||
"project": ["./tsconfig.json"] | ||
}, | ||
"overrides": [ | ||
{ | ||
"files": ["./spec/**/*"], | ||
"rules": { | ||
"jsx-a11y/click-events-have-key-events": "off", | ||
"jsx-a11y/no-static-element-interactions": "off" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
.env | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Phantom Fleet Client | ||
|
||
This web client allows sending data to a fleet-telemetry server. It is in its early stages and only has minimal functionality at this time. | ||
|
||
More documentation to come. | ||
|
||
 | ||
|
||
 | ||
|
||
## Configuration | ||
|
||
**Environment Variables**: | ||
|
||
- `NEXT_PUBLIC_PHANTOM_FLEET_API_URL`: the URL the phantom-fleet API is exposed on |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import Methods from "./methods"; | ||
|
||
export const setConfig = async (host: string, port: number) => { | ||
try { | ||
const res = await Methods.post("/config", { | ||
body: JSON.stringify({ host, port }), | ||
}); | ||
return res.json(); | ||
} catch (e) { | ||
return { reason: `Unexpected error: ${(e as Error).message}` }; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { KeyData, Vehicle } from "@/context/types"; | ||
import Methods from "./methods"; | ||
import { Data, VehicleData } from "./types.d"; | ||
|
||
let msgCount = 0; | ||
|
||
const createData = (data: KeyData) => { | ||
return Object.entries(data).reduce((arr, [key, value]) => { | ||
arr.push({ key, value }); | ||
return arr; | ||
}, [] as Data[]); | ||
}; | ||
|
||
const sendData = async (vin: string, data: Vehicle) => { | ||
const id = `msg-${msgCount++}`; | ||
const payload: VehicleData = { | ||
cert: data.cert, | ||
key: data.key, | ||
data: createData(data.data), | ||
messageId: id, | ||
createdAt: Date.now(), | ||
txid: id, | ||
topic: "V", | ||
vin, | ||
device_type: "vehicle_device", | ||
}; | ||
|
||
const res = await Methods.post("/data", { | ||
body: JSON.stringify(payload), | ||
}); | ||
if (!res.ok) { | ||
throw new Error("Failed to send data"); | ||
} | ||
}; | ||
|
||
export default sendData; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
class Methods { | ||
static async post(path: string, init?: RequestInit) { | ||
return fetch( | ||
`${process.env.NEXT_PUBLIC_PHANTOM_FLEET_API_URL as string}${path}`, | ||
{ | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
...(init?.headers ?? {}), | ||
}, | ||
...(init ?? {}), | ||
} | ||
); | ||
} | ||
} | ||
export default Methods; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export type VehicleData = { | ||
txid: string; | ||
key: string; | ||
cert: string; | ||
topic: string; | ||
vin: string; | ||
device_type: string; | ||
createdAt: number; | ||
messageId: string; | ||
data: Data[]; | ||
}; | ||
|
||
export type Data = { | ||
key: string; | ||
value: unknown; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
'use client'; | ||
|
||
import { setConfig } from '@/api/config'; | ||
import AppBar from '@/components/AppBar/AppBar'; | ||
import { useApp } from '@/context/ApplicationProvider'; | ||
import { useSnackbar } from '@/components/SnackbarContext'; | ||
import { FLEET } from '@/constants/paths'; | ||
import { | ||
Box, | ||
Button, | ||
Grid, | ||
Skeleton, | ||
TextField, | ||
Typography, | ||
} from '@mui/material'; | ||
import Image from 'next/image'; | ||
import { useRouter } from 'next/navigation'; | ||
import { FormEventHandler, useRef, useState } from 'react'; | ||
import Link from 'next/link'; | ||
|
||
const validateFormInput = (host?: string, port?: string) => { | ||
const helpText = { host: '', port: '' }; | ||
let isValid = true; | ||
if (host?.trim() === '') { | ||
helpText.host = 'Host cannot be empty'; | ||
isValid = false; | ||
} | ||
if (port?.trim() === '') { | ||
helpText.port = 'Port cannot be empty'; | ||
isValid = false; | ||
} else if (port?.match(/^\d+$/) === null) { | ||
helpText.port = 'Port must be a number'; | ||
isValid = false; | ||
} | ||
|
||
return { isValid, helpText }; | ||
}; | ||
|
||
export default function ConfigurePage() { | ||
const { server, isLoading, configureServer } = useApp(); | ||
const [helpText, setHelpText] = useState({ | ||
host: '', | ||
port: '', | ||
}); | ||
const hostRef = useRef<HTMLInputElement>(null); | ||
const portRef = useRef<HTMLInputElement>(null); | ||
const snackbar = useSnackbar(); | ||
const router = useRouter(); | ||
|
||
const handleSubmit: FormEventHandler<HTMLFormElement> = async (e) => { | ||
e.preventDefault(); | ||
const host = hostRef.current?.value as string; | ||
const port = portRef.current?.value as string; | ||
const validation = validateFormInput(host, port); | ||
if (!validation.isValid) { | ||
setHelpText(validation.helpText); | ||
return; | ||
} | ||
|
||
const { valid, reason } = await setConfig(host, Number.parseInt(port, 10)); | ||
if (!valid) { | ||
snackbar.openSnackbar( | ||
`Unable to connect to fleet-telemetry server: ${reason}`, | ||
'error', | ||
); | ||
} else { | ||
snackbar.openSnackbar('Connection successful', 'success'); | ||
configureServer(host, port); | ||
router.push(FLEET); | ||
} | ||
}; | ||
|
||
return ( | ||
<AppBar> | ||
<Grid container spacing={4} sx={{ mt: 4 }}> | ||
<Grid item xs={12} sm={6} textAlign="right"> | ||
<Image | ||
src="/fleet.jpeg" | ||
alt="fleet" | ||
width="400" | ||
height="400" | ||
style={{ borderRadius: 15 }} | ||
/> | ||
</Grid> | ||
<Grid | ||
item | ||
xs={12} | ||
sm={6} | ||
sx={{ | ||
display: 'flex', | ||
flexDirection: 'column', | ||
justifyContent: 'center', | ||
}} | ||
> | ||
<Typography variant="h4">Welcome to Phantom Fleet</Typography> | ||
<Typography variant="body1"> | ||
To get started, enter your fleet-telemetry server information. | ||
</Typography> | ||
<Box | ||
sx={{ mt: 1, maxWidth: 300 }} | ||
onSubmit={handleSubmit} | ||
component="form" | ||
> | ||
{isLoading ? ( | ||
<> | ||
<Skeleton> | ||
<TextField variant="outlined" margin="normal" fullWidth /> | ||
</Skeleton> | ||
<Skeleton> | ||
<TextField variant="outlined" margin="normal" fullWidth /> | ||
</Skeleton> | ||
</> | ||
) : ( | ||
<> | ||
<TextField | ||
error={helpText.host !== ''} | ||
helperText={helpText.host} | ||
label="Host" | ||
variant="outlined" | ||
margin="normal" | ||
fullWidth | ||
inputRef={hostRef} | ||
defaultValue={server?.host} | ||
/> | ||
<TextField | ||
error={helpText.port !== ''} | ||
helperText={helpText.port} | ||
label="Port" | ||
variant="outlined" | ||
margin="normal" | ||
fullWidth | ||
inputRef={portRef} | ||
defaultValue={server?.port} | ||
/> | ||
</> | ||
)} | ||
<Button variant="contained" type="submit" sx={{ mt: 3, mb: 2 }}> | ||
Validate Connection | ||
</Button> | ||
<Typography> | ||
<Link style={{ color: 'grey' }} href={FLEET}> | ||
Skip connection setup | ||
</Link> | ||
</Typography> | ||
</Box> | ||
</Grid> | ||
</Grid> | ||
</AppBar> | ||
); | ||
} |
Binary file not shown.
Oops, something went wrong.