diff --git a/.env b/.env
deleted file mode 100644
index d3e6955..0000000
--- a/.env
+++ /dev/null
@@ -1,5 +0,0 @@
-NODE_ENV=development
-API_URL=http://localhost:3001/api/
-EXTERNAL_LOGIN=true
-CKEDITOR_LICENSE_KEY=GPL
-STICKER_TEXT=Source
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 8551ab6..ee41b3c 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -15,37 +15,34 @@
"background": {
"activeOnStart": true,
"beginsPattern": "^.*",
- "endsPattern": "listening on|started|ready"
+ "endsPattern": "proxy"
}
}
},
{
- "label": "Start CRA",
+ "label": "Start Vite",
"type": "process",
"command": "npm",
- "args": ["start"],
+ "args": ["run", "dev"],
"isBackground": true,
"runOptions": {
"reevaluateOnRerun": true,
"terminateOnExit": true
},
- "options": {
- "env": {
- "BROWSER": "none"
- }
- },
"problemMatcher": {
- "pattern": { "regexp": ".*" },
+ "pattern": {
+ "regexp": ".*"
+ },
"background": {
"activeOnStart": true,
- "beginsPattern": "^.*",
- "endsPattern": "Compiled successfully|webpack compiled"
+ "beginsPattern": "vite",
+ "endsPattern": "ready in"
}
}
},
{
"label": "Start All",
- "dependsOn": ["Start Proxy", "Start CRA"],
+ "dependsOn": ["Start Proxy", "Start Vite"],
"dependsOrder": "parallel"
},
{
diff --git a/Dockerfile b/Dockerfile
index 342155e..a2ec430 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,32 +1,28 @@
-#Stage 1 - the build process
+# Stage 1 - Build Vite app
FROM node:latest as build-deps
WORKDIR /app
-#COPY package.json .
+
COPY . .
RUN npm install
RUN npm run build
RUN npm run build-css
-#Stage 2 - the production environment
+# Stage 2 - Production environment (Nginx)
FROM nginx:latest
-ENV EXTERNAL_LOGIN=true
-
-RUN apt-get update && apt-get upgrade -y && \
- apt-get install -y nodejs \
- npm # note this one
-WORKDIR /usr/share/nginx/html
+# Copy Nginx config
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
-COPY --from=build-deps /app/build /usr/share/nginx/html
-copy --from=build-deps /app/public/styles.css /usr/share/nginx/html
-# copy .env.example as .env to the container
-COPY .env.example .env
+# Copy built Vite output
+COPY --from=build-deps /app/dist /usr/share/nginx/html
-RUN npm install -g cross-env
-RUN npm install -g runtime-env-cra
-
-EXPOSE 80
-EXPOSE 443
-
-CMD ["/bin/sh", "-c", "runtime-env-cra && nginx -g \"daemon off;\""]
\ No newline at end of file
+# Create env.js at container startup
+# This injects runtime environment variables into window._env_
+CMD ["/bin/sh", "-c", "\
+ echo \"window._env_ = { \
+ API_URL: '${API_URL}', \
+ EXTERNAL_LOGIN: true, \
+ CKEDITOR_LICENSE_KEY: '${CKEDITOR_LICENSE_KEY}', \
+ STICKER_TEXT: '${STICKER_TEXT}' \
+ };\" > /usr/share/nginx/html/env.js && \
+ nginx -g 'daemon off;'"]
\ No newline at end of file
diff --git a/config-overrides.js b/config-overrides.js
deleted file mode 100644
index 485793a..0000000
--- a/config-overrides.js
+++ /dev/null
@@ -1,77 +0,0 @@
-//const { styles } = require( '@ckeditor/ckeditor5-dev-utils' );
-
-module.exports = function override(config, env) {
- if (!config.plugins) {
- config.plugins = [];
- }
-
- for ( const rule of config.module.rules )
- {
- if (rule.oneOf !== undefined) {
- //loader: require.resolve('file-loader'),
- rule.oneOf[2].use[1].options = {
- // Exclude `js` files to keep the "css" loader working as it injects
- // its runtime that would otherwise be processed through the "file" loader.
- // Also exclude `html` and `json` extensions so they get processed
- // by webpack's internal loaders.
- exclude: [
- /\.(js|mjs|jsx|ts|tsx)$/,
- /\.html$/,
- /\.json$/,
- /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
- /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/
- ],
- name: 'static/media/[name].[hash:8].[ext]',
- }
-
- //test: cssRegex,
- rule.oneOf[5].exclude = [
- /\.module\.css$/,
- /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/,
- ];
-
- //test: cssModuleRegex,
- rule.oneOf[6].exclude = [
- /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/,
- ];
-
- //Added items
- // rule.oneOf.unshift( {
- // test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/,
- // use: [
- // {
- // loader: 'style-loader',
- // options: {
- // injectType: 'singletonStyleTag',
- // attributes: {
- // 'data-cke': true
- // }
- // }
- // },
- // 'css-loader',
- // {
- // loader: 'postcss-loader',
- // options: {
- // postcssOptions: styles.getPostCssConfig( {
- // themeImporter: {
- // themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
- // },
- // minify: true
- // } )
- // }
- // }
- // ]
- // }
- // );
-
- // rule.oneOf.unshift( {
- // test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
- // use: [ 'raw-loader' ]
- // }
- // );
-
- }
- }
-
- return config;
-}
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..da8896c
--- /dev/null
+++ b/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ e-suite
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
index e7071a4..4c3495c 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,6 @@
"react-helmet-async": "^2.0.5",
"react-i18next": "^16.5.4",
"react-router-dom": "^7.13.0",
- "react-scripts": "^5.0.1",
"react-toastify": "^11.0.5",
"react-toggle": "^4.1.3",
"runtime-env-cra": "^0.2.4",
@@ -54,13 +53,10 @@
"scripts": {
"build-css": "sass src/Sass/global.scss public/styles.css",
"watch-css": "nodemon -e scss -x \"npm run build-css\" ",
- "start-react": "cross-env NODE_ENV=development runtime-env-cra --config-name=./public/runtime-env.js && react-app-rewired start",
"prestart": "node scripts/generate-locales.js",
- "start": "concurrently \"npm run start-react\" \"npm run watch-css\" ",
- "prebuild": "node scripts/generate-locales.js",
- "build": "react-app-rewired build",
- "test": "react-app-rewired test",
- "eject": "react-scripts eject",
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview",
"i18n:extract": "i18next \"src/**/*.{ts,tsx,js,jsx}\" \"!src/components/common/ckeditor/**\" --config i18next-parser.config.js",
"i18n:unused": "i18n-unused display-unused",
"i18n:missed": "i18n-unused display-missed",
@@ -87,9 +83,10 @@
"devDependencies": {
"@types/node": "^22.13.5",
"@types/react-toggle": "^4.0.5",
+ "@vitejs/plugin-react": "^5.1.4",
"i18n-unused": "^0.19.0",
"i18next-parser": "^9.3.0",
- "react-app-rewired": "^2.2.1",
- "typescript": "^4.9.5"
+ "typescript": "^5.9.3",
+ "vite": "^7.3.1"
}
}
diff --git a/public/env.js b/public/env.js
new file mode 100644
index 0000000..38005c9
--- /dev/null
+++ b/public/env.js
@@ -0,0 +1,6 @@
+window._env_ = {
+ API_URL: "http://localhost:3001/api/",
+ EXTERNAL_LOGIN: true,
+ CKEDITOR_LICENSE_KEY: "GPL",
+ STICKER_TEXT: "Source",
+};
diff --git a/public/index.html b/public/index.html
deleted file mode 100644
index 8f385bb..0000000
--- a/public/index.html
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- e-suite
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/public/runtime-env.js b/public/runtime-env.js
deleted file mode 100644
index 2be6a9b..0000000
--- a/public/runtime-env.js
+++ /dev/null
@@ -1 +0,0 @@
-window.__RUNTIME_CONFIG__ = {"NODE_ENV":"development","API_URL":"http://localhost:3001/api/","EXTERNAL_LOGIN":"true","CKEDITOR_LICENSE_KEY":"GPL","STICKER_TEXT":"Source"};
\ No newline at end of file
diff --git a/src/components/common/ckeditor/TextEditor.jsx b/src/components/common/ckeditor/TextEditor.jsx
index 7e24beb..6d7ab42 100644
--- a/src/components/common/ckeditor/TextEditor.jsx
+++ b/src/components/common/ckeditor/TextEditor.jsx
@@ -2,6 +2,8 @@ import { useState, useEffect, useRef } from "react";
import { CKEditor } from "@ckeditor/ckeditor5-react";
import Field from "./plugins/field/field";
+import { CKEDITOR_LICENSE_KEY } from "../../../environment";
+
import {
DecoupledEditor,
AccessibilityHelp,
@@ -198,7 +200,7 @@ export default function TextEditor(props) {
customfields = props.customFields;
}
- const licenseKey = window.__RUNTIME_CONFIG__?.CKEDITOR_LICENSE_KEY || "GPL";
+ const licenseKey = CKEDITOR_LICENSE_KEY || "GPL";
const editorConfig = {
licenseKey: licenseKey,
diff --git a/src/environment.ts b/src/environment.ts
new file mode 100644
index 0000000..2214a21
--- /dev/null
+++ b/src/environment.ts
@@ -0,0 +1,4 @@
+export const API_URL = window._env_.API_URL;
+export const EXTERNAL_LOGIN = window._env_.EXTERNAL_LOGIN;
+export const CKEDITOR_LICENSE_KEY = window._env_.CKEDITOR_LICENSE_KEY;
+export const STICKER_TEXT = window._env_.STICKER_TEXT;
diff --git a/src/i18n/generatedLocales.ts b/src/i18n/generatedLocales.ts
index d3a8d32..522c0a0 100644
--- a/src/i18n/generatedLocales.ts
+++ b/src/i18n/generatedLocales.ts
@@ -10,22 +10,8 @@ export const availableLocales = [
"fr-CA",
"fr-FR",
"hi-IN",
- "ur-AE",
- "ur-AF",
- "ur-AU",
- "ur-BH",
- "ur-CA",
- "ur-GB",
"ur-IN",
- "ur-KW",
- "ur-OM",
- "ur-PK",
- "ur-QA",
- "ur-SA",
- "ur-TJ",
- "ur-US",
- "ur-UZ",
- "ur-ZA"
+ "ur-PK"
] as const;
export const baseLocales = [
@@ -67,69 +53,13 @@ export const fallbackLng = {
"hi-IN": [
"en"
],
- "ur-AE": [
- "ur",
- "en"
- ],
- "ur-AF": [
- "ur",
- "en"
- ],
- "ur-AU": [
- "ur",
- "en"
- ],
- "ur-BH": [
- "ur",
- "en"
- ],
- "ur-CA": [
- "ur",
- "en"
- ],
- "ur-GB": [
- "ur",
- "en"
- ],
"ur-IN": [
"ur",
"en"
],
- "ur-KW": [
- "ur",
- "en"
- ],
- "ur-OM": [
- "ur",
- "en"
- ],
"ur-PK": [
"ur",
"en"
- ],
- "ur-QA": [
- "ur",
- "en"
- ],
- "ur-SA": [
- "ur",
- "en"
- ],
- "ur-TJ": [
- "ur",
- "en"
- ],
- "ur-US": [
- "ur",
- "en"
- ],
- "ur-UZ": [
- "ur",
- "en"
- ],
- "ur-ZA": [
- "ur",
- "en"
]
} as const;
diff --git a/src/index.css b/src/index.css
deleted file mode 100644
index ec2585e..0000000
--- a/src/index.css
+++ /dev/null
@@ -1,13 +0,0 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
-}
diff --git a/src/logo.svg b/src/logo.svg
deleted file mode 100644
index 9dfc1c0..0000000
--- a/src/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/index.tsx b/src/main.tsx
similarity index 96%
rename from src/index.tsx
rename to src/main.tsx
index d330605..3a9e1ae 100644
--- a/src/index.tsx
+++ b/src/main.tsx
@@ -1,4 +1,4 @@
-import "./i18n/i18n";
+//import "./i18n/i18n";
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
diff --git a/src/modules/frame/components/LoginForm.tsx b/src/modules/frame/components/LoginForm.tsx
index e4d9f9f..08fc45c 100644
--- a/src/modules/frame/components/LoginForm.tsx
+++ b/src/modules/frame/components/LoginForm.tsx
@@ -1,8 +1,9 @@
+import { EXTERNAL_LOGIN } from "../../../environment";
import ExternalLoginForm from "./ExternalLoginForm";
import InternalLoginForm from "./InternalLoginForm";
const LoginForm: React.FC = () => {
- if (window.__RUNTIME_CONFIG__.EXTERNAL_LOGIN) {
+ if (EXTERNAL_LOGIN) {
return (
<>
diff --git a/src/modules/frame/components/Logout.tsx b/src/modules/frame/components/Logout.tsx
index 2b9d529..b39de20 100644
--- a/src/modules/frame/components/Logout.tsx
+++ b/src/modules/frame/components/Logout.tsx
@@ -2,13 +2,14 @@ import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import authentication from "../services/authenticationService";
+import { EXTERNAL_LOGIN } from "../../../environment";
const Logout: React.FC = () => {
const { t } = useTranslation(Namespaces.Common);
useEffect(() => {
authentication.logout();
- if (window.__RUNTIME_CONFIG__.EXTERNAL_LOGIN) {
+ if (EXTERNAL_LOGIN) {
window.location.href = "/account/logout";
} else {
window.location.href = "/";
diff --git a/src/modules/frame/components/Sticker.tsx b/src/modules/frame/components/Sticker.tsx
index ba7bb6c..7b2bd45 100644
--- a/src/modules/frame/components/Sticker.tsx
+++ b/src/modules/frame/components/Sticker.tsx
@@ -1,14 +1,14 @@
+import { STICKER_TEXT } from "../../../environment";
+
const isBlank = (value: string | null | undefined) =>
!value || value.trim().length === 0;
const Sticker: React.FC = () => {
- if (isBlank(window.__RUNTIME_CONFIG__.STICKER_TEXT)) {
+ if (isBlank(STICKER_TEXT)) {
return null;
}
- return (
- {window.__RUNTIME_CONFIG__.STICKER_TEXT}
- );
+ return {STICKER_TEXT};
};
export default Sticker;
diff --git a/src/modules/frame/services/authenticationService.ts b/src/modules/frame/services/authenticationService.ts
index 98c57aa..e012c19 100644
--- a/src/modules/frame/services/authenticationService.ts
+++ b/src/modules/frame/services/authenticationService.ts
@@ -3,6 +3,7 @@ import Cookies from "js-cookie";
import httpService from "../../../services/httpService";
import { IEmailUserAction } from "../models/IEmailUserAction";
import JwtToken from "../models/JwtToken";
+import { EXTERNAL_LOGIN } from "../../../environment";
const apiEndpoint = "/Authentication";
//const tokenKey = "token";
@@ -37,7 +38,7 @@ async function refreshToken() {
const fiveMinutesFromNow: Date = new Date(Date.now() + 5 * 60 * 1000);
if (currentUser.expiry < fiveMinutesFromNow) {
- const refreshTokenRoute = window.__RUNTIME_CONFIG__.EXTERNAL_LOGIN
+ const refreshTokenRoute = EXTERNAL_LOGIN
? "/../account/refreshToken"
: apiEndpoint + "/refreshToken";
diff --git a/src/modules/homepage/Env.tsx b/src/modules/homepage/Env.tsx
index befc6b6..72b5075 100644
--- a/src/modules/homepage/Env.tsx
+++ b/src/modules/homepage/Env.tsx
@@ -1,4 +1,10 @@
import React from "react";
+import {
+ API_URL,
+ CKEDITOR_LICENSE_KEY,
+ EXTERNAL_LOGIN,
+ STICKER_TEXT,
+} from "../../environment";
const EnvPage: React.FC = () => {
return (
@@ -9,23 +15,16 @@ const EnvPage: React.FC = () => {
window.__RUNTIME_CONFIG__.NODE_ENV ={" "}
{window.__RUNTIME_CONFIG__.NODE_ENV}
-
- window.__RUNTIME_CONFIG__.API_URL = {window.__RUNTIME_CONFIG__.API_URL}
-
+ window.__RUNTIME_CONFIG__.API_URL = {API_URL}
window.__RUNTIME_CONFIG__.EXTERNAL_LOGIN ={" "}
- {window.__RUNTIME_CONFIG__.EXTERNAL_LOGIN ? "true" : "false"}
+ {EXTERNAL_LOGIN ? "true" : "false"}
window.__RUNTIME_CONFIG__?.CKEDITOR_LICENSE_KEY ={" "}
- {window.__RUNTIME_CONFIG__?.CKEDITOR_LICENSE_KEY === "GPL"
- ? "GPL"
- : "hidden"}
-
-
- window.__RUNTIME_CONFIG__.STICKER_TEXT ={" "}
- {window.__RUNTIME_CONFIG__.STICKER_TEXT}
+ {CKEDITOR_LICENSE_KEY === "GPL" ? "GPL" : "hidden"}
+ window.__RUNTIME_CONFIG__.STICKER_TEXT = {STICKER_TEXT}
>
);
};
diff --git a/src/services/httpService.ts b/src/services/httpService.ts
index be0ce93..a166670 100644
--- a/src/services/httpService.ts
+++ b/src/services/httpService.ts
@@ -6,6 +6,7 @@ import axios, {
} from "axios";
import { isValid, parseISO } from "date-fns";
import { toast } from "react-toastify";
+import { API_URL } from "../environment";
Object.defineProperty(BigInt.prototype, "toJSON", {
get() {
@@ -55,7 +56,7 @@ export function setupInterceptorsTo(
return axiosInstance;
}
-axios.defaults.baseURL = window.__RUNTIME_CONFIG__.API_URL;
+axios.defaults.baseURL = API_URL; // window.__RUNTIME_CONFIG__.API_URL;
setupInterceptorsTo(axios);
export function setJwt(jwt: string | null) {
diff --git a/stop-tasks.ps1 b/stop-tasks.ps1
index 6025f22..77d3906 100644
--- a/stop-tasks.ps1
+++ b/stop-tasks.ps1
@@ -4,8 +4,8 @@ Write-Host "Stopping development tasks..."
# Find and stop processes by command line
$processes = Get-WmiObject Win32_Process | Where-Object {
($_.CommandLine -like '*proxy.cmd*') -or
- ($_.CommandLine -like '*npm*start*') -or
- ($_.CommandLine -like '*react-scripts*')
+ ($_.CommandLine -like '*npm*run*dev*') -or
+ ($_.CommandLine -like '*vite*')
}
foreach ($proc in $processes) {
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..a25bb64
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,12 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+
+export default defineConfig({
+ plugins: [react()],
+ server: {
+ port: 3000,
+ strictPort: true,
+ host: true,
+ allowedHosts: ["host.docker.internal"],
+ },
+});