This commit is contained in:
Edouard DUPIN 2022-08-08 01:09:54 +02:00
parent e92b6c7651
commit 7a24b688c0
31 changed files with 676 additions and 196 deletions

View File

@ -69,8 +69,8 @@ public class Front {
// use this if I want to download the file:
//response.header("Content-Disposition", "attachment; filename=" + fileName);
CacheControl cc = new CacheControl();
cc.setMaxAge(60);
cc.setNoCache(false);
cc.setMaxAge(1);
cc.setNoCache(true);
response.cacheControl(cc);
response.type(mineType);

View File

@ -23,6 +23,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
@Path("/track")
@ -228,7 +229,8 @@ public class TrackResource {
trackElem.dataId = data.id;
// Now list of artis has an internal management:
if (artistElem != null) {
trackElem.artists = List.of(artistElem.id);
trackElem.artists = new ArrayList<>();
trackElem.artists.add(artistElem.id);
}
trackElem = SqlWrapper.insert(trackElem);
/*

View File

@ -8,8 +8,8 @@ import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; // CLI imports router
import { SsoScene } from 'common/scene';
import { HelpScene, HomeScene, AlbumEditScene, AlbumScene, ArtistEditScene, ArtistScene, SettingsScene,
GenderScene, PlaylistScene, TrackEditScene, TrackScene, UploadScene, ArtistsScene, ArtistAlbumScene } from './scene';
import { HelpScene, HomeScene, AlbumEditScene, AlbumsScene, ArtistEditScene, ArtistScene, SettingsScene,
GenderScene, PlaylistScene, TrackEditScene, TrackScene, UploadScene, ArtistsScene, ArtistAlbumScene, AlbumScene } from './scene';
// import { HelpComponent } from './help/help.component';
@ -64,10 +64,8 @@ const routes: Routes = [
// -- Album:
// ------------------------------------
// display all Album
{ path: 'album', component: AlbumScene },
// display all album for a specific artist
// display all album for a specific gender
{ path: 'album/:genderId/:artistId', component: AlbumScene },
{ path: 'album', component: AlbumsScene },
{ path: 'album/:albumId', component: AlbumScene },
{ path: 'album-edit/:albumId', component: AlbumEditScene },

View File

@ -23,7 +23,7 @@ import { PopInDeleteConfirm } from '../common/popin/delete-confirm/delete-confir
import { AppComponent } from './app.component';
import { ErrorComponent } from '../common/error/error';
import { HomeScene, HelpScene, GenderScene, PlaylistScene, ArtistScene, AlbumScene, TrackScene, SettingsScene,
import { HomeScene, HelpScene, GenderScene, PlaylistScene, ArtistScene, AlbumScene, AlbumsScene, TrackScene, SettingsScene,
TrackEditScene, AlbumEditScene, ArtistEditScene, ArtistsScene, ArtistAlbumScene } from './scene';
import { GenderService, DataService, PlaylistService, ArtistService, AlbumService, TrackService, ArianeService, PlayerService } from './service';
import { BddService, CookiesService, HttpWrapperService, PopInService, SessionService, SSOService, StorageService, UserService } from 'common/service';
@ -60,6 +60,7 @@ import { ElementSeriesComponent, ElementTrackComponent, ElementSeasonComponent,
ArtistsScene,
ArtistScene,
AlbumScene,
AlbumsScene,
TrackScene,
SettingsScene,
TrackEditScene,

View File

@ -16,9 +16,6 @@
</video>
</div>
<div class="controls">
<button (click)="onPlay()" *ngIf="!isPlaying" ><i class="material-icons">play_arrow</i></button>
<button (click)="onPause()" *ngIf="isPlaying" ><i class="material-icons">pause</i></button>
<button (click)="onStop()" ><i class="material-icons">stop</i></button>
<div class="timer">
<div>
<input type="range" min="0" class="slider"
@ -27,9 +24,12 @@
(input)="seek($event.target)">
</div>
<div class="timer-text">
<label class="unselectable">{{currentTimeDisplay}} / {{durationDisplay}}</label>
</div>
<label class="unselectable label">{{currentTimeDisplay}} / {{durationDisplay}}</label>
</div>
<div class="timer-control">
<button (click)="onPlay()" *ngIf="!isPlaying" ><i class="material-icons">play_arrow</i></button>
<button (click)="onPause()" *ngIf="isPlaying" ><i class="material-icons">pause</i></button>
<button (click)="onStop()" ><i class="material-icons">stop</i></button>
<button [disabled]="havePrevious" (click)="onBefore()"><i class="material-icons">navigate_before</i></button>
<button (click)="onRewind()"><i class="material-icons">fast_rewind</i></button>
<button (click)="onForward()"><i class="material-icons">fast_forward</i></button>
@ -39,6 +39,8 @@
<!--<button (click)="onTakeScreenShoot()"><i class="material-icons">add_a_photo</i></button>-->
<button (click)="onVolumeMenu()" ><i class="material-icons">volume_up</i></button>
</div>
</div>
</div>
<div class="volume" *ngIf="volume_displayMenu">
<div class="volume-menu">

View File

@ -28,7 +28,7 @@
//visibility: hidden;
opacity: 0.5;
width: 96%;
height: 60px;
height: 150px;
border-radius: 10px;
position: absolute;
bottom: 20px;
@ -121,7 +121,7 @@
.slider {
position: relative;
-webkit-appearance: none;
width: 98%;
width: 100%;
height: 10px;
top: 5px;
border-radius: 5px;
@ -149,14 +149,32 @@
background: #4CAF50;
cursor: pointer;
}
.timer-text {
position: absolute;
top: 25px;
//top: 25px;
left: 30px;
width: 100%;
//line-height: 38px;
font-size: 20px;
font-weight:bold;
}
.timer-control {
position: absolute;
//top: 25px;
left: 0px;
width: 100%;
line-height: 38px;
//line-height: 38px;
font-size: 30px;
font-weight:bold;
bottom: 20px;
}
.label {
//transform: translate(-12px,-12px);
vertical-align: text-top;
line-height: 18px;
min-width: 50%;
//display: block,
}
}
/*

View File

@ -11,9 +11,31 @@
<div class="season-small">
{{prefixName}} {{numberAlbum}}
</div>
<div class="description-small" *ngIf="count > 1">
{{count}} Episodes
<div class="description-small" *ngIf="countSubType && (!count || count == 0)">
No {{countSubType}}
</div>
<div class="description-small" *ngIf="count == 1">
{{count}} Episode
<div class="description-small" *ngIf="countSubType && count > 1">
{{count}} {{countSubType}}s
</div>
<div class="description-small" *ngIf="countSubType && count == 1">
{{count}} {{countSubType}}
</div>
<div class="description-small" *ngIf="countSubType2 && (!count2 || count2 == 0)">
No {{countSubType2}}
</div>
<div class="description-small" *ngIf="countSubType2 && count2 > 1">
{{count2}} {{countSubType2}}s
</div>
<div class="description-small" *ngIf="countSubType2 && count2 == 1">
{{count2}} {{countSubType2}}
</div>
<div class="description-small" *ngIf="subValueData">
{{subValues}}: {{subValueData}}
</div>
<div class="description-small" *ngIf="!description">
{{description}}
</div>

View File

@ -18,10 +18,18 @@ export class ElementSeasonComponent implements OnInit {
// input parameters
@Input() element:NodeData;
@Input() prefix:String;
@Input() countSubTypeCallBack: (arg0: number) => Promise<number>;
@Input() countSubType: String;
@Input() countSubType2CallBack: (arg0: number) => Promise<number>;
@Input() countSubType2: String;
@Input() subValuesCallBack: (arg0: number) => Promise<string[]>;
@Input() subValues: String;
prefixName: string = "";
numberAlbum: string;
count: number;
count2: number;
subValueData: String;
covers: string[];
description: string;
@ -32,6 +40,9 @@ export class ElementSeasonComponent implements OnInit {
}
ngOnInit() {
this.prefix = this.prefixName??"";
this.count = undefined;
this.count2 = undefined;
if (isNullOrUndefined(this.element)) {
this.numberAlbum = undefined;
this.covers = undefined;
@ -41,11 +52,39 @@ export class ElementSeasonComponent implements OnInit {
this.description = this.element.description;
this.covers = this.dataService.getCoverListThumbnailUrl(this.element.covers);
let self = this;
this.albumService.countTrack(this.element.id)
if (!isNullOrUndefined(this.countSubTypeCallBack)) {
this.countSubTypeCallBack(this.element.id)
.then((response) => {
self.count = response;
//console.log(`get values: ${this.element.id} ==> ${self.count}`)
}).catch((response) => {
self.count = null;
self.count = undefined;
});
}
if (!isNullOrUndefined(this.countSubType2CallBack)) {
this.countSubType2CallBack(this.element.id)
.then((response) => {
self.count2 = response;
//console.log(`get values: ${this.element.id} ==> ${self.count}`)
}).catch((response) => {
self.count2 = undefined;
});
}
if (!isNullOrUndefined(this.subValuesCallBack)) {
//console.log(`Value call back define ==> call values`)
this.subValuesCallBack(this.element.id)
.then((response: string[]) => {
this.subValueData = "";
for (let kkk=0; kkk<response.length; kkk++) {
if (kkk != 0) {
this.subValueData += ", ";
}
this.subValueData += response[kkk];
}
console.log(`get values: ${this.element.id} ==> ${self.subValueData}`)
}).catch((response) => {
self.count2 = undefined;
});
}
}
}

View File

@ -1,11 +1,8 @@
<div class="item-list-element">
<div class="season-small">
{{prefixName}} {{numberAlbum}}
{{name}}
</div>
<div class="description-small" *ngIf="count > 1">
{{count}} Episodes
</div>
<div class="description-small" *ngIf="count == 1">
{{count}} Episode
<div class="description-small" *ngIf="track">
n° {{track}}
</div>
</div>

View File

@ -20,8 +20,8 @@ export class ElementTrackComponent implements OnInit {
@Input() prefix:String;
prefixName: string = "";
numberAlbum: string;
count: number;
name: string;
track: number;
covers: string[];
description: string;
@ -33,19 +33,14 @@ export class ElementTrackComponent implements OnInit {
ngOnInit() {
this.prefix = this.prefixName??"";
if (isNullOrUndefined(this.element)) {
this.numberAlbum = undefined;
this.name = undefined;
this.covers = undefined;
this.description = undefined;
}
this.numberAlbum = this.element.name;
this.name = this.element.name;
this.description = this.element.description;
this.track = this.element["track"];
this.covers = this.dataService.getCoverListThumbnailUrl(this.element.covers);
let self = this;
this.albumService.countTrack(this.element.id)
.then((response) => {
self.count = response;
}).catch((response) => {
self.count = null;
});
}
}

View File

@ -1,29 +1,40 @@
<div class="generic-page">
<div class="fill-title colomn_mutiple">
<div class="cover-area">
<div class="cover" *ngIf="cover != null" >
<img src="{{cover}}"/>
<div class="cover" *ngIf="covers" >
<img src="{{covers[0]}}"/>
</div>
</div>
<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
<div *ngIf="artistName" class="title">
{{artistName}}
<div [className]="covers ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
<div class="title">
{{name}}
</div>
<div class="sub-title-main">
Album {{name}}
<div class="title">
{{albumName}}
</div>
<div class="description" *ngIf="description">
{{description}}
<div class="description" *ngIf="albumDescription">
{{albumDescription}}
</div>
<div class="description" *ngIf="albumDescription">
{{albumDescription}}
</div>
<button class="button color-button color-shadow-black" (click)="playAll($event)" type="submit">
<i class="material-icons">play_arrow</i> Play All
</button>
<button class="button color-button color-shadow-black" style="margin-left:10px;" (click)="playShuffe($event)" type="submit">
<i class="material-icons">shuffle</i> Shuffle
</button>
</div>
</div>
</div>
<div class="fill-content colomn_mutiple">
<div class="fill-content colomn_mutiple" *ngIf="tracks">
<div class="clear"></div>
<div class="title" *ngIf="tracks.length > 1">Tracks:</div>
<div class="title" *ngIf="tracks.length == 1">Track:</div>
<div *ngFor="let data of tracks" class="item item-track" (click)="onSelectTrack($event, data.id)" (auxclick)="onSelectTrack($event, data.id)">
<app-element-track [element]="data"></app-element-track>
</div>
<div class="clear"></div>
<app-element-track
*ngFor="let data of tracks"
[element]="data"
(click)="onSelectTrack($event, data.id)"
(auxclick)="onSelectTrack($event, data.id)"></app-element-track>
</div>
<div class="clear-end"></div>
</div>

View File

@ -1 +0,0 @@

View File

@ -4,86 +4,122 @@
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Media } from 'app/model';
import { AlbumModel, isAlbumModel } from 'app/model/album';
import { AlbumService, DataService, ArtistService, ArianeService } from 'app/service';
import { ArtistService, DataService, ArianeService, AlbumService, TrackService, PlayerService } from 'app/service';
import { NodeData } from 'common/model';
@Component({
@Component({
selector: 'app-album',
templateUrl: './album.html',
styleUrls: [ './album.less' ]
})
export class AlbumScene implements OnInit {
name: string = '';
artistName: string = '';
description: string = '';
artistId: number = null;
cover: string = '';
covers: Array<string> = [];
idAlbum = -1;
tracksError = '';
tracks = [];
templateUrl: './album.html'
})
export class AlbumScene implements OnInit {
public idArtist = -1;
public idAlbum = -1;
public name: string = '';
public description: string = undefined;
public covers: Array<string> = undefined;
public albumName: string = '';
public albumDescription: string = undefined;
public albumCovers: string[] = undefined;
public tracksIds: number[] = undefined;
public tracks: Media[] = undefined;
constructor(
private route: ActivatedRoute,
private albumService: AlbumService,
private artistService: ArtistService,
private albumService: AlbumService,
private trackService: TrackService,
private arianeService: ArianeService,
private playerService: PlayerService,
private dataService: DataService) {
}
ngOnInit() {
console.log('ngOnInit(AlbumComponent)');
this.arianeService.updateManual(this.route.snapshot.paramMap);
// this.idPlaylist = parseInt(this.route.snapshot.paramMap.get('universId'));
// this.idType = parseInt(this.route.snapshot.paramMap.get('typeId'));
this.idArtist = this.arianeService.getArtistId();
this.idAlbum = this.arianeService.getAlbumId();
let self = this;
this.albumService.get(this.idAlbum)
.then((response:any) => {
console.log("Get element ! " + JSON.stringify(response));
this.artistService.get(this.idArtist)
.then((response) => {
self.name = response.name;
self.artistId = response.parentId;
self.description = response.description;
if(response.covers === undefined || response.covers === null || response.covers.length === 0) {
self.cover = null;
self.covers = [];
} else {
self.cover = self.dataService.getCoverUrl(response.covers[0]);
for(let iii = 0; iii < response.covers.length; iii++) {
self.covers.push(self.dataService.getCoverUrl(response.covers[iii]));
}
}
self.artistService.get(self.artistId)
.then((response2:any) => {
self.artistName = response2.name;
}).catch((response2:any) => {
self.artistName = '';
});
}).catch((response3:any) => {
self.description = '';
self.covers = this.dataService.getCoverListUrl(response.covers);
}).catch((response) => {
self.description = undefined;
self.name = '???';
self.artistName = '';
self.artistId = null;
self.cover = null;
self.covers = [];
self.covers = undefined;
// no check just ==> an error occured on album
});
console.log(`get parameter id: ${ this.idAlbum}`);
this.albumService.getTrack(this.idAlbum)
.then((response4:any) => {
self.tracksError = '';
self.tracks = response4;
}).catch((response5:any) => {
self.tracksError = 'Can not get the List of track without album';
self.tracks = [];
this.albumService.get(this.idAlbum)
.then((response) => {
self.albumName = response.name;
self.albumDescription = response.description;
self.albumCovers = this.dataService.getCoverListUrl(response.covers);
}).catch((response) => {
self.albumDescription = undefined;
self.albumName = '???';
self.albumCovers = undefined;
// no check just ==> an error occured on album
});
//console.log("all the tracks: " + self.tracksIds);
this.trackService.getWithAlbum(self.idAlbum)
.then((response2: Media[]) => {
self.tracks = response2;
console.log(`>>>>BBB get tracks : ${JSON.stringify(response2, null, 2)}`);
}).catch((response) => {
//console.log(`>>>>BBB plop`);
self.tracks = undefined;
});
}
onSelectTrack(event: any, idSelected: number):void {
if (event.ctrlKey === false) {
this.arianeService.navigateTrack({ trackId: idSelected, newWindows:event.which === 2} );
//this.arianeService.navigateTrack({trackId: idSelected, newWindows:event.which === 2} );
// TODO: add on global player ...
//this.playerService.play(idSelected);
let elements: number[] = [];
let valuePlayed: number = undefined;
for (let iii=0; iii< this.tracks.length; iii++) {
elements.push(this.tracks[iii].id);
console.log(`plop: ${this.tracks[iii].id} == ${idSelected} ==> ${this.tracks[iii].name}`);
if (this.tracks[iii].id == idSelected) {
console.log(` ==> find`);
valuePlayed = iii;
}
}
this.playerService.playInList(valuePlayed, elements);
} else {
this.arianeService.navigateTrackEdit({ id: idSelected, newWindows:event.which === 2} );
}
}
}
playAll(event: any):void {
let elements: number[] = [];
for (let iii=0; iii< this.tracks.length; iii++) {
elements.push(this.tracks[iii].id);
}
this.playerService.clear();
this.playerService.setNewPlaylist(elements);
}
playShuffe(event: any):void {
let elements: number[] = [];
for (let iii=0; iii< this.tracks.length; iii++) {
elements.push(this.tracks[iii].id);
}
this.playerService.clear();
this.playerService.setNewPlaylistShuffle(elements);
}
}

View File

@ -0,0 +1,42 @@
<div class="generic-page">
<div class="fill-title colomn_mutiple">
<div class="cover-area">
<div class="cover" *ngIf="covers" >
<img src="{{covers[0]}}"/>
</div>
</div>
<div [className]="covers ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
<div class="title">
{{name}}
</div>
<div class="description" *ngIf="description">
{{description}}
</div>
</div>
</div>
<div class="fill-content colomn_mutiple" *ngIf="albums">
<div class="clear"></div>
<div class="title" *ngIf="albums.length > 1">Albums:</div>
<div class="title" *ngIf="albums.length == 1">Album:</div>
<div *ngFor="let data of albums" class="item-list" (click)="onSelectAlbum($event, data.id)" (auxclick)="onSelectAlbum($event, data.id)">
<app-element-season
[element]="data"
countSubType="Track"
[countSubTypeCallBack]="countTrack"
subValues="Artist"
[subValuesCallBack]="getArtistsString"
></app-element-season>
</div>
</div>
<div class="fill-content colomn_mutiple" *ngIf="tracks">
<div class="clear"></div>
<div class="title" *ngIf="tracks.length > 1">Tracks:</div>
<div class="title" *ngIf="tracks.length == 1">Track:</div>
<div *ngFor="let data of tracks" class="item item-video" (click)="onSelectTrack($event, data.id)" (auxclick)="onSelectTrack($event, data.id)">
<app-element-video
[element]="data"
></app-element-video>
</div>
</div>
<div class="clear-end"></div>
</div>

View File

@ -0,0 +1,93 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ArtistService, DataService, ArianeService, AlbumService } from 'app/service';
import { NodeData } from 'common/model';
import { isNullOrUndefined } from 'common/utils';
@Component({
selector: 'app-albums',
templateUrl: './albums.html'
})
export class AlbumsScene implements OnInit {
public name: string = '';
public description: string = undefined;
public covers: string[] = undefined;
public albums: NodeData[] = undefined;
public tracks: any[] = undefined;
public countSubElement: number = undefined;
countTrack: (id: number) => Promise<Number>;
getArtistsString: (id: number) => Promise<String[]>;
constructor(
private route: ActivatedRoute,
private albumService: AlbumService,
private artistService: ArtistService,
private arianeService: ArianeService,
private dataService: DataService) {
}
countTrackCallback(albumId: number) : Promise<Number> {
return this.albumService.countTrack(albumId);
}
getArtistsStringCallback(albumId: number) : Promise<String[]> {
console.log(`request all artist for album: {albumId}`)
return this.albumService.getArtists(albumId);
}
ngOnInit() {
this.getArtistsString = (id:number) => {return self.getArtistsStringCallback(id);};
this.countTrack = (id:number) => {return self.countTrackCallback(id);};
this.arianeService.updateManual(this.route.snapshot.paramMap);
let self = this;
self.name = "All Albums";
self.description = "View all albums (no specific artist)";
//console.log(`get parameter id: ${ this.idArtist}`);
this.albumService.getOrder()
.then((response: NodeData[]) => {
//console.log(`>>>> get album : ${JSON.stringify(response)}`)
self.albums = response;
}).catch((response) => {
self.albums = undefined;
});
// TODO later: get all orfan tracks ...
/*
this.artistService.getTrack(this.idArtist)
.then((response: NodeData[]) => {
//console.log(`>>>> get track : ${JSON.stringify(response)}`)
self.tracks = response;
}).catch((response) => {
self.tracks = undefined;
});
*/
}
onSelectAlbum(event: any, idSelected: number):void {
if (event.ctrlKey) {
this.arianeService.navigateAlbumEdit({ id: idSelected, newWindows: event.which === 2 } );
} else {
this.arianeService.navigateAlbum({albumId: idSelected, newWindows: event.which === 2 } );
}
}
onSelectTrack(event: any, idSelected: number):void {
if (event.ctrlKey) {
this.arianeService.navigateTrackEdit({ id: idSelected, newWindows:event.which === 2} );
} else {
this.arianeService.navigateTrack({trackId: idSelected, newWindows:event.which === 2} );
}
}
}

View File

@ -122,7 +122,7 @@ export class ArtistEditScene implements OnInit {
}).catch((response) => {
self.albumsCount = '---';
});
this.artistService.getTrack(this.idArtist)
this.artistService.getAllTracks(this.idArtist)
.then((response) => {
self.trackCount = "" + response.length;
}).catch((response) => {

View File

@ -15,6 +15,12 @@
<div class="description" *ngIf="albumDescription">
{{albumDescription}}
</div>
<button class="button color-button color-shadow-black" (click)="playAll($event)" type="submit">
<i class="material-icons">play_arrow</i> Play All
</button>
<button class="button color-button color-shadow-black" style="margin-left:10px;" (click)="playShuffe($event)" type="submit">
<i class="material-icons">shuffle</i> Shuffle
</button>
</div>
</div>
<div class="fill-content colomn_mutiple" *ngIf="tracks">
@ -27,5 +33,5 @@
(click)="onSelectTrack($event, data.id)"
(auxclick)="onSelectTrack($event, data.id)"></app-element-track>
</div>
<div class="clear"></div>
<div class="clear-end"></div>
</div>

View File

@ -104,5 +104,20 @@ export class ArtistAlbumScene implements OnInit {
this.arianeService.navigateTrackEdit({ id: idSelected, newWindows:event.which === 2} );
}
}
playAll(event: any):void {
let elements: number[] = [];
for (let iii=0; iii< this.tracks.length; iii++) {
elements.push(this.tracks[iii].id);
}
this.playerService.clear();
this.playerService.setNewPlaylist(elements);
}
playShuffe(event: any):void {
let elements: number[] = [];
for (let iii=0; iii< this.tracks.length; iii++) {
elements.push(this.tracks[iii].id);
}
this.playerService.clear();
this.playerService.setNewPlaylistShuffle(elements);
}
}

View File

@ -12,6 +12,12 @@
<div class="description" *ngIf="description">
{{description}}
</div>
<button class="button color-button color-shadow-black" (click)="playAll($event)" type="submit">
<i class="material-icons">play_arrow</i> Play All
</button>
<button class="button color-button color-shadow-black" style="margin-left:10px;" (click)="playShuffe($event)" type="submit">
<i class="material-icons">shuffle</i> Shuffle
</button>
</div>
</div>
<div class="fill-content colomn_mutiple" *ngIf="albums">
@ -19,7 +25,11 @@
<div class="title" *ngIf="albums.length > 1">Albums:</div>
<div class="title" *ngIf="albums.length == 1">Album:</div>
<div *ngFor="let data of albums" class="item-list" (click)="onSelectAlbum($event, data.id)" (auxclick)="onSelectAlbum($event, data.id)">
<app-element-season [element]="data"></app-element-season>
<app-element-season
[element]="data"
countSubType="Track"
[countSubTypeCallBack]="countTrack"
></app-element-season>
</div>
</div>
<div class="fill-content colomn_mutiple" *ngIf="tracks">
@ -27,8 +37,10 @@
<div class="title" *ngIf="tracks.length > 1">Tracks:</div>
<div class="title" *ngIf="tracks.length == 1">Track:</div>
<div *ngFor="let data of tracks" class="item item-video" (click)="onSelectTrack($event, data.id)" (auxclick)="onSelectTrack($event, data.id)">
<app-element-video [element]="data"></app-element-video>
<app-element-video
[element]="data"
></app-element-video>
</div>
</div>
<div class="clear"></div>
<div class="clear-end"></div>
</div>

View File

@ -7,7 +7,7 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ArtistService, DataService, ArianeService } from 'app/service';
import { ArtistService, DataService, ArianeService, AlbumService, PlayerService } from 'app/service';
import { NodeData } from 'common/model';
import { isNullOrUndefined } from 'common/utils';
@ -23,16 +23,25 @@ export class ArtistScene implements OnInit {
public covers: string[] = undefined;
public albums: NodeData[] = undefined;
public tracks: any[] = undefined;
public countSubElement: number = undefined;
countTrack: (id: number) => Promise<Number>;
constructor(
private route: ActivatedRoute,
private albumService: AlbumService,
private artistService: ArtistService,
private playerService: PlayerService,
private arianeService: ArianeService,
private dataService: DataService) {
}
countTrackCallback(albumId: number) : Promise<Number> {
return this.albumService.countTrack(albumId);
}
ngOnInit() {
this.countTrack = (id:number) => {return self.countTrackCallback(id);};
this.arianeService.updateManual(this.route.snapshot.paramMap);
// this.idPlaylist = parseInt(this.route.snapshot.paramMap.get('universId'));
// this.idType = parseInt(this.route.snapshot.paramMap.get('typeId'));
@ -68,6 +77,9 @@ export class ArtistScene implements OnInit {
});
*/
}
onSelectAlbum(event: any, idSelected: number):void {
if (event.ctrlKey) {
this.arianeService.navigateAlbumEdit({ id: idSelected, newWindows: event.which === 2 } );
@ -83,5 +95,36 @@ export class ArtistScene implements OnInit {
this.arianeService.navigateTrackEdit({ id: idSelected, newWindows:event.which === 2} );
}
}
getAllTracksIds(): Promise<number[]> {
let elements: number[] = [];
for (let iii=0; iii< this.albums.length; iii++) {
elements.push(this.albums[iii].id);
}
return this.albumService.getAllTracksForAlbums(elements);
}
playAll(event: any):void {
this.playerService.clear();
let self = this;
this.getAllTracksIds()
.then((response: number[]) => {
self.playerService.setNewPlaylist(response);
})
.catch(() => {
console.log(`error to get list o ftrack ...`)
});
}
playShuffe(event: any):void {
this.playerService.clear();
let self = this;
this.getAllTracksIds()
.then((response: number[]) => {
self.playerService.setNewPlaylistShuffle(response);
})
.catch(() => {
console.log(`error to get list o ftrack ...`)
});
}
}

View File

@ -1,11 +1,17 @@
<div class="generic-page">
<div class="fill-content colomn_mutiple" *ngIf="artists">
<div class="clear"></div>
<div class="title" *ngIf="artists.length > 1">Artits:</div>
<div class="title" *ngIf="artists.length > 1">Artists:</div>
<div class="title" *ngIf="artists.length == 1">Artist:</div>
<div *ngFor="let data of artists" class="item-list" (click)="onSelectAlbum($event, data.id)" (auxclick)="onSelectArtist($event, data.id)">
<app-element-season [element]="data"></app-element-season>
<app-element-season
[element]="data"
countSubType="Album"
[countSubTypeCallBack]="countAlbum"
countSubType2="Track"
[countSubType2CallBack]="countTrack"
></app-element-season>
</div>
</div>
<div class="clear"></div>
<div class="clear-end"></div>
</div>

View File

@ -7,7 +7,7 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ArtistService, DataService, ArianeService } from 'app/service';
import { ArtistService, DataService, ArianeService, AlbumService } from 'app/service';
import { NodeData } from 'common/model';
import { isNullOrUndefined } from 'common/utils';
@ -20,19 +20,24 @@ export class ArtistsScene implements OnInit {
cover: string = '';
covers: Array<string> = [];
artists: NodeData[];
countTrack: (id: number) => Promise<Number>;
countAlbum: (id: number) => Promise<Number>;
constructor(
private route: ActivatedRoute,
private artistService: ArtistService,
private albumService: AlbumService,
private arianeService: ArianeService) {
}
ngOnInit() {
let self = this;
this.countTrack = (id:number) => {return self.countTrackCallback(id);};
this.countAlbum = (id:number) => {return self.countAlbumCallback(id);};
this.arianeService.updateManual(this.route.snapshot.paramMap);
// this.idPlaylist = parseInt(this.route.snapshot.paramMap.get('universId'));
// this.idType = parseInt(this.route.snapshot.paramMap.get('typeId'));
let self = this;
this.artistService.getOrder()
.then((response: NodeData[]) => {
self.artists = response;
@ -49,5 +54,11 @@ export class ArtistsScene implements OnInit {
}
}
countTrackCallback(artistId: number) : Promise<Number> {
return this.artistService.countTrack(artistId);
}
countAlbumCallback(artistId: number) : Promise<Number> {
return this.artistService.countAlbum(artistId);
}
}

View File

@ -3,6 +3,7 @@ import { HelpScene } from "./help/help";
import { HomeScene } from "./home/home";
import { AlbumEditScene } from "./album-edit/album-edit";
import { AlbumScene } from "./album/album";
import { AlbumsScene } from "./album/albums";
import { ArtistEditScene } from "./artist-edit/artist-edit";
import { ArtistScene } from "./artist/artist";
import { ArtistsScene } from "./artist/artists";
@ -19,6 +20,7 @@ export {
HomeScene,
SettingsScene,
AlbumScene,
AlbumsScene,
AlbumEditScene,
ArtistsScene,
ArtistScene,

View File

@ -521,7 +521,7 @@ export class UploadScene implements OnInit {
// no album check only the artist files.
if(isNullOrUndefined(this.globalAlbum)) {
console.error(`NO ALBUM ==> check artist ID...`);
self.artistService.getTrack(self.artistId)
self.artistService.getAllTracks(self.artistId)
.then((response: any[]) => {
self.listFileInBdd = response;
console.error(`find track: ${JSON.stringify(response, null, 2)}`);

View File

@ -19,7 +19,28 @@ export class AlbumService extends GenericInterfaceModelDB {
bdd: BddService) {
super('album', http, bdd);
}
getAllTracksForAlbums(idAlbums: number[]): Promise<number[]> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get('track')
.then((response: DataInterface) => {
let data = response.getsWhere([
{
check: TypeCheck.EQUAL,
key: 'albumId',
value: idAlbums,
},
],
[ 'name' ]); // tODO : set the Id in the track ...
// filter with artist- ID !!!
const listId = DataInterface.extractLimitOne(data, "id");
resolve(listId);
}).catch((response) => {
reject(response);
});
});
}
/**
* Get all the track for a specific album
* @param idAlbum - Id of the album.
@ -44,13 +65,12 @@ export class AlbumService extends GenericInterfaceModelDB {
});
});
}
/**
* Get the number of track in this saison ID
* @param id - Id of the album.
* @returns The number of element present in this saison
* Get all the artists for a specific album
* @param idAlbum - Id of the album.
* @returns a promise on the list of Artist names for this album
*/
countTrack(id:number): Promise<number> {
getArtists(idAlbum:number): Promise<String[]> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get('track')
@ -59,7 +79,49 @@ export class AlbumService extends GenericInterfaceModelDB {
{
check: TypeCheck.EQUAL,
key: 'albumId',
value: id,
value: idAlbum,
},
],
[ 'name' ]);
// filter with artist- ID !!!
const listArtistId = DataInterface.extractLimitOneList(data, "artists");
//console.log(`${idAlbum} ==> List Of ids: ${JSON.stringify(listArtistId, null, 2)} `);
self.bdd.get('artist')
.then((response:DataInterface) => {
let dataArtist = response.getsWhere([
{
check: TypeCheck.EQUAL,
key: 'id',
value: listArtistId,
},
], [ 'name']);
const listArtistNames = DataInterface.extractLimitOne(dataArtist, "name");
resolve(listArtistNames);
return;
}).catch((response) => {
reject(response);
});
}).catch((response) => {
reject(response);
});
});
}
/**
* Get the number of track in this saison ID
* @param AlbumId - Id of the album.
* @returns The number of element present in this saison
*/
countTrack(AlbumId:number): Promise<number> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get('track')
.then((response: DataInterface) => {
let data = response.getsWhere([
{
check: TypeCheck.EQUAL,
key: 'albumId',
value: AlbumId,
},
]);
resolve(data.length);

View File

@ -370,8 +370,8 @@ export class ArianeService {
this.genericNavigateEdit('gender', id, newWindows);
}
navigateAlbum({ genderId, artistId, newWindows }: { genderId?: number; artistId?: number; newWindows?: boolean; }):void {
this.genericNavigate('album', [ genderId, artistId ], newWindows);
navigateAlbum({ albumId, newWindows }: { albumId?: number; newWindows?: boolean; }):void {
this.genericNavigate('album', [ albumId ], newWindows);
}
navigateAlbumEdit({ id, newWindows }: { id: number; newWindows?: boolean; }):void {
this.genericNavigateEdit('album', id, newWindows);

View File

@ -27,15 +27,15 @@ export class ArtistService extends GenericInterfaceModelDB {
* @param idArtist - Id of the artist.
* @returns a promise on the list of track elements
*/
getTrack(idArtist:number): Promise<NodeData[]> {
getTrackNoAlbum(idArtist:number): Promise<NodeData[]> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get('track')
.then((response: DataInterface) => {
let data = response.getsWhere([
{
check: TypeCheck.EQUAL,
key: 'artistId',
check: TypeCheck.CONTAINS,
key: 'artists',
value: idArtist,
}, {
check: TypeCheck.EQUAL,
@ -43,7 +43,31 @@ export class ArtistService extends GenericInterfaceModelDB {
value: undefined,
},
],
[ 'episode', 'name' ]);
[ 'track', 'name' ]);
resolve(data);
}).catch((response) => {
reject(response);
});
});
}
/**
* Get all the track for a specific artist
* @param idArtist - Id of the artist.
* @returns a promise on the list of track elements
*/
getAllTracks(idArtist:number): Promise<NodeData[]> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get('track')
.then((response: DataInterface) => {
let data = response.getsWhere([
{
check: TypeCheck.CONTAINS,
key: 'artists',
value: idArtist,
}
],
[ 'track', 'name' ]);
resolve(data);
}).catch((response) => {
reject(response);
@ -56,16 +80,16 @@ export class ArtistService extends GenericInterfaceModelDB {
* @param id - Id of the artist.
* @returns The number of track present in this artist
*/
countTrack(id:number): Promise<number> {
countTrack(artistId:number): Promise<number> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get('track')
.then((response:DataInterface) => {
let data = response.getsWhere([
{
check: TypeCheck.EQUAL,
key: 'artistId',
value: id,
check: TypeCheck.CONTAINS,
key: 'artists',
value: artistId,
},
]);
resolve(data.length);
@ -93,10 +117,10 @@ export class ArtistService extends GenericInterfaceModelDB {
value: idArtist,
},
], [ 'id' ]);
console.log("==> get all tracks of the artist: " + JSON.stringify(data, null, 2));
//console.log("==> get all tracks of the artist: " + JSON.stringify(data, null, 2));
// extract a single time all value "id" in an array
const listAlbumId = DataInterface.extractLimitOne(data, "albumId");
console.log("==> List Of ids: " + JSON.stringify(listAlbumId, null, 2));
//console.log("==> List Of ids: " + JSON.stringify(listAlbumId, null, 2));
self.bdd.get('album')
.then((response:DataInterface) => {
let dataAlbum = response.getsWhere([
@ -107,7 +131,7 @@ export class ArtistService extends GenericInterfaceModelDB {
},
], [ 'publication', 'name', 'id' ]);
resolve(dataAlbum);
console.log("==> get all albums: " + JSON.stringify(dataAlbum, null, 2));
//console.log("==> get all albums: " + JSON.stringify(dataAlbum, null, 2));
return;
}).catch((response) => {
reject(response);
@ -118,6 +142,28 @@ export class ArtistService extends GenericInterfaceModelDB {
});
});
}
countAlbum(idArtist:number): Promise<number> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get('track')
.then((response:DataInterface) => {
console.log(" <<<========================================>>> " + idArtist);
let data = response.getsWhere([
{
check: TypeCheck.CONTAINS, //< this is for array containing
key: 'artists',
value: idArtist,
},
], [ 'id' ]);
//console.log("==> get all tracks of the artist: " + JSON.stringify(data, null, 2));
// extract a single time all value "id" in an array
const listAlbumId = DataInterface.extractLimitOne(data, "albumId");
resolve(listAlbumId.length);
}).catch((response) => {
reject(response);
});
});
}
}

View File

@ -68,13 +68,13 @@ export class BddService {
get(name: string): Promise<DataInterface> {
let self = this;
console.log(`Try to get DB '${ name }'`);
//console.log(`Try to get DB '${ name }'`);
if( !isNullOrUndefined(this.bdd[name]) ) {
return new Promise((resolve, reject) => {
resolve(self.bdd[name]);
});
}
console.log(`get DB: ?? ${ name } ??`);
//console.log(`get DB: ?? ${ name } ??`);
if(isNullOrUndefined(this.bddPomise[name])) {
this.bddPomise[name] = [];
// Try to load Local Data (storage)
@ -83,31 +83,31 @@ export class BddService {
localStorage.getItem(this.baseLocalStorageName + name);
}
if(retriveBDDString !== null) {
console.log(`retrive local bdd string (${ name })= ${ retriveBDDString}`);
//console.log(`retrive local bdd string (${ name })= ${ retriveBDDString}`);
let retriveBDD = JSON.parse(retriveBDDString);
console.log(`retrive local bdd (${ name })= ${ retriveBDD}`);
//console.log(`retrive local bdd (${ name })= ${ retriveBDD}`);
let retriveBDDTmp = new DataInterface(name, retriveBDD);
self.bdd[name] = retriveBDDTmp;
for(let iii = 0; iii < self.bddPomise[name].length; iii++) {
self.bddPomise[name][iii].resolve(self.bdd[name]);
}
// brut force update of the BDD : TODO optimise it later ...
console.log(`Update BDD (${ name })`);
//console.log(`Update BDD (${ name })`);
self.http.getSpecific(name)
.then((response) => {
console.log(`end download DB: ==> ${ name } ${ response.length}`);
//console.log(`end download DB: ==> ${ name } ${ response.length}`);
self.bdd[name] = new DataInterface(name, response);
localStorage.setItem(self.baseLocalStorageName + name, JSON.stringify(self.bdd[name].bdd));
}).catch((response) => {
console.log(`[E] ${ self.constructor.name }: cant not get data from remote server: ${ name}`);
});
} else {
console.log(`Download BDD (${ name })`);
//console.log(`Download BDD (${ name })`);
return new Promise((resolve, reject) => {
self.http.getSpecific(name)
.then((response) => {
console.log(`end download DB: ==> ${ name } ${ response.length}`);// + " " + JSON.stringify(response).length);
//console.log(`end download DB: ==> ${ name } ${ response.length}`);// + " " + JSON.stringify(response).length);
self.bdd[name] = new DataInterface(name, response);
if(self.useLocalStorage === true) {
localStorage.setItem(self.baseLocalStorageName + name, JSON.stringify(self.bdd[name].bdd));

View File

@ -41,6 +41,17 @@ export class DataInterface {
}
return out;
}
static extractLimitOneList(data: NodeData[], key: string): any[] {
const out = [];
for (let iii=0; iii<data.length; iii++) {
const value = data[iii][key];
for (let jjj = 0; jjj < value.length; jjj++)
if(DataInterface.existIn(value[jjj], out) === false) {
out.push(value[jjj]);
}
}
return out;
}
constructor(
private name: string,
private bdd: NodeData[] ) {

View File

@ -50,5 +50,5 @@ export const environment_hybrid = {
frontBaseUrl: '',
apiMode: 'REWRITE'
};
export const environment = environment_local;
export const environment = environment_back_prod;

View File

@ -7,6 +7,12 @@
float: left;
width: 100%;
}
.clear-end {
display: block;
float: left;
width: 100%;
height: 250px;
}
.generic-page {
.fill-title {
display:block;
@ -282,6 +288,11 @@
text-align: center;
}
.clear-end {
clear: both;
text-align: center;
height: 250px;
}
.generic-page {
.fill-title {
display:block;