add comic artists
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
@@ -1,5 +1,4 @@
|
||||
import { Component, DestroyRef, inject, OnInit, signal } from '@angular/core';
|
||||
import { RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import { Artist } from '../comic-artists/artist.model';
|
||||
import { ComicArtistComponent } from '../comic-artist/comic-artist.component';
|
||||
import { ArtistService } from '../comic-artists/artist.service';
|
||||
|
||||
@@ -2,3 +2,9 @@ export interface Artist {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ArtistDetails {
|
||||
id: string;
|
||||
name: string;
|
||||
weblink: string;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { inject, Injectable, signal } from "@angular/core";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { catchError, map, throwError } from "rxjs";
|
||||
import { ErrorService } from "../../../shared/error.service";
|
||||
import { Artist } from "./artist.model";
|
||||
import { Artist, ArtistDetails } from "./artist.model";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -18,6 +18,10 @@ export class ArtistService {
|
||||
return this.fetchArtists('http://127.0.0.1:8800/api/comics/artists', 'Someting went wrong fetching artists. Please try again later-');
|
||||
}
|
||||
|
||||
loadArtistDetails(artistId: string | null) {
|
||||
return this.fetchArtistDetails('http://127.0.0.1:8800/api/comics/artists/' + artistId, 'Someting went wrong fetching comic artists. Please try again later.');
|
||||
}
|
||||
|
||||
private fetchArtists(url: string, errorMessage: string) {
|
||||
return this.httpClient.get<Artist[]>(url).pipe(
|
||||
map((resData) => resData),
|
||||
@@ -27,4 +31,17 @@ export class ArtistService {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private fetchArtistDetails(url: string, errorMessage: string) {
|
||||
return this.httpClient.get<ArtistDetails>(url).pipe(
|
||||
map((resData) => {
|
||||
console.log(resData);
|
||||
return resData;
|
||||
}),
|
||||
catchError((error) => {
|
||||
console.log(error);
|
||||
return throwError(() => new Error(errorMessage));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
<app-comic-artists-list />
|
||||
</div>
|
||||
<div>
|
||||
<h2>Artist Details</h2>
|
||||
@if (artist()) {
|
||||
<h2>{{ artist().name }}</h2>
|
||||
<a href="{{ artist().weblink }}">{{ artist().name }}</a>
|
||||
} @else {
|
||||
<h2>Artist Details</h2>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, inject, input } from '@angular/core';
|
||||
import { ComicArtistsListComponent } from '../comic-artists-list/comic-artists-list.component';
|
||||
import { ArtistDetails } from './artist.model';
|
||||
import { ActivatedRouteSnapshot, ResolveFn, RouterStateSnapshot } from '@angular/router';
|
||||
import { ArtistService } from './artist.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-comic-artists',
|
||||
@@ -8,5 +11,13 @@ import { ComicArtistsListComponent } from '../comic-artists-list/comic-artists-l
|
||||
styleUrl: './comic-artists.component.css'
|
||||
})
|
||||
export class ComicArtistsComponent {
|
||||
|
||||
artist = input.required<ArtistDetails>();
|
||||
}
|
||||
|
||||
export const artistResolver: ResolveFn<ArtistDetails> = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
||||
const artistService = inject(ArtistService);
|
||||
const artistId = route.paramMap.get('artistId');
|
||||
const artistDetails = artistService.loadArtistDetails(artistId);
|
||||
console.log(artistDetails);
|
||||
return artistDetails;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Routes } from "@angular/router";
|
||||
import { ComicArtistsComponent } from "../comic-artists/comic-artists.component";
|
||||
import { artistResolver, ComicArtistsComponent } from "../comic-artists/comic-artists.component";
|
||||
import { ComicPublishersComponent } from './../comic-publishers/comic-publishers.component';
|
||||
import { ComicComicsComponent, comicResolver } from "../comic-comics/comic-comics.component";
|
||||
|
||||
@@ -19,10 +19,10 @@ export const comicRoutes: Routes = [
|
||||
path: 'publisher',
|
||||
component: ComicPublishersComponent
|
||||
},
|
||||
// {
|
||||
// path: 'publishers/:publisherId',
|
||||
// component: PublishersComponent,
|
||||
// },
|
||||
{
|
||||
path: 'publishers/:publisherId',
|
||||
component: ComicPublishersComponent,
|
||||
},
|
||||
{
|
||||
path: 'artist',
|
||||
component: ComicArtistsComponent
|
||||
@@ -30,5 +30,8 @@ export const comicRoutes: Routes = [
|
||||
{
|
||||
path: 'artist/:artistId',
|
||||
component: ComicArtistsComponent,
|
||||
resolve: {
|
||||
artist: artistResolver
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<div>
|
||||
<article>
|
||||
<a [routerLink]="['/', 'media', 'file', mediafile().id]" routerLinkActive="active">
|
||||
<span>{{ mediafile().title }}</span>
|
||||
</a>
|
||||
<a href="{{ mediafile().url }}"> >></a>
|
||||
<p>
|
||||
<span>
|
||||
@if (mediafile().review) {
|
||||
Review<img class="images" src="tick.png" />
|
||||
} @else {
|
||||
Review<img class="images" src="cross.png" />
|
||||
}
|
||||
</span>
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MediaFileComponent } from './media-file.component';
|
||||
|
||||
describe('MediaFileComponent', () => {
|
||||
let component: MediaFileComponent;
|
||||
let fixture: ComponentFixture<MediaFileComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MediaFileComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MediaFileComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Component, input } from '@angular/core';
|
||||
import { MediaFile } from '../media-files/media-file.model';
|
||||
import { RouterLink, RouterLinkActive } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-media-file',
|
||||
imports: [RouterLink, RouterLinkActive],
|
||||
templateUrl: './media-file.component.html',
|
||||
styleUrl: './media-file.component.css'
|
||||
})
|
||||
export class MediaFileComponent {
|
||||
mediafile = input.required<MediaFile>();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
ul {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<ul>
|
||||
@for (mediafile of files(); track mediafile.id) {
|
||||
<li>
|
||||
<app-media-file [mediafile]="mediafile" />
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MediaFilesListComponent } from './media-files-list.component';
|
||||
|
||||
describe('MediaFilesListComponent', () => {
|
||||
let component: MediaFilesListComponent;
|
||||
let fixture: ComponentFixture<MediaFilesListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MediaFilesListComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MediaFilesListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Component, DestroyRef, inject, OnInit, signal } from '@angular/core';
|
||||
import { MediaFileComponent } from '../media-file/media-file.component';
|
||||
import { MediaFileService } from '../media-files/media-file.service';
|
||||
import { MediaFile } from '../media-files/media-file.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-media-files-list',
|
||||
imports: [MediaFileComponent],
|
||||
templateUrl: './media-files-list.component.html',
|
||||
styleUrl: './media-files-list.component.css'
|
||||
})
|
||||
export class MediaFilesListComponent implements OnInit {
|
||||
files = signal<MediaFile[]>([]);
|
||||
isFetching = signal(false);
|
||||
error = signal('');
|
||||
private mediaFileService = inject(MediaFileService);
|
||||
private destroyRef = inject(DestroyRef);
|
||||
|
||||
ngOnInit() {
|
||||
this.isFetching.set(true);
|
||||
const subscription = this.mediaFileService.loadFiles().subscribe({
|
||||
next: (files) => {
|
||||
this.files.set(files);
|
||||
},
|
||||
error: (error: Error) => {
|
||||
this.error.set(error.message);
|
||||
},
|
||||
complete: () => {
|
||||
this.isFetching.set(false);
|
||||
},
|
||||
});
|
||||
|
||||
this.destroyRef.onDestroy(() => {
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { StreamingResourceOptions } from "@angular/core";
|
||||
|
||||
export interface MediaFile {
|
||||
id: string;
|
||||
title: string;
|
||||
file_name: string;
|
||||
cloud_link: string;
|
||||
url: string;
|
||||
review: boolean;
|
||||
should_download: boolean;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { inject, Injectable, signal } from "@angular/core";
|
||||
import { ErrorService } from "../../../shared/error.service";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { MediaFile } from "./media-file.model";
|
||||
import { catchError, map, throwError } from "rxjs";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class MediaFileService {
|
||||
private errorService = inject(ErrorService);
|
||||
private httpClient = inject(HttpClient);
|
||||
private files = signal<MediaFile[]>([]);
|
||||
|
||||
loadedFiles = this.files.asReadonly();
|
||||
|
||||
loadFiles() {
|
||||
return this.fetchMediaFiles('http://127.0.0.1:8800/api/media/files', 'Someting went wrong fetching artists. Please try again later-');
|
||||
}
|
||||
|
||||
private fetchMediaFiles(url: string, errorMessage: string) {
|
||||
return this.httpClient.get<MediaFile[]>(url).pipe(
|
||||
map((resData) => resData),
|
||||
catchError((error) => {
|
||||
console.log(error);
|
||||
return throwError(() => new Error(errorMessage));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: 20px;
|
||||
}
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
<p>media-files works!</p>
|
||||
<div class="grid-container">
|
||||
<div>
|
||||
<app-media-files-list />
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MediaFilesListComponent } from '../media-files-list/media-files-list.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-media-files',
|
||||
imports: [],
|
||||
imports: [MediaFilesListComponent],
|
||||
templateUrl: './media-files.component.html',
|
||||
styleUrl: './media-files.component.css'
|
||||
})
|
||||
|
||||
@@ -8,12 +8,24 @@ export const mediaRoutes: Routes = [
|
||||
path: 'file',
|
||||
component: MediaFilesComponent
|
||||
},
|
||||
{
|
||||
path: 'file/:fileId',
|
||||
component: MediaFilesComponent,
|
||||
},
|
||||
{
|
||||
path: 'actor',
|
||||
component: MediaActorsComponent
|
||||
},
|
||||
{
|
||||
path: 'actor/:actorId',
|
||||
component: MediaActorsComponent,
|
||||
},
|
||||
{
|
||||
path: 'video',
|
||||
component: MediaVideosComponent
|
||||
},
|
||||
];
|
||||
{
|
||||
path: 'video/:videoId',
|
||||
component: MediaVideosComponent,
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user