Navigation bar (shell.component.html/.scss) - Restyle top-level nav items as compact tabs and add responsive breakpoints (1400px, 1200px, 1080px, 880px) that shrink icon, caret and padding so the full menu fits on smaller laptop screens. - Long labels now carry a short form shown on narrow widths: Loan Origination -> Loans, General Ledger -> GL, Sub Ledger -> Sub GL, Reconciliation -> Recon, Documents Hub -> Docs Hub. - Reports and Insurance menus are regrouped into titled mega panels (reports-mega-panel, insurance-mega-panel) using deposit-menu-group sections instead of one long flat list. - No route was added or removed: all 64 menu links (Account Register, Day Book, End of the Day, Form 97/98, Risk Review, Re-KYC, Dormancy, Savings/FD Interest Posting, TDS, BOR, DIP lookups, digital payment reports, CKYC, DICGC, Clerk Desk, ...) still point to the same routes. Global mega panel styles (main.scss) - Shared grid and overlay styling for every Material mega menu (cdk-overlay-pane with a menu panel) plus a coloured top accent per panel: admin, cashier, clerk, branch-ops, hrm, digital, reports, share, others, npa, letter, insurance, ckyc and reconciliation. - Fixed column layouts for the dense panels (NPA 3 columns, Reconciliation 5 columns, Reports, CKYC). Toolbar (toolbar.component.html/.scss) - User account dropdown gets its own t-user-menu panel style and opens towards the left (xPosition="before") so it no longer clips at the screen edge. - Restyled AI assistant menu cards. Density and products page - Material density lowered from 0 to -1 (mifosx-theme.scss) for a tighter, more data-dense UI. - Products page cards: wider container (1280px), smaller icons, fonts, gaps and padding to match the compact look. Loaders (index.html, loading-screen component) - Boot splash in index.html and the fullscreen mifosx-loading-screen now show the CBS Nexora logo image (assets/images/cbsnexora-logo.png) instead of the generic four-square SVG and text title. Lint clean-up required by the pre-commit hook - Prettier formatting and stylelint auto-fixes (modern rgb() notation, range media queries, shorthand properties, empty lines before rules). - Merged duplicate selectors into their first block without changing the cascade: the second .reports-mega-panel (top accent border) in main.scss and the second ::ng-deep .ai-menu (AI card styles) in toolbar.component.scss. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
402 lines
13 KiB
HTML
402 lines
13 KiB
HTML
<!--
|
|
Copyright since 2025 Mifos Initiative
|
|
|
|
This Source Code Form is subject to the terms of the Mozilla Public
|
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
-->
|
|
|
|
<!doctype html>
|
|
|
|
<html lang="en" class="h-full bg-gray-100">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>CBS Nexora</title>
|
|
<base href="/" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
|
|
<link rel="icon" type="image/svg+xml" href="assets/images/cbsnexora-favicon.svg" />
|
|
<link rel="apple-touch-icon" type="image/svg+xml" href="assets/images/cbsnexora-favicon.svg" />
|
|
<link rel="manifest" href="manifest.json" />
|
|
|
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
|
|
rel="stylesheet"
|
|
/>
|
|
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Mono:300" rel="stylesheet" />
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Serif:wght@600&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700;800&family=Newsreader:ital,wght@0,400;0,500;1,400;1,500&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
<!-- Load environment variables -->
|
|
</head>
|
|
<body class="h-full">
|
|
<!--
|
|
OAuth Redirect Interceptor (PRODUCTION)
|
|
-------------------------------------
|
|
OAuth providers cannot redirect to hash-based routes (#).
|
|
This script intercepts OAuth callbacks BEFORE Angular initializes,
|
|
stores the response parameters, and rewrites the URL to a hash route
|
|
that Angular can handle.
|
|
|
|
DO NOT remove unless migrating to path-based routing.
|
|
-->
|
|
<script>
|
|
(function () {
|
|
// ===== CONFIGURATION =====
|
|
var OAUTH_CALLBACK_PATHS = ['/callback'];
|
|
var STORAGE_KEY = 'oauth_callback_query';
|
|
|
|
// ===== DETECTION =====
|
|
var params = new URLSearchParams(window.location.search);
|
|
var isOAuthResponse = params.has('code') || params.has('error');
|
|
|
|
if (!isOAuthResponse) {
|
|
return;
|
|
}
|
|
|
|
// Prevent redirect loop
|
|
if (window.location.hash && window.location.hash.length > 1) {
|
|
return;
|
|
}
|
|
|
|
var currentPath = window.location.pathname;
|
|
|
|
// Only allow known OAuth callback paths
|
|
if (OAUTH_CALLBACK_PATHS.indexOf(currentPath) === -1) {
|
|
return;
|
|
}
|
|
|
|
// ===== PERSIST & REDIRECT =====
|
|
try {
|
|
sessionStorage.setItem(STORAGE_KEY, window.location.search);
|
|
} catch (e) {
|
|
console.warn('OAuth interceptor: sessionStorage unavailable, appending query to hash');
|
|
}
|
|
|
|
// Always redirect, even if storage fails
|
|
var redirectUrl = window.location.origin + '/#' + currentPath;
|
|
|
|
if (!sessionStorage.getItem(STORAGE_KEY)) {
|
|
redirectUrl += window.location.search;
|
|
}
|
|
|
|
window.location.replace(redirectUrl);
|
|
})();
|
|
</script>
|
|
<script src="assets/env.js"></script>
|
|
<!--[if lt IE 10]>
|
|
<p>
|
|
You are using an <strong>outdated</strong> browser. Please
|
|
<a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.
|
|
</p>
|
|
<![endif]-->
|
|
|
|
<noscript>
|
|
<p>This page requires JavaScript to work properly. Please enable JavaScript in your browser.</p>
|
|
</noscript>
|
|
|
|
<script>
|
|
// This hides the address bar on mobile browsers
|
|
// https://developers.google.com/web/fundamentals/native-hardware/fullscreen/
|
|
window.addEventListener('load', function () {
|
|
window.scrollTo(0, 1);
|
|
});
|
|
</script>
|
|
|
|
<div id="cbs-app-splash-screen" class="cbs-init-screen">
|
|
<style>
|
|
.cbs-init-screen {
|
|
position: fixed;
|
|
inset: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: radial-gradient(circle at center, #0f172a 0%, #090d16 100%);
|
|
color: #f8fafc;
|
|
font-family:
|
|
'Plus Jakarta Sans',
|
|
-apple-system,
|
|
BlinkMacSystemFont,
|
|
'Segoe UI',
|
|
Roboto,
|
|
sans-serif;
|
|
z-index: 999999;
|
|
overflow: hidden;
|
|
transition:
|
|
opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1),
|
|
transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
|
|
}
|
|
.cbs-init-screen.cbs-splash-fade-out {
|
|
opacity: 0;
|
|
transform: scale(1.02);
|
|
pointer-events: none;
|
|
}
|
|
.cbs-init-brand {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
}
|
|
.cbs-init-logo-wrap {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.cbs-init-logo-img {
|
|
height: 52px;
|
|
width: auto;
|
|
max-width: 260px;
|
|
object-fit: contain;
|
|
filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.5));
|
|
transition: transform 0.3s ease;
|
|
}
|
|
.cbs-init-icon {
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: 14px;
|
|
background: linear-gradient(135deg, #1e3a8a 0%, #0284c7 100%);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 10px 24px rgba(14, 165, 233, 0.35);
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
}
|
|
.cbs-init-title {
|
|
font-size: 1.5rem;
|
|
font-weight: 800;
|
|
letter-spacing: -0.02em;
|
|
margin: 0;
|
|
}
|
|
.cbs-init-sub {
|
|
font-size: 0.78rem;
|
|
color: #94a3b8;
|
|
font-weight: 500;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
}
|
|
.cbs-init-lottie-box {
|
|
width: 130px;
|
|
height: 130px;
|
|
margin: 8px auto;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
filter: drop-shadow(0 8px 24px rgba(37, 99, 235, 0.25));
|
|
}
|
|
.cbs-init-spinner {
|
|
width: 64px;
|
|
height: 64px;
|
|
position: relative;
|
|
}
|
|
.cbs-init-ring {
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: 50%;
|
|
border: 3px solid transparent;
|
|
}
|
|
.cbs-init-ring-1 {
|
|
border-top-color: #2563eb;
|
|
border-right-color: #2563eb;
|
|
animation: cbsInitSpin 1.1s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
|
}
|
|
.cbs-init-ring-2 {
|
|
inset: 6px;
|
|
border-bottom-color: #0ea5e9;
|
|
border-left-color: #0ea5e9;
|
|
animation: cbsInitSpin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite reverse;
|
|
}
|
|
.cbs-init-ring-3 {
|
|
inset: 12px;
|
|
border-top-color: #10b981;
|
|
animation: cbsInitSpin 0.9s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
|
}
|
|
.cbs-init-track {
|
|
width: 260px;
|
|
height: 5px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border-radius: 99px;
|
|
overflow: hidden;
|
|
margin: 18px 0 12px;
|
|
position: relative;
|
|
}
|
|
.cbs-init-fill {
|
|
height: 100%;
|
|
width: 0%;
|
|
background: linear-gradient(90deg, #2563eb, #38bdf8);
|
|
border-radius: 99px;
|
|
box-shadow: 0 0 12px rgba(56, 189, 248, 0.6);
|
|
transition: width 0.3s ease;
|
|
}
|
|
.cbs-init-status {
|
|
font-size: 0.82rem;
|
|
color: #94a3b8;
|
|
font-family: inherit;
|
|
margin: 0;
|
|
height: 20px;
|
|
}
|
|
@keyframes cbsInitSpin {
|
|
from {
|
|
transform: rotate(0deg);
|
|
}
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
</style>
|
|
<div class="cbs-init-brand">
|
|
<div class="cbs-init-logo-wrap">
|
|
<img
|
|
src="assets/images/cbsnexora-logo.png"
|
|
alt="CBS Nexora"
|
|
class="cbs-init-logo-img"
|
|
onerror="
|
|
this.style.display = 'none';
|
|
document.getElementById('cbs-init-fallback-brand').style.display = 'flex';
|
|
"
|
|
/>
|
|
<div id="cbs-init-fallback-brand" style="display: none; align-items: center; gap: 8px">
|
|
<div class="cbs-init-icon">
|
|
<svg width="32" height="32" viewBox="0 0 32 32">
|
|
<rect x="2" y="2" width="13" height="13" rx="2.5" fill="#ffffff" />
|
|
<rect x="17" y="2" width="13" height="13" rx="2.5" fill="#29abe2" />
|
|
<rect x="2" y="17" width="13" height="13" rx="2.5" fill="#00b388" />
|
|
<rect x="17" y="17" width="13" height="13" rx="2.5" fill="#6b7fa3" />
|
|
</svg>
|
|
</div>
|
|
<h2 class="cbs-init-title" style="margin: 0; font-size: 1.4rem">CBS Nexora</h2>
|
|
</div>
|
|
</div>
|
|
<span class="cbs-init-sub">Next-Generation Core Banking</span>
|
|
</div>
|
|
|
|
<div id="cbs-init-lottie-target" class="cbs-init-lottie-box">
|
|
<div class="cbs-init-spinner">
|
|
<div class="cbs-init-ring cbs-init-ring-1"></div>
|
|
<div class="cbs-init-ring cbs-init-ring-2"></div>
|
|
<div class="cbs-init-ring cbs-init-ring-3"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="cbs-init-track">
|
|
<div class="cbs-init-fill" id="cbs-init-progress-bar"></div>
|
|
</div>
|
|
|
|
<p class="cbs-init-status" id="cbs-init-status-text">Connecting to Secure Banking Gateway...</p>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
var splash = document.getElementById('cbs-app-splash-screen');
|
|
var bar = document.getElementById('cbs-init-progress-bar');
|
|
var status = document.getElementById('cbs-init-status-text');
|
|
var progress = 0;
|
|
var minTimePassed = false;
|
|
var angularReady = false;
|
|
var dismissed = false;
|
|
|
|
// Load Lottie Vector Animation
|
|
var script = document.createElement('script');
|
|
script.src = 'assets/js/lottie.min.js';
|
|
script.onload = function () {
|
|
if (typeof lottie !== 'undefined') {
|
|
var target = document.getElementById('cbs-init-lottie-target');
|
|
if (target) {
|
|
target.innerHTML = '';
|
|
lottie.loadAnimation({
|
|
container: target,
|
|
renderer: 'svg',
|
|
loop: true,
|
|
autoplay: true,
|
|
path: 'assets/animations/loading_animation.json'
|
|
});
|
|
}
|
|
}
|
|
};
|
|
document.head.appendChild(script);
|
|
|
|
// Progress simulation stages (Guaranteed ~2 seconds duration on refresh)
|
|
var interval = setInterval(function () {
|
|
if (progress < 90) {
|
|
progress += 5;
|
|
} else if (angularReady && progress < 100) {
|
|
progress += 5;
|
|
}
|
|
|
|
if (bar) bar.style.width = Math.min(progress, 100) + '%';
|
|
|
|
if (status) {
|
|
if (progress >= 85) {
|
|
status.innerText = 'Launching CBS Nexora Dashboard...';
|
|
} else if (progress >= 60) {
|
|
status.innerText = 'Synchronizing core banking ledger schema...';
|
|
} else if (progress >= 30) {
|
|
status.innerText = 'Authenticating token & cryptographic keys...';
|
|
}
|
|
}
|
|
|
|
if (progress >= 100 && angularReady && minTimePassed) {
|
|
clearInterval(interval);
|
|
dismissSplash();
|
|
}
|
|
}, 90);
|
|
|
|
// Enforce minimum hold time (2000ms = 2 seconds) so refresh always shows the animation
|
|
setTimeout(function () {
|
|
minTimePassed = true;
|
|
if (angularReady) {
|
|
progress = 100;
|
|
if (bar) bar.style.width = '100%';
|
|
dismissSplash();
|
|
}
|
|
}, 2000);
|
|
|
|
function dismissSplash() {
|
|
if (dismissed) return;
|
|
dismissed = true;
|
|
clearInterval(interval);
|
|
if (bar) bar.style.width = '100%';
|
|
if (status) status.innerText = 'Ready! System loaded successfully.';
|
|
setTimeout(function () {
|
|
if (splash) {
|
|
splash.classList.add('cbs-splash-fade-out');
|
|
setTimeout(function () {
|
|
if (splash && splash.parentNode) {
|
|
splash.parentNode.removeChild(splash);
|
|
}
|
|
}, 600);
|
|
}
|
|
}, 250);
|
|
}
|
|
|
|
// Global hook for Angular to notify when ready
|
|
window.hideAppSplash = function () {
|
|
angularReady = true;
|
|
if (minTimePassed) {
|
|
dismissSplash();
|
|
}
|
|
};
|
|
|
|
// Safety fallback (Max 7s in case of backend network failure)
|
|
setTimeout(function () {
|
|
angularReady = true;
|
|
minTimePassed = true;
|
|
dismissSplash();
|
|
}, 7000);
|
|
})();
|
|
</script>
|
|
|
|
<mifosx-web-app></mifosx-web-app>
|
|
</body>
|
|
</html>
|