update the readme and created a new whitelabel for MiPCA that will be used to replace the omniAir one
37
README.md
|
|
@ -7,6 +7,43 @@ Currently, two official plugins are available:
|
||||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||||
|
|
||||||
|
### White-labeling
|
||||||
|
|
||||||
|
Steps to add a new white label
|
||||||
|
|
||||||
|
1. Client Instructions:
|
||||||
|
|
||||||
|
- supply assets and colours to be used for the white-label (favicon if necessary)
|
||||||
|
- determine a sub-domain to use as mask, dashboard is preferred (ex: dashboard.example.com)
|
||||||
|
- add a `CNAME` record pointing their custom subdomain (ex: dashboard.example.com) to brandxtech.ca
|
||||||
|
- add a login button on their website point to `/login` of their custom subdomain (ex: dashboard.example.com/login)
|
||||||
|
|
||||||
|
<!-- frontend steps -->
|
||||||
|
2. Create a PWA folder in `public` that is named after the client and generate PWA assets using [this](https://realfavicongenerator.net/) website (use the company logo but you might need to use a custom favicon depending on the result)
|
||||||
|
|
||||||
|
- https://maskable.app/ also create a maskable icon for PWA
|
||||||
|
- create a 512x512 png as well for PWA
|
||||||
|
|
||||||
|
3. Create a white-label branding folder in `src/assets/whitelabels` and create a `darkLogo.png` and `lightLogo.png` from the client's logo
|
||||||
|
4. In `src/services/whiteLabel.ts`, add a new `Whitelabel` instance with the required fields and add its hostname mapping to the `whitelabels` map (it is very similar to step one but had some constraints when dealing with the `public` folder)
|
||||||
|
5. If there are any pages specific to the whitelabel be sure to update the side and bottom navigator
|
||||||
|
|
||||||
|
<!-- backend steps -->
|
||||||
|
6. In `dynamic-config.prod.yml`, add a router entry for the new whitelabel
|
||||||
|
7. In `pond/http/server.go`, add the sub-domain to the `allowedOrigins`
|
||||||
|
8. In `pond/whitelabel.go`, add an entry for the new white label
|
||||||
|
|
||||||
|
7. Create a new `Auth0` application for the client
|
||||||
|
- use a image bucket like [postimg](https://postimages.org/) to store their company logo and favicon
|
||||||
|
- add a whitelabel logo
|
||||||
|
- allow necessary `origins`, `callback URLs`, and `CORS domains` to the application settings (see the default application as a guideline)
|
||||||
|
- customize the Universal Login page to handle the new whitelabel
|
||||||
|
- check if the client ID matches this client's Auth0 application
|
||||||
|
- change the Universal Login theme using white-label colours and images stored in a bucket (ex: [postimg](https://postimages.org/))
|
||||||
|
8. Enable the white-label sub-domain for CORS in the backend
|
||||||
|
|
||||||
|
- in [http.go](https://gitlab.com/brandx/backend/blob/master/pond/http.go), add the white-label sub-domain to the `AllowedOrigins` list
|
||||||
|
|
||||||
## Expanding the ESLint configuration
|
## Expanding the ESLint configuration
|
||||||
|
|
||||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||||
|
|
|
||||||
BIN
public/MiPCA/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 4 KiB |
BIN
public/MiPCA/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/MiPCA/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
9
public/MiPCA/browserconfig.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square150x150logo src="/mstile-150x150.png"/>
|
||||||
|
<TileColor>#da532c</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
||||||
BIN
public/MiPCA/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 808 B |
BIN
public/MiPCA/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/MiPCA/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
33
public/MiPCA/manifest.json
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "MiPCA",
|
||||||
|
"short_name": "MiPCA",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "48x48",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "maskable_icon.png",
|
||||||
|
"sizes": "196x196",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "any maskable"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": "/",
|
||||||
|
"theme_color": "#272727",
|
||||||
|
"background_color": "#303030",
|
||||||
|
"display": "standalone",
|
||||||
|
"orientation": "any"
|
||||||
|
}
|
||||||
|
|
||||||
BIN
public/MiPCA/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
50
public/MiPCA/safari-pinned-tab.svg
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1059.000000pt" height="1059.000000pt" viewBox="0 0 1059.000000 1059.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,1059.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M7029 6666 c-2 -2 -31 -7 -64 -10 -426 -43 -727 -354 -781 -806 -10
|
||||||
|
-89 -11 -984 -1 -1090 27 -277 151 -517 340 -659 92 -69 256 -140 366 -157 18
|
||||||
|
-3 43 -8 55 -10 11 -3 80 -8 151 -11 408 -17 711 161 894 525 39 77 95 242
|
||||||
|
114 335 l14 67 -36 1 c-174 5 -484 0 -490 -7 -4 -5 -15 -36 -25 -69 -40 -134
|
||||||
|
-128 -250 -226 -300 -73 -37 -171 -51 -268 -38 -177 23 -289 121 -347 303 -16
|
||||||
|
49 -18 107 -20 522 -3 508 1 556 51 668 15 33 30 60 34 60 3 0 13 12 20 26 20
|
||||||
|
36 100 92 167 115 116 41 247 36 353 -14 52 -25 157 -127 182 -178 36 -73 56
|
||||||
|
-125 63 -161 4 -21 10 -38 14 -38 9 -1 494 -1 512 -1 15 1 15 7 -2 79 -37 158
|
||||||
|
-60 225 -114 332 -141 281 -357 448 -651 504 -62 11 -296 21 -305 12z"/>
|
||||||
|
<path d="M0 5298 c0 -1071 3 -1348 13 -1349 55 -4 439 -1 444 4 3 3 6 420 6
|
||||||
|
927 0 506 2 919 4 917 2 -3 62 -190 134 -418 72 -228 178 -565 236 -749 58
|
||||||
|
-184 108 -345 110 -357 3 -13 10 -23 17 -24 6 0 107 -1 225 -2 205 -2 214 -1
|
||||||
|
222 18 9 21 232 743 429 1390 29 94 55 173 59 177 3 4 6 -418 5 -938 -1 -861
|
||||||
|
0 -944 15 -945 93 -5 426 -2 434 3 9 5 12 346 12 1348 l0 1340 -35 1 c-46 0
|
||||||
|
-555 0 -601 0 l-35 -1 -28 -97 c-15 -54 -32 -111 -37 -128 -5 -16 -40 -140
|
||||||
|
-78 -275 -38 -135 -101 -360 -141 -500 -40 -140 -81 -284 -90 -320 -10 -36
|
||||||
|
-41 -146 -69 -245 -29 -99 -54 -191 -57 -205 -8 -39 -12 -36 -28 21 -8 30 -47
|
||||||
|
167 -86 304 -40 138 -82 288 -95 335 -33 121 -120 427 -221 780 -47 168 -87
|
||||||
|
311 -87 318 0 6 -7 12 -16 12 -9 1 -161 2 -339 3 l-322 2 0 -1347z"/>
|
||||||
|
<path d="M2890 6400 l0 -245 253 0 252 0 0 245 0 245 -252 0 -253 0 0 -245z"/>
|
||||||
|
<path d="M3948 6642 l-46 -3 0 -244 1 -244 591 -3 c575 -3 592 -4 636 -24 85
|
||||||
|
-39 141 -114 165 -219 43 -186 -50 -367 -212 -411 -38 -10 -170 -12 -610 -10
|
||||||
|
l-563 2 -1 -30 c-4 -176 0 -1499 5 -1503 4 -5 417 -8 486 -4 14 1 15 63 15
|
||||||
|
521 0 343 3 520 10 521 5 0 170 1 365 3 384 3 419 7 558 63 270 108 449 345
|
||||||
|
478 632 10 109 11 132 3 224 -22 244 -131 442 -322 581 -93 68 -273 131 -408
|
||||||
|
142 -69 6 -1070 11 -1151 6z"/>
|
||||||
|
<path d="M9279 6642 c-46 -3 -47 -4 -64 -50 -9 -26 -21 -56 -25 -67 -5 -11
|
||||||
|
-50 -128 -100 -260 -50 -132 -94 -249 -99 -260 -5 -11 -55 -141 -111 -290 -56
|
||||||
|
-148 -105 -279 -110 -290 -11 -24 2 10 -296 -770 -284 -741 -267 -697 -255
|
||||||
|
-704 11 -7 2358 -8 2364 -1 3 4 -59 172 -126 340 -3 8 -144 377 -312 820 -169
|
||||||
|
443 -322 843 -340 890 -18 47 -79 207 -135 355 -57 149 -106 274 -110 278 -7
|
||||||
|
8 -198 14 -281 9z m144 -932 c8 -25 45 -130 82 -235 37 -104 86 -246 110 -315
|
||||||
|
24 -69 71 -204 105 -300 34 -96 76 -218 95 -270 18 -52 38 -107 44 -122 6 -16
|
||||||
|
9 -29 8 -29 -1 -1 -213 -2 -470 -3 l-468 -1 6 23 c5 22 54 162 300 862 51 146
|
||||||
|
108 307 126 358 17 51 35 89 39 85 4 -4 14 -28 23 -53z"/>
|
||||||
|
<path d="M2890 4720 c0 -609 3 -770 13 -771 6 0 120 -1 252 -2 l240 0 3 771 2
|
||||||
|
772 -255 0 -255 0 0 -770z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
BIN
src/assets/whitelabels/MiPCA/MiPCALogo.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
|
|
@ -13,7 +13,7 @@ import BinsIcon from "products/Bindapt/BinsIcon";
|
||||||
import { useGlobalState } from "providers";
|
import { useGlobalState } from "providers";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useNavigate, useLocation } from "react-router-dom";
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
import { IsAdaptiveAgriculture, isBXT, IsMiVent, IsAdCon, IsOmniAir } from "services/whiteLabel";
|
import { IsAdaptiveAgriculture, isBXT, IsMiVent, IsAdCon, IsOmniAir, IsMiPCA } from "services/whiteLabel";
|
||||||
import FieldsIcon from "products/AgIcons/FieldsIcon";
|
import FieldsIcon from "products/AgIcons/FieldsIcon";
|
||||||
import NexusSTIcon from "products/Construction/NexusSTIcon";
|
import NexusSTIcon from "products/Construction/NexusSTIcon";
|
||||||
import OmniAirDeviceIcon from "products/AviationIcons/OmniAirDeviceIcon";
|
import OmniAirDeviceIcon from "products/AviationIcons/OmniAirDeviceIcon";
|
||||||
|
|
@ -40,6 +40,7 @@ export default function BottomNavigator(props: Props) {
|
||||||
const isMiVent = IsMiVent();
|
const isMiVent = IsMiVent();
|
||||||
const isAdCon = IsAdCon();
|
const isAdCon = IsAdCon();
|
||||||
const isOmni = IsOmniAir();
|
const isOmni = IsOmniAir();
|
||||||
|
const isMiPCA = IsMiPCA();
|
||||||
|
|
||||||
const reRoute = useCallback(
|
const reRoute = useCallback(
|
||||||
(path: string) => {
|
(path: string) => {
|
||||||
|
|
@ -117,14 +118,14 @@ export default function BottomNavigator(props: Props) {
|
||||||
value="constructionMap"
|
value="constructionMap"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isOmni && (
|
{(isOmni || isMiPCA) && (
|
||||||
<BottomNavigationAction
|
<BottomNavigationAction
|
||||||
label="Map"
|
label="Map"
|
||||||
icon={<AirportMapIcon type={getType()} />}
|
icon={<AirportMapIcon type={getType()} />}
|
||||||
value="aviationMap"
|
value="aviationMap"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isOmni && (
|
{(isOmni || isMiPCA) && (
|
||||||
<BottomNavigationAction
|
<BottomNavigationAction
|
||||||
label="Terminals"
|
label="Terminals"
|
||||||
icon={<PlaneIcon type={getType()} />}
|
icon={<PlaneIcon type={getType()} />}
|
||||||
|
|
@ -139,7 +140,7 @@ export default function BottomNavigator(props: Props) {
|
||||||
<BindaptIcon type={getType()} />
|
<BindaptIcon type={getType()} />
|
||||||
) : isAdCon ? (
|
) : isAdCon ? (
|
||||||
<NexusSTIcon type={getType()} />
|
<NexusSTIcon type={getType()} />
|
||||||
) : isOmni ? (
|
) : (isOmni || isMiPCA) ? (
|
||||||
<OmniAirDeviceIcon type={getType()} />
|
<OmniAirDeviceIcon type={getType()} />
|
||||||
) : (
|
) : (
|
||||||
<DevicesIcon />
|
<DevicesIcon />
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import {
|
||||||
IsAdaptiveAgriculture,
|
IsAdaptiveAgriculture,
|
||||||
// hasTutorialPlaylist,
|
// hasTutorialPlaylist,
|
||||||
IsAdCon,
|
IsAdCon,
|
||||||
|
IsMiPCA,
|
||||||
// isBXT,
|
// isBXT,
|
||||||
IsMiVent,
|
IsMiVent,
|
||||||
IsOmniAir,
|
IsOmniAir,
|
||||||
|
|
@ -166,7 +167,8 @@ export default function SideNavigator(props: Props) {
|
||||||
const isMiVent = IsMiVent();
|
const isMiVent = IsMiVent();
|
||||||
const isAg = IsAdaptiveAgriculture()
|
const isAg = IsAdaptiveAgriculture()
|
||||||
const isStreamline = IsStreamline()
|
const isStreamline = IsStreamline()
|
||||||
const isMiPCA = IsOmniAir()
|
const isOmni = IsOmniAir()
|
||||||
|
const isMiPCA = IsMiPCA()
|
||||||
const isAdCon = IsAdCon()
|
const isAdCon = IsAdCon()
|
||||||
return (
|
return (
|
||||||
<List className={classes.list} component="nav">
|
<List className={classes.list} component="nav">
|
||||||
|
|
@ -184,7 +186,7 @@ export default function SideNavigator(props: Props) {
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{(isMiPCA || user.hasFeature("admin")) && (
|
{((isOmni || isMiPCA) || user.hasFeature("admin")) && (
|
||||||
<Tooltip title="Aviation Map" placement="right">
|
<Tooltip title="Aviation Map" placement="right">
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
id="tour-aviation-map"
|
id="tour-aviation-map"
|
||||||
|
|
@ -240,7 +242,7 @@ export default function SideNavigator(props: Props) {
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{(isMiPCA || user.hasFeature("admin")) && (
|
{((isOmni || isMiPCA) || user.hasFeature("admin")) && (
|
||||||
<Tooltip title="Terminals" placement="right">
|
<Tooltip title="Terminals" placement="right">
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
id="tour-terminals"
|
id="tour-terminals"
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ export default function Gate(props: Props) {
|
||||||
const deviceDrawer = () => {
|
const deviceDrawer = () => {
|
||||||
return (
|
return (
|
||||||
<DeviceLinkDrawer
|
<DeviceLinkDrawer
|
||||||
deviceTags={["omniair"]}
|
deviceTags={["omniair", "mipca"]}
|
||||||
devicePrefMap={devPrefs}
|
devicePrefMap={devPrefs}
|
||||||
prefOptions={[
|
prefOptions={[
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import AeroGrowDarkLogo from "../assets/whitelabels/AeroGrow/darkLogo.png";
|
||||||
import AeroGrowLightLogo from "../assets/whitelabels/AeroGrow/lightLogo.png";
|
import AeroGrowLightLogo from "../assets/whitelabels/AeroGrow/lightLogo.png";
|
||||||
import MiVentLightLogo from "../assets/whitelabels/MiVent/lightLogo.png";
|
import MiVentLightLogo from "../assets/whitelabels/MiVent/lightLogo.png";
|
||||||
// import OmniAirLogo from "../assets/whitelabels/OmniAir/OmniAirLogo.png";
|
// import OmniAirLogo from "../assets/whitelabels/OmniAir/OmniAirLogo.png";
|
||||||
import MiPCALogo from "../assets/whitelabels/OmniAir/MiPCALogo.png";
|
import MiPCALogo from "../assets/whitelabels/MiPCA/MiPCALogo.png";
|
||||||
import StreamlineLogo from "../assets/whitelabels/Streamline/stream-logo.png"
|
import StreamlineLogo from "../assets/whitelabels/Streamline/stream-logo.png"
|
||||||
// import { green, yellow } from "@mui/material/colors";
|
// import { green, yellow } from "@mui/material/colors";
|
||||||
|
|
||||||
|
|
@ -284,6 +284,32 @@ export function IsOmniAir(): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MIPCA_WHITE_LABEL: WhiteLabel = {
|
||||||
|
name: "MiPCA",
|
||||||
|
primaryColour: "#004f9b",
|
||||||
|
secondaryColour: "yellow",
|
||||||
|
signatureColour: "#272727",
|
||||||
|
signatureAccentColour: "#fff",
|
||||||
|
//omni air and MiPCA are the same client ID in Auth0, it is to replace it, once omniair gets removed we can re-name this
|
||||||
|
auth0ClientId: import.meta.env.VITE_AUTH0_OMNIAIR_CLIENT_ID,
|
||||||
|
redirectOnLogout: true,
|
||||||
|
logoutRedirectTarget: "https://mionetech.com",
|
||||||
|
darkLogo: MiPCALogo,
|
||||||
|
lightLogo: MiPCALogo,
|
||||||
|
transparentLogoBG: true,
|
||||||
|
blacklist: ["cost"],
|
||||||
|
docs: "MiPCA",
|
||||||
|
protips: protips.concat([])
|
||||||
|
};
|
||||||
|
|
||||||
|
export function IsMiPCA(): boolean {
|
||||||
|
return (
|
||||||
|
getName() === "MiPCA" ||
|
||||||
|
window.location.origin.includes("staging") ||
|
||||||
|
window.location.origin.includes("localhost")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const whitelabels = new Map<string, WhiteLabel>([
|
const whitelabels = new Map<string, WhiteLabel>([
|
||||||
["streamline", STREAMLINE_WHITE_LABEL],
|
["streamline", STREAMLINE_WHITE_LABEL],
|
||||||
["adaptiveag", ADAPTIVE_AGRICULTURE_WHITE_LABEL],
|
["adaptiveag", ADAPTIVE_AGRICULTURE_WHITE_LABEL],
|
||||||
|
|
@ -296,7 +322,8 @@ const whitelabels = new Map<string, WhiteLabel>([
|
||||||
["10.0", ADAPTIVE_CONSTRUCTION_WHITE_LABEL],
|
["10.0", ADAPTIVE_CONSTRUCTION_WHITE_LABEL],
|
||||||
["mivent", MIVENT_WHITE_LABEL],
|
["mivent", MIVENT_WHITE_LABEL],
|
||||||
["adaptiveconstruction", ADAPTIVE_CONSTRUCTION_WHITE_LABEL],
|
["adaptiveconstruction", ADAPTIVE_CONSTRUCTION_WHITE_LABEL],
|
||||||
["omniair", OMNIAIR_WHITE_LABEL]
|
["omniair", OMNIAIR_WHITE_LABEL],
|
||||||
|
["mipca", MIPCA_WHITE_LABEL]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export function getWhitelabel(): WhiteLabel {
|
export function getWhitelabel(): WhiteLabel {
|
||||||
|
|
|
||||||