diff --git a/src/app/home/admin-latest-news/admin-latest-news.component.spec.ts b/src/app/home/admin-latest-news/admin-latest-news.component.spec.ts index 49d99ef606f..936f44669e1 100644 --- a/src/app/home/admin-latest-news/admin-latest-news.component.spec.ts +++ b/src/app/home/admin-latest-news/admin-latest-news.component.spec.ts @@ -6,13 +6,18 @@ import { News } from '../../domain/news'; import { of } from 'rxjs'; import { MockProvider } from 'ng-mocks'; import { ActivatedRoute } from '@angular/router'; +import { UserService } from '../../services/user.service'; describe('AdminLatestNewsComponent', () => { let component: AdminLatestNewsComponent; let fixture: ComponentFixture; beforeEach(async () => { - const newsServiceSpy = jasmine.createSpyObj(['getAllNews']); + const newsServiceSpy = jasmine.createSpyObj([ + 'getNewsPageNews', + 'getHomePageNews' + ]); + const userServiceSpy = jasmine.createSpyObj(['isSignedIn']); const news1 = new News({ id: 1, date: '2026-02-01 19:14:23.0', @@ -38,11 +43,17 @@ describe('AdminLatestNewsComponent', () => { owner: undefined }); - newsServiceSpy.getAllNews.and.callFake(() => of([news1, news2, news3])); + newsServiceSpy.getNewsPageNews.and.callFake(() => of([news1, news2, news3])); + newsServiceSpy.getHomePageNews.and.callFake(() => of([news1, news2, news3])); + userServiceSpy.isSignedIn.and.callFake(() => true); await TestBed.configureTestingModule({ imports: [AdminLatestNewsComponent], - providers: [{ provide: NewsService, useValue: newsServiceSpy }, MockProvider(ActivatedRoute)] + providers: [ + { provide: NewsService, useValue: newsServiceSpy }, + { provide: UserService, useValue: userServiceSpy }, + MockProvider(ActivatedRoute) + ] }).compileComponents(); fixture = TestBed.createComponent(AdminLatestNewsComponent); @@ -54,11 +65,10 @@ describe('AdminLatestNewsComponent', () => { expect(component).toBeTruthy(); }); - it('should filter and sort topics', fakeAsync(() => { + it('should sort topics', fakeAsync(() => { component.ngOnInit(); tick(); expect(component['topics']).toBeTruthy(); - expect(component['topics'].length).toBe(2); expect(component['topics'][0].title).toBe('Test News 3'); })); }); diff --git a/src/app/home/admin-latest-news/admin-latest-news.component.ts b/src/app/home/admin-latest-news/admin-latest-news.component.ts index 6a4b98776df..535d29e96ae 100644 --- a/src/app/home/admin-latest-news/admin-latest-news.component.ts +++ b/src/app/home/admin-latest-news/admin-latest-news.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { LatestNewsComponent } from '../latest-news/latest-news.component'; import { News } from '../../domain/news'; import { NewsService } from '../../services/news.service'; +import { UserService } from '../../services/user.service'; @Component({ imports: [LatestNewsComponent], @@ -12,13 +13,19 @@ export class AdminLatestNewsComponent { protected loaded: boolean = false; protected topics: News[] = []; - constructor(private newsService: NewsService) {} + constructor( + private newsService: NewsService, + private userService: UserService + ) {} ngOnInit(): void { - this.newsService.getAllNews().subscribe((news) => { - this.topics = news - .filter((news) => news.type === 'public') - .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); + const newsType = this.userService.isSignedIn() ? 'publicAndTeacher' : 'publicOnly'; + this.retrieveNews(newsType); + } + + private retrieveNews(newsType: string): void { + this.newsService.getHomePageNews(newsType).subscribe((news) => { + this.topics = news.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); this.loaded = true; }); } diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts index 707a544f6fb..0155a2309d6 100644 --- a/src/app/home/home.component.spec.ts +++ b/src/app/home/home.component.spec.ts @@ -2,10 +2,11 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { HomeComponent } from './home.component'; import { ConfigService } from '../services/config.service'; import { provideHttpClient } from '@angular/common/http'; -import { MockComponent, MockProvider } from 'ng-mocks'; +import { MockComponent, MockProviders } from 'ng-mocks'; import { CallToActionComponent } from '../modules/shared/call-to-action/call-to-action.component'; import { provideAnimations } from '@angular/platform-browser/animations'; import { ActivatedRoute } from '@angular/router'; +import { UserService } from '../services/user.service'; describe('HomeComponent', () => { let component: HomeComponent; @@ -18,7 +19,7 @@ describe('HomeComponent', () => { ConfigService, provideAnimations(), provideHttpClient(), - MockProvider(ActivatedRoute) + MockProviders(ActivatedRoute, UserService) ] }).compileComponents(); })); diff --git a/src/app/home/latest-news/latest-news.component.html b/src/app/home/latest-news/latest-news.component.html index bf135cfde06..b40607833bc 100644 --- a/src/app/home/latest-news/latest-news.component.html +++ b/src/app/home/latest-news/latest-news.component.html @@ -8,7 +8,7 @@ What's New? 
    - @for (topic of threeTopics; track topic; let index = $index) { + @for (topic of topics; track topic; let index = $index) { @if (!xsScreen || index === 0) {
  • @if (isDiscourseNewsAvailable) { diff --git a/src/app/home/latest-news/latest-news.component.ts b/src/app/home/latest-news/latest-news.component.ts index 8d5d2eb2eb1..217e1a33aa9 100644 --- a/src/app/home/latest-news/latest-news.component.ts +++ b/src/app/home/latest-news/latest-news.component.ts @@ -21,7 +21,6 @@ export class LatestNewsComponent { @Input() isDiscourseNewsAvailable: boolean; @Input() loaded: boolean; protected smallScreen: boolean; - protected threeTopics: Topic[]; @Input() topics: Topic[]; protected xsScreen: boolean; @@ -39,8 +38,4 @@ export class LatestNewsComponent { this.xsScreen = result.matches; }); } - - ngOnChanges(): void { - this.threeTopics = this.topics?.slice(0, 3) ?? []; - } } diff --git a/src/app/news/news.component.html b/src/app/news/news.component.html index 76ee0f6bdb0..6e0bbaa5fe6 100644 --- a/src/app/news/news.component.html +++ b/src/app/news/news.component.html @@ -8,7 +8,7 @@

    - @for (newsItem of allNewsItems; track newsItem; let i = $index) { + @for (newsItem of newsItems; track newsItem; let i = $index) { @if (i < 10 || showAll) { @@ -37,7 +37,7 @@

    {{ newsItem.title }}

    } }
    - @if (allNewsItems.length > 10 && !showAll) { + @if (newsItems.length > 10 && !showAll) { diff --git a/src/app/news/news.component.spec.ts b/src/app/news/news.component.spec.ts index 49969701669..76adbecced7 100644 --- a/src/app/news/news.component.spec.ts +++ b/src/app/news/news.component.spec.ts @@ -1,11 +1,11 @@ +import { ActivatedRoute } from '@angular/router'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MockProvider } from 'ng-mocks'; import { NewsComponent } from './news.component'; import { NewsService } from '../services/news.service'; import { News } from '../domain/news'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; import { User } from '../domain/user'; -import { ActivatedRoute } from '@angular/router'; -import { MockProvider, MockProviders } from 'ng-mocks'; import { UserService } from '../services/user.service'; const createNewsItem = (id, date, type, title, news, owner) => { @@ -39,7 +39,7 @@ const news2Text = 'We have been working on a new portal website. The new website will have a more modern user interface.'; export class MockNewsService { - getAllNews(): Observable { + getNewsPageNews(): Observable { return new Observable((observer) => { const allNewsItems: News[] = []; const user1 = createUser(100, 'Spongebob', 'Squarepants', 'Spongebob Squarepants'); @@ -76,11 +76,8 @@ describe('NewsComponent', () => { }; beforeEach(() => { - const userServiceSpy = jasmine.createSpyObj(['getUser']); - const user = new User({ roles: ['teacher'] }); - userServiceSpy.getUser.and.callFake(() => { - return new BehaviorSubject(user); - }); + const userServiceSpy = jasmine.createSpyObj(['isSignedIn']); + userServiceSpy.isSignedIn.and.callFake(() => true); TestBed.configureTestingModule({ imports: [NewsComponent], @@ -105,28 +102,28 @@ describe('NewsComponent', () => { }); it('should display the news date', () => { - const newsItem1 = getNewsItem(1); + const newsItem1 = getNewsItem(0); const date1 = getNewsDate(newsItem1); expect(date1).toContain('Oct 16, 2018'); - const newsItem2 = getNewsItem(0); + const newsItem2 = getNewsItem(1); const date2 = getNewsDate(newsItem2); expect(date2).toContain('Sep 21, 2018'); }); it('should display the news title', () => { - const newsItem1 = getNewsItem(1); + const newsItem1 = getNewsItem(0); const title1 = getNewsTitle(newsItem1); expect(title1).toContain(news1Title); - const newsItem2 = getNewsItem(0); + const newsItem2 = getNewsItem(1); const title2 = getNewsTitle(newsItem2); expect(title2).toContain(news2Title); }); it('should display the news text', () => { - const newsItem1 = getNewsItem(1); + const newsItem1 = getNewsItem(0); const text1 = getNewsText(newsItem1); expect(text1).toContain(news1Text); - const newsItem2 = getNewsItem(0); + const newsItem2 = getNewsItem(1); const text2 = getNewsText(newsItem2); expect(text2).toContain(news2Text); }); diff --git a/src/app/news/news.component.ts b/src/app/news/news.component.ts index 270d6086877..4834532a6fd 100644 --- a/src/app/news/news.component.ts +++ b/src/app/news/news.component.ts @@ -31,7 +31,7 @@ import { UserService } from '../services/user.service'; templateUrl: './news.component.html' }) export class NewsComponent implements OnInit { - allNewsItems: any = []; + newsItems: any = []; newsShowMore: boolean[] = []; showAll: boolean = false; showTeacherNews: boolean = false; @@ -44,30 +44,18 @@ export class NewsComponent implements OnInit { ) {} ngOnInit() { - this.showTeacherNewsIfLoggedIn(); - this.retrieveNews(); + const newsType = this.userService.isSignedIn() ? 'publicAndTeacher' : 'publicOnly'; + this.retrieveNews(newsType); } - private showTeacherNewsIfLoggedIn(): void { - this.userService.getUser().subscribe((user) => { - this.showTeacherNews = user && user.roles?.length > 0; - }); - } - - private retrieveNews(): void { - this.newsService.getAllNews().subscribe((allNewsItems: News[]) => { - this.prepareNewsItems(allNewsItems); - this.newsShowMore = new Array(this.allNewsItems.length).fill(false); + private retrieveNews(newsType: string): void { + this.newsService.getNewsPageNews(newsType).subscribe((news: News[]) => { + this.newsItems = news.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); + this.newsShowMore = new Array(this.newsItems.length).fill(false); this.scrollToFragmentNewsItem(); }); } - private prepareNewsItems(allNewsItems: News[]) { - this.allNewsItems = allNewsItems - .filter((newsItem) => this.showTeacherNews || newsItem.type === 'public') - .reverse(); - } - private scrollToFragmentNewsItem() { setTimeout(() => { const fragment = this.route.snapshot.fragment; diff --git a/src/app/services/news.service.ts b/src/app/services/news.service.ts index 5c984fe7b65..b4558ea71b6 100644 --- a/src/app/services/news.service.ts +++ b/src/app/services/news.service.ts @@ -1,5 +1,5 @@ +import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { HttpClient, HttpHeaders } from '@angular/common/http'; import { News } from '../domain/news'; import { Observable } from 'rxjs'; @@ -7,12 +7,29 @@ import { Observable } from 'rxjs'; providedIn: 'root' }) export class NewsService { - private newsUrl = '/api/news'; + private allNewsEndpoint = '/api/news'; + private homeNewsEndpoint = '/api/news/home'; constructor(private http: HttpClient) {} - getAllNews(): Observable { + getNewsPageNews(type: string): Observable { + const params = this.buildUrlParams(type); + return this.getNews(this.allNewsEndpoint, params); + } + + getHomePageNews(type: string): Observable { + const params = this.buildUrlParams(type); + return this.getNews(this.homeNewsEndpoint, params); + } + + private getNews(endpoint: string, params: HttpParams): Observable { const headers = new HttpHeaders({ 'Cache-Control': 'no-cache' }); - return this.http.get(this.newsUrl, { headers: headers }) as Observable; + return this.http.get(endpoint, { headers: headers, params: params }) as Observable; + } + + private buildUrlParams(type: string): HttpParams { + let params = new HttpParams(); + params = params.set('type', type); + return params; } }