diff --git a/.env_example b/.env_example index 311fe59..4d7105f 100644 --- a/.env_example +++ b/.env_example @@ -1,6 +1,6 @@ NODE_ENV=development ROOT=https://your-produciton-server.com KEY= -USER_JOHNDOE= +USER_XX= USER_TEST= MAPBOX= diff --git a/.eslintrc.json b/.eslintrc.json index c69a5cb..de350aa 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -17,11 +17,8 @@ }, "plugins": ["jest", "@typescript-eslint"], "rules": { - //"no-console": "off", - //"import/prefer-default-export": "off", - //"@typescript-eslint/no-unused-vars": "warn" "jest/no-conditional-expect": "off" }, - "ignorePatterns": ["dist", "jest.config.js", "httpdocs", "webpack.config.js", "src/client", "init"] + "ignorePatterns": ["dist", "jest.config.js", "httpdocs", "webpack.config.js", "src/client", "init", "jest.testData.config.js"] } diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fea0e1d..b84044a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,6 +39,7 @@ jobs: run: npm run test:login - name: Run unit tests run: npm run test:unit + - run: echo "--- base tests complete ---" - name: Run integration tests run: npm run test:integration diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index 7bd9917..0000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,26 +0,0 @@ -# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. -# -# You can adjust the behavior by modifying this file. -# For more information, see: -# https://github.com/actions/stale -name: stale Issues - -on: - schedule: - - cron: '16 11 * * *' - -jobs: - stale: - - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - - steps: - - uses: actions/stale@v5 - with: - stale-issue-message: '[Stale] issue message' - stale-pr-message: '[Stale] pull request message' - stale-issue-label: 'no-issue-activity' - stale-pr-label: 'no-pr-activity' diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 864577f..c5e0c9b 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -15,4 +15,4 @@ "problemMatcher": "$tsc" } ] -} +} \ No newline at end of file diff --git a/demo.png b/demo.png index 8cfb494..2d14ea6 100644 Binary files a/demo.png and b/demo.png differ diff --git a/httpdocs/color-table.svg b/httpdocs/color-table.svg index 4e05122..6dccf17 100644 --- a/httpdocs/color-table.svg +++ b/httpdocs/color-table.svg @@ -1 +1,137 @@ -HEXmaininfoalertsuccessneutralOKLCH900750625500375250100 \ No newline at end of file + + + + HEX + + main + + info + + alert + + success + + neutral + + OKLCH + + + 900 + + 750 + + 625 + + 500 + + 375 + + 250 + + 100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/init/generateKey.js b/init/generateKey.js index e2633f0..e3569f4 100644 --- a/init/generateKey.js +++ b/init/generateKey.js @@ -24,7 +24,7 @@ rl.question('Enter the string to be encoded: ', (input) => { const base64String = Buffer.from(escapedString).toString('base64'); // print the result - console.log('Base64 Encoded String:', base64String); + console.log('encoded String:', base64String); rl.close(); }); \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 5cada10..d2e3ff2 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,4 +7,4 @@ module.exports = { '^@src/(.*)$': '/src/$1', }, bail: true -}; \ No newline at end of file +}; diff --git a/jest.testData.config.js b/jest.testData.config.js index f8e72a3..82628d9 100644 --- a/jest.testData.config.js +++ b/jest.testData.config.js @@ -1,4 +1,5 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ + module.exports = { preset: 'ts-jest', testEnvironment: 'node', diff --git a/package-lock.json b/package-lock.json index 32837d6..8f0bd48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5766,6 +5766,21 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -7860,12 +7875,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { diff --git a/src/client/components/App.tsx b/src/client/components/App.tsx index 19e7916..c8679bc 100644 --- a/src/client/components/App.tsx +++ b/src/client/components/App.tsx @@ -47,6 +47,8 @@ const App = () => { const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); const [mapToken, setMapToken] = useState(null); + const contextObj = {isLoggedIn, setLogin, userInfo, setUserInfo, mode, setMode, prefersDarkMode, mapToken} + useEffect(() => { setMode(prefersDarkMode ? "dark" : "light"); }, [prefersDarkMode, setMode]); @@ -73,7 +75,7 @@ const App = () => { }, [isLoggedIn]); return ( - + ); diff --git a/src/client/components/Map.tsx b/src/client/components/Map.tsx index c1f925c..774b0a6 100644 --- a/src/client/components/Map.tsx +++ b/src/client/components/Map.tsx @@ -80,8 +80,8 @@ function Map({ entries }: { entries: Models.IEntry[] }) { if (!entries?.length) { return No Data to be displayed } - const [, , , , mode, , , mapToken] = useContext(Context); - const [mapStyle, setMapStyle] = useState(mode); + const [contextObj] = useContext(Context); + const [mapStyle, setMapStyle] = useState(contextObj.mode); const lastEntry = entries.at(-1); const cleanEntries = entries.filter((entry) => !entry.ignore); @@ -169,12 +169,12 @@ function Map({ entries }: { entries: Models.IEntry[] }) { return ( diff --git a/src/client/components/ModeSwitcher.tsx b/src/client/components/ModeSwitcher.tsx index f8f6523..236c28c 100644 --- a/src/client/components/ModeSwitcher.tsx +++ b/src/client/components/ModeSwitcher.tsx @@ -1,26 +1,26 @@ -import React, { useContext} from 'react'; +import React, { useContext } from 'react'; import { Context } from "../components/App"; import { Button } from '@mui/material'; import { LightMode, Nightlight } from '@mui/icons-material'; import * as css from "../css/modeSwticher.module.css"; function ModeSwitcher() { - const [, , , , mode, setMode] = useContext(Context); + const [contextObj] = useContext(Context); - return ( + return ( ); } diff --git a/src/client/pages/Login.tsx b/src/client/pages/Login.tsx index 2b2d9a7..35adcc8 100644 --- a/src/client/pages/Login.tsx +++ b/src/client/pages/Login.tsx @@ -13,12 +13,13 @@ function Login() { const [finish, setFinish] = useState(1); const [start, setStart] = useState(1); const navigate = useNavigate(); - const [isLoggedIn, setLogin, userInfo, setUserInfo] = useContext(Context); + const [contextObj] = useContext(Context); + const [formInfo, updateFormInfo] = useState({ user: { isError: false, message: "Minimum 2", - value: userInfo?.user || "" + value: contextObj.userInfo?.user || "" }, password: { isError: false, @@ -88,14 +89,14 @@ function Login() { }) const token = response.data.token; localStorage.setItem("jwt", token); - setLogin(true); + contextObj.setLogin(true); setMessageObj({ isError: false, status: , message: "Success!" }) // update linearBar for delay until redirect const date = new Date(); setStart(date.getTime()); setFinish(new Date(date.getTime() + 1000).getTime()); - setUserInfo(convertJwt()); + contextObj.setUserInfo(convertJwt()); // redirect back to main page setTimeout(() => { setLoading(false); navigate("/") }, 1000); @@ -116,8 +117,8 @@ function Login() {

Login Page

- {isLoggedIn && -

You are logged in

+ {contextObj.isLoggedIn && +

You are logged in

}
([]); const [messageObj, setMessageObj] = useState({ isError: null, status: null, message: null }); const [lastFetch, setLastFetch] = useState(); @@ -54,7 +56,7 @@ function Start() { let response; if (!token) { - setLogin(false); + contextObj.setLogin(false); setMessageObj({ isError: true, status: "403", message: "No valid login" }) return false; } @@ -101,7 +103,7 @@ function Start() { return; } - if (error.response.status == 403) { setLogin(false) } + if (error.response.status == 403) { contextObj.setLogin(false) } setMessageObj({ isError: true, status: error.response.data.status || error.response.status, message: error.response.data.message || error.message }); @@ -112,11 +114,11 @@ function Start() { }; useEffect(() => { - if (isLoggedIn) { + if (contextObj.isLoggedIn) { getData(); intervalID.current = setInterval(getData, fetchIntervalMs); // capture interval ID as return from setInterval and pass to state return () => { console.log("cleanup"); clearInterval(intervalID.current); intervalID.current = null; }; - } else if (userInfo) { // no valid login but userInfo + } else if (contextObj.userInfo) { // no valid login but userInfo setMessageObj({ isError: true, status: "403", message: "Login expired" }) } }, []); @@ -130,22 +132,22 @@ function Start() { {messageObj.status} {messageObj.message} } - {!messageObj.isError && userInfo && + {!messageObj.isError && contextObj.userInfo &&
- {userInfo.user} Welcome back + {contextObj.userInfo.user} Welcome back
} @@ -161,10 +163,10 @@ function Start() {
- {isLoggedIn && intervalID && + {contextObj.isLoggedIn && intervalID && } - {isLoggedIn && intervalID && entries?.length > 0 && + {contextObj.isLoggedIn && intervalID && entries?.length > 0 && <> GPS: {entries.at(-1).lat} / {entries.at(-1).lon} diff --git a/tsconfig.json b/tsconfig.json index 64098b6..61c6e53 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,21 +1,28 @@ { "extends": "@tsconfig/node20/tsconfig.json", - "include": ["src/**/*"], - "exclude": ["node_modules", "src/client/"], + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "src/client/" + ], "compilerOptions": { - "rootDir": "src", - "outDir": "dist", - "module": "CommonJS", - "moduleResolution": "node", - "target": "ES6", - "sourceMap": true, - "baseUrl": "./src", - "esModuleInterop": true, - "paths": { - "@src/*": ["./*"], - } + "rootDir": "src", + "outDir": "dist", + "module": "CommonJS", + "moduleResolution": "node", + "target": "ES6", + "sourceMap": true, + "baseUrl": "./src", + "esModuleInterop": true, + "paths": { + "@src/*": [ + "./*" + ], + } }, "files": [ - "types.d.ts" - ] + "types.d.ts" + ] } \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs index ff3d550..2663cd1 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -15,7 +15,6 @@ - diff --git a/webpack.config.js b/webpack.config.js index 4e5df71..641fd28 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -15,7 +15,7 @@ module.exports = (args) => { configFile: 'src/client/tsconfig.json' } }, - exclude: /node_modules/, + exclude: /node_modules/ }, { test: /\.css$/, @@ -34,16 +34,16 @@ module.exports = (args) => { { test: /\.css$/, use: ["style-loader", "css-loader"], - exclude: /\.module\.css$/, + exclude: /\.module\.css$/ }, ], }, resolve: { - extensions: ['.tsx', '.ts', '.js'], + extensions: ['.tsx', '.ts', '.js'] }, output: { filename: 'bundle.js', - path: path.resolve(__dirname, 'dist/httpdocs/js'), + path: path.resolve(__dirname, 'dist/httpdocs/js') } } };