chore: update Angular dependencies to version 20.2.0 and refactor HTTP interceptors to use new functional API

- Updated Angular dependencies in package.json to version 20.2.0, including Angular Material and CDK.
- Refactored AuthInterceptor and LoadingInterceptor to use the new HttpInterceptorFn functional API.
- Modified the index file for interceptors to export the new functional interceptors.
- Enhanced the styling of the project detail popup with a dark theme and encapsulation settings.
- Updated main.ts to use the new interceptor setup with provideHttpClient.
- Added theming support for Angular Material in styles.scss, including light and dark themes.
This commit is contained in:
Bangara Raju Kottedi 2026-03-14 22:54:01 +05:30
parent b4c5fddf0d
commit 797163d1ba
9 changed files with 2722 additions and 3220 deletions

5763
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,22 +10,24 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^20.0.0", "@angular/animations": "^20.2.0",
"@angular/common": "^20.0.0", "@angular/cdk": "^20.2.0",
"@angular/compiler": "^20.0.0", "@angular/common": "^20.2.0",
"@angular/core": "^20.0.0", "@angular/compiler": "^20.2.0",
"@angular/forms": "^20.0.0", "@angular/core": "^20.2.0",
"@angular/platform-browser": "^20.0.0", "@angular/forms": "^20.2.0",
"@angular/platform-browser-dynamic": "^20.0.0", "@angular/material": "^20.2.0",
"@angular/router": "^20.0.0", "@angular/platform-browser": "^20.2.0",
"@angular/platform-browser-dynamic": "^20.2.0",
"@angular/router": "^20.2.0",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.15.0" "zone.js": "~0.15.0"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^20.0.0", "@angular-devkit/build-angular": "^20.2.0",
"@angular/cli": "~20.0.0", "@angular/cli": "~20.2.0",
"@angular/compiler-cli": "^20.0.0", "@angular/compiler-cli": "^20.2.0",
"@types/jasmine": "~4.3.0", "@types/jasmine": "~4.3.0",
"jasmine-core": "~4.6.0", "jasmine-core": "~4.6.0",
"karma": "~6.4.0", "karma": "~6.4.0",

View File

@ -1,18 +1,14 @@
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http"; import { HttpInterceptorFn } from "@angular/common/http";
import { Observable } from "rxjs"; import { inject } from "@angular/core";
import { AuthService } from "../services/auth.service"; import { AuthService } from "../services/auth.service";
import { Injectable } from "@angular/core";
@Injectable() export const authInterceptor: HttpInterceptorFn = (req, next) => {
export class AuthInterceptor implements HttpInterceptor{ const authSvc = inject(AuthService);
constructor(public authSvc: AuthService){} const apiKey = authSvc.getApiKey();
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const apiKey = this.authSvc.getApiKey();
const authReq = req.clone({ const authReq = req.clone({
headers: req.headers.set('XApiKey', apiKey) headers: req.headers.set('XApiKey', apiKey)
}); });
return next.handle(authReq); return next(authReq);
} };
}

View File

@ -1,9 +1,4 @@
import { HTTP_INTERCEPTORS } from "@angular/common/http"; import { authInterceptor } from "./auth.interceptor";
import { loadingInterceptor } from "./loading.interceptor";
import { AuthInterceptor } from "./auth.interceptor"; export const httpInterceptors = [authInterceptor, loadingInterceptor];
import { LoadingInterceptor } from "./loading.interceptor";
export const httpInterceptorProviders = [
{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
{provide: HTTP_INTERCEPTORS, useClass: LoadingInterceptor, multi: true}
]

View File

@ -1,27 +1,22 @@
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http"; import { HttpInterceptorFn } from "@angular/common/http";
import { Injectable } from "@angular/core"; import { inject } from "@angular/core";
import { Observable, finalize } from "rxjs"; import { finalize } from "rxjs";
import { LoaderService } from "../services/loader.service"; import { LoaderService } from "../services/loader.service";
@Injectable() let totalRequests: number = 0;
export class LoadingInterceptor implements HttpInterceptor {
private totalRequests: number = 0; export const loadingInterceptor: HttpInterceptorFn = (req, next) => {
const loadingSvc = inject(LoaderService);
constructor(private loadingSvc: LoaderService) { } totalRequests++;
loadingSvc.setLoading(true);
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next(req).pipe(
this.totalRequests++; finalize(() => {
this.loadingSvc.setLoading(true); totalRequests--;
return next.handle(req).pipe( if (totalRequests === 0) {
finalize( loadingSvc.setLoading(false);
() => { }
this.totalRequests--; })
if (this.totalRequests == 0) { );
this.loadingSvc.setLoading(false); };
}
}
)
);
}
}

View File

@ -8,6 +8,37 @@
border-radius: 14px; border-radius: 14px;
} }
/* Override Material Dialog container defaults - must be global due to ViewEncapsulation.None */
.dark-popup-panel {
border-radius: 14px !important;
overflow: hidden !important;
.mat-dialog-container {
background: var(--eerie-black-2, #1e1e1e) !important;
border-radius: 14px !important;
overflow: hidden !important;
border: 2px solid rgba(227, 179, 65, 0.9) !important;
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, 0.08),
0 8px 32px rgba(0, 0, 0, 0.5) !important;
padding: 0 !important;
/* Ensure no white background shows */
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 14px;
pointer-events: none;
background: var(--eerie-black-2, #1e1e1e);
z-index: -1;
}
}
}
.detail-header { .detail-header {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;

View File

@ -1,4 +1,4 @@
import { Component, inject } from '@angular/core'; import { Component, inject, ViewEncapsulation } from '@angular/core';
import { CommonModule, DatePipe } from '@angular/common'; import { CommonModule, DatePipe } from '@angular/common';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { IProject } from '../../models/project.model'; import { IProject } from '../../models/project.model';
@ -8,7 +8,8 @@ import { IProject } from '../../models/project.model';
templateUrl: './project-detail-popup.html', templateUrl: './project-detail-popup.html',
styleUrls: ['./project-detail-popup.scss'], styleUrls: ['./project-detail-popup.scss'],
standalone: true, standalone: true,
imports: [CommonModule, DatePipe] imports: [CommonModule, DatePipe],
encapsulation: ViewEncapsulation.None
}) })
export class ProjectDetailPopupComponent { export class ProjectDetailPopupComponent {
private dialogRef = inject(MatDialogRef<ProjectDetailPopupComponent>); private dialogRef = inject(MatDialogRef<ProjectDetailPopupComponent>);

View File

@ -2,15 +2,14 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component'; import { AppComponent } from './app/app.component';
import { provideRouter } from '@angular/router'; import { provideRouter } from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations'; import { provideAnimations } from '@angular/platform-browser/animations';
import { provideHttpClient, withInterceptors } from '@angular/common/http'; import { provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
import { appRoutes } from './app/app-routing.module'; import { appRoutes } from './app/app-routing.module';
import { httpInterceptorProviders } from './app/http-interceptors'; import { httpInterceptors } from './app/http-interceptors';
bootstrapApplication(AppComponent, { bootstrapApplication(AppComponent, {
providers: [ providers: [
provideRouter(appRoutes), provideRouter(appRoutes),
provideAnimations(), provideAnimations(),
provideHttpClient(), provideHttpClient(withInterceptors(httpInterceptors), withFetch())
httpInterceptorProviders
] ]
}).catch(err => console.error(err)); }).catch(err => console.error(err));

View File

@ -1,3 +1,38 @@
// Include theming for Angular Material with `mat.theme()`.
// This Sass mixin will define CSS variables that are used for styling Angular Material
// components according to the Material 3 design spec.
// Learn more about theming and how to use it for your application's
// custom components at https://material.angular.dev/guide/theming
@use '@angular/material' as mat;
html {
@include mat.theme((
color: (
primary: mat.$azure-palette,
tertiary: mat.$blue-palette,
),
typography: Roboto,
density: 0,
));
}
body {
// Default the application to a light color theme. This can be changed to
// `dark` to enable the dark color theme, or to `light dark` to defer to the
// user's system settings.
color-scheme: light;
// Set a default background, font and text colors for the application using
// Angular Material's system-level CSS variables. Learn more about these
// variables at https://material.angular.dev/guide/system-variables
background-color: var(--mat-sys-surface);
color: var(--mat-sys-on-surface);
font: var(--mat-sys-body-medium);
// Reset the user agent margin.
margin: 0;
}
/*-----------------------------------*\ /*-----------------------------------*\
#style.css #style.css
\*-----------------------------------*/ \*-----------------------------------*/
@ -1890,3 +1925,6 @@
} }
html, body { height: 100%; } html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }