Merge branch 'release/0.0.3'

This commit is contained in:
jwu-fisker
2023-02-09 09:46:52 -08:00
29 changed files with 1031 additions and 495 deletions

View File

@@ -1,6 +1,7 @@
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.cec-euprd.fiskerinc.com
REACT_APP_AUTH_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/compute_auth
REACT_APP_CERT_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/certificate
REACT_APP_ENV=cec-euprd
REACT_APP_MAGNA_PROVIDER=Magna
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
REACT_APP_OTA_SERVICE_URL=https://gw.cec-euprd.fiskerinc.com/ota_update

View File

@@ -1,6 +1,7 @@
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.cec-prd.fiskerinc.com
REACT_APP_AUTH_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/compute_auth
REACT_APP_CERT_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/certificate
REACT_APP_ENV=cec-prd
REACT_APP_MAGNA_PROVIDER=Magna
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
REACT_APP_OTA_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/ota_update

View File

@@ -1,6 +1,7 @@
REACT_APP_AUTH_CALLBACK_URL=https://dev-ota-admin.cloud.fiskerinc.com
REACT_APP_AUTH_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/compute_auth
REACT_APP_CERT_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/certificate
REACT_APP_ENV=dev
REACT_APP_MAGNA_PROVIDER=Fisker-QA
REACT_APP_MAGNA_GROUP_ID=efcc3025-e2d8-4212-8227-805c7be39d2c
REACT_APP_OTA_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/ota_update

View File

@@ -1,6 +1,7 @@
REACT_APP_AUTH_CALLBACK_URL=http://localhost:3000
REACT_APP_AUTH_SERVICE_URL=http://localhost/compute_auth
REACT_APP_CERT_SERVICE_URL=http://localhost/certificate
REACT_APP_ENV=local
REACT_APP_MAGNA_PROVIDER=Fisker-QA
REACT_APP_MAGNA_GROUP_ID=efcc3025-e2d8-4212-8227-805c7be39d2c
REACT_APP_OTA_SERVICE_URL=http://localhost/ota_update

View File

@@ -1,6 +1,7 @@
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.cloud.fiskerinc.com
REACT_APP_AUTH_SERVICE_URL=https://gw.cloud.fiskerinc.com/compute_auth
REACT_APP_CERT_SERVICE_URL=https://gw.cloud.fiskerinc.com/certificate
REACT_APP_ENV=prd
REACT_APP_MAGNA_PROVIDER=Magna
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
REACT_APP_OTA_SERVICE_URL=https://gw.cloud.fiskerinc.com/ota_update

View File

@@ -1,6 +1,7 @@
REACT_APP_AUTH_CALLBACK_URL=https://stg-ota-admin.cloud.fiskerinc.com
REACT_APP_AUTH_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/compute_auth
REACT_APP_CERT_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/certificate
REACT_APP_ENV=stg
REACT_APP_MAGNA_PROVIDER=Magna
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
REACT_APP_OTA_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/ota_update

View File

@@ -1,6 +1,7 @@
REACT_APP_AUTH_CALLBACK_URL=http://localhost:3000
REACT_APP_AUTH_SERVICE_URL=http://localhost/compute_auth
REACT_APP_CERT_SERVICE_URL=http://localhost/certificate
REACT_APP_ENV=local
REACT_APP_MAGNA_PROVIDER=Magna
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
REACT_APP_OTA_SERVICE_URL=http://localhost/ota_update

29
.eslintrc.json Normal file
View File

@@ -0,0 +1,29 @@
{
"env": {
"browser": true,
"es6": true,
"jest": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:react/jsx-runtime",
"react-app",
"react-app/jest"
],
"overrides": [],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"no-unused-vars": "warn"
},
"ignorePatterns": [
"build/**/*",
"*.test.*"
]
}

View File

@@ -11,3 +11,7 @@ jobs:
uses: Fisker-Inc/github-actions/.github/workflows/blackduck.yml@main
with:
project: ota-admin-portal
secrets:
github-token: ${{ secrets.GITHUB_TOKEN }}
blackduck-url: ${{ secrets.BLACKDUCK_URL }}
blackduck-api-token: ${{ secrets.BLACKDUCK_API_KEY }}

10
.github/workflows/pr.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
name: Pull Request Jira Check
on:
pull_request:
types: [opened, edited, synchronize, reopened]
jobs:
prcheck:
uses: Fisker-Inc/github-actions/.github/workflows/pr.yml@main

View File

@@ -11,12 +11,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: "16"
cache: "npm"

1244
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -68,6 +68,8 @@
"node": "^16.13.0"
},
"devDependencies": {
"eslint": "^8.32.0",
"eslint-plugin-react": "^7.32.1",
"react-test-renderer": "^17.0.2"
},
"jest": {

View File

@@ -1778,6 +1778,13 @@ exports[`App Route /issue-info authenticated 1`] = `
:
FISKER123
</p>
<p>
<b>
Driver ID
</b>
:
valid-cognito-id-1
</p>
<p>
<b>
VIN
@@ -9959,6 +9966,16 @@ exports[`App Route /vehicle-status authenticated 1`] = `
3
</p>
</div>
<div
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-12"
>
<p>
<b>
DebugMask
</b>
:
</p>
</div>
<div
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-12"
>

View File

@@ -137,6 +137,16 @@ exports[`VehicleDetailsTab Render 1`] = `
3
</p>
</div>
<div
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-12"
>
<p>
<b>
DebugMask
</b>
:
</p>
</div>
<div
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-12"
>

View File

@@ -32,6 +32,9 @@ const MainForm = ({ vin }) => {
providers,
} = useUserContext();
const ENV = process.env.REACT_APP_ENV;
const showDebugMask = (ENV === 'local' || ENV === 'dev' || ENV === 'stg')
useEffect(() => {
(async () => {
try {
@@ -120,6 +123,13 @@ const MainForm = ({ vin }) => {
</p>
</Grid>
)}
{showDebugMask && (
<Grid item md={12} className={classes.textCenterAlign}>
<p>
<b>DebugMask</b>: {vehicle.debug_mask}
</p>
</Grid>
)}
<Grid item md={12} className={classes.textCenterAlign}>
<RoleWrap
groups={groups}

View File

@@ -80,6 +80,29 @@ exports[`CarUpdatesTab Render 1`] = `
</svg>
</span>
</th>
<th
class="MuiTableCell-root MuiTableCell-head MuiTableCell-alignCenter"
scope="col"
>
<span
aria-disabled="false"
class="MuiButtonBase-root MuiTableSortLabel-root"
role="button"
tabindex="0"
>
Username
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiTableSortLabel-icon MuiTableSortLabel-iconDirectionAsc"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z"
/>
</svg>
</span>
</th>
<th
class="MuiTableCell-root MuiTableCell-head MuiTableCell-alignCenter"
scope="col"

View File

@@ -145,6 +145,16 @@ exports[`DetailsTab Render 1`] = `
3
</p>
</div>
<div
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-12"
>
<p>
<b>
DebugMask
</b>
:
</p>
</div>
<div
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-12"
>

View File

@@ -272,6 +272,16 @@ exports[`CarStatus Render 1`] = `
:
</p>
</div>
<div
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-12"
>
<p>
<b>
DebugMask
</b>
:
</p>
</div>
<div
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-12"
>

View File

@@ -931,6 +931,43 @@ exports[`VehicleUpdate Render 1`] = `
</fieldset>
</div>
</div>
<div
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined"
data-shrink="true"
for="debug_mask"
id="debug_mask-label"
>
DebugMask
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-fullWidth MuiInputBase-formControl"
>
<input
aria-invalid="false"
class="MuiInputBase-input MuiOutlinedInput-input"
id="debug_mask"
maxlength="255"
name="debug_mask"
type="text"
value=""
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-0 MuiOutlinedInput-notchedOutline"
>
<legend
class="PrivateNotchedOutline-legendLabelled-0 PrivateNotchedOutline-legendNotched-0"
>
<span>
DebugMask
</span>
</legend>
</fieldset>
</div>
</div>
<button
class="MuiButtonBase-root MuiButton-root MuiButton-contained makeStyles-submit-0 MuiButton-containedPrimary MuiButton-fullWidth"
tabindex="0"

View File

@@ -46,6 +46,10 @@ const MainForm = () => {
const [dataLoggerEnabled, setDataLoggerEnabled] = useState(false);
const [maxMemBufferSize, setMaxMemBufferSize] = useState(0);
const [maxDiskBufferSize, setMaxDiskBufferSize] = useState(0);
const debugMaskEl = useRef(null);
const ENV = process.env.REACT_APP_ENV;
const showDebugMask = (ENV === 'local' || ENV === 'dev' || ENV === 'stg')
useEffect(() => {
setTitle("Update Vehicle");
@@ -93,6 +97,11 @@ const MainForm = () => {
setMaxMemBufferSize(vehicle.canbus.max_mem_buffer_size ?? maxMemBufferSize);
setMaxDiskBufferSize(vehicle.canbus.max_disk_buffer_size ?? maxDiskBufferSize);
}
if (showDebugMask) {
debugMaskEl.current.value = vehicle.debug_mask ?? ""
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [vehicle]);
@@ -136,7 +145,8 @@ const MainForm = () => {
data_logger_enabled: canbusEnabled ? dataLoggerEnabled : false,
max_mem_buffer_size: canbusEnabled ? parseInt(maxMemBufferSize) : 0,
max_disk_buffer_size: canbusEnabled && dataLoggerEnabled ? parseInt(maxDiskBufferSize) : 0
}
},
debug_mask: debugMaskEl.current.value
};
const result = await updateVehicle(vin, formData, token);
@@ -379,6 +389,24 @@ const MainForm = () => {
required
fullWidth
/>
{showDebugMask && (
<TextField
id="debug_mask"
name="debug_mask"
label="DebugMask"
InputLabelProps={{
shrink: true
}}
defaultValue=""
variant="outlined"
margin="normal"
inputProps={{
maxLength: "255",
}}
fullWidth
inputRef={debugMaskEl}
/>
)}
<Button
type="submit"
disabled={busy}

View File

@@ -177,6 +177,7 @@ export const CarUpdatesProvider = ({ children }) => {
applyProgressStatuses(result.statuses);
} catch (e) {
throw new Error(`Get update progress error. ${e}`);
} finally {
setBusy(false);
}

View File

@@ -30,6 +30,7 @@ let carUpdateLog = {
{
id: 90,
carupdate_id: 283,
username: "test username 1",
status: "package_install_complete",
error_code: 0,
created: "2021-08-23T17:06:38.410115Z",
@@ -38,6 +39,7 @@ let carUpdateLog = {
{
id: 89,
carupdate_id: 283,
username: "test username 2",
status: "package_install_start",
error_code: 0,
info: "TEST",
@@ -47,6 +49,7 @@ let carUpdateLog = {
{
id: 88,
carupdate_id: 284,
username: "test username 3",
status: "install_approval_await",
error_code: 0,
info: "TEST",

View File

@@ -14,6 +14,7 @@ import { Link } from "react-router-dom";
import { logger } from "../../../services/monitoring";
import { LocalDateTimeString } from "../../../utils/dates";
import { Permissions } from "../../../utils/roles";
import {
CarUpdatesProvider,
useCarUpdatesContext
@@ -34,6 +35,10 @@ const tableColumns = [
id: "update_package_id",
label: "Name",
},
{
id: "username",
label: "Username",
},
{
id: "status",
label: "Status",
@@ -167,6 +172,9 @@ const MainForm = ({ vin, token }) => {
{updateName(row)}
</Link>
</TableCell>
<TableCell align="center">
{row.username}
</TableCell>
<TableCell align="center">
{row.status}
{row.progress > -1 && (

View File

@@ -1,6 +1,7 @@
import React from "react";
import { LocalDateTimeString } from "../../utils/dates";
import { ValidateLocationByParam } from "../../utils/locations"
import useStyles from "../useStyles";
const keyValueTemplate = (key, value) => (
@@ -83,6 +84,9 @@ const DigitalTwin = (props) => {
<div className={classes.popupSection}>
<h3>Location</h3>
{Object.entries(location).map((value) => {
if (ValidateLocationByParam(value[0], value[1]) === false) {
return keyValueTemplate(value[0], "Invalid")
}
if (value[0] === "altitude") {
return keyValueTemplate(value[0], value[1]);
} else {

View File

@@ -26,7 +26,9 @@ export default class ErrorBoundary extends Component {
if (this.state.hasError) {
try {
logger.error(this.state.error.stack);
} catch (e) {}
} catch (e) {
logger.error(e);
}
if (this.state.error && this.state.error.name === "ChunkLoadError") {
reload();

View File

@@ -44,6 +44,9 @@ const MainForm = ({ id }) => {
<p>
<b>ID</b>: {id}
</p>
<p>
<b>Driver ID</b>: {issue.driver_id}
</p>
<p>
<b>VIN</b>: {issue.vin}
</p>

View File

@@ -44,7 +44,7 @@ const Component = () => {
const retrieveAndStoreLocations = (accessToken) => {
return getLocations(accessToken)
.then((result) => {
if (result.data != null) {
if (result.data != null && ValidateLocationData(result.data) !== false) {
const points = result.data.map((point) => [
point.latitude,
point.longitude,

22
src/utils/locations.js Normal file
View File

@@ -0,0 +1,22 @@
export const ValidateLocationData = (location) => {
if (Math.abs(location.latitude) > 90 || Math.abs(location.longitude) > 180) {
return false;
}
if (location.altitude === 1401) {
return false;
}
return true;
}
export const ValidateLocationByParam = (parameter, value) => {
switch (parameter) {
case "latitude":
return Math.abs(value) <= 90;
case "longitude":
return Math.abs(value) <= 180;
case "altitude":
return value !== 1401;
default:
return false;
}
}