From 0bfcc9c14717c261d76061aeb8c75b58c1a691e6 Mon Sep 17 00:00:00 2001 From: Benjamim Lacerda Date: Wed, 28 Aug 2024 19:54:42 -0300 Subject: [PATCH 01/26] Adiciona HTML --- src/app/pages/your-unbtv/your-unbtv.component.html | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/app/pages/your-unbtv/your-unbtv.component.html diff --git a/src/app/pages/your-unbtv/your-unbtv.component.html b/src/app/pages/your-unbtv/your-unbtv.component.html new file mode 100644 index 00000000..ef735129 --- /dev/null +++ b/src/app/pages/your-unbtv/your-unbtv.component.html @@ -0,0 +1,6 @@ +
+ + + + +
\ No newline at end of file From bf51e1f9ab8e8526516d20d544960761364a825d Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Wed, 28 Aug 2024 20:19:24 -0300 Subject: [PATCH 02/26] cria html favorite-video --- .../favorite-videos.component.html | 11 + test-reports/TESTS.xml | 360 +++++++++--------- 2 files changed, 191 insertions(+), 180 deletions(-) create mode 100644 src/app/pages/favorite-videos/favorite-videos.component.html diff --git a/src/app/pages/favorite-videos/favorite-videos.component.html b/src/app/pages/favorite-videos/favorite-videos.component.html new file mode 100644 index 00000000..52ee0c04 --- /dev/null +++ b/src/app/pages/favorite-videos/favorite-videos.component.html @@ -0,0 +1,11 @@ +
+
+
+
+
+ {{ video.title }} +
+
+
+
+
\ No newline at end of file diff --git a/test-reports/TESTS.xml b/test-reports/TESTS.xml index 2df6de95..7ff68c38 100644 --- a/test-reports/TESTS.xml +++ b/test-reports/TESTS.xml @@ -1,53 +1,53 @@ - + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - + + - - - - - - - + + + + + + + - - + + - - - + + + @@ -60,58 +60,58 @@ - - - + + + - + - - - - - + + + + + - + - - + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + @@ -119,46 +119,46 @@ - + - - - - + + + + - - - + + + - - - + + + - - + + - + - - + + - - + + - + - + @@ -168,129 +168,129 @@ - - - + + + - - + + - + - - - - - - - - - - - - + + + + + + + + + + + + - - + + + + + + + + - - + + - - - - - - - + - - - - - - - + + - - - + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - + - - - + + + - - + + - - - - - - - - - - - - + - + - - + + - - - - - + + + + + - - - + + + - - + + - - + + + + + + + + + + + + + Date: Wed, 28 Aug 2024 20:28:43 -0300 Subject: [PATCH 03/26] Adiciona component no favorite-videos --- .../favorite-videos.component.ts | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/app/pages/favorite-videos/favorite-videos.component.ts diff --git a/src/app/pages/favorite-videos/favorite-videos.component.ts b/src/app/pages/favorite-videos/favorite-videos.component.ts new file mode 100644 index 00000000..8bf3122c --- /dev/null +++ b/src/app/pages/favorite-videos/favorite-videos.component.ts @@ -0,0 +1,102 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { IVideo } from 'src/shared/model/video.model'; +import { UNB_TV_CHANNEL_ID } from 'src/app/app.constant'; +import { Catalog } from 'src/shared/model/catalog.model'; +import jwt_decode from 'jwt-decode'; +import { UserService } from '../../services/user.service'; +import { VideoService } from '../../services/video.service'; + + +@Component({ + selector: 'app-favorite-videos', + templateUrl: './favorite-videos.component.html', + styleUrls: ['./favorite-videos.component.css'] +}) +export class FavoriteVideosComponent implements OnInit { + unbTvChannelId = UNB_TV_CHANNEL_ID; + videosEduplay: IVideo[] = []; + unbTvVideos: IVideo[] = []; + catalog: Catalog = new Catalog(); + userId: string; // Adicionado para armazenar os detalhes do usuário + user: any; + favoriteVideos: IVideo[] = []; + + constructor( + private userService: UserService, + private videoService: VideoService, + private router: Router + ) {} + + async ngOnInit(): Promise { + this.setUserIdFromToken(localStorage.getItem('token') as string); + try { + await this.findAll(); // Aguarde findAll() antes de continuar + this.getUserDetails(); + } catch (error) { + console.error('Erro ao buscar os vídeos:', error); + } + } + + + setUserIdFromToken(token: string) { + const decodedToken: any = jwt_decode(token); + this.userId = decodedToken.id; + } + + getUserDetails() { + this.userService.getUser(this.userId).subscribe({ + next: (user) => { + this.user = user; + this.getFavoriteVideos(); + }, + error: (err) => { + console.error('Error fetching user details', err); + } + }); + } + + getFavoriteVideos(): void { + this.videoService.getFavoriteVideos(this.userId).subscribe({ + next: (data) => { + if (data && Array.isArray(data.videoList)) { + const favorite_videos_ids = data.videoList.map((item: any) => String(item.video_id)); // Converta IDs para string + + this.favoriteVideos = this.unbTvVideos.filter(video => favorite_videos_ids.includes(String(video.id))); // Converta IDs para string + } else { + console.warn('A estrutura da resposta da API não está conforme o esperado:', data); + } + }, + error: (error) => { + console.log('Erro ao buscar vídeos marcados como "favoritos"', error); + } + }); + } + + findAll(): Promise { + return new Promise((resolve, reject) => { + this.videoService.findAll().subscribe({ + next: (data) => { + this.videosEduplay = data.body?.videoList ?? []; + this.filterVideosByChannel(this.videosEduplay); + this.videoService.videosCatalog(this.unbTvVideos, this.catalog); + resolve(); // Resolva a promessa quando o findAll() estiver concluído + }, + error: (error) => { + console.log(error); + reject(error); // Rejeite a promessa em caso de erro + } + }); + }); + } + + + filterVideosByChannel(videos: IVideo[]): void { + videos.forEach((video) => { + const channel = video?.channels; + if (channel && channel[0].id === this.unbTvChannelId) { + this.unbTvVideos.push(video); + } + }); + } +} \ No newline at end of file From 3e01e16f7ebcabad8f82a026b51e7a292579e2a5 Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Wed, 28 Aug 2024 20:41:51 -0300 Subject: [PATCH 04/26] Cria CSS favorite-videos --- .../favorite-videos.component.css | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/app/pages/favorite-videos/favorite-videos.component.css diff --git a/src/app/pages/favorite-videos/favorite-videos.component.css b/src/app/pages/favorite-videos/favorite-videos.component.css new file mode 100644 index 00000000..ff500523 --- /dev/null +++ b/src/app/pages/favorite-videos/favorite-videos.component.css @@ -0,0 +1,90 @@ +.header-title { + color: green; /* Azul escuro para o título */ + text-align: center; + margin-bottom: 20px; + font-size: 2rem; + font-weight: bold; + text-transform: uppercase; +} + + +.videos-container { + display: flex; + justify-content: center; + margin-bottom: 20px; +} + + +.videos { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 20px; +} + + +.flex { + display: flex; + flex-direction: column; + align-items: center; + transition: transform 0.3s ease; +} + + +.video-img { + display: block; + margin: 0 auto; + border-radius: 7px; + width: 220px; /* Mantém a proporção original da imagem */ + height: 124px; /* Mantém a proporção original da imagem */ + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + transition: box-shadow 0.3s ease, transform 0.3s ease; +} + + +.video-img:hover { + box-shadow: 0 8px 12px rgba(0, 0, 0, 0.2); + transform: translateY(-5px); /* Eleva o vídeo ligeiramente ao passar o mouse */ +} + + +.checkbox-label { + display: flex; + align-items: center; + font-size: 1.2rem; + margin-bottom: 20px; + cursor: pointer; + color: #34495e; +} + + +.checkbox-label input[type="checkbox"] { + margin-right: 10px; + width: 24px; + height: 24px; + cursor: pointer; +} + + +.record-controls { + text-align: center; + margin-bottom: 20px; +} + + +.record-controls button { + background-color: #2980b9; + color: #fff; + border: none; + padding: 12px 24px; + margin: 5px; + border-radius: 5px; + cursor: pointer; + font-size: 1.1rem; + transition: background-color 0.3s ease, transform 0.2s ease; +} + + +.record-controls button:hover { + background-color: #1f6395; +} From af7361397dcc141874bf48c40187a034dbdfb363 Mon Sep 17 00:00:00 2001 From: Benjamim Lacerda Date: Thu, 29 Aug 2024 10:20:04 -0300 Subject: [PATCH 05/26] Adiciona component ao your-unbtv --- .../pages/your-unbtv/your-unbtv.component.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/app/pages/your-unbtv/your-unbtv.component.ts diff --git a/src/app/pages/your-unbtv/your-unbtv.component.ts b/src/app/pages/your-unbtv/your-unbtv.component.ts new file mode 100644 index 00000000..5e1026ac --- /dev/null +++ b/src/app/pages/your-unbtv/your-unbtv.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-your-unbtv', + templateUrl: './your-unbtv.component.html', + styleUrls: ['./your-unbtv.component.css'] +}) +export class YourUnBTVComponent { + + constructor( + ) {}; + + ngOnInit(): void { + + } + +} \ No newline at end of file From 3b634b602211e1df56c874c9d2d8fc8b841bafa1 Mon Sep 17 00:00:00 2001 From: Benjamim Lacerda Date: Thu, 29 Aug 2024 10:25:03 -0300 Subject: [PATCH 06/26] AdicionaCSS ao your-unbtv --- src/app/pages/your-unbtv/your-unbtv.component.css | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/app/pages/your-unbtv/your-unbtv.component.css diff --git a/src/app/pages/your-unbtv/your-unbtv.component.css b/src/app/pages/your-unbtv/your-unbtv.component.css new file mode 100644 index 00000000..c39224ca --- /dev/null +++ b/src/app/pages/your-unbtv/your-unbtv.component.css @@ -0,0 +1,6 @@ +.button-container { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + } \ No newline at end of file From 81b9030b8ee7b2aec71c3416ec5bee42a9a279cc Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Thu, 29 Aug 2024 21:01:44 -0300 Subject: [PATCH 07/26] Adiciona CSS e ajuste HTML --- .../favorite-videos.component.css | 2 +- .../favorite-videos.component.html | 30 +++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/app/pages/favorite-videos/favorite-videos.component.css b/src/app/pages/favorite-videos/favorite-videos.component.css index ff500523..d3feda92 100644 --- a/src/app/pages/favorite-videos/favorite-videos.component.css +++ b/src/app/pages/favorite-videos/favorite-videos.component.css @@ -87,4 +87,4 @@ .record-controls button:hover { background-color: #1f6395; -} +} \ No newline at end of file diff --git a/src/app/pages/favorite-videos/favorite-videos.component.html b/src/app/pages/favorite-videos/favorite-videos.component.html index 52ee0c04..f6927434 100644 --- a/src/app/pages/favorite-videos/favorite-videos.component.html +++ b/src/app/pages/favorite-videos/favorite-videos.component.html @@ -1,9 +1,27 @@ -
-
-
-
-
- {{ video.title }} +
+
+

Vídeos Favoritos

+
+ + + +
+ + + +
+ + +
+
+
+
+
+ {{ video.title }} +
From ca2e839fa9392078b94de2a159f7c1f66bba267c Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Thu, 29 Aug 2024 21:07:30 -0300 Subject: [PATCH 08/26] Adiciona componente watchlater --- .../watchlater-videos.component.ts | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/app/pages/watchlater-videos/watchlater-videos.component.ts diff --git a/src/app/pages/watchlater-videos/watchlater-videos.component.ts b/src/app/pages/watchlater-videos/watchlater-videos.component.ts new file mode 100644 index 00000000..973ecebe --- /dev/null +++ b/src/app/pages/watchlater-videos/watchlater-videos.component.ts @@ -0,0 +1,101 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { IVideo } from 'src/shared/model/video.model'; +import { UNB_TV_CHANNEL_ID } from 'src/app/app.constant'; +import { Catalog } from 'src/shared/model/catalog.model'; +import jwt_decode from 'jwt-decode'; +import { UserService } from '../../services/user.service'; +import { VideoService } from '../../services/video.service'; + + +@Component({ + selector: 'app-watchlater-videos', + templateUrl: './watchlater-videos.component.html', + styleUrls: ['./watchlater-videos.component.css'] +}) +export class WatchLaterVideosComponent implements OnInit { + unbTvChannelId = UNB_TV_CHANNEL_ID; + videosEduplay: IVideo[] = []; + unbTvVideos: IVideo[] = []; + catalog: Catalog = new Catalog(); + userId: string; // Adicionado para armazenar os detalhes do usuário + user: any; + watchLaterVideos: IVideo[] = []; + + constructor( + private userService: UserService, + private videoService: VideoService, + private router: Router + ) {} + + async ngOnInit(): Promise { + this.setUserIdFromToken(localStorage.getItem('token') as string); + try { + await this.findAll(); // Aguarde findAll() antes de continuar + this.getUserDetails(); + } catch (error) { + console.error('Erro ao buscar os vídeos:', error); + } + } + + setUserIdFromToken(token: string) { + const decodedToken: any = jwt_decode(token); + this.userId = decodedToken.id; + } + + getUserDetails() { + this.userService.getUser(this.userId).subscribe({ + next: (user) => { + this.user = user; + this.getWatchLaterVideos(); + }, + error: (err) => { + console.error('Error fetching user details', err); + } + }); + } + + getWatchLaterVideos(): void { + this.videoService.getWatchLaterVideos(this.userId).subscribe({ + next: (data) => { + if (data && Array.isArray(data.videoList)) { + const watchLaterVideoIds = data.videoList.map((item: any) => String(item.video_id)); // Converta IDs para string + + this.watchLaterVideos = this.unbTvVideos.filter(video => watchLaterVideoIds.includes(String(video.id))); // Converta IDs para string + } else { + console.warn('A estrutura da resposta da API não está conforme o esperado:', data); + } + }, + error: (error) => { + console.log('Erro ao buscar vídeos marcados como "assista mais tarde"', error); + } + }); + } + + findAll(): Promise { + return new Promise((resolve, reject) => { + this.videoService.findAll().subscribe({ + next: (data) => { + this.videosEduplay = data.body?.videoList ?? []; + this.filterVideosByChannel(this.videosEduplay); + this.videoService.videosCatalog(this.unbTvVideos, this.catalog); + resolve(); // Resolva a promessa quando o findAll() estiver concluído + }, + error: (error) => { + console.log(error); + reject(error); // Rejeite a promessa em caso de erro + } + }); + }); + } + + + filterVideosByChannel(videos: IVideo[]): void { + videos.forEach((video) => { + const channel = video?.channels; + if (channel && channel[0].id === this.unbTvChannelId) { + this.unbTvVideos.push(video); + } + }); + } +} \ No newline at end of file From c9a27fd42e50afeaf98137374c96371cfe4e81bc Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Thu, 29 Aug 2024 21:12:09 -0300 Subject: [PATCH 09/26] Cria HTML de watchlater --- .../watchlater-videos.component.html | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/app/pages/watchlater-videos/watchlater-videos.component.html diff --git a/src/app/pages/watchlater-videos/watchlater-videos.component.html b/src/app/pages/watchlater-videos/watchlater-videos.component.html new file mode 100644 index 00000000..9fa0ab16 --- /dev/null +++ b/src/app/pages/watchlater-videos/watchlater-videos.component.html @@ -0,0 +1,29 @@ +
+
+

Vídeos Assistir mais tarde

+
+ + + +
+ + + +
+ + +
+
+
+
+
+ {{ video.title }} +
+
+
+
+
+
\ No newline at end of file From dfd4b7084a98e3217b67740a770447615b0a2cce Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Thu, 29 Aug 2024 21:14:53 -0300 Subject: [PATCH 10/26] Adiciona CSS a watchlater --- .../watchlater-videos.component.css | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/app/pages/watchlater-videos/watchlater-videos.component.css diff --git a/src/app/pages/watchlater-videos/watchlater-videos.component.css b/src/app/pages/watchlater-videos/watchlater-videos.component.css new file mode 100644 index 00000000..ff500523 --- /dev/null +++ b/src/app/pages/watchlater-videos/watchlater-videos.component.css @@ -0,0 +1,90 @@ +.header-title { + color: green; /* Azul escuro para o título */ + text-align: center; + margin-bottom: 20px; + font-size: 2rem; + font-weight: bold; + text-transform: uppercase; +} + + +.videos-container { + display: flex; + justify-content: center; + margin-bottom: 20px; +} + + +.videos { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 20px; +} + + +.flex { + display: flex; + flex-direction: column; + align-items: center; + transition: transform 0.3s ease; +} + + +.video-img { + display: block; + margin: 0 auto; + border-radius: 7px; + width: 220px; /* Mantém a proporção original da imagem */ + height: 124px; /* Mantém a proporção original da imagem */ + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + transition: box-shadow 0.3s ease, transform 0.3s ease; +} + + +.video-img:hover { + box-shadow: 0 8px 12px rgba(0, 0, 0, 0.2); + transform: translateY(-5px); /* Eleva o vídeo ligeiramente ao passar o mouse */ +} + + +.checkbox-label { + display: flex; + align-items: center; + font-size: 1.2rem; + margin-bottom: 20px; + cursor: pointer; + color: #34495e; +} + + +.checkbox-label input[type="checkbox"] { + margin-right: 10px; + width: 24px; + height: 24px; + cursor: pointer; +} + + +.record-controls { + text-align: center; + margin-bottom: 20px; +} + + +.record-controls button { + background-color: #2980b9; + color: #fff; + border: none; + padding: 12px 24px; + margin: 5px; + border-radius: 5px; + cursor: pointer; + font-size: 1.1rem; + transition: background-color 0.3s ease, transform 0.2s ease; +} + + +.record-controls button:hover { + background-color: #1f6395; +} From a61bcacd474227b665ce9e0908759bd11e823dac Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Thu, 29 Aug 2024 21:21:49 -0300 Subject: [PATCH 11/26] =?UTF-8?q?Remo=C3=A7=C3=A3o=20de=20checkbox=20em=20?= =?UTF-8?q?catalog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/pages/catalog/catalog.component.html | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/app/pages/catalog/catalog.component.html b/src/app/pages/catalog/catalog.component.html index 5d3da92f..d5e6a3c3 100755 --- a/src/app/pages/catalog/catalog.component.html +++ b/src/app/pages/catalog/catalog.component.html @@ -1,19 +1,5 @@
- -
- - - -
-
-

Jornalismo

From 644c69148bae74bf65d420badee925a5d698d85d Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Fri, 30 Aug 2024 17:26:11 -0300 Subject: [PATCH 12/26] Cria Teste watchlater-videos --- .../watchlater-videos.component.spec.ts | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/app/pages/watchlater-videos/watchlater-videos.component.spec.ts diff --git a/src/app/pages/watchlater-videos/watchlater-videos.component.spec.ts b/src/app/pages/watchlater-videos/watchlater-videos.component.spec.ts new file mode 100644 index 00000000..709c09b7 --- /dev/null +++ b/src/app/pages/watchlater-videos/watchlater-videos.component.spec.ts @@ -0,0 +1,123 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { WatchLaterVideosComponent } from './watchlater-videos.component'; +import { VideoService } from 'src/app/services/video.service'; +import { AuthService } from 'src/app/services/auth.service'; +import { UserService } from 'src/app/services/user.service'; +import { Router } from '@angular/router'; +import { of, throwError } from 'rxjs'; +import { IVideo } from 'src/shared/model/video.model'; +import { FormsModule } from '@angular/forms'; + +describe('WatchLaterVideosComponent', () => { + let component: WatchLaterVideosComponent; + let fixture: ComponentFixture; + let videoServiceMock: any; + let authServiceMock: any; + let userServiceMock: any; + let routerMock: any; + + beforeEach(async () => { + videoServiceMock = { + findAll: jasmine.createSpy('findAll').and.returnValue(of({ body: { videoList: [] } })), + videosCatalog: jasmine.createSpy('videosCatalog'), + setVideosCatalog: jasmine.createSpy('setVideosCatalog'), + getWatchLaterVideos: jasmine.createSpy('getWatchLaterVideos').and.returnValue(of({ videoList: [] })) + }; + + userServiceMock = { + getUser: jasmine.createSpy('getUser').and.returnValue(of({ id: 'user123' })) + }; + + routerMock = { + navigate: jasmine.createSpy('navigate') + }; + + await TestBed.configureTestingModule({ + declarations: [WatchLaterVideosComponent], + imports: [FormsModule], + providers: [ + { provide: VideoService, useValue: videoServiceMock }, + { provide: AuthService, useValue: authServiceMock }, + { provide: UserService, useValue: userServiceMock }, + { provide: Router, useValue: routerMock } + ] + }).compileComponents(); + }); + + + beforeEach(() => { + fixture = TestBed.createComponent(WatchLaterVideosComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call findAll and getUserDetails on init if authenticated', (done) => { + spyOn(component, 'findAll').and.callThrough(); + spyOn(component, 'getUserDetails').and.callThrough(); + + component.ngOnInit().then(() => { + expect(component.getUserDetails).toHaveBeenCalled(); + expect(component.findAll).toHaveBeenCalled(); + done(); + }); + }); + + it('should populate videosEduplay and unbTvVideos on findAll success', (done) => { + const videos: IVideo[] = [ + { id: 1, channels: [{ id: 1, name: 'unbtv' }] }, + { id: 2, channels: [{ id: 2, name: 'other' }] } + ]; + + videoServiceMock.findAll.and.returnValue(of({ body: { videoList: videos } })); + + component.findAll().then(() => { + expect(component.videosEduplay.length).toBe(2); + expect(component.videosEduplay[0].id).toBe(1); + done(); + }); + }); + + it('should log error on findAll error', (done) => { + spyOn(console, 'log'); + videoServiceMock.findAll.and.returnValue(throwError('Error')); + + component.findAll().catch(() => { + expect(console.log).toHaveBeenCalledWith('Error'); + done(); + }); + }); + + it('should populate watchLaterVideos on getWatchLaterVideos success', () => { + const watchLaterVideos = [ + { id: 1, video_id: 1, title: 'Watch Later 1', channels: [{ id: 1, name: 'unbtv' }] }, + { id: 2, video_id: 2, title: 'Watch Later 2', channels: [{ id: 1, name: 'unbtv' }] } + ]; + + component.unbTvVideos = [ + { id: 1, title: 'Watch Later 1', channels: [{ id: 1, name: 'unbtv' }] }, + { id: 2, title: 'Watch Later 2', channels: [{ id: 1, name: 'unbtv' }] } + ]; + + videoServiceMock.getWatchLaterVideos.and.returnValue(of({ videoList: watchLaterVideos })); + + component.getWatchLaterVideos(); + + expect(component.watchLaterVideos.length).toBe(2); + expect(component.watchLaterVideos[0].id).toBe(1); + expect(component.watchLaterVideos[1].id).toBe(2); + }); + + + it('should log warning on getWatchLaterVideos with unexpected structure', () => { + spyOn(console, 'warn'); + videoServiceMock.getWatchLaterVideos.and.returnValue(of({ incorrectKey: [] })); + + component.getWatchLaterVideos(); + + expect(console.warn).toHaveBeenCalledWith('A estrutura da resposta da API não está conforme o esperado:', { incorrectKey: [] }); + }); +}); \ No newline at end of file From 1955b662183cd356a17bef4f56cf85f3a64da975 Mon Sep 17 00:00:00 2001 From: vcpVitor Date: Fri, 30 Aug 2024 17:37:22 -0300 Subject: [PATCH 13/26] Adiciona Testes em favorite-videos --- .../favorite-videos.component.spec.ts | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/app/pages/favorite-videos/favorite-videos.component.spec.ts diff --git a/src/app/pages/favorite-videos/favorite-videos.component.spec.ts b/src/app/pages/favorite-videos/favorite-videos.component.spec.ts new file mode 100644 index 00000000..5d8d37b1 --- /dev/null +++ b/src/app/pages/favorite-videos/favorite-videos.component.spec.ts @@ -0,0 +1,123 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FavoriteVideosComponent } from './favorite-videos.component'; +import { VideoService } from 'src/app/services/video.service'; +import { AuthService } from 'src/app/services/auth.service'; +import { UserService } from 'src/app/services/user.service'; +import { Router } from '@angular/router'; +import { of, throwError } from 'rxjs'; +import { IVideo } from 'src/shared/model/video.model'; +import { FormsModule } from '@angular/forms'; + +describe('FavoriteVideosComponent', () => { + let component: FavoriteVideosComponent; + let fixture: ComponentFixture; + let videoServiceMock: any; + let authServiceMock: any; + let userServiceMock: any; + let routerMock: any; + + beforeEach(async () => { + videoServiceMock = { + findAll: jasmine.createSpy('findAll').and.returnValue(of({ body: { videoList: [] } })), + videosCatalog: jasmine.createSpy('videosCatalog'), + setVideosCatalog: jasmine.createSpy('setVideosCatalog'), + getFavoriteVideos: jasmine.createSpy('getFavoriteVideos').and.returnValue(of({ videoList: [] })), + getWatchLaterVideos: jasmine.createSpy('getWatchLaterVideos').and.returnValue(of({ videoList: [] })) + }; + + userServiceMock = { + getUser: jasmine.createSpy('getUser').and.returnValue(of({ id: 'user123' })) + }; + + routerMock = { + navigate: jasmine.createSpy('navigate') + }; + + await TestBed.configureTestingModule({ + declarations: [FavoriteVideosComponent], + imports: [FormsModule], + providers: [ + { provide: VideoService, useValue: videoServiceMock }, + { provide: AuthService, useValue: authServiceMock }, + { provide: UserService, useValue: userServiceMock }, + { provide: Router, useValue: routerMock } + ] + }).compileComponents(); + }); + + + beforeEach(() => { + fixture = TestBed.createComponent(FavoriteVideosComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call findAll and getUserDetails on init if authenticated', (done) => { + spyOn(component, 'findAll').and.callThrough(); + spyOn(component, 'getUserDetails').and.callThrough(); + + component.ngOnInit().then(() => { + expect(component.getUserDetails).toHaveBeenCalled(); + expect(component.findAll).toHaveBeenCalled(); + done(); + }); + }); + + it('should populate videosEduplay and unbTvVideos on findAll success', (done) => { + const videos: IVideo[] = [ + { id: 1, channels: [{ id: 1, name: 'unbtv' }] }, + { id: 2, channels: [{ id: 2, name: 'other' }] } + ]; + + videoServiceMock.findAll.and.returnValue(of({ body: { videoList: videos } })); + + component.findAll().then(() => { + expect(component.videosEduplay.length).toBe(2); + expect(component.videosEduplay[0].id).toBe(1); + done(); + }); + }); + + it('should log error on findAll error', (done) => { + spyOn(console, 'log'); + videoServiceMock.findAll.and.returnValue(throwError('Error')); + + component.findAll().catch(() => { + expect(console.log).toHaveBeenCalledWith('Error'); + done(); + }); + }); + + it('should populate favoriteVideos on getFavoriteVideos success', () => { + const favoriteVideos = [ + { id: 1, video_id: 1, title: 'Favorite 1', channels: [{ id: 1, name: 'unbtv' }] }, + { id: 2, video_id: 2, title: 'Favorite 2', channels: [{ id: 1, name: 'unbtv' }] } + ]; + + component.unbTvVideos = [ + { id: 1, title: 'Favorite 1', channels: [{ id: 1, name: 'unbtv' }] }, + { id: 2, title: 'Favorite 2', channels: [{ id: 1, name: 'unbtv' }] } + ]; + + videoServiceMock.getFavoriteVideos.and.returnValue(of({ videoList: favoriteVideos })); + + component.getFavoriteVideos(); + + expect(component.favoriteVideos.length).toBe(2); + expect(component.favoriteVideos[0].id).toBe(1); + expect(component.favoriteVideos[1].id).toBe(2); + }); + + it('should log warning on getFavoriteVideos with unexpected structure', () => { + spyOn(console, 'warn'); + videoServiceMock.getFavoriteVideos.and.returnValue(of({ incorrectKey: [] })); + + component.getFavoriteVideos(); + + expect(console.warn).toHaveBeenCalledWith('A estrutura da resposta da API não está conforme o esperado:', { incorrectKey: [] }); + }); +}); \ No newline at end of file From 7a7d935d5de68908a3a9834fbb9b7f4f3b47e717 Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Fri, 30 Aug 2024 18:45:40 -0300 Subject: [PATCH 14/26] Criacao do componente recommendation-videos --- .../recommendation-videos.component.css | 0 .../recommendation-videos.component.html | 1 + .../recommendation-videos.component.spec.ts | 23 +++++++++++++++++++ .../recommendation-videos.component.ts | 12 ++++++++++ 4 files changed, 36 insertions(+) create mode 100644 src/app/pages/recommendation-videos/recommendation-videos.component.css create mode 100644 src/app/pages/recommendation-videos/recommendation-videos.component.html create mode 100644 src/app/pages/recommendation-videos/recommendation-videos.component.spec.ts create mode 100644 src/app/pages/recommendation-videos/recommendation-videos.component.ts diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.css b/src/app/pages/recommendation-videos/recommendation-videos.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.html b/src/app/pages/recommendation-videos/recommendation-videos.component.html new file mode 100644 index 00000000..448f3b02 --- /dev/null +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.html @@ -0,0 +1 @@ +

recommendation-videos works!

diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.spec.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.spec.ts new file mode 100644 index 00000000..dacd8bfe --- /dev/null +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RecommendationVideosComponent } from './recommendation-videos.component'; + +describe('RecommendationVideosComponent', () => { + let component: RecommendationVideosComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [RecommendationVideosComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(RecommendationVideosComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.ts new file mode 100644 index 00000000..28935474 --- /dev/null +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-recommendation-videos', + standalone: true, + imports: [], + templateUrl: './recommendation-videos.component.html', + styleUrl: './recommendation-videos.component.css' +}) +export class RecommendationVideosComponent { + +} From 9119db9a5a8e1fd0f4fca03e4f22e050b9c36f05 Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Fri, 30 Aug 2024 19:01:13 -0300 Subject: [PATCH 15/26] Adicao do construtor, variaveis e funcao oninit --- .../recommendation-videos.component.ts | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.ts index 28935474..6a8fa7ae 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.ts +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.ts @@ -1,12 +1,35 @@ import { Component } from '@angular/core'; +import { UNB_TV_CHANNEL_ID } from 'src/app/app.constant'; +import { Catalog } from 'src/shared/model/catalog.model'; +import { IVideo } from 'src/shared/model/video.model'; @Component({ selector: 'app-recommendation-videos', - standalone: true, - imports: [], templateUrl: './recommendation-videos.component.html', - styleUrl: './recommendation-videos.component.css' + styleUrls: ['./recommendation-videos.component.css'] }) -export class RecommendationVideosComponent { +export class RecommendationVideosComponent implements OnInit { + unbTvChannelId = UNB_TV_CHANNEL_ID; + videosEduplay: IVideo[] = []; + unbTvVideos: IVideo[] = []; + catalog: Catalog = new Catalog(); + userId: string; + user: any; + recommendVideos: IVideo[] = []; + + constructor( + private userService: UserService, + private videoService: VideoService, + private router: Router + ) {} + async ngOnInit(): Promise { + this.setUserIdFromToken(localStorage.getItem('token') as string); + try { + await this.findAll(); + this.getUserDetails(); + } catch (error) { + console.error('Erro ao buscar os vídeos:', error); + } + } } From e25c9334d97d3d1628f8756884151a7a67693b29 Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Fri, 30 Aug 2024 19:13:13 -0300 Subject: [PATCH 16/26] Adicao da funcao para obter detalhes do usuario --- .../recommendation-videos.component.ts | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.ts index 6a8fa7ae..cc75980d 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.ts +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.ts @@ -1,7 +1,11 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { UNB_TV_CHANNEL_ID } from 'src/app/app.constant'; import { Catalog } from 'src/shared/model/catalog.model'; import { IVideo } from 'src/shared/model/video.model'; +import { Router } from '@angular/router'; +import jwt_decode from 'jwt-decode'; +import { UserService } from '../../services/user.service'; +import { VideoService } from '../../services/video.service'; @Component({ selector: 'app-recommendation-videos', @@ -32,4 +36,21 @@ export class RecommendationVideosComponent implements OnInit { console.error('Erro ao buscar os vídeos:', error); } } + + setUserIdFromToken(token: string) { + const decodedToken: any = jwt_decode(token); + this.userId = decodedToken.id; + } + + getUserDetails() { + this.userService.getUser(this.userId).subscribe({ + next: (user) => { + this.user = user; + this.recommendVideosByRecord(); + }, + error: (err) => { + console.error('Error fetching user details', err); + } + }); + } } From d4174df6c8bd43c0ba0f7aa493337fb828cd46ba Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Fri, 30 Aug 2024 19:14:50 -0300 Subject: [PATCH 17/26] Adicao da funcao para recomendar videos --- .../recommendation-videos.component.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.ts index cc75980d..6249640b 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.ts +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.ts @@ -53,4 +53,16 @@ export class RecommendationVideosComponent implements OnInit { } }); } + + recommendVideosByRecord() { + this.videoService.getRecommendationFromRecord(this.userId.toString()).subscribe({ + next: (response) => { + const videosID = Object.values(response.recommend_videos).map(id => (id as number).toString()); + this.recommendVideos = this.unbTvVideos.filter(video => videosID.includes(String(video.id))); + }, + error: (err) => { + + } + }); + } } From ce8bb01e30cdbbf3a7e1f007b310c0ba43fd76f3 Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Fri, 30 Aug 2024 19:24:06 -0300 Subject: [PATCH 18/26] Adicao da funcao para buscar e filtrar videos --- .../recommendation-videos.component.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.ts index 6249640b..ac0986a9 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.ts +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.ts @@ -49,7 +49,7 @@ export class RecommendationVideosComponent implements OnInit { this.recommendVideosByRecord(); }, error: (err) => { - console.error('Error fetching user details', err); + console.error('Erro ao buscar detalhes do usuário', err); } }); } @@ -65,4 +65,30 @@ export class RecommendationVideosComponent implements OnInit { } }); } + + findAll(): Promise { + return new Promise((resolve, reject) => { + this.videoService.findAll().subscribe({ + next: (data) => { + this.videosEduplay = data.body?.videoList ?? []; + this.filterVideosByChannel(this.videosEduplay); + this.videoService.videosCatalog(this.unbTvVideos, this.catalog); + resolve(); + }, + error: (error) => { + console.log(error); + reject(error); + } + }); + }); + } + + filterVideosByChannel(videos: IVideo[]): void { + videos.forEach((video) => { + const channel = video?.channels; + if ( channel && channel[0].id === this.unbTvChannelId) { + this.unbTvVideos.push(video); + } + } + )}; } From dc49614ce48134e61283243c29b2594f35f5d77c Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Fri, 30 Aug 2024 19:38:03 -0300 Subject: [PATCH 19/26] Adicao das rotas --- src/app/app-routing.module.ts | 5 +++++ src/app/app.module.ts | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 038d38fc..7b584e41 100755 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -29,6 +29,7 @@ import { VideoViewsComponent } from './pages/video-views/video-views.component'; import { RecordComponent } from './pages/record/record.component'; import { DashboardCategoryComponent } from './pages/dashboard-category/dashboard-category.component'; import { ControleSuperAdminComponent } from './pages/controle-super-admin/controle-super-admin.component'; +import { RecommendationVideosComponent } from './pages/recommendation-videos/recommendation-videos.component'; import { WithTokenGuard } from './guard/with-token.guard'; import { TokenAdminGuard } from './guard/admin.guard'; @@ -133,6 +134,10 @@ const routes: Routes = [ component: ControleSuperAdminComponent, canActivate: [TokenSuperAdminGuard], }, + { + path: 'recommendation', + component: RecommendationVideosComponent, + } ]; @NgModule({ diff --git a/src/app/app.module.ts b/src/app/app.module.ts index e77d0785..2027804d 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -54,6 +54,7 @@ import { CategoryTableComponent } from './pages/category-table/category-table.co import { VideoViewsComponent } from './pages/video-views/video-views.component'; import { DashboardCategoryComponent } from './pages/dashboard-category/dashboard-category.component'; import { RecordComponent } from './pages/record/record.component'; +import { RecommendationVideosComponent } from './pages/recommendation-videos/recommendation-videos.component'; @NgModule({ imports: [ @@ -113,6 +114,7 @@ import { RecordComponent } from './pages/record/record.component'; DashboardCategoryComponent, RecordComponent, ControleSuperAdminComponent, + RecommendationVideosComponent, ], providers: [ From 3277884c0358523b96f296e240660a027df64e28 Mon Sep 17 00:00:00 2001 From: Benjamim Lacerda Date: Fri, 30 Aug 2024 20:47:46 -0300 Subject: [PATCH 20/26] Adicionarotas para your-unbtv --- src/app/app-routing.module.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 7b584e41..93a306e9 100755 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -30,6 +30,9 @@ import { RecordComponent } from './pages/record/record.component'; import { DashboardCategoryComponent } from './pages/dashboard-category/dashboard-category.component'; import { ControleSuperAdminComponent } from './pages/controle-super-admin/controle-super-admin.component'; import { RecommendationVideosComponent } from './pages/recommendation-videos/recommendation-videos.component'; +import { YourUnBTVComponent } from './pages/your-unbtv/your-unbtv.component'; +import { FavoriteVideosComponent } from './pages/favorite-videos/favorite-videos.component'; +import { WatchLaterVideosComponent } from './pages/watchlater-videos/watchlater-videos.component'; import { WithTokenGuard } from './guard/with-token.guard'; import { TokenAdminGuard } from './guard/admin.guard'; @@ -138,6 +141,21 @@ const routes: Routes = [ path: 'recommendation', component: RecommendationVideosComponent, } + { + path: 'sua-unbtv', + component: YourUnBTVComponent, + canActivate: [AuthGuard], + }, + { + path: 'favorites', + component: FavoriteVideosComponent, + canActivate: [AuthGuard], + }, + { + path: 'watch-later', + component: WatchLaterVideosComponent, + canActivate: [AuthGuard], + } ]; @NgModule({ From 8065ca5248aed214d046a69d9e7f63e4da479ccc Mon Sep 17 00:00:00 2001 From: Benjamim Lacerda Date: Fri, 30 Aug 2024 20:51:23 -0300 Subject: [PATCH 21/26] Adiciona component sua-unbtv no app --- src/app/app.module.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2027804d..6b314518 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -55,6 +55,10 @@ import { VideoViewsComponent } from './pages/video-views/video-views.component'; import { DashboardCategoryComponent } from './pages/dashboard-category/dashboard-category.component'; import { RecordComponent } from './pages/record/record.component'; import { RecommendationVideosComponent } from './pages/recommendation-videos/recommendation-videos.component'; +import { YourUnBTVComponent } from './pages/your-unbtv/your-unbtv.component'; +import { FavoriteVideosComponent } from './pages/favorite-videos/favorite-videos.component'; +import { WatchLaterVideosComponent } from './pages/watchlater-videos/watchlater-videos.component'; + @NgModule({ imports: [ @@ -115,6 +119,9 @@ import { RecommendationVideosComponent } from './pages/recommendation-videos/rec RecordComponent, ControleSuperAdminComponent, RecommendationVideosComponent, + YourUnBTVComponent, + FavoriteVideosComponent, + WatchLaterVideosComponent ], providers: [ From fb1a94d9e99ada8162edf0a8edd0afde3c77f346 Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Fri, 30 Aug 2024 21:12:14 -0300 Subject: [PATCH 22/26] Adicao da funcao recomendacao por historico --- src/app/services/video.service.ts | 32 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/app/services/video.service.ts b/src/app/services/video.service.ts index b5e67377..1dac5874 100755 --- a/src/app/services/video.service.ts +++ b/src/app/services/video.service.ts @@ -431,7 +431,7 @@ export class VideoService { } - addToRecord(userId: string, videoId: string): Observable { + addToRecord(userId: string, videoId: string): Observable { const currentDateTime: string = new Date().toLocaleString(); return this.http.post(`${this.videoServiceApiURL}/record/`, { user_id: userId.toString(), videos: { [videoId]: currentDateTime}}); } @@ -441,23 +441,25 @@ export class VideoService { return this.http.post(`${this.videoServiceApiURL}/record/toggle_tracking/`, null, { params: { user_id: userId, track: track.toString() } }); -} - - -getRecordSorted(userId: string, ascending: boolean): Observable { - return this.http.get(`${this.videoServiceApiURL}/record/get_record_sorted/`, { - params: { user_id: userId, ascending: ascending.toString() } - }); -} - + } -checkTrackingStatus(userId: string): Observable { - return this.http.get(`${this.videoServiceApiURL}/record/get_tracking_status/`, { - params: { user_id: userId } - }); -} + getRecordSorted(userId: string, ascending: boolean): Observable { + return this.http.get(`${this.videoServiceApiURL}/record/get_record_sorted/`, { + params: { user_id: userId, ascending: ascending.toString() } + }); + } + checkTrackingStatus(userId: string): Observable { + return this.http.get(`${this.videoServiceApiURL}/record/get_tracking_status/`, { + params: { user_id: userId } + }); + } + getRecommendationFromRecord(userId: string): Observable { + return this.http.get(`${this.videoServiceApiURL}/recommendation/get_recommendation_record/`, { + params: { user_id: userId } + }); + } } From 1e364a011ad09d3e0688095bc9fbb7cad7148738 Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Fri, 30 Aug 2024 22:47:22 -0300 Subject: [PATCH 23/26] Correcao de erros --- src/app/app-routing.module.ts | 3 +- .../background/background.component.html | 14 +-- .../favorite-videos.component.html | 7 +- .../recommendation-videos.component.css | 90 +++++++++++++++++++ .../recommendation-videos.component.html | 16 +++- .../recommendation-videos.component.ts | 31 +++---- .../watchlater-videos.component.html | 7 +- 7 files changed, 138 insertions(+), 30 deletions(-) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 93a306e9..78fde233 100755 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -140,7 +140,8 @@ const routes: Routes = [ { path: 'recommendation', component: RecommendationVideosComponent, - } + canActivate: [AuthGuard], + }, { path: 'sua-unbtv', component: YourUnBTVComponent, diff --git a/src/app/components/background/background.component.html b/src/app/components/background/background.component.html index ad988b47..58032bd7 100755 --- a/src/app/components/background/background.component.html +++ b/src/app/components/background/background.component.html @@ -27,23 +27,23 @@
|
|
-
+ -
+
|
@@ -139,4 +139,4 @@
-
+
\ No newline at end of file diff --git a/src/app/pages/favorite-videos/favorite-videos.component.html b/src/app/pages/favorite-videos/favorite-videos.component.html index f6927434..20346084 100644 --- a/src/app/pages/favorite-videos/favorite-videos.component.html +++ b/src/app/pages/favorite-videos/favorite-videos.component.html @@ -1,10 +1,10 @@ -
+ + Controle de Rastreamento com Checkbox
-
\ No newline at end of file +
+--> \ No newline at end of file diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.css b/src/app/pages/recommendation-videos/recommendation-videos.component.css index e69de29b..d3feda92 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.css +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.css @@ -0,0 +1,90 @@ +.header-title { + color: green; /* Azul escuro para o título */ + text-align: center; + margin-bottom: 20px; + font-size: 2rem; + font-weight: bold; + text-transform: uppercase; +} + + +.videos-container { + display: flex; + justify-content: center; + margin-bottom: 20px; +} + + +.videos { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 20px; +} + + +.flex { + display: flex; + flex-direction: column; + align-items: center; + transition: transform 0.3s ease; +} + + +.video-img { + display: block; + margin: 0 auto; + border-radius: 7px; + width: 220px; /* Mantém a proporção original da imagem */ + height: 124px; /* Mantém a proporção original da imagem */ + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + transition: box-shadow 0.3s ease, transform 0.3s ease; +} + + +.video-img:hover { + box-shadow: 0 8px 12px rgba(0, 0, 0, 0.2); + transform: translateY(-5px); /* Eleva o vídeo ligeiramente ao passar o mouse */ +} + + +.checkbox-label { + display: flex; + align-items: center; + font-size: 1.2rem; + margin-bottom: 20px; + cursor: pointer; + color: #34495e; +} + + +.checkbox-label input[type="checkbox"] { + margin-right: 10px; + width: 24px; + height: 24px; + cursor: pointer; +} + + +.record-controls { + text-align: center; + margin-bottom: 20px; +} + + +.record-controls button { + background-color: #2980b9; + color: #fff; + border: none; + padding: 12px 24px; + margin: 5px; + border-radius: 5px; + cursor: pointer; + font-size: 1.1rem; + transition: background-color 0.3s ease, transform 0.2s ease; +} + + +.record-controls button:hover { + background-color: #1f6395; +} \ No newline at end of file diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.html b/src/app/pages/recommendation-videos/recommendation-videos.component.html index 448f3b02..22475c3b 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.html +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.html @@ -1 +1,15 @@ -

recommendation-videos works!

+
+

Nenhum vídeo recomendado disponível.

+
+
+
+
+
+
+ {{ video.title }} +

oi

+
+
+
+
+
diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.ts index ac0986a9..2bbe733c 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.ts +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.ts @@ -1,12 +1,13 @@ import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { IVideo } from 'src/shared/model/video.model'; import { UNB_TV_CHANNEL_ID } from 'src/app/app.constant'; import { Catalog } from 'src/shared/model/catalog.model'; -import { IVideo } from 'src/shared/model/video.model'; -import { Router } from '@angular/router'; import jwt_decode from 'jwt-decode'; import { UserService } from '../../services/user.service'; import { VideoService } from '../../services/video.service'; + @Component({ selector: 'app-recommendation-videos', templateUrl: './recommendation-videos.component.html', @@ -17,10 +18,10 @@ export class RecommendationVideosComponent implements OnInit { videosEduplay: IVideo[] = []; unbTvVideos: IVideo[] = []; catalog: Catalog = new Catalog(); - userId: string; + userId: string; user: any; recommendVideos: IVideo[] = []; - + constructor( private userService: UserService, private videoService: VideoService, @@ -30,8 +31,8 @@ export class RecommendationVideosComponent implements OnInit { async ngOnInit(): Promise { this.setUserIdFromToken(localStorage.getItem('token') as string); try { - await this.findAll(); - this.getUserDetails(); + await this.findAll(); + this.getUserDetails(); } catch (error) { console.error('Erro ao buscar os vídeos:', error); } @@ -41,7 +42,7 @@ export class RecommendationVideosComponent implements OnInit { const decodedToken: any = jwt_decode(token); this.userId = decodedToken.id; } - + getUserDetails() { this.userService.getUser(this.userId).subscribe({ next: (user) => { @@ -49,7 +50,7 @@ export class RecommendationVideosComponent implements OnInit { this.recommendVideosByRecord(); }, error: (err) => { - console.error('Erro ao buscar detalhes do usuário', err); + console.error('Error fetching user details', err); } }); } @@ -58,10 +59,10 @@ export class RecommendationVideosComponent implements OnInit { this.videoService.getRecommendationFromRecord(this.userId.toString()).subscribe({ next: (response) => { const videosID = Object.values(response.recommend_videos).map(id => (id as number).toString()); - this.recommendVideos = this.unbTvVideos.filter(video => videosID.includes(String(video.id))); + + this.recommendVideos = this.unbTvVideos.filter(video => videosID.includes(String(video.id))); }, error: (err) => { - } }); } @@ -82,13 +83,13 @@ export class RecommendationVideosComponent implements OnInit { }); }); } - + filterVideosByChannel(videos: IVideo[]): void { videos.forEach((video) => { const channel = video?.channels; - if ( channel && channel[0].id === this.unbTvChannelId) { + if (channel && channel[0].id === this.unbTvChannelId) { this.unbTvVideos.push(video); } - } - )}; -} + }); + } +} \ No newline at end of file diff --git a/src/app/pages/watchlater-videos/watchlater-videos.component.html b/src/app/pages/watchlater-videos/watchlater-videos.component.html index 9fa0ab16..3f100204 100644 --- a/src/app/pages/watchlater-videos/watchlater-videos.component.html +++ b/src/app/pages/watchlater-videos/watchlater-videos.component.html @@ -1,10 +1,10 @@ -
+ +
-
\ No newline at end of file +
+--> \ No newline at end of file From a99fe7b9298927ac10c4c912c4d84f253e091314 Mon Sep 17 00:00:00 2001 From: Jauzimm Date: Sat, 31 Aug 2024 10:13:01 -0300 Subject: [PATCH 24/26] Correcao do html e css --- .../recommendation-videos.component.css | 89 +++++-------------- .../recommendation-videos.component.html | 15 ++-- 2 files changed, 28 insertions(+), 76 deletions(-) diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.css b/src/app/pages/recommendation-videos/recommendation-videos.component.css index d3feda92..f859ddd1 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.css +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.css @@ -1,90 +1,45 @@ .header-title { - color: green; /* Azul escuro para o título */ + color: green; text-align: center; - margin-bottom: 20px; + margin-bottom: 1em; font-size: 2rem; font-weight: bold; text-transform: uppercase; } - -.videos-container { +.container { + margin: 1.5em auto; display: flex; - justify-content: center; - margin-bottom: 20px; + justify-content: center; } - -.videos { +.container-videos { display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 20px; + flex-wrap: wrap; + gap: 1em; + justify-content: center; } - -.flex { +.videos-frame { + flex: 0 1 auto; display: flex; - flex-direction: column; align-items: center; - transition: transform 0.3s ease; + justify-content: center; + width: 10.5em; + height: 6.5em; } - -.video-img { - display: block; - margin: 0 auto; +.videos-frame img { + width: 100%; + height: 100%; + object-fit: cover; border-radius: 7px; - width: 220px; /* Mantém a proporção original da imagem */ - height: 124px; /* Mantém a proporção original da imagem */ - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); transition: box-shadow 0.3s ease, transform 0.3s ease; } - -.video-img:hover { - box-shadow: 0 8px 12px rgba(0, 0, 0, 0.2); - transform: translateY(-5px); /* Eleva o vídeo ligeiramente ao passar o mouse */ -} - - -.checkbox-label { - display: flex; - align-items: center; - font-size: 1.2rem; - margin-bottom: 20px; - cursor: pointer; - color: #34495e; -} - - -.checkbox-label input[type="checkbox"] { - margin-right: 10px; - width: 24px; - height: 24px; - cursor: pointer; -} - - -.record-controls { - text-align: center; - margin-bottom: 20px; -} - - -.record-controls button { - background-color: #2980b9; - color: #fff; - border: none; - padding: 12px 24px; - margin: 5px; - border-radius: 5px; +.videos-frame img:hover { + box-shadow: 0 8px 12px rgba(0, 0, 0, 0.3); + transform: translateY(-5px); cursor: pointer; - font-size: 1.1rem; - transition: background-color 0.3s ease, transform 0.2s ease; -} - - -.record-controls button:hover { - background-color: #1f6395; } \ No newline at end of file diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.html b/src/app/pages/recommendation-videos/recommendation-videos.component.html index 22475c3b..fbe3b159 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.html +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.html @@ -1,13 +1,10 @@ -
-

Nenhum vídeo recomendado disponível.

-
-
-
-
+

Sua Recomendação

+
+
+
-
- {{ video.title }} -

oi

+
+ {{ video.title }}
From 357568286d5701855e2549fae0e7af23701440e7 Mon Sep 17 00:00:00 2001 From: victorleaoo Date: Sun, 1 Sep 2024 00:01:17 -0300 Subject: [PATCH 25/26] adicionando testes para o component de recommendation e correcoes pontuais da US --- .../background/background.component.ts | 4 - src/app/pages/catalog/catalog.component.html | 2 +- .../pages/catalog/catalog.component.spec.ts | 135 ------ src/app/pages/catalog/catalog.component.ts | 68 +-- .../favorite-videos.component.css | 89 +--- .../favorite-videos.component.html | 32 +- .../recommendation-videos.component.html | 13 +- .../recommendation-videos.component.spec.ts | 110 ++++- .../recommendation-videos.component.ts | 13 + src/app/pages/record/record.component.html | 2 +- src/app/pages/record/record.component.ts | 2 - .../video-viewer.component.spec.ts | 14 - .../watchlater-videos.component.css | 91 +--- .../watchlater-videos.component.html | 32 +- .../your-unbtv/your-unbtv.component.spec.ts | 26 ++ .../pages/your-unbtv/your-unbtv.component.ts | 2 +- test-reports/TESTS.xml | 426 +++++++++--------- 17 files changed, 438 insertions(+), 623 deletions(-) create mode 100644 src/app/pages/your-unbtv/your-unbtv.component.spec.ts diff --git a/src/app/components/background/background.component.ts b/src/app/components/background/background.component.ts index 8367720a..9a3df625 100755 --- a/src/app/components/background/background.component.ts +++ b/src/app/components/background/background.component.ts @@ -18,10 +18,6 @@ export class BackgroundComponent implements OnInit { { label: 'Perfil', routerLink: '/profile', - }, - { - label: 'Histórico de Vídeos', - routerLink: '/record', } ]; this.identifiesUserDevice(); diff --git a/src/app/pages/catalog/catalog.component.html b/src/app/pages/catalog/catalog.component.html index d5e6a3c3..af8fd5ea 100755 --- a/src/app/pages/catalog/catalog.component.html +++ b/src/app/pages/catalog/catalog.component.html @@ -193,7 +193,7 @@

Variedades

-
+
diff --git a/src/app/pages/catalog/catalog.component.spec.ts b/src/app/pages/catalog/catalog.component.spec.ts index 4bd013df..ebaeda6e 100755 --- a/src/app/pages/catalog/catalog.component.spec.ts +++ b/src/app/pages/catalog/catalog.component.spec.ts @@ -110,139 +110,4 @@ describe('CatalogComponent', () => { expect(videoServiceMock.setVideosCatalog).toHaveBeenCalledWith(videos); expect(routerMock.navigate).toHaveBeenCalledWith(['/videos']); }); - - it('should populate favoriteVideos on getFavoriteVideos success', () => { - const favoriteVideos = [ - { id: 1, video_id: 1, title: 'Favorite 1', channels: [{ id: 1, name: 'unbtv' }] }, - { id: 2, video_id: 2, title: 'Favorite 2', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - component.unbTvVideos = [ - { id: 1, title: 'Favorite 1', channels: [{ id: 1, name: 'unbtv' }] }, - { id: 2, title: 'Favorite 2', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - videoServiceMock.getFavoriteVideos.and.returnValue(of({ videoList: favoriteVideos })); - - component.getFavoriteVideos(); - - expect(component.favoriteVideos.length).toBe(2); - expect(component.favoriteVideos[0].id).toBe(1); - expect(component.favoriteVideos[1].id).toBe(2); - }); - - it('should log warning on getFavoriteVideos with unexpected structure', () => { - spyOn(console, 'warn'); - videoServiceMock.getFavoriteVideos.and.returnValue(of({ incorrectKey: [] })); - - component.getFavoriteVideos(); - - expect(console.warn).toHaveBeenCalledWith('A estrutura da resposta da API não está conforme o esperado:', { incorrectKey: [] }); - }); - - it('should filter videos to favorite when checkbox is checked', () => { - const favoriteVideos = [ - { id: 1, video_id: 1, title: 'Favorite 1', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - component.unbTvVideos = [ - { id: 1, title: 'Favorite 1', channels: [{ id: 1, name: 'unbtv' }] }, - { id: 2, title: 'Not Favorite', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - videoServiceMock.getFavoriteVideos.and.returnValue(of({ videoList: favoriteVideos })); - - component.filterFavorite = true; - component.onFilterFavoriteVideosChange(); - - expect(component.filteredVideos.length).toBe(1); - expect(component.filteredVideos[0].title).toBe('Favorite 1'); - }); - - it('should not filter videos to favorite when checkbox is unchecked', () => { - const favoriteVideos = [ - { id: 1, video_id: 1, title: 'Favorite 1', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - component.unbTvVideos = [ - { id: 1, title: 'Favorite 1', channels: [{ id: 1, name: 'unbtv' }] }, - { id: 2, title: 'Not Favorite', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - videoServiceMock.getFavoriteVideos.and.returnValue(of({ videoList: favoriteVideos })); - - component.filterFavorite = false; - component.onFilterFavoriteVideosChange(); - - expect(component.filteredVideos.length).toBe(2); - }); - - it('should populate watchLaterVideos on getWatchLaterVideos success', () => { - const watchLaterVideos = [ - { id: 1, video_id: 1, title: 'Watch Later 1', channels: [{ id: 1, name: 'unbtv' }] }, - { id: 2, video_id: 2, title: 'Watch Later 2', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - component.unbTvVideos = [ - { id: 1, title: 'Watch Later 1', channels: [{ id: 1, name: 'unbtv' }] }, - { id: 2, title: 'Watch Later 2', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - videoServiceMock.getWatchLaterVideos.and.returnValue(of({ videoList: watchLaterVideos })); - - component.getWatchLaterVideos(); - - expect(component.watchLaterVideos.length).toBe(2); - expect(component.watchLaterVideos[0].id).toBe(1); - expect(component.watchLaterVideos[1].id).toBe(2); - }); - - - it('should log warning on getWatchLaterVideos with unexpected structure', () => { - spyOn(console, 'warn'); - videoServiceMock.getWatchLaterVideos.and.returnValue(of({ incorrectKey: [] })); - - component.getWatchLaterVideos(); - - expect(console.warn).toHaveBeenCalledWith('A estrutura da resposta da API não está conforme o esperado:', { incorrectKey: [] }); - }); - - - it('should filter videos to watch later when checkbox is checked', () => { - const watchLaterVideos = [ - { id: 1, video_id: 1, title: 'Watch Later 1', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - component.unbTvVideos = [ - { id: 1, title: 'Watch Later 1', channels: [{ id: 1, name: 'unbtv' }] }, - { id: 2, title: 'Not Watch Later', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - videoServiceMock.getWatchLaterVideos.and.returnValue(of({ videoList: watchLaterVideos })); - - component.filterWatchLater = true; - component.onFilterWatchLaterChange(); - - expect(component.filteredVideos.length).toBe(1); - expect(component.filteredVideos[0].title).toBe('Watch Later 1'); - }); - - - it('should not filter videos to watch later when checkbox is unchecked', () => { - const watchLaterVideos = [ - { id: 1, video_id: 1, title: 'Watch Later 1', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - component.unbTvVideos = [ - { id: 1, title: 'Watch Later 1', channels: [{ id: 1, name: 'unbtv' }] }, - { id: 2, title: 'Not Watch Later', channels: [{ id: 1, name: 'unbtv' }] } - ]; - - videoServiceMock.getWatchLaterVideos.and.returnValue(of({ videoList: watchLaterVideos })); - - component.filterWatchLater = false; - component.onFilterWatchLaterChange(); - - expect(component.filteredVideos.length).toBe(2); - }); }); \ No newline at end of file diff --git a/src/app/pages/catalog/catalog.component.ts b/src/app/pages/catalog/catalog.component.ts index 677e5efa..dd80b01e 100755 --- a/src/app/pages/catalog/catalog.component.ts +++ b/src/app/pages/catalog/catalog.component.ts @@ -53,8 +53,6 @@ export class CatalogComponent implements OnInit { this.userService.getUser(this.userId).subscribe({ next: (user) => { this.user = user; - this.getFavoriteVideos(); - this.getWatchLaterVideos(); // Carregue os vídeos de "assistir mais tarde" após obter os detalhes do usuário }, error: (err) => { console.error('Error fetching user details', err); @@ -76,68 +74,6 @@ export class CatalogComponent implements OnInit { }); } - getFavoriteVideos(): void { - if (this.isAuthenticated) { - this.videoService.getFavoriteVideos(this.userId).subscribe({ - next: (data) => { - - // Verifique se `videoList` existe e é um array - if (data && Array.isArray(data.videoList)) { - const favorite_videos_ids = data.videoList.map((item: any) => String(item.video_id)); // Converta IDs para string - - this.favoriteVideos = this.unbTvVideos.filter(video => favorite_videos_ids.includes(String(video.id))); // Converta IDs para string - } else { - console.warn('A estrutura da resposta da API não está conforme o esperado:', data); - } - - this.filterVideos(); // Atualize a filtragem após carregar os vídeos de "favoritos" - }, - error: (error) => { - console.log('Erro ao buscar vídeos marcados como "favoritos"', error); - } - }); - } - } - - onFilterFavoriteVideosChange() { - if (this.filterFavorite) { - this.getFavoriteVideos(); - } else { - this.filterVideos(); - } - } - - getWatchLaterVideos(): void { - if (this.isAuthenticated) { - this.videoService.getWatchLaterVideos(this.userId).subscribe({ - next: (data) => { - - // Verifique se `videoList` existe e é um array - if (data && Array.isArray(data.videoList)) { - const watchLaterVideoIds = data.videoList.map((item: any) => String(item.video_id)); // Converta IDs para string - - this.watchLaterVideos = this.unbTvVideos.filter(video => watchLaterVideoIds.includes(String(video.id))); // Converta IDs para string - } else { - console.warn('A estrutura da resposta da API não está conforme o esperado:', data); - } - - this.filterVideos(); // Atualize a filtragem após carregar os vídeos de "assistir mais tarde" - }, - error: (error) => { - console.log('Erro ao buscar vídeos marcados como "assistir mais tarde"', error); - } - }); - } - } - - onFilterWatchLaterChange() { - if (this.filterWatchLater) { - this.getWatchLaterVideos(); - } else { - this.filterVideos(); - } - } - filterVideosByChannel(videos: IVideo[]): void { videos.forEach((video) => { @@ -150,14 +86,12 @@ export class CatalogComponent implements OnInit { filterVideos() { this.filteredVideos = this.unbTvVideos.filter(video => { - const isWatchLater = this.filterWatchLater ? this.watchLaterVideos.some(wlVideo => wlVideo.id == video.id) : true; - const isFavorite = this.filterFavorite? this.favoriteVideos.some(wlVideo => wlVideo.id == video.id) : true; const matchesTitle = this.filterTitle ? video.title?.toLowerCase().includes(this.filterTitle.toLowerCase()) : true; const matchesDescription = this.filterTitle ? video.description?.toLowerCase().includes(this.filterTitle.toLowerCase()) : true; const matchesKeywords = this.filterTitle ? video.keywords?.toLowerCase().includes(this.filterTitle.toLowerCase()) : true; const matchesCatalog = this.filterTitle ? video.catalog?.toLowerCase().includes(this.filterTitle.toLowerCase()) : true; - return isWatchLater && isFavorite && (matchesTitle || matchesDescription || matchesKeywords || matchesCatalog); + return (matchesTitle || matchesDescription || matchesKeywords || matchesCatalog); }); } diff --git a/src/app/pages/favorite-videos/favorite-videos.component.css b/src/app/pages/favorite-videos/favorite-videos.component.css index d3feda92..f859ddd1 100644 --- a/src/app/pages/favorite-videos/favorite-videos.component.css +++ b/src/app/pages/favorite-videos/favorite-videos.component.css @@ -1,90 +1,45 @@ .header-title { - color: green; /* Azul escuro para o título */ + color: green; text-align: center; - margin-bottom: 20px; + margin-bottom: 1em; font-size: 2rem; font-weight: bold; text-transform: uppercase; } - -.videos-container { +.container { + margin: 1.5em auto; display: flex; - justify-content: center; - margin-bottom: 20px; + justify-content: center; } - -.videos { +.container-videos { display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 20px; + flex-wrap: wrap; + gap: 1em; + justify-content: center; } - -.flex { +.videos-frame { + flex: 0 1 auto; display: flex; - flex-direction: column; align-items: center; - transition: transform 0.3s ease; + justify-content: center; + width: 10.5em; + height: 6.5em; } - -.video-img { - display: block; - margin: 0 auto; +.videos-frame img { + width: 100%; + height: 100%; + object-fit: cover; border-radius: 7px; - width: 220px; /* Mantém a proporção original da imagem */ - height: 124px; /* Mantém a proporção original da imagem */ - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); transition: box-shadow 0.3s ease, transform 0.3s ease; } - -.video-img:hover { - box-shadow: 0 8px 12px rgba(0, 0, 0, 0.2); - transform: translateY(-5px); /* Eleva o vídeo ligeiramente ao passar o mouse */ -} - - -.checkbox-label { - display: flex; - align-items: center; - font-size: 1.2rem; - margin-bottom: 20px; - cursor: pointer; - color: #34495e; -} - - -.checkbox-label input[type="checkbox"] { - margin-right: 10px; - width: 24px; - height: 24px; - cursor: pointer; -} - - -.record-controls { - text-align: center; - margin-bottom: 20px; -} - - -.record-controls button { - background-color: #2980b9; - color: #fff; - border: none; - padding: 12px 24px; - margin: 5px; - border-radius: 5px; +.videos-frame img:hover { + box-shadow: 0 8px 12px rgba(0, 0, 0, 0.3); + transform: translateY(-5px); cursor: pointer; - font-size: 1.1rem; - transition: background-color 0.3s ease, transform 0.2s ease; -} - - -.record-controls button:hover { - background-color: #1f6395; } \ No newline at end of file diff --git a/src/app/pages/favorite-videos/favorite-videos.component.html b/src/app/pages/favorite-videos/favorite-videos.component.html index 20346084..5a9018d2 100644 --- a/src/app/pages/favorite-videos/favorite-videos.component.html +++ b/src/app/pages/favorite-videos/favorite-videos.component.html @@ -1,30 +1,12 @@ - \ No newline at end of file diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.html b/src/app/pages/recommendation-videos/recommendation-videos.component.html index fbe3b159..109f0855 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.html +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.html @@ -1,5 +1,14 @@ -

Sua Recomendação

+

Vídeos Recomendados

+
+
+

Adicione o rastreamento do histórico para ver vídeos recomendados!

+
+ +
+

Assista um vídeo para ter vídeos recomendados!

+
+
@@ -9,4 +18,4 @@
-
+
\ No newline at end of file diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.spec.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.spec.ts index dacd8bfe..1b81c078 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.spec.ts +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.spec.ts @@ -1,23 +1,123 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; - +import { HttpResponse } from '@angular/common/http'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { RouterTestingModule } from '@angular/router/testing'; import { RecommendationVideosComponent } from './recommendation-videos.component'; +import { UserService } from 'src/app/services/user.service'; +import { VideoService } from 'src/app/services/video.service'; +import { IVideo } from 'src/shared/model/video.model'; +import { of, throwError } from 'rxjs'; +import * as jwt_decode from 'jwt-decode'; describe('RecommendationVideosComponent', () => { let component: RecommendationVideosComponent; let fixture: ComponentFixture; + let userService: UserService; + let videoService: VideoService; beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [RecommendationVideosComponent] - }) - .compileComponents(); - + imports: [HttpClientTestingModule, RouterTestingModule], + declarations: [RecommendationVideosComponent], + providers: [UserService, VideoService], + }).compileComponents(); + fixture = TestBed.createComponent(RecommendationVideosComponent); component = fixture.componentInstance; + userService = TestBed.inject(UserService); + videoService = TestBed.inject(VideoService); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + it('should check and set tracking status from localStorage', () => { + spyOn(localStorage, 'getItem').and.callFake((key) => { + if (key === 'trackingEnabled') { + return 'false'; + } + return null; + }); + + component.checkTrackingStatus(); + + expect(component.trackingEnabled).toBe(false); + }); + + it('should call findAll and populate videosEduplay and unbTvVideos', async () => { + const mockResponse = { + body: { + videoList: [{ id: 1, title: 'Video 1', channels: [{ id: 12, name: 'unbtvchannel' }] }] + } + }; + + const findAllSpy = spyOn(videoService, 'findAll').and.returnValue(of(new HttpResponse({ body: mockResponse.body }))); + const filterSpy = spyOn(component, 'filterVideosByChannel').and.callThrough(); + const videosCatalogSpy = spyOn(videoService, 'videosCatalog').and.callThrough(); + + await component.findAll(); + + expect(findAllSpy).toHaveBeenCalled(); + expect(component.videosEduplay).toEqual(mockResponse.body.videoList); + expect(filterSpy).toHaveBeenCalledWith(mockResponse.body.videoList); + expect(videosCatalogSpy).toHaveBeenCalledWith(component.unbTvVideos, component.catalog); + }); + + it('should filter videos by channel and populate unbTvVideos', () => { + const mockVideos: IVideo[] = [ + { id: 1, title: 'Video 1', channels: [{ id: component.unbTvChannelId, name: 'unbtvchannel' }] }, + { id: 2, title: 'Video 2', channels: [{ id: 13, name: 'otherchannel' }] } + ]; + + component.unbTvVideos = []; + component.filterVideosByChannel(mockVideos); + + expect(component.unbTvVideos.length).toBe(1); + expect(component.unbTvVideos[0].id).toBe(1); + }); + + it('should call getUserDetails and fetch user data', () => { + const mockUser = { id: '12345', name: 'Test User' }; + const getUserSpy = spyOn(userService, 'getUser').and.returnValue(of(mockUser)); + const recommendSpy = spyOn(component, 'recommendVideosByRecord').and.callThrough(); + + component.userId = '12345'; + component.getUserDetails(); + + expect(getUserSpy).toHaveBeenCalledWith('12345'); + expect(component.user).toEqual(mockUser); + expect(recommendSpy).toHaveBeenCalled(); + }); + + it('should call recommendVideosByRecord and filter recommended videos', () => { + const mockRecommendation = { + recommend_videos: [1, 2] + }; + const mockVideos: IVideo[] = [ + { id: 1, title: 'Video 1' }, + { id: 2, title: 'Video 2' }, + { id: 3, title: 'Video 3' } + ]; + + spyOn(videoService, 'getRecommendationFromRecord').and.returnValue(of(mockRecommendation)); + component.unbTvVideos = mockVideos; + + component.recommendVideosByRecord(); + + expect(component.recommendVideos.length).toBe(2); + expect(component.recommendVideos).toEqual([{ id: 1, title: 'Video 1' }, { id: 2, title: 'Video 2' }]); + }); + + it('should handle error during getUserDetails', () => { + const getUserSpy = spyOn(userService, 'getUser').and.returnValue(throwError({ status: 500 })); + const consoleErrorSpy = spyOn(console, 'error'); + + component.userId = '12345'; + component.getUserDetails(); + + expect(getUserSpy).toHaveBeenCalledWith('12345'); + expect(consoleErrorSpy).toHaveBeenCalledWith('Error fetching user details', { status: 500 }); + }); }); diff --git a/src/app/pages/recommendation-videos/recommendation-videos.component.ts b/src/app/pages/recommendation-videos/recommendation-videos.component.ts index 2bbe733c..2709f929 100644 --- a/src/app/pages/recommendation-videos/recommendation-videos.component.ts +++ b/src/app/pages/recommendation-videos/recommendation-videos.component.ts @@ -21,6 +21,7 @@ export class RecommendationVideosComponent implements OnInit { userId: string; user: any; recommendVideos: IVideo[] = []; + trackingEnabled: boolean = true; // Estado da checkbox de rastreamento constructor( private userService: UserService, @@ -30,6 +31,8 @@ export class RecommendationVideosComponent implements OnInit { async ngOnInit(): Promise { this.setUserIdFromToken(localStorage.getItem('token') as string); + this.checkTrackingStatus(); // Verifica o estado inicial do rastreamento + try { await this.findAll(); this.getUserDetails(); @@ -38,6 +41,16 @@ export class RecommendationVideosComponent implements OnInit { } } + checkTrackingStatus(): void { + const storedTrackingStatus = localStorage.getItem('trackingEnabled'); + + if (storedTrackingStatus !== null) { + this.trackingEnabled = storedTrackingStatus === 'true'; + } else { + this.trackingEnabled = true; + } + } + setUserIdFromToken(token: string) { const decodedToken: any = jwt_decode(token); this.userId = decodedToken.id; diff --git a/src/app/pages/record/record.component.html b/src/app/pages/record/record.component.html index c790c88c..45b32102 100644 --- a/src/app/pages/record/record.component.html +++ b/src/app/pages/record/record.component.html @@ -27,4 +27,4 @@

Histórico de Vídeos

-
+
\ No newline at end of file diff --git a/src/app/pages/record/record.component.ts b/src/app/pages/record/record.component.ts index 6c073ad0..f7e39dc8 100644 --- a/src/app/pages/record/record.component.ts +++ b/src/app/pages/record/record.component.ts @@ -79,12 +79,10 @@ export class RecordComponent { } } - saveTrackingStatus(): void { localStorage.setItem('trackingEnabled', this.trackingEnabled.toString()); } - toggleTracking(enabled: boolean): void { this.trackingEnabled = enabled; this.saveTrackingStatus(); // Salva o estado atualizado diff --git a/src/app/pages/video-viewer/video-viewer.component.spec.ts b/src/app/pages/video-viewer/video-viewer.component.spec.ts index 953ea74b..fccde441 100755 --- a/src/app/pages/video-viewer/video-viewer.component.spec.ts +++ b/src/app/pages/video-viewer/video-viewer.component.spec.ts @@ -156,20 +156,6 @@ describe('VideoViewerComponent', () => { expect(component).toBeTruthy(); }); - /*it('should decode token and set userId as a string', () => { - const token = localStorage.getItem('token') as string; - const originalJwtDecode = jwt_decode.default; - - // Redefinir a função jwt_decode - (jwt_decode as any).default = (): { id: string } => ({ id: '1' }); - - component.setUserIdFromToken(token); - expect(component.userId).toBe('1'); // Ensure the userId is '1' as string - - // Restaurar a função original após o teste - (jwt_decode as any).default = originalJwtDecode; - });*/ - it('should call findVideoById and set video description', () => { const expectedVideo = { id: 190329, diff --git a/src/app/pages/watchlater-videos/watchlater-videos.component.css b/src/app/pages/watchlater-videos/watchlater-videos.component.css index ff500523..f859ddd1 100644 --- a/src/app/pages/watchlater-videos/watchlater-videos.component.css +++ b/src/app/pages/watchlater-videos/watchlater-videos.component.css @@ -1,90 +1,45 @@ .header-title { - color: green; /* Azul escuro para o título */ + color: green; text-align: center; - margin-bottom: 20px; + margin-bottom: 1em; font-size: 2rem; font-weight: bold; text-transform: uppercase; } - -.videos-container { +.container { + margin: 1.5em auto; display: flex; - justify-content: center; - margin-bottom: 20px; + justify-content: center; } - -.videos { +.container-videos { display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 20px; + flex-wrap: wrap; + gap: 1em; + justify-content: center; } - -.flex { +.videos-frame { + flex: 0 1 auto; display: flex; - flex-direction: column; align-items: center; - transition: transform 0.3s ease; + justify-content: center; + width: 10.5em; + height: 6.5em; } - -.video-img { - display: block; - margin: 0 auto; +.videos-frame img { + width: 100%; + height: 100%; + object-fit: cover; border-radius: 7px; - width: 220px; /* Mantém a proporção original da imagem */ - height: 124px; /* Mantém a proporção original da imagem */ - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); transition: box-shadow 0.3s ease, transform 0.3s ease; } - -.video-img:hover { - box-shadow: 0 8px 12px rgba(0, 0, 0, 0.2); - transform: translateY(-5px); /* Eleva o vídeo ligeiramente ao passar o mouse */ -} - - -.checkbox-label { - display: flex; - align-items: center; - font-size: 1.2rem; - margin-bottom: 20px; +.videos-frame img:hover { + box-shadow: 0 8px 12px rgba(0, 0, 0, 0.3); + transform: translateY(-5px); cursor: pointer; - color: #34495e; -} - - -.checkbox-label input[type="checkbox"] { - margin-right: 10px; - width: 24px; - height: 24px; - cursor: pointer; -} - - -.record-controls { - text-align: center; - margin-bottom: 20px; -} - - -.record-controls button { - background-color: #2980b9; - color: #fff; - border: none; - padding: 12px 24px; - margin: 5px; - border-radius: 5px; - cursor: pointer; - font-size: 1.1rem; - transition: background-color 0.3s ease, transform 0.2s ease; -} - - -.record-controls button:hover { - background-color: #1f6395; -} +} \ No newline at end of file diff --git a/src/app/pages/watchlater-videos/watchlater-videos.component.html b/src/app/pages/watchlater-videos/watchlater-videos.component.html index 3f100204..baff666c 100644 --- a/src/app/pages/watchlater-videos/watchlater-videos.component.html +++ b/src/app/pages/watchlater-videos/watchlater-videos.component.html @@ -1,30 +1,12 @@ - \ No newline at end of file diff --git a/src/app/pages/your-unbtv/your-unbtv.component.spec.ts b/src/app/pages/your-unbtv/your-unbtv.component.spec.ts new file mode 100644 index 00000000..f381f868 --- /dev/null +++ b/src/app/pages/your-unbtv/your-unbtv.component.spec.ts @@ -0,0 +1,26 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterModule } from '@angular/router'; +import { YourUnBTVComponent } from './your-unbtv.component'; + +describe('YourUnBTVComponent', () => { + let component: YourUnBTVComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ YourUnBTVComponent ], + imports: [ RouterModule.forRoot([]) ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(YourUnBTVComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/pages/your-unbtv/your-unbtv.component.ts b/src/app/pages/your-unbtv/your-unbtv.component.ts index 5e1026ac..86c8a955 100644 --- a/src/app/pages/your-unbtv/your-unbtv.component.ts +++ b/src/app/pages/your-unbtv/your-unbtv.component.ts @@ -14,4 +14,4 @@ export class YourUnBTVComponent { } -} \ No newline at end of file +} \ No newline at end of file diff --git a/test-reports/TESTS.xml b/test-reports/TESTS.xml index 7ff68c38..412a144f 100644 --- a/test-reports/TESTS.xml +++ b/test-reports/TESTS.xml @@ -1,296 +1,308 @@ - + - + - - - - - + + + + + - + - - + + - - + + - - + + - - - - - - - + + + + + + + - - + + - + - + - - + + - - + + - + - - - - - + + + + + - - - + + + - + - + - - - - - - - - + + + + + + + + - + - - - + + + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - - - - + + + + - - + + - - - - - + + + + + - + - + - + - + - - - + + + - + - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - + - - - - - - + + + + + + - - - - - + + + + + - + - + + + + + + + + - + - + - - - - + + + + - - - + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + + + From 7a5e97a4f840949a2b3db0dcb211b347b76f2634 Mon Sep 17 00:00:00 2001 From: victorleaoo Date: Sun, 1 Sep 2024 20:03:04 -0300 Subject: [PATCH 26/26] removendo componentes nao existentes --- src/app/app.module.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3ba18413..f716016a 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -88,7 +88,6 @@ import { NotificationsComponent } from './pages/notifications/notifications.comp NgChartsModule, CommonModule, ], - declarations: [ AppComponent, LoginComponent, @@ -116,11 +115,10 @@ import { NotificationsComponent } from './pages/notifications/notifications.comp VideoViewsComponent, DashboardCategoryComponent, RecordComponent, - ControleSuperAdminComponent, RecommendationVideosComponent, YourUnBTVComponent, FavoriteVideosComponent, - WatchLaterVideosComponent + WatchLaterVideosComponent, NotificationsComponent, ],