Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions oidc-ui/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_API_URL=https://localhost:8090
1 change: 1 addition & 0 deletions oidc-ui/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_API_URL=https://localhost:8090
24 changes: 24 additions & 0 deletions oidc-ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
151 changes: 151 additions & 0 deletions oidc-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# eSignet OIDC UI

This is the user interface for eSignet Services, implementing OpenID Connect specifications. Built with React 19, TypeScript, Vite, and Tailwind CSS.

## Pages

| Route | Page | Description |
|-------|------|-------------|
| `/` | eSignet Details | Displays well-known endpoints from runtime configuration |
| `/login/signin` | Login | Authentication interface for sign-in |
| `/something-went-wrong` | Error | Generic error page with status code display |
| `/network-error` | Network Error | Shown when the app is offline or API is unreachable |
| `*` | Page Not Found | Catch-all for unmatched routes |

## Tech Stack

- **Framework:** React 19 + TypeScript (strict mode)
- **Build Tool:** Vite
- **Styling:** Tailwind CSS 4 + CSS custom properties
- **Routing:** React Router v7
- **Server State:** TanStack React Query
- **HTTP Client:** Axios (with CSRF token handling)
- **i18n:** i18next with browser language detection and HTTP backend
- **JWT/Crypto:** `jose` + Web Crypto API (no `crypto-js`)
- **UI Components:** Radix UI (dropdown menu, popover)
- **Testing:** Vitest + React Testing Library

## Prerequisites

- Node.js >= 18
- npm >= 9

## Getting Started

### Install dependencies

```bash
npm install
```

### Local development

```bash
npm run dev
```

The dev server starts at `http://localhost:5173` by default.

### Environment configuration

Runtime configuration is managed through `public/env-config.js`:

```javascript
window._env_ = {
DEFAULT_LANG: 'en',
DEFAULT_WELLKNOWN: '<encoded JSON array of well-known endpoints>',
DEFAULT_THEME: '',
DEFAULT_FAVICON: 'favicon.ico',
DEFAULT_TITLE: 'eSignet',
DEFAULT_ID_PROVIDER_NAME: 'eSignet',
DEFAULT_FONT_URL: 'https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap',
};
```

Optional polling configuration:

| Variable | Default | Description |
|----------|---------|-------------|
| `POLLING_URL` | `/v1/esignet/actuator/health` | Health check endpoint |
| `POLLING_INTERVAL` | `10000` | Polling interval in ms |
| `POLLING_TIMEOUT` | `5000` | Polling timeout in ms |
| `POLLING_ENABLED` | `true` | Enable/disable network polling |

## Available Scripts

| Command | Description |
|---------|-------------|
| `npm run dev` | Start Vite dev server with HMR |
| `npm run build` | TypeScript check + production build |
| `npm run preview` | Preview production build locally |
| `npm run test` | Run all tests with Vitest |
| `npm run test:coverage` | Run tests with coverage report |
| `npm run typecheck` | TypeScript type checking only |
| `npm run lint` | Run ESLint |

## Theme Customization

To customize the theme, modify the CSS custom properties in `public/theme/variables.css`. Key variables include:

- `--primary-color` — Primary brand color (default: `#1262c9`)
- `--brand-logo-url` — Header brand logo
- `--footer-brand-logo-url` — Footer logo
- `--login-background` — Login page background color
- `--primary-button-*` — Primary button colors and states
- `--secondary-button-*` — Secondary button colors and states

UI feature toggles are configured in `public/theme/config.json`:

```json
{
"background_logo": false,
"footer": true,
"remove_language_indicator_pipe": true,
"outline_toggle": false,
"outline_dropdown": false
}
```

## Internationalization

Supported languages are configured in `public/locales/default.json`. Translation files are in `public/locales/`:

- `en.json` — English
- `ar.json` — Arabic (RTL)
- `hi.json` — Hindi
- `kn.json` — Kannada
- `km.json` — Khmer
- `ta.json` — Tamil

RTL languages are automatically detected and the `dir` attribute is set accordingly.

## Project Structure

```text
oidc-ui/
├── index.html # Entry HTML
├── vite.config.ts # Vite + Tailwind + Vitest config
├── tsconfig.json # TypeScript config
├── package.json
├── public/
│ ├── env-config.js # Runtime environment config
│ ├── theme-config.js # Theme initialization script
│ ├── theme/
│ │ ├── variables.css # CSS custom properties
│ │ └── config.json # UI feature toggles
│ ├── locales/ # i18n translation files
│ └── images/ # Static image assets
└── src/
├── main.tsx # Entry point
├── App.tsx # Root component (i18n, QueryClient, RTL)
├── App.css # Global styles + Tailwind
├── i18n.ts # i18next configuration
├── types/ # Shared TypeScript interfaces
├── constants/ # Route paths, loading states, asset URLs
├── utils/ # Encoding, hashing (Web Crypto), parsing
├── services/ # API, config, CSS variable, lang config
├── components/ # NavHeader, Footer, LoadingIndicator
├── pages/ # Page components (Login, Error, 404, etc.)
├── routes/ # AppRouter with lazy-loaded routes
└── __tests__/ # Test files mirroring src structure
```
22 changes: 22 additions & 0 deletions oidc-ui/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
globals: globals.browser,
},
},
])
21 changes: 21 additions & 0 deletions oidc-ui/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" id="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title id="title">eSignet</title>
<link
id="fonts-url"
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap"
/>
<link rel="stylesheet" href="/theme/variables.css" />
<script src="/env-config.js"></script>
<script src="/theme-config.js"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading
Loading