Compare commits

...

1 Commits

Author SHA1 Message Date
3cb47c7c1a chore: upgrade Angular and related dependencies to version 20.0.0
feat: refactor AboutComponent to be standalone and include CommonModule
feat: refactor BlogComponent to be standalone and include CommonModule
feat: refactor ContactSidebarComponent to be standalone and include CommonModule
feat: refactor ContactComponent to be standalone and include CommonModule and FormsModule
feat: refactor NavbarComponent to be standalone and include CommonModule and RouterModule
feat: refactor ProjectsComponent to be standalone and include CommonModule
feat: refactor ResumeComponent to be standalone and include CommonModule
feat: refactor AppComponent to be standalone and include necessary components
feat: remove AppModule in favor of standalone components
fix: update tests to include HttpClientTestingModule where necessary
fix: update routing module to export appRoutes without NgModule
chore: add environment configuration for production
2026-03-14 09:38:15 +05:30
25 changed files with 7096 additions and 4653 deletions

View File

@ -113,5 +113,8 @@
} }
} }
} }
},
"cli": {
"analytics": false
} }
} }

11513
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,22 +10,22 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^17.3.3", "@angular/animations": "^20.0.0",
"@angular/common": "^17.3.3", "@angular/common": "^20.0.0",
"@angular/compiler": "^17.3.3", "@angular/compiler": "^20.0.0",
"@angular/core": "^17.3.3", "@angular/core": "^20.0.0",
"@angular/forms": "^17.3.3", "@angular/forms": "^20.0.0",
"@angular/platform-browser": "^17.3.3", "@angular/platform-browser": "^20.0.0",
"@angular/platform-browser-dynamic": "^17.3.3", "@angular/platform-browser-dynamic": "^20.0.0",
"@angular/router": "^17.3.3", "@angular/router": "^20.0.0",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.14.4" "zone.js": "~0.15.0"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^17.3.3", "@angular-devkit/build-angular": "^20.0.0",
"@angular/cli": "~17.3.3", "@angular/cli": "~20.0.0",
"@angular/compiler-cli": "^17.3.3", "@angular/compiler-cli": "^20.0.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",
@ -33,6 +33,6 @@
"karma-coverage": "~2.2.0", "karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0", "karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0", "karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.4.4" "typescript": "~5.8.0"
} }
} }

View File

@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { AboutComponent } from './about.component'; import { AboutComponent } from './about.component';
@ -8,7 +9,7 @@ describe('AboutComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [AboutComponent] imports: [AboutComponent, HttpClientTestingModule]
}) })
.compileComponents(); .compileComponents();

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CvService } from '../services/cv.service'; import { CvService } from '../services/cv.service';
import { IAbout } from './about.model'; import { IAbout } from './about.model';
import { BaseComponent } from '../base/base.component'; import { BaseComponent } from '../base/base.component';
@ -6,7 +7,9 @@ import { BaseComponent } from '../base/base.component';
@Component({ @Component({
selector: 'app-about', selector: 'app-about',
templateUrl: './about.component.html', templateUrl: './about.component.html',
styleUrl: './about.component.scss' styleUrl: './about.component.scss',
standalone: true,
imports: [CommonModule]
}) })
export class AboutComponent extends BaseComponent<IAbout> implements OnInit { export class AboutComponent extends BaseComponent<IAbout> implements OnInit {
constructor(svc: CvService){ constructor(svc: CvService){

View File

@ -1,12 +1,11 @@
import { NgModule } from '@angular/core'; import { Routes } from '@angular/router';
import { AboutComponent } from './about/about.component'; import { AboutComponent } from './about/about.component';
import { RouterModule, Routes } from '@angular/router';
import { ResumeComponent } from './resume/resume.component'; import { ResumeComponent } from './resume/resume.component';
import { ProjectsComponent } from './projects/projects.component'; import { ProjectsComponent } from './projects/projects.component';
import { BlogComponent } from './blog/blog.component'; import { BlogComponent } from './blog/blog.component';
import { ContactComponent } from './contact/contact.component'; import { ContactComponent } from './contact/contact.component';
const routes: Routes = [ export const appRoutes: Routes = [
{ path: '', component: AboutComponent, title: "Bangara Raju Kottedi" }, { path: '', component: AboutComponent, title: "Bangara Raju Kottedi" },
{ path: 'resume', component: ResumeComponent, title: "Bangara Raju Kottedi - Resume" }, { path: 'resume', component: ResumeComponent, title: "Bangara Raju Kottedi - Resume" },
{ path: 'projects', component: ProjectsComponent, title: "Bangara Raju Kottedi - Projects" }, { path: 'projects', component: ProjectsComponent, title: "Bangara Raju Kottedi - Projects" },
@ -14,12 +13,3 @@ const routes: Routes = [
{ path: 'contact', component: ContactComponent, title: "Bangara Raju Kottedi - Contact" }, { path: 'contact', component: ContactComponent, title: "Bangara Raju Kottedi - Contact" },
{ path: '**', redirectTo: '/'} { path: '**', redirectTo: '/'}
]; ];
@NgModule({
declarations: [],
imports: [
RouterModule.forRoot(routes)
],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@ -1,27 +1,18 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(() => TestBed.configureTestingModule({ beforeEach(async () => {
declarations: [AppComponent] await TestBed.configureTestingModule({
})); imports: [AppComponent, HttpClientTestingModule, RouterTestingModule]
}).compileComponents();
});
it('should create the app', () => { it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance; const app = fixture.componentInstance;
expect(app).toBeTruthy(); expect(app).toBeTruthy();
}); });
it(`should have as title 'my-portfolio'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('my-portfolio');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.content span')?.textContent).toContain('my-portfolio app is running!');
});
}); });

View File

@ -1,9 +1,17 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { NavbarComponent } from './navbar/navbar.component';
import { ContactSidebarComponent } from './contact-sidebar/contact-sidebar.component';
import { SpinnerComponent } from './spinner/spinner.component';
import { HttpClientModule } from '@angular/common/http';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'] styleUrls: ['./app.component.scss'],
standalone: true,
imports: [RouterOutlet, NavbarComponent, ContactSidebarComponent, SpinnerComponent]
}) })
export class AppComponent { export class AppComponent {
constructor() {} constructor() {}

View File

@ -1,40 +0,0 @@
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { ContactSidebarComponent } from './contact-sidebar/contact-sidebar.component';
import { NavbarComponent } from './navbar/navbar.component';
import { AboutComponent } from './about/about.component';
import { ResumeComponent } from './resume/resume.component';
import { ProjectsComponent } from './projects/projects.component';
import { BlogComponent } from './blog/blog.component';
import { ContactComponent } from './contact/contact.component';
import { AppRoutingModule } from './app-routing.module';
import { httpInterceptorProviders } from './http-interceptors';
import { SpinnerComponent } from './spinner/spinner.component';
@NgModule({
declarations: [
AppComponent,
SpinnerComponent,
ContactSidebarComponent,
NavbarComponent,
AboutComponent,
ResumeComponent,
ProjectsComponent,
BlogComponent,
ContactComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
FormsModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [httpInterceptorProviders],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { BlogComponent } from './blog.component'; import { BlogComponent } from './blog.component';
@ -8,7 +9,7 @@ describe('BlogComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [BlogComponent] imports: [BlogComponent, HttpClientTestingModule]
}) })
.compileComponents(); .compileComponents();

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CvService } from '../services/cv.service'; import { CvService } from '../services/cv.service';
import { BaseComponent } from '../base/base.component'; import { BaseComponent } from '../base/base.component';
import { IBlog } from './blog.model'; import { IBlog } from './blog.model';
@ -7,7 +8,9 @@ import { environment } from 'src/environments/environment';
@Component({ @Component({
selector: 'app-blog', selector: 'app-blog',
templateUrl: './blog.component.html', templateUrl: './blog.component.html',
styleUrl: './blog.component.scss' styleUrl: './blog.component.scss',
standalone: true,
imports: [CommonModule]
}) })
export class BlogComponent extends BaseComponent<IBlog> implements OnInit{ export class BlogComponent extends BaseComponent<IBlog> implements OnInit{
blogUrl!: string; blogUrl!: string;

View File

@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ContactSidebarComponent } from './contact-sidebar.component'; import { ContactSidebarComponent } from './contact-sidebar.component';
@ -8,7 +9,7 @@ describe('ContactSidebarComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [ContactSidebarComponent] imports: [ContactSidebarComponent, HttpClientTestingModule]
}) })
.compileComponents(); .compileComponents();

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BaseComponent } from '../base/base.component'; import { BaseComponent } from '../base/base.component';
import { CvService } from '../services/cv.service'; import { CvService } from '../services/cv.service';
import { ISideBar } from './side-bar.model'; import { ISideBar } from './side-bar.model';
@ -6,7 +7,9 @@ import { ISideBar } from './side-bar.model';
@Component({ @Component({
selector: 'app-contact-sidebar', selector: 'app-contact-sidebar',
templateUrl: './contact-sidebar.component.html', templateUrl: './contact-sidebar.component.html',
styleUrl: './contact-sidebar.component.scss' styleUrl: './contact-sidebar.component.scss',
standalone: true,
imports: [CommonModule]
}) })
export class ContactSidebarComponent extends BaseComponent<ISideBar> implements OnInit { export class ContactSidebarComponent extends BaseComponent<ISideBar> implements OnInit {
sideBarExpanded: boolean = false; sideBarExpanded: boolean = false;

View File

@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ContactComponent } from './contact.component'; import { ContactComponent } from './contact.component';
@ -8,7 +9,7 @@ describe('ContactComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [ContactComponent] imports: [ContactComponent, HttpClientTestingModule]
}) })
.compileComponents(); .compileComponents();

View File

@ -1,12 +1,15 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, FormBuilder, FormControl, NgForm } from '@angular/forms';
import { CvService } from '../services/cv.service'; import { CvService } from '../services/cv.service';
import { IContact } from './contact.model'; import { IContact } from './contact.model';
import { FormBuilder, FormControl, NgForm } from '@angular/forms';
@Component({ @Component({
selector: 'app-contact', selector: 'app-contact',
templateUrl: './contact.component.html', templateUrl: './contact.component.html',
styleUrl: './contact.component.scss' styleUrl: './contact.component.scss',
standalone: true,
imports: [CommonModule, FormsModule]
}) })
export class ContactComponent { export class ContactComponent {
messageModel: IContact = {name: '', email: '', content: '' }; messageModel: IContact = {name: '', email: '', content: '' };

View File

@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { NavbarComponent } from './navbar.component'; import { NavbarComponent } from './navbar.component';
@ -8,7 +9,7 @@ describe('NavbarComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [NavbarComponent] imports: [NavbarComponent, RouterTestingModule]
}) })
.compileComponents(); .compileComponents();

View File

@ -1,9 +1,13 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
@Component({ @Component({
selector: 'app-navbar', selector: 'app-navbar',
templateUrl: './navbar.component.html', templateUrl: './navbar.component.html',
styleUrl: './navbar.component.scss' styleUrl: './navbar.component.scss',
standalone: true,
imports: [CommonModule, RouterModule]
}) })
export class NavbarComponent { export class NavbarComponent {
} }

View File

@ -1,18 +1,19 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { PortfolioComponent } from './projects.component'; import { ProjectsComponent } from './projects.component';
describe('PortfolioComponent', () => { describe('ProjectsComponent', () => {
let component: PortfolioComponent; let component: ProjectsComponent;
let fixture: ComponentFixture<PortfolioComponent>; let fixture: ComponentFixture<ProjectsComponent>;
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [PortfolioComponent] imports: [ProjectsComponent, HttpClientTestingModule]
}) })
.compileComponents(); .compileComponents();
fixture = TestBed.createComponent(PortfolioComponent); fixture = TestBed.createComponent(ProjectsComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BaseComponent } from '../base/base.component'; import { BaseComponent } from '../base/base.component';
import { CvService } from '../services/cv.service'; import { CvService } from '../services/cv.service';
import { IProjects } from './projects.model'; import { IProjects } from './projects.model';
@ -9,7 +10,9 @@ import { Subscription } from 'rxjs';
@Component({ @Component({
selector: 'app-projects', selector: 'app-projects',
templateUrl: './projects.component.html', templateUrl: './projects.component.html',
styleUrl: './projects.component.scss' styleUrl: './projects.component.scss',
standalone: true,
imports: [CommonModule]
}) })
export class ProjectsComponent extends BaseComponent<IProjects> implements OnInit { export class ProjectsComponent extends BaseComponent<IProjects> implements OnInit {
filter: string = 'All'; filter: string = 'All';

View File

@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ResumeComponent } from './resume.component'; import { ResumeComponent } from './resume.component';
@ -8,7 +9,7 @@ describe('ResumeComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [ResumeComponent] imports: [ResumeComponent, HttpClientTestingModule]
}) })
.compileComponents(); .compileComponents();

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BaseComponent } from '../base/base.component'; import { BaseComponent } from '../base/base.component';
import { IResume } from './resume.model'; import { IResume } from './resume.model';
import { CvService } from '../services/cv.service'; import { CvService } from '../services/cv.service';
@ -6,7 +7,9 @@ import { CvService } from '../services/cv.service';
@Component({ @Component({
selector: 'app-resume', selector: 'app-resume',
templateUrl: './resume.component.html', templateUrl: './resume.component.html',
styleUrl: './resume.component.scss' styleUrl: './resume.component.scss',
standalone: true,
imports: [CommonModule]
}) })
export class ResumeComponent extends BaseComponent<IResume> implements OnInit { export class ResumeComponent extends BaseComponent<IResume> implements OnInit {
constructor(svc: CvService){ constructor(svc: CvService){

View File

@ -1,13 +1,16 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ResumeService } from './cv.service'; import { CvService } from './cv.service';
describe('ResumeService', () => { describe('CvService', () => {
let service: ResumeService; let service: CvService;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({}); TestBed.configureTestingModule({
service = TestBed.inject(ResumeService); imports: [HttpClientTestingModule]
});
service = TestBed.inject(CvService);
}); });
it('should be created', () => { it('should be created', () => {

View File

@ -1,11 +1,14 @@
import { Component, ViewEncapsulation } from '@angular/core'; import { Component, ViewEncapsulation } from '@angular/core';
import { LoaderService } from '../services/loader.service'; import { LoaderService } from '../services/loader.service';
import { CommonModule } from '@angular/common';
@Component({ @Component({
selector: 'app-spinner', selector: 'app-spinner',
templateUrl: './spinner.component.html', templateUrl: './spinner.component.html',
styleUrl: './spinner.component.scss', styleUrl: './spinner.component.scss',
encapsulation: ViewEncapsulation.ShadowDom encapsulation: ViewEncapsulation.ShadowDom,
standalone: true,
imports: [CommonModule]
}) })
export class SpinnerComponent { export class SpinnerComponent {

View File

@ -0,0 +1,4 @@
export const environment = {
apiUrl: 'https://localhost:7013',
apiKey: "c6eAXYcNT873TT7BfMgQyS4ii7hxa53TLEUN7pAGaaU="
};

View File

@ -1,7 +1,16 @@
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { provideRouter } from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { appRoutes } from './app/app-routing.module';
import { httpInterceptorProviders } from './app/http-interceptors';
import { AppModule } from './app/app.module'; bootstrapApplication(AppComponent, {
providers: [
provideRouter(appRoutes),
platformBrowserDynamic().bootstrapModule(AppModule) provideAnimations(),
.catch(err => console.error(err)); provideHttpClient(),
httpInterceptorProviders
]
}).catch(err => console.error(err));