From 1985848922d9e2dc8063ae5489500764d8ea5d6b Mon Sep 17 00:00:00 2001 From: Daniel Cortes Date: Thu, 28 May 2020 04:34:44 -0400 Subject: [PATCH] Interfaz de home basica --- src/app/app-routing.module.ts | 5 +- src/app/app.component.html | 67 +---------- src/app/app.module.ts | 8 +- src/app/brainz.service.spec.ts | 16 --- src/app/brainz.service.ts | 60 ---------- src/app/homepage/homepage.component.html | 10 ++ src/app/homepage/homepage.component.scss | 0 src/app/homepage/homepage.component.spec.ts | 25 ++++ src/app/homepage/homepage.component.ts | 15 +++ .../searchHome/searchHome.component.html | 41 +++++++ .../searchHome/searchHome.component.scss | 55 +++++++++ .../searchHome/searchHome.component.spec.ts} | 10 +- .../searchHome/searchHome.component.ts | 51 ++++++++ src/app/models/brainz.ts | 112 ++++++++++-------- src/app/nav/nav.component.html | 21 ++++ src/app/nav/nav.component.scss | 0 src/app/nav/nav.component.spec.ts | 25 ++++ src/app/nav/nav.component.ts | 15 +++ src/app/search.service.ts | 56 +++++++-- src/app/search/search.component.html | 14 --- src/app/search/search.component.scss | 30 ----- src/app/search/search.component.ts | 26 ---- 22 files changed, 384 insertions(+), 278 deletions(-) delete mode 100644 src/app/brainz.service.spec.ts delete mode 100644 src/app/brainz.service.ts create mode 100644 src/app/homepage/homepage.component.html create mode 100644 src/app/homepage/homepage.component.scss create mode 100644 src/app/homepage/homepage.component.spec.ts create mode 100644 src/app/homepage/homepage.component.ts create mode 100644 src/app/homepage/searchHome/searchHome.component.html create mode 100644 src/app/homepage/searchHome/searchHome.component.scss rename src/app/{search/search.component.spec.ts => homepage/searchHome/searchHome.component.spec.ts} (60%) create mode 100644 src/app/homepage/searchHome/searchHome.component.ts create mode 100644 src/app/nav/nav.component.html create mode 100644 src/app/nav/nav.component.scss create mode 100644 src/app/nav/nav.component.spec.ts create mode 100644 src/app/nav/nav.component.ts delete mode 100644 src/app/search/search.component.html delete mode 100644 src/app/search/search.component.scss delete mode 100644 src/app/search/search.component.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 06c7342..3a698cd 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,8 +1,11 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; +import {HomepageComponent} from "./homepage/homepage.component"; -const routes: Routes = []; +const routes: Routes = [ + {path: '', component: HomepageComponent} +]; @NgModule({ imports: [RouterModule.forRoot(routes)], diff --git a/src/app/app.component.html b/src/app/app.component.html index 20f7756..0680b43 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,66 +1 @@ - -
-
-
-

Busca la musica que disfrutas!

- -
-
-
-
-
-

Artistas populares

-
-
-
-
-

Mago de oz

-
-
-
- -
-
-
-
-
-
-
-
-
-

Ultimas opiniones

-
-
-
-
-

Jhon

-
-
- Facere esse corrupti modi qui aut commodi. Saepe culpa corporis ut doloribus excepturi temporibus commodi - animi. Est ut ut enim dolorem fugit voluptatem. Qui sunt earum vel excepturi aliquam dolor numquam... -
-
-
-
-
-
+ diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 39cdcc2..d1b7635 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -3,13 +3,17 @@ import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; -import { SearchComponent } from './search/search.component'; +import { SearchHomeComponent } from './homepage/searchHome/searchHome.component'; import {HttpClientModule} from "@angular/common/http"; +import { HomepageComponent } from './homepage/homepage.component'; +import { NavComponent } from './nav/nav.component'; @NgModule({ declarations: [ AppComponent, - SearchComponent + SearchHomeComponent, + HomepageComponent, + NavComponent, ], imports: [ HttpClientModule, diff --git a/src/app/brainz.service.spec.ts b/src/app/brainz.service.spec.ts deleted file mode 100644 index 3073dfb..0000000 --- a/src/app/brainz.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { BrainzService } from './brainz.service'; - -describe('BrainzService', () => { - let service: BrainzService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(BrainzService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/brainz.service.ts b/src/app/brainz.service.ts deleted file mode 100644 index f564b11..0000000 --- a/src/app/brainz.service.ts +++ /dev/null @@ -1,60 +0,0 @@ -import {Injectable} from '@angular/core'; -import {HttpClient, HttpErrorResponse, HttpHeaders} from '@angular/common/http'; -import {Observable, of} from 'rxjs'; -import {catchError, map, tap} from 'rxjs/operators'; -import {BrainzError, Artist, BrowseReleaseGroup, CoverArt, ReleaseGroup} from './models/brainz'; - -@Injectable({ - providedIn: 'root' -}) -export class BrainzService { - private httpOptions = { - headers: new HttpHeaders({'content-type': 'application/json'}) - }; - - private url = 'http://127.0.0.1:8000/api/brainz'; - - constructor(private http: HttpClient) { - } - - private log(message: string) { - console.log(`BrainzService: ${message}`); - } - - private handleError(operation: string) { - return (error: HttpErrorResponse): Observable => { - const brainzError = error.error as BrainzError; - this.log(`${operation} failed: ${brainzError.status} - ${brainzError.error}`); - return of(brainzError); - }; - } - - getArtist(id: string): Observable { - const url = `${this.url}/get/artist/${id}/`; - this.log(`Querying ${url}`); - return this.http.get(url).pipe( - tap(artist => this.log(`getArtist found`)), - tap(artist => console.log(artist)), - catchError(this.handleError('getArtist')) - ); - } - - getDiscography(artistID: string): Observable { - const url = `${this.url}/browse/release-group/?artist=${artistID}&limit=10`; - this.log(`Querying ${url}`); - return this.http.get(url).pipe( - map(discography => discography.release_groups), - tap(d => this.log(`getDiscography found`)), - tap(d => console.log(d)), - catchError(this.handleError('getDiscography')) - ); - } - - getCoverReleaseGroup(id: string): Observable { - const url = `${this.url}/coverart/release-group/${id}/`; - return this.http.get(url).pipe( - tap(cover => this.log(`cover found for ${id}`)), - catchError(this.handleError('getCoverReleaseGroup ')) - ); - }; -} diff --git a/src/app/homepage/homepage.component.html b/src/app/homepage/homepage.component.html new file mode 100644 index 0000000..46e5973 --- /dev/null +++ b/src/app/homepage/homepage.component.html @@ -0,0 +1,10 @@ + +
+
+
+

Busca la musica que disfrutas!

+ +
+
+
+ diff --git a/src/app/homepage/homepage.component.scss b/src/app/homepage/homepage.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/homepage/homepage.component.spec.ts b/src/app/homepage/homepage.component.spec.ts new file mode 100644 index 0000000..8d1d3bb --- /dev/null +++ b/src/app/homepage/homepage.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HomepageComponent } from './homepage.component'; + +describe('HomepageComponent', () => { + let component: HomepageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HomepageComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HomepageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/homepage/homepage.component.ts b/src/app/homepage/homepage.component.ts new file mode 100644 index 0000000..710ca29 --- /dev/null +++ b/src/app/homepage/homepage.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-homepage', + templateUrl: './homepage.component.html', + styleUrls: ['./homepage.component.scss'] +}) +export class HomepageComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/homepage/searchHome/searchHome.component.html b/src/app/homepage/searchHome/searchHome.component.html new file mode 100644 index 0000000..200488d --- /dev/null +++ b/src/app/homepage/searchHome/searchHome.component.html @@ -0,0 +1,41 @@ +
+
+ +
+
+ +
+
+ +
+
+
+

Artistas

+
+
+ {{ result.name }} +
+
+
+
+

Discos

+
+
+
+ {{result.title}} cover art + {{result.title}} missing cover art +
+
+

{{result.title}}

+
+
+
+
+
+

Canciones

+
+
+ {{ result.title }} +
+
+
diff --git a/src/app/homepage/searchHome/searchHome.component.scss b/src/app/homepage/searchHome/searchHome.component.scss new file mode 100644 index 0000000..ea1c22e --- /dev/null +++ b/src/app/homepage/searchHome/searchHome.component.scss @@ -0,0 +1,55 @@ +@import "~bulma"; + +.media + .media { + margin-top: inherit; + border-top: inherit; +} + +.field:not(:last-child) { + margin-bottom: 0; +} + +.autocomplete { + position: absolute; + z-index: 2; + margin-top: 1em; + width: 40ch; + max-height: 30ch; + overflow-y: auto; + background-color: $body-background-color; + color: $text; + border: 1px solid $border; + + .header { + padding: .6em .8em; + background: $grey-lightest; + font-weight: bold; + } + + .artist, .disc, .recording { + padding-top: 1em; + padding-bottom: 1em; + padding-left: 1em; + + &:not(:last-child) { + border-bottom: 1px solid $border; + } + + &:hover { + background-color: $warning; + } + } + + .disc { + padding-top: .5em; + padding-bottom: .5em; + padding-left: .5em; + } +} + +.image.cropped{ + object-fit: cover; +} + + + diff --git a/src/app/search/search.component.spec.ts b/src/app/homepage/searchHome/searchHome.component.spec.ts similarity index 60% rename from src/app/search/search.component.spec.ts rename to src/app/homepage/searchHome/searchHome.component.spec.ts index 4372919..feaea52 100644 --- a/src/app/search/search.component.spec.ts +++ b/src/app/homepage/searchHome/searchHome.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { SearchComponent } from './search.component'; +import { SearchHomeComponent } from './searchHome.component'; describe('SearchComponent', () => { - let component: SearchComponent; - let fixture: ComponentFixture; + let component: SearchHomeComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ SearchComponent ] + declarations: [ SearchHomeComponent ] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(SearchComponent); + fixture = TestBed.createComponent(SearchHomeComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/homepage/searchHome/searchHome.component.ts b/src/app/homepage/searchHome/searchHome.component.ts new file mode 100644 index 0000000..29068ac --- /dev/null +++ b/src/app/homepage/searchHome/searchHome.component.ts @@ -0,0 +1,51 @@ +import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {BehaviorSubject, forkJoin, Subject} from "rxjs"; +import {SearchService} from "../../search.service"; +import {Artist, Disc, Recording} from "../../models/brainz"; + +@Component({ + selector: 'app-search', + templateUrl: './searchHome.component.html', + styleUrls: ['./searchHome.component.scss'] +}) +export class SearchHomeComponent implements OnInit { + @ViewChild("input") input: ElementRef; + showList: boolean; + + artists: Artist[] = []; + discs: Disc[] = []; + recordings: Recording[] = []; + + searchTerm$ = new Subject(); + + constructor(private searchService: SearchService) { + } + + + areResults() { + return this.artists.length > 0 || this.discs.length > 0 || this.recordings.length > 0; + } + + show() { + if (this.input.nativeElement === document.activeElement) return true; + this.showList = false; + } + + ngOnInit(): void { + this.searchTerm$.subscribe(() => { + this.artists = []; + this.discs = []; + this.recordings = []; + } + ); + let searchArtist = this.searchService.searchArtist(this.searchTerm$).subscribe((result) => { + this.artists = result.artists; + }); + let searchDisc = this.searchService.searchDisc(this.searchTerm$).subscribe((result) => { + this.discs = result.discs; + }); + let searchRecording = this.searchService.searchRecording(this.searchTerm$).subscribe((result) => { + this.recordings = result.recordings; + }); + } +} diff --git a/src/app/models/brainz.ts b/src/app/models/brainz.ts index 9f0b850..c01d161 100644 --- a/src/app/models/brainz.ts +++ b/src/app/models/brainz.ts @@ -7,56 +7,74 @@ export function isBrainzError(object: any): boolean { return 'status' in object && 'error' in object; } -export interface LifeSpan { - begin: number; - end: number; - ended: boolean; +export interface Paginate { + total: number + current_page: number + last_page: number + per_page: number } -export interface Area { - id: string; - type: string; - type_id: string; - name: string; - sort_name: string; - iso_3166_1_codes: string[]; - disambiguation: string; -} - -export interface Artist { - id: string; - isnis: string; - ipis: string; - name: string; - sort_name: string; - area: Area; - begin_area: Area; - end_area: Area; - country: string; - life_span: LifeSpan; - gender: string; - gender_id: string; - type: string; - disambiguation: string; -} - -export interface ReleaseGroup { - id: string; - title: string; - first_release_date: string; - disambiguation: string; - primary_type: string; - primary_type_id: string; - secondary_types: string[]; - secondary_type_ids: string[]; -} - -export interface BrowseReleaseGroup { - release_groups: ReleaseGroup[]; - release_group_count: number; - release_group_offset: number; +export interface Tag { + name: string + count: number } export interface CoverArt { - link: string; + image: string + 1200: string + 500: string + 250: string + large: string + small: string +} + +export interface Artist { + id: string + name: string + sort_name: string + disambiguation: string + type: string + country: string + tags: Tag[] +} + +export interface ArtistCredit { + id: string + name: string + sort_name: string + disambiguation: string +} + +export interface ArtistSearch { + paginate: Paginate + artists: Artist[] +} + +export interface Disc { + id: string + title: string + disambiguation: string + first_release_date: string + primary_type: string + secondary_type: string + cover_art: CoverArt + artists: ArtistCredit[] +} + +export interface DiscSearch { + paginate: Paginate + discs: Disc[] +} + +export interface Recording { + id: string + title: string + disambiguation: string + length: string + artist: ArtistCredit[] +} + +export interface RecordingSearch { + paginate: Paginate + recordings: Recording[] } diff --git a/src/app/nav/nav.component.html b/src/app/nav/nav.component.html new file mode 100644 index 0000000..b580595 --- /dev/null +++ b/src/app/nav/nav.component.html @@ -0,0 +1,21 @@ + diff --git a/src/app/nav/nav.component.scss b/src/app/nav/nav.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/nav/nav.component.spec.ts b/src/app/nav/nav.component.spec.ts new file mode 100644 index 0000000..c386910 --- /dev/null +++ b/src/app/nav/nav.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NavComponent } from './nav.component'; + +describe('NavComponent', () => { + let component: NavComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ NavComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(NavComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/nav/nav.component.ts b/src/app/nav/nav.component.ts new file mode 100644 index 0000000..8fcdd84 --- /dev/null +++ b/src/app/nav/nav.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-nav', + templateUrl: './nav.component.html', + styleUrls: ['./nav.component.scss'] +}) +export class NavComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/search.service.ts b/src/app/search.service.ts index 5186a95..914bbfd 100644 --- a/src/app/search.service.ts +++ b/src/app/search.service.ts @@ -1,30 +1,64 @@ import {Injectable} from '@angular/core'; -import {Observable, of} from "rxjs"; +import {forkJoin, merge, Observable, of} from "rxjs"; import {HttpClient} from "@angular/common/http"; -import {debounceTime, distinctUntilChanged, switchMap} from "rxjs/operators"; +import {debounceTime, distinctUntilChanged, switchMap, tap} from "rxjs/operators"; +import {ArtistSearch, DiscSearch, RecordingSearch} from "./models/brainz"; @Injectable({ providedIn: 'root' }) export class SearchService { - baseUrl: string = 'https://api.cdnjs.com/libraries'; - queryUrl: string = '?search='; + baseUrl: string = 'http://localhost:8000/api/brainz'; constructor(private http: HttpClient) { } - search(terms: Observable): Observable { + searchArtist(terms: Observable): Observable { return terms.pipe( debounceTime(400), distinctUntilChanged(), - switchMap(term => this.searchEntries(term)) + switchMap(term => this.searchArtistQuery(term)) ); } - private searchEntries(term: string) { - if(!term){ - return of({results: []}); - } - return this.http.get(this.baseUrl + this.queryUrl + term); + searchDisc(terms: Observable): Observable { + return terms.pipe( + debounceTime(400), + distinctUntilChanged(), + switchMap(term => this.searchDiscQuery(term)) + ); } + + searchRecording(terms: Observable): Observable { + return terms.pipe( + debounceTime(400), + distinctUntilChanged(), + switchMap(term => this.searchRecordingQuery(term)) + ); + } + + private searchArtistQuery(term: string): Observable { + if (!term) { + return of({paginate: {total: 0, current_page: 0, last_page: 0, per_page: 0}, artists: []} as ArtistSearch); + } + + return this.http.get(`${this.baseUrl}/artist?query=${term}`); + } + + private searchDiscQuery(term: string): Observable { + if (!term) { + return of({paginate: {total: 0, current_page: 0, last_page: 0, per_page: 0}, discs: []} as DiscSearch); + } + + return this.http.get(`${this.baseUrl}/disc?query=${term}`); + } + + private searchRecordingQuery(term: string): Observable { + if (!term) { + return of({paginate: {total: 0, current_page: 0, last_page: 0, per_page: 0}, recordings: []} as RecordingSearch); + } + + return this.http.get(`${this.baseUrl}/recording?query=${term}`); + } + } diff --git a/src/app/search/search.component.html b/src/app/search/search.component.html deleted file mode 100644 index d26aaa4..0000000 --- a/src/app/search/search.component.html +++ /dev/null @@ -1,14 +0,0 @@ -
-
- -
-
- -
-
- -
    -
  • - {{ result.name }} -
  • -
diff --git a/src/app/search/search.component.scss b/src/app/search/search.component.scss deleted file mode 100644 index 52cb9b9..0000000 --- a/src/app/search/search.component.scss +++ /dev/null @@ -1,30 +0,0 @@ -@import "~bulma"; -.field:not(:last-child){ - margin-bottom: 0; -} -.autocomplete { - position: absolute; - z-index: 2; - margin-top: 1em; - width: 40ch; - max-height: 30ch; - overflow-y: auto; - background-color: $body-background-color; - color: $text; - border: 1px solid $border; -} - -.autocomplete li { - padding-top: 1em; - padding-bottom: 1em; - padding-left: 1em; -} - -.autocomplete li:not(:last-child) { - border-bottom: 1px solid $border; -} - -.autocomplete li:hover { - background-color: $warning; -} - diff --git a/src/app/search/search.component.ts b/src/app/search/search.component.ts deleted file mode 100644 index e42c641..0000000 --- a/src/app/search/search.component.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import {Subject} from "rxjs"; -import {SearchService} from "../search.service"; - -@Component({ - selector: 'app-search', - templateUrl: './search.component.html', - styleUrls: ['./search.component.scss'] -}) -export class SearchComponent implements OnInit { - results: Object[] = []; - searchTerm$ = new Subject(); - isFocused: boolean = false; - - constructor(private searchService: SearchService) { - this.searchService.search(this.searchTerm$).subscribe(results => this.results = results.results); - } - - setFocus(status: boolean): void { - this.isFocused = status; - } - - ngOnInit(): void { - } - -}