diff --git a/.vscode/settings.json b/.vscode/settings.json index 9bf4d12..a707edd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "[dockerfile]": { + "editor.defaultFormatter": "ms-azuretools.vscode-docker" + } } diff --git a/Dockerfile b/Dockerfile index 0f88cdc..c651322 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,11 +2,12 @@ FROM cubetiq/calpine-node AS builder RUN apk update && \ + # For build commit hash in "process.env.COMMIT_ID" + apk add git && \ apk add tzdata && \ cp /usr/share/zoneinfo/Asia/Phnom_Penh /etc/localtime && \ - echo "Asia/Phnom_Penh" > /etc/timezone && \ - apk del tzdata - + echo "Asia/Phnom_Penh" > /etc/timezone + WORKDIR /app COPY package.json ./ # Set custom registry for npm registry (from cubetiq local server) @@ -15,6 +16,10 @@ RUN yarn COPY . . RUN yarn build +# Clean up unused packages +RUN apk del tzdata && \ + apk del git + # Build production image FROM nginx:alpine LABEL maintainer="sombochea@cubetiqs.com" diff --git a/craco.config.js b/craco.config.js index e4e748f..5dad72a 100644 --- a/craco.config.js +++ b/craco.config.js @@ -1,16 +1,53 @@ -const path = require('path'); +const path = require('path') +const webpack = require('webpack') +const npmPackage = require('./package.json') +const { v4: uuidv4 } = require('uuid') +const { execSync } = require('child_process') + +// Get the last commit id/log +const gitFetchCommitIdCommand = 'git rev-parse HEAD' + +// Execute the command +const fetchGitCommitId = () => { + try { + return execSync(gitFetchCommitIdCommand).toString().trim() + } catch (e) { + console.error(e) + return '-1' + } +} + +// get current date (build date time) +const today = new Date() + +// get date as version suffix: 10112021 +const dateVersion = `${today.getDay()}${today.getMonth()}${today.getFullYear()}` module.exports = { - webpack: { - alias: { - '@': path.resolve(__dirname, 'src/') - } - }, - jest: { - configure: { - moduleNameMapper: { - '^@(.*)$': '/src$1' - } - } - } -}; \ No newline at end of file + webpack: { + alias: { + '@': path.resolve(__dirname, 'src/'), + }, + plugins: { + add: [ + new webpack.DefinePlugin({ + 'process.env': { + PACKAGE_NAME: `"${npmPackage.name}"`, + PACKAGE_VERSION: + '"' + npmPackage.version + '-' + dateVersion + '"', + BUILD_NUMBER: '"' + uuidv4() + '"', + BUILD_DATE: '"' + today.toLocaleString() + '"', + COMMIT_ID: '"' + fetchGitCommitId() + '"', + }, + }), + ], + }, + }, + jest: { + configure: { + moduleNameMapper: { + '^@(.*)$': '/src$1', + }, + }, + }, +} diff --git a/run-in-docker.sh b/run-in-docker.sh new file mode 100755 index 0000000..324b581 --- /dev/null +++ b/run-in-docker.sh @@ -0,0 +1,9 @@ +#!/bin/sh -e + +echo "Building docker image..." +docker build . -t myreactapp:latest + +echo "Running docker image..." +docker run --cpus=".1" --memory="5m" --rm -it -p 3003:3000 myreactapp:latest + +# Now you can access the app at http://localhost:3003 \ No newline at end of file diff --git a/src/app.config.ts b/src/app.config.ts new file mode 100644 index 0000000..6b34e69 --- /dev/null +++ b/src/app.config.ts @@ -0,0 +1,5 @@ +export const APP_NAME = process.env.PACKAGE_NAME +export const APP_VERSION = process.env.PACKAGE_VERSION +export const APP_BUILD_NUMBER = process.env.BUILD_NUMBER +export const APP_BUILD_DATE = process.env.BUILD_DATE +export const APP_COMMIT_ID = process.env.COMMIT_ID diff --git a/src/pages/Info/index.less b/src/pages/Info/index.less new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/Info/index.tsx b/src/pages/Info/index.tsx new file mode 100644 index 0000000..0e54345 --- /dev/null +++ b/src/pages/Info/index.tsx @@ -0,0 +1,25 @@ +import { + APP_BUILD_DATE, + APP_BUILD_NUMBER, + APP_COMMIT_ID, + APP_NAME, + APP_VERSION, +} from '@/app.config' +import { RouteTypes } from '@/routes/types' +import './index.less' + +export default function Info() { + return ( +
+

App Info

+

App name: {APP_NAME}

+

App version: {APP_VERSION}

+

App build number: {APP_BUILD_NUMBER}

+

App build date: {APP_BUILD_DATE}

+

App commit id: {APP_COMMIT_ID}

+ +
+ Reset +
+ ) +} diff --git a/src/pages/Reset/index.tsx b/src/pages/Reset/index.tsx new file mode 100644 index 0000000..622f5e1 --- /dev/null +++ b/src/pages/Reset/index.tsx @@ -0,0 +1,23 @@ +import { RouteTypes } from '@/routes/types' +import { clearStorage } from '@/utils/ls_util' +import { useEffect } from 'react' +import { Redirect } from 'react-router' + +const Reset = () => { + const clearAllCaches = () => { + caches.keys().then((cacheNames) => { + cacheNames.forEach((cacheName) => { + caches.delete(cacheName).then((r) => console.log('Caches cleared', r)) + }) + }) + } + useEffect(() => { + clearStorage() + sessionStorage.clear() + clearAllCaches() + }, []) + + return +} + +export default Reset diff --git a/src/routes/routes.tsx b/src/routes/routes.tsx index 3fd5a69..e0c9e2d 100644 --- a/src/routes/routes.tsx +++ b/src/routes/routes.tsx @@ -1,8 +1,10 @@ import About from '@/pages/About' import NotFound from '@/pages/Error/404' import Home from '@/pages/Home' +import Info from '@/pages/Info' import Login from '@/pages/Login' import Profile from '@/pages/Profile' +import Reset from '@/pages/Reset' import { CustomRouteProps } from '@/routes/interfaces' import { RouteTypes } from '@/routes/types' @@ -24,6 +26,18 @@ const routes: CustomRouteProps[] = [ path: RouteTypes.ABOUT, component: () => , }, + { + exact: true, + key: 'info', + path: RouteTypes.INFO, + component: () => , + }, + { + exact: true, + key: 'reset', + path: RouteTypes.RESET, + component: () => , + }, { exact: true, key: 'profile', diff --git a/src/routes/types.ts b/src/routes/types.ts index ef8de34..8630ec9 100644 --- a/src/routes/types.ts +++ b/src/routes/types.ts @@ -2,6 +2,8 @@ const RouteTypes = { HOME: "/", ABOUT: "/about", PROFILE: "/profile", + INFO: "/info", + RESET: "/reset", // Auth LOGIN: '/login', diff --git a/src/utils/ls_util.ts b/src/utils/ls_util.ts index e112993..4a9bf4c 100644 --- a/src/utils/ls_util.ts +++ b/src/utils/ls_util.ts @@ -4,4 +4,8 @@ export const setStorage = (key: string, value?: any) => { export const getStorage = (key: string, defaultValue?: string): (string | undefined | null) => { return localStorage.getItem(key) ?? defaultValue +} + +export const clearStorage = () => { + return localStorage.clear() } \ No newline at end of file