real basic player ... must be upgrade really soon...

This commit is contained in:
Edouard DUPIN 2022-07-11 00:00:20 +02:00
parent 574197870e
commit 9eb301731e
63 changed files with 2379 additions and 489 deletions

View File

@ -143,6 +143,7 @@ public class SqlWrapper {
if (rs.wasNull()) {
field.set(data, null);
} else {
System.out.println(" ==> " + tmp);
field.set(data, tmp);
}
} else if (type == long.class ) {
@ -481,7 +482,108 @@ public class SqlWrapper {
ex.printStackTrace();
}
}
public static <T> T getWith(Class<T> clazz, String key, String value) throws Exception {
//public static NodeSmall createNode(String typeInNode, String name, String description, Long parentId) {
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
T out = null;
// real add in the BDD:
try {
String tableName = getTableName(clazz);
boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
StringBuilder query = new StringBuilder();
query.append("SELECT ");
//query.append(tableName);
//query.append(" SET ");
boolean firstField = true;
Field primaryKeyField = null;
int count = 0;
for (Field elem : clazz.getFields()) {
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
if (primaryKey) {
primaryKeyField = elem;
}
boolean linkGeneric = elem.getDeclaredAnnotationsByType(SQLTableLinkGeneric.class).length != 0;
if (linkGeneric) {
continue;
}
boolean createTime = elem.getDeclaredAnnotationsByType(SQLCreateTime.class).length != 0;
if (createTime) {
continue;
}
String name = elem.getName();
boolean updateTime = elem.getDeclaredAnnotationsByType(SQLUpdateTime.class).length != 0;
if (updateTime) {
continue;
}
count++;
if (firstField) {
firstField = false;
} else {
query.append(",");
}
query.append(" ");
query.append(tableName);
query.append(".");
query.append(name);
}
query.append("\n FROM `");
query.append(tableName);
query.append("` ");
query.append("\n WHERE ");
query.append(tableName);
query.append(".");
query.append(key);
query.append(" = ?");
query.append("\n LIMIT 1 ");
/*
query.append(" AND ");
query.append(tableName);
query.append(".deleted = false ");
*/
firstField = true;
System.out.println("generate the querry: '" + query.toString() + "'");
// prepare the request:
PreparedStatement ps = entry.connection.prepareStatement(query.toString(), Statement.RETURN_GENERATED_KEYS);
int iii = 1;
ps.setString(iii++, value);
// execute the request
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Object data = clazz.getConstructors()[0].newInstance();
count = 1;
for (Field elem : clazz.getFields()) {
boolean linkGeneric = elem.getDeclaredAnnotationsByType(SQLTableLinkGeneric.class).length != 0;
if (linkGeneric) {
continue;
}
boolean createTime = elem.getDeclaredAnnotationsByType(SQLCreateTime.class).length != 0;
if (createTime) {
continue;
}
String name = elem.getName();
boolean updateTime = elem.getDeclaredAnnotationsByType(SQLUpdateTime.class).length != 0;
if (updateTime) {
continue;
}
//this.name = rs.getString(iii++);
//this.description = rs.getString(iii++);
//this.covers = getListOfIds(rs, iii++);
setValueFromDb(elem.getType(), data, count, elem, rs);
count++;
}
out = (T)data;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
entry.disconnect();
entry = null;
return out;
}
public static <T> T get(Class<T> clazz, long id) throws Exception {
//public static NodeSmall createNode(String typeInNode, String name, String description, Long parentId) {
@ -632,15 +734,15 @@ public class SqlWrapper {
query.append(" WHERE ");
query.append(tmpVariable);
query.append(".deleted = false AND ");
query.append(localName);
query.append(tableName);
query.append(".id = ");
query.append(tmpVariable);
query.append(".");
query.append(localName);
query.append(tableName);
query.append("_id GROUP BY ");
query.append(tmpVariable);
query.append(".");
query.append(localName);
query.append(tableName);
query.append("_id ) AS ");
query.append(name);
query.append(" ");
@ -684,32 +786,16 @@ public class SqlWrapper {
continue;
}
String name = elem.getName();
boolean linkGeneric = elem.getDeclaredAnnotationsByType(SQLTableLinkGeneric.class).length != 0;
if (linkGeneric) {
List<Long> idList = getListOfIds(rs, count);
elem.set(data, idList);
/*String query = "SELECT node.id," +
" node.name," +
" node.description," +
" node.parent_id," +
" (SELECT GROUP_CONCAT(tmp.data_id SEPARATOR '-')" +
" FROM cover_link_node tmp" +
" WHERE tmp.deleted = false" +
" AND node.id = tmp.node_id" +
" GROUP BY tmp.node_id) AS covers" +
" FROM node" +
" WHERE node.deleted = false " +
" AND node.type = ?" +
" AND node.id = ?" +
" ORDER BY node.name";
*/
continue;
} else {
setValueFromDb(elem.getType(), data, count, elem, rs);
}
count++;
}
//System.out.println("Read: " + (T)data);
out.add((T)data);
}

View File

@ -86,7 +86,7 @@ public class UserDB {
private static void createUsersInfoFromOAuth(long userId, String login) {
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
String query = "INSERT INTO `user` (`id`, `login`, `lastConnection`, `admin`, `blocked`, `removed`) VALUE (?,?,now(3),'FALSE','FALSE','FALSE')";
String query = "INSERT INTO `user` (`id`, `login`, `lastConnection`, `admin`, `blocked`, `removed`) VALUE (?,?,now(3),'0','0','0')";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
ps.setLong(1, userId);

View File

@ -6,6 +6,7 @@ import org.kar.karusic.WebLauncher;
import org.kar.karusic.annotation.PermitTokenInURI;
import org.kar.karusic.db.DBEntry;
import org.kar.karusic.filter.GenericContext;
import org.kar.karusic.internal.Log;
import org.kar.karusic.model.Data;
import org.kar.karusic.model.DataSmall;
import org.kar.karusic.util.ConfigVariable;
@ -46,13 +47,13 @@ public class DataResource {
private final static int CHUNK_SIZE = 1024 * 1024; // 1MB chunks
private final static int CHUNK_SIZE_IN = 50 * 1024 * 1024; // 1MB chunks
/**
* Upload some datas
* Upload some data
*/
private static long tmpFolderId = 1;
private static void createFolder(String path) throws IOException {
if (!Files.exists(java.nio.file.Path.of(path))) {
//Log.print("Create folder: " + path);
System.out.println("Create folder: " + path);
Files.createDirectories(java.nio.file.Path.of(path));
}
}

View File

@ -3,6 +3,10 @@ package org.kar.karusic.api;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.karusic.SqlWrapper;
import org.kar.karusic.model.Album;
import org.kar.karusic.model.Artist;
import org.kar.karusic.model.Data;
import org.kar.karusic.model.Gender;
import org.kar.karusic.model.Track;
import org.kar.karusic.util.CoverTools;
@ -11,7 +15,13 @@ import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.List;
@Path("/track")
@ -94,5 +104,142 @@ public class TrackResource {
SqlWrapper.removeLink(Track.class, id, "cover", coverId);
return Response.ok(SqlWrapper.get(Track.class, id)).build();
}
@POST
@Path("/upload/")
@RolesAllowed("ADMIN")
@Consumes({MediaType.MULTIPART_FORM_DATA})
public Response uploadFile(@FormDataParam("fileName") String fileName,
@FormDataParam("gender") String gender,
@FormDataParam("artist") String artist,
//@FormDataParam("seriesId") String seriesId, Not used ...
@FormDataParam("album") String album,
@FormDataParam("trackId") String trackId,
@FormDataParam("title") String title,
@FormDataParam("file") InputStream fileInputStream,
@FormDataParam("file") FormDataContentDisposition fileMetaData
) {
try {
// correct input string stream :
fileName = CoverTools.multipartCorrection(fileName);
gender = CoverTools.multipartCorrection(gender);
artist = CoverTools.multipartCorrection(artist);
album = CoverTools.multipartCorrection(album);
trackId = CoverTools.multipartCorrection(trackId);
title = CoverTools.multipartCorrection(title);
//public NodeSmall uploadFile(final FormDataMultiPart form) {
System.out.println("Upload media file: " + fileMetaData);
System.out.println(" - fileName: " + fileName);
System.out.println(" - gender: " + gender);
System.out.println(" - artist: " + artist);
System.out.println(" - album: " + album);
System.out.println(" - trackId: " + trackId);
System.out.println(" - title: " + title);
System.out.println(" - fileInputStream: " + fileInputStream);
System.out.println(" - fileMetaData: " + fileMetaData);
System.out.flush();
/*
if (typeId == null) {
return Response.status(406).
entity("Missong Input 'type'").
type("text/plain").
build();
}
*/
long tmpUID = DataResource.getTmpDataId();
String sha512 = DataResource.saveTemporaryFile(fileInputStream, tmpUID);
Data data = DataResource.getWithSha512(sha512);
if (data == null) {
System.out.println("Need to add the data in the BDD ... ");
System.out.flush();
try {
data = DataResource.createNewData(tmpUID, fileName, sha512);
} catch (IOException ex) {
DataResource.removeTemporaryFile(tmpUID);
ex.printStackTrace();
return Response.notModified("can not create input media").build();
} catch (SQLException ex) {
ex.printStackTrace();
DataResource.removeTemporaryFile(tmpUID);
return Response.notModified("Error in SQL insertion ...").build();
}
} else if (data.deleted == true) {
System.out.println("Data already exist but deleted");
System.out.flush();
DataResource.undelete(data.id);
data.deleted = false;
} else {
System.out.println("Data already exist ... all good");
System.out.flush();
}
// Fist step: retive all the Id of each parents:...
System.out.println("Find typeNode");
Gender genderElem = null;
if (gender != null) {
genderElem = SqlWrapper.getWith(Gender.class, "name", gender);
if (genderElem == null) {
genderElem = new Gender();
genderElem.name = gender;
genderElem = SqlWrapper.insert(genderElem);
}
}
// NodeSmall typeNode = TypeResource.getWithId(Long.parseLong(typeId));
// if (typeNode == null) {
// DataResource.removeTemporaryFile(tmpUID);
// return Response.notModified("TypeId does not exist ...").build();
// }
System.out.println(" ==> " + genderElem);
Artist artistElem = null;
if (artist != null) {
artistElem = SqlWrapper.getWith(Artist.class, "name", artist);
if (artistElem == null){
artistElem = new Artist();
artistElem.name = artist;
artistElem = SqlWrapper.insert(artistElem);
}
}
System.out.println(" ==> " + artistElem);
Album albumElem = null;
if (album != null) {
albumElem = SqlWrapper.getWith(Album.class, "name", album);
if (albumElem == null) {
albumElem = new Album();
albumElem.name = album;
albumElem = SqlWrapper.insert(albumElem);
}
}
System.out.println(" ==> " + album);
System.out.println("add media");
Track trackElem = new Track();
trackElem.name = title;
trackElem.genderId = genderElem!=null?genderElem.id:null;
trackElem.dataId = data.id;
trackElem = SqlWrapper.insert(trackElem);
if (artistElem != null) {
SqlWrapper.addLink(Track.class, trackElem.id, "artist", artistElem.id);
}
if (artistElem != null) {
SqlWrapper.addLink(Album.class, albumElem.id , "track", trackElem.id);
}
return Response.ok(trackElem).build();
} catch (Exception ex) {
System.out.println("Catch an unexpected error ... " + ex.getMessage());
ex.printStackTrace();
return Response.status(417).
entity("Back-end error : " + ex.getMessage()).
type("text/plain").
build();
}
}
}

View File

@ -13,7 +13,7 @@ import org.kar.karusic.model.Data;
public class CoverTools {
static private String multipartCorrection(String data) {
public static String multipartCorrection(String data) {
if (data == null) {
return null;
}

View File

@ -27,21 +27,20 @@ services:
read_only: false
mem_limit: 100m
# karusic_back_service:
# build: .
# restart: always
# image: org.kar.karusic
# depends_on:
# - karusic_db_service
# ports:
# - 19080:18080
# env_file:
# - ./config.env
# links:
# - karusic_db_service:db
# read_only: true
# mem_limit: 1200m
# healthcheck:
# test: ["CMD", "wget" ,"http://localhost:18080/karusic/api/health_check", "-O", "/dev/null"]
# timeout: 20s
# retries: 3
karusic_back_service:
restart: always
image: gitea.atria-soft.org/kangaroo-and-rabbit/karusic:latest
depends_on:
- karusic_db_service
ports:
- 19080:18080
env_file:
- ./config.env
links:
- karusic_db_service:db
read_only: true
mem_limit: 1200m
healthcheck:
test: ["CMD", "wget" ,"http://localhost:18080/karusic/api/health_check", "-O", "/dev/null"]
timeout: 20s
retries: 3

421
front/package-lock.json generated
View File

@ -23,7 +23,7 @@
"jquery": "^3.6.0",
"rxjs": "^7.5.4",
"tslib": "^2.3.1",
"videogular": "^1.4.4",
"videogular": "^2.2.1",
"zone.js": "^0.11.5"
},
"devDependencies": {
@ -41,7 +41,7 @@
"@types/node": "^17.0.21",
"@typescript-eslint/eslint-plugin": "^5.17.0",
"@typescript-eslint/parser": "^5.17.0",
"codelyzer": "^0.0.28",
"codelyzer": "^6.0.2",
"eslint": "^8.12.0",
"eslint-config-google": "^0.14.0",
"jasmine-core": "^4.0.1",
@ -4446,9 +4446,21 @@
}
},
"node_modules/angular": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==",
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.4.14.tgz",
"integrity": "sha512-C7sWDna0j/RcDq0+aUhFPhkWqOS+8CSMPx7Mz0hmxOcu921GWwgD3zyDqTkLlOA+wxwh5ecmVyG1lggqvD+icQ==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
},
"node_modules/angular-animate": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.4.14.tgz",
"integrity": "sha512-Ir1k5YlBTFgyrG24XKXEdelTVsADXzijQ9w66EKeJci0cwp/5rKMesIu4WJIVe6CoSth5fzfZsElCocvui9Juw==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
},
"node_modules/angular-route": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/angular-route/-/angular-route-1.4.14.tgz",
"integrity": "sha512-HJwoKvERIlptZfN2vDqlP+eE/8NLw/gI9yyb90gKSc5Xh6ZCM0Ojkw2yAb16TKJcw4jaSw4KB+IgG8jljMdIwg==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
},
"node_modules/angular-sanitize": {
@ -4457,6 +4469,11 @@
"integrity": "sha512-WUxneGpsoF5m8EXpFN0cQP5PPZiAOjktIeWsdJjpFJHaxi9ZktLwYE1yeiKQLc2fR0/O3jwdrCR6zmjytszQyg==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
},
"node_modules/angulartics": {
"version": "0.17.2",
"resolved": "https://registry.npmjs.org/angulartics/-/angulartics-0.17.2.tgz",
"integrity": "sha512-hgR+uxOO3qeide/HrNqQIkj4asSM/8/g2U365sQzvTaXkp6dggIyVp+AclZJxHRHBwhcFS9rJXY4XrSfwzqQsQ=="
},
"node_modules/ansi-colors": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
@ -4527,6 +4544,15 @@
"node": ">= 8"
}
},
"node_modules/app-root-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz",
"integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==",
"dev": true,
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/aproba": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
@ -4631,6 +4657,12 @@
"node": ">=0.8"
}
},
"node_modules/ast-types-flow": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
"dev": true
},
"node_modules/async": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
@ -4977,6 +5009,11 @@
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true
},
"node_modules/bootstrap": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.1.1.tgz",
"integrity": "sha512-TAzqS8E/ISpVHP29gYhy+1NSV+FJwApDVQhDfgLYsIuUDJiqJzH2DfORN5tiu+Ie2iBLrzEG34t4Rf465cigqg=="
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -5366,17 +5403,104 @@
}
},
"node_modules/codelyzer": {
"version": "0.0.28",
"resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-0.0.28.tgz",
"integrity": "sha512-DfrZrFWP4MnowANXJHUL0ZMhLqAEFLjC3lJofkHZM+QAczdOvlq8CmLrvqspCXmIdyotVD0xyjUWoPGOPo4lKA==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.2.tgz",
"integrity": "sha512-v3+E0Ucu2xWJMOJ2fA/q9pDT/hlxHftHGPUay1/1cTgyPV5JTHFdO9hqo837Sx2s9vKBMTt5gO+lhF95PO6J+g==",
"dev": true,
"dependencies": {
"sprintf-js": "^1.0.3"
"@angular/compiler": "9.0.0",
"@angular/core": "9.0.0",
"app-root-path": "^3.0.0",
"aria-query": "^3.0.0",
"axobject-query": "2.0.2",
"css-selector-tokenizer": "^0.7.1",
"cssauron": "^1.4.0",
"damerau-levenshtein": "^1.0.4",
"rxjs": "^6.5.3",
"semver-dsl": "^1.0.1",
"source-map": "^0.5.7",
"sprintf-js": "^1.1.2",
"tslib": "^1.10.0",
"zone.js": "~0.10.3"
},
"peerDependencies": {
"tslint": "^3.9.0"
"@angular/compiler": ">=2.3.1 <13.0.0 || ^12.0.0-next || ^12.1.0-next || ^12.2.0-next",
"@angular/core": ">=2.3.1 <13.0.0 || ^12.0.0-next || ^12.1.0-next || ^12.2.0-next",
"tslint": "^5.0.0 || ^6.0.0"
}
},
"node_modules/codelyzer/node_modules/@angular/compiler": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz",
"integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==",
"dev": true,
"peerDependencies": {
"tslib": "^1.10.0"
}
},
"node_modules/codelyzer/node_modules/@angular/core": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz",
"integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==",
"dev": true,
"peerDependencies": {
"rxjs": "^6.5.3",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
}
},
"node_modules/codelyzer/node_modules/aria-query": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
"integrity": "sha512-majUxHgLehQTeSA+hClx+DY09OVUqG3GtezWkF1krgLGNdlDu9l9V8DaqNMWbq4Eddc8wsyDA0hpDUtnYxQEXw==",
"dev": true,
"dependencies": {
"ast-types-flow": "0.0.7",
"commander": "^2.11.0"
}
},
"node_modules/codelyzer/node_modules/axobject-query": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
"integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
"dev": true,
"dependencies": {
"ast-types-flow": "0.0.7"
}
},
"node_modules/codelyzer/node_modules/rxjs": {
"version": "6.6.7",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
"dev": true,
"dependencies": {
"tslib": "^1.9.0"
},
"engines": {
"npm": ">=2.0.0"
}
},
"node_modules/codelyzer/node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/codelyzer/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/codelyzer/node_modules/zone.js": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz",
"integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==",
"dev": true
},
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -6020,6 +6144,16 @@
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-selector-tokenizer": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz",
"integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==",
"dev": true,
"dependencies": {
"cssesc": "^3.0.0",
"fastparse": "^1.1.2"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
@ -6041,6 +6175,15 @@
"node": ">=0.10.0"
}
},
"node_modules/cssauron": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
"integrity": "sha512-Ht70DcFBh+/ekjVrYS2PlDMdSQEl3OFNmjK6lcn49HptBgilXf/Zwg4uFh9Xn0pX3Q8YOkSjIFOfK2osvdqpBw==",
"dev": true,
"dependencies": {
"through": "X.X.X"
}
},
"node_modules/cssdb": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cssdb/-/cssdb-5.1.0.tgz",
@ -6065,6 +6208,12 @@
"integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==",
"dev": true
},
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
"dev": true
},
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@ -6644,6 +6793,15 @@
"integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
"dev": true
},
"node_modules/es5-shim": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-2.0.12.tgz",
"integrity": "sha512-qamWDNeoOU3ALhUZFvcciNiadl19WnF5SZFXOTu7BmFC7HGwY6lwdPTEU45N4Wco7Z+j4GOFImzna2xCrmuZUQ==",
"deprecated": "Please update to the latest version; it overrides noncompliant native methods even in modern implementations",
"engines": {
"node": ">=0.2.0"
}
},
"node_modules/es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
@ -7685,6 +7843,12 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
"node_modules/fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
"dev": true
},
"node_modules/fastq": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
@ -9513,6 +9677,12 @@
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
"dev": true
},
"node_modules/json3": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz",
"integrity": "sha512-KA+GHhYTLTo7Ri4DyjwUgW8kn98AYtVZtBC94qL5yD0ZSYct8/eF8qBmTNyk+gPE578bKeIL4WBq+MUyd1I26g==",
"deprecated": "Please use the native JSON object instead of JSON 3"
},
"node_modules/json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
@ -13275,6 +13445,24 @@
"node": ">=10"
}
},
"node_modules/semver-dsl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz",
"integrity": "sha512-e8BOaTo007E3dMuQQTnPdalbKTABKNS7UxoBIDnwOqRa+QwMrCPjynB8zAlPF6xlqUfdLPPLIJ13hJNmhtq8Ng==",
"dev": true,
"dependencies": {
"semver": "^5.3.0"
}
},
"node_modules/semver-dsl/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
@ -14648,15 +14836,21 @@
}
},
"node_modules/videogular": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/videogular/-/videogular-1.4.4.tgz",
"integrity": "sha512-WJjJipSWWhhcP0oojQsq5M99EfDemALa22eQdosWXmK4XdxHJFfR1D6qzWOBDe7kPw1mT/2qgE+jIB2KMGJmIw==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/videogular/-/videogular-2.2.1.tgz",
"integrity": "sha512-v2wpwCW8TDKV7OCRrrVVlx3odgrXodb9DbjfT2o577I+MZVj5qqc4u1W1xlO1JyNVtrwlWiq8dZVZPm3KDdRUg==",
"dependencies": {
"angular": "^1.3.0",
"angular-sanitize": "^1.3.0"
"angular": "~1.4.0",
"angular-animate": "~1.4.0",
"angular-route": "~1.4.0",
"angular-sanitize": "~1.4.0",
"angulartics": "~0.17.1",
"bootstrap": "~3.1.1",
"es5-shim": "~2.0.8",
"json3": "~3.2.4"
},
"engines": {
"node": ">=0.8.0"
"node": ">= 4"
}
},
"node_modules/void-elements": {
@ -18616,15 +18810,30 @@
}
},
"angular": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw=="
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.4.14.tgz",
"integrity": "sha512-C7sWDna0j/RcDq0+aUhFPhkWqOS+8CSMPx7Mz0hmxOcu921GWwgD3zyDqTkLlOA+wxwh5ecmVyG1lggqvD+icQ=="
},
"angular-animate": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.4.14.tgz",
"integrity": "sha512-Ir1k5YlBTFgyrG24XKXEdelTVsADXzijQ9w66EKeJci0cwp/5rKMesIu4WJIVe6CoSth5fzfZsElCocvui9Juw=="
},
"angular-route": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/angular-route/-/angular-route-1.4.14.tgz",
"integrity": "sha512-HJwoKvERIlptZfN2vDqlP+eE/8NLw/gI9yyb90gKSc5Xh6ZCM0Ojkw2yAb16TKJcw4jaSw4KB+IgG8jljMdIwg=="
},
"angular-sanitize": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.4.14.tgz",
"integrity": "sha512-WUxneGpsoF5m8EXpFN0cQP5PPZiAOjktIeWsdJjpFJHaxi9ZktLwYE1yeiKQLc2fR0/O3jwdrCR6zmjytszQyg=="
},
"angulartics": {
"version": "0.17.2",
"resolved": "https://registry.npmjs.org/angulartics/-/angulartics-0.17.2.tgz",
"integrity": "sha512-hgR+uxOO3qeide/HrNqQIkj4asSM/8/g2U365sQzvTaXkp6dggIyVp+AclZJxHRHBwhcFS9rJXY4XrSfwzqQsQ=="
},
"ansi-colors": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
@ -18671,6 +18880,12 @@
"picomatch": "^2.0.4"
}
},
"app-root-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz",
"integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==",
"dev": true
},
"aproba": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
@ -18759,6 +18974,12 @@
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"dev": true
},
"ast-types-flow": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
"dev": true
},
"async": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
@ -19022,6 +19243,11 @@
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true
},
"bootstrap": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.1.1.tgz",
"integrity": "sha512-TAzqS8E/ISpVHP29gYhy+1NSV+FJwApDVQhDfgLYsIuUDJiqJzH2DfORN5tiu+Ie2iBLrzEG34t4Rf465cigqg=="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -19300,12 +19526,87 @@
}
},
"codelyzer": {
"version": "0.0.28",
"resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-0.0.28.tgz",
"integrity": "sha512-DfrZrFWP4MnowANXJHUL0ZMhLqAEFLjC3lJofkHZM+QAczdOvlq8CmLrvqspCXmIdyotVD0xyjUWoPGOPo4lKA==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.2.tgz",
"integrity": "sha512-v3+E0Ucu2xWJMOJ2fA/q9pDT/hlxHftHGPUay1/1cTgyPV5JTHFdO9hqo837Sx2s9vKBMTt5gO+lhF95PO6J+g==",
"dev": true,
"requires": {
"sprintf-js": "^1.0.3"
"@angular/compiler": "9.0.0",
"@angular/core": "9.0.0",
"app-root-path": "^3.0.0",
"aria-query": "^3.0.0",
"axobject-query": "2.0.2",
"css-selector-tokenizer": "^0.7.1",
"cssauron": "^1.4.0",
"damerau-levenshtein": "^1.0.4",
"rxjs": "^6.5.3",
"semver-dsl": "^1.0.1",
"source-map": "^0.5.7",
"sprintf-js": "^1.1.2",
"tslib": "^1.10.0",
"zone.js": "~0.10.3"
},
"dependencies": {
"@angular/compiler": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz",
"integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==",
"dev": true,
"requires": {}
},
"@angular/core": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz",
"integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==",
"dev": true,
"requires": {}
},
"aria-query": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
"integrity": "sha512-majUxHgLehQTeSA+hClx+DY09OVUqG3GtezWkF1krgLGNdlDu9l9V8DaqNMWbq4Eddc8wsyDA0hpDUtnYxQEXw==",
"dev": true,
"requires": {
"ast-types-flow": "0.0.7",
"commander": "^2.11.0"
}
},
"axobject-query": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
"integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
"dev": true,
"requires": {
"ast-types-flow": "0.0.7"
}
},
"rxjs": {
"version": "6.6.7",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
}
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
"dev": true
},
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"zone.js": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz",
"integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==",
"dev": true
}
}
},
"color-convert": {
@ -19797,12 +20098,31 @@
"nth-check": "^2.0.1"
}
},
"css-selector-tokenizer": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz",
"integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
"fastparse": "^1.1.2"
}
},
"css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"dev": true
},
"cssauron": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
"integrity": "sha512-Ht70DcFBh+/ekjVrYS2PlDMdSQEl3OFNmjK6lcn49HptBgilXf/Zwg4uFh9Xn0pX3Q8YOkSjIFOfK2osvdqpBw==",
"dev": true,
"requires": {
"through": "X.X.X"
}
},
"cssdb": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cssdb/-/cssdb-5.1.0.tgz",
@ -19821,6 +20141,12 @@
"integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==",
"dev": true
},
"damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
"dev": true
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@ -20278,6 +20604,11 @@
"integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
"dev": true
},
"es5-shim": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-2.0.12.tgz",
"integrity": "sha512-qamWDNeoOU3ALhUZFvcciNiadl19WnF5SZFXOTu7BmFC7HGwY6lwdPTEU45N4Wco7Z+j4GOFImzna2xCrmuZUQ=="
},
"es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
@ -20970,6 +21301,12 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
"fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
"dev": true
},
"fastq": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
@ -22360,6 +22697,11 @@
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
"dev": true
},
"json3": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz",
"integrity": "sha512-KA+GHhYTLTo7Ri4DyjwUgW8kn98AYtVZtBC94qL5yD0ZSYct8/eF8qBmTNyk+gPE578bKeIL4WBq+MUyd1I26g=="
},
"json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
@ -25152,6 +25494,23 @@
"lru-cache": "^6.0.0"
}
},
"semver-dsl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz",
"integrity": "sha512-e8BOaTo007E3dMuQQTnPdalbKTABKNS7UxoBIDnwOqRa+QwMrCPjynB8zAlPF6xlqUfdLPPLIJ13hJNmhtq8Ng==",
"dev": true,
"requires": {
"semver": "^5.3.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
},
"send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
@ -26176,12 +26535,18 @@
}
},
"videogular": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/videogular/-/videogular-1.4.4.tgz",
"integrity": "sha512-WJjJipSWWhhcP0oojQsq5M99EfDemALa22eQdosWXmK4XdxHJFfR1D6qzWOBDe7kPw1mT/2qgE+jIB2KMGJmIw==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/videogular/-/videogular-2.2.1.tgz",
"integrity": "sha512-v2wpwCW8TDKV7OCRrrVVlx3odgrXodb9DbjfT2o577I+MZVj5qqc4u1W1xlO1JyNVtrwlWiq8dZVZPm3KDdRUg==",
"requires": {
"angular": "^1.3.0",
"angular-sanitize": "^1.3.0"
"angular": "~1.4.0",
"angular-animate": "~1.4.0",
"angular-route": "~1.4.0",
"angular-sanitize": "~1.4.0",
"angulartics": "~0.17.1",
"bootstrap": "~3.1.1",
"es5-shim": "~2.0.8",
"json3": "~3.2.4"
}
},
"void-elements": {

View File

@ -5,7 +5,7 @@
"scripts": {
"all": "npm run build && npm run test",
"ng": "ng",
"start": "ng serve --watch",
"start": "ng serve --watch --port 4203",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
@ -27,7 +27,7 @@
"jquery": "^3.6.0",
"rxjs": "^7.5.4",
"tslib": "^2.3.1",
"videogular": "^1.4.4",
"videogular": "^2.2.1",
"zone.js": "^0.11.5"
},
"devDependencies": {
@ -45,7 +45,7 @@
"@types/node": "^17.0.21",
"@typescript-eslint/eslint-plugin": "^5.17.0",
"@typescript-eslint/parser": "^5.17.0",
"codelyzer": "^0.0.28",
"codelyzer": "^6.0.2",
"eslint": "^8.12.0",
"eslint-config-google": "^0.14.0",
"jasmine-core": "^4.0.1",

View File

@ -8,8 +8,9 @@ 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, TypeScene, PlaylistScene, TrackEditScene, TrackScene } from './scene';
import { UploadScene } from './scene/upload/upload';
import { HelpScene, HomeScene, AlbumEditScene, AlbumScene, ArtistEditScene, ArtistScene, SettingsScene,
GenderScene, PlaylistScene, TrackEditScene, TrackScene, UploadScene, ArtistsScene, ArtistAlbumScene } from './scene';
// import { HelpComponent } from './help/help.component';
// see https://angular.io/guide/router
@ -17,23 +18,75 @@ import { UploadScene } from './scene/upload/upload';
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
// ------------------------------------
// -- home global interface
// ------------------------------------
{ path: 'home', component: HomeScene },
// ------------------------------------
// -- upload new data:
// ------------------------------------
{ path: 'upload', component: UploadScene },
{ path: 'gender/:genderId/:artistId/:albumId/:trackId', component: TypeScene },
// ------------------------------------
// -- gender:
// ------------------------------------
// display all gender
{ path: 'gender', component: GenderScene },
// display all (artist | album | traks)
{ path: 'gender/:genderId', component: GenderScene },
//{ path: 'gender-edit/:genderId', component: GenderEditScene },
//{ path: 'gender/:genderId', component: GenderScene },
//{ path: 'gender/:genderId/:artistId/:albumId/:trackId', component: GenderScene },
// ------------------------------------
// -- playlist:
// ------------------------------------
{ path: 'playlist', component: PlaylistScene },
{ path: 'playlist/:playlistId', component: PlaylistScene },
//{ path: 'playlist-edit/:playlistId', component: PlaylistEditScene },
{ path: 'artist/:genderId/:artistId/:albumId/:trackId', component: ArtistScene },
{ path: 'artist-edit/:genderId/:artistId/:albumId/:trackId', component: ArtistEditScene },
// ------------------------------------
// -- Artist:
// ------------------------------------
// display list of all artist
{ path: 'artist', component: ArtistsScene },
// display list af all artist with a specific gender
{ path: 'artist/:artistId', component: ArtistScene },
{ path: 'artist/:artistId/:albumId', component: ArtistAlbumScene },
{ path: 'album/:genderId/:artistId/:albumId/:trackId', component: AlbumScene },
{ path: 'album-edit/:genderId/:artistId/:albumId/:trackId', component: AlbumEditScene },
{ path: 'artist-edit/:artistId', component: ArtistEditScene },
// ------------------------------------
// -- 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-edit/:albumId', component: AlbumEditScene },
// ------------------------------------
// -- Tracks:
// ------------------------------------
{ path: 'track/:genderId/:artistId/:albumId/:trackId', component: TrackScene },
{ path: 'track-edit/:genderId/:artistId/:albumId/:trackId', component: TrackEditScene },
{ path: 'track-edit/:trackId', component: TrackEditScene },
// ------------------------------------
// -- SSO Generic interface
// ------------------------------------
{ path: 'sso/:data/:keepConnected/:token', component: SsoScene },
{ path: 'sso', component: SsoScene },
// ------------------------------------
// -- Generic pages
// ------------------------------------
{ path: 'help/:page', component: HelpScene },
{ path: 'help', component: HelpScene },
{ path: 'settings', component: SettingsScene },

View File

@ -14,3 +14,4 @@
</div>
</div>
</div>
<app-element-player-audio></app-element-player-audio>

View File

@ -23,15 +23,16 @@ import { PopInDeleteConfirm } from '../common/popin/delete-confirm/delete-confir
import { AppComponent } from './app.component';
import { ErrorComponent } from '../common/error/error';
import { HomeScene, HelpScene, TypeScene, PlaylistScene, ArtistScene, AlbumScene, TrackScene, SettingsScene,
TrackEditScene, AlbumEditScene, ArtistEditScene } from './scene';
import { GenderService, DataService, PlaylistService, ArtistService, AlbumService, TrackService, ArianeService } from './service';
import { HomeScene, HelpScene, GenderScene, PlaylistScene, ArtistScene, AlbumScene, 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';
import { ErrorViewerScene, SsoScene } from 'common/scene';
import { UploadScene } from './scene/upload/upload';
import { ElementSeriesComponent } from './component/element-series/element-series';
import { ElementVideoComponent } from './component/element-video/element-video';
import { ElementSeasonComponent } from './component/element-season/element-season';
import { ElementPlayerAudioComponent } from './component/element-player-audio/element-player-audio';
@NgModule({
declarations: [
@ -43,6 +44,7 @@ import { ElementSeasonComponent } from './component/element-season/element-seaso
ElementSeriesComponent,
ElementSeasonComponent,
ElementVideoComponent,
ElementPlayerAudioComponent,
ErrorComponent,
PopInComponent,
@ -54,8 +56,10 @@ import { ElementSeasonComponent } from './component/element-season/element-seaso
ErrorViewerScene,
HelpScene,
SsoScene,
TypeScene,
GenderScene,
PlaylistScene,
ArtistAlbumScene,
ArtistsScene,
ArtistScene,
AlbumScene,
TrackScene,
@ -79,9 +83,11 @@ import { ElementSeasonComponent } from './component/element-season/element-seaso
SessionService,
CookiesService,
StorageService,
UserService,
SSOService,
BddService,
PlayerService,
GenderService,
DataService,
PlaylistService,

View File

@ -0,0 +1,44 @@
<div class="bottom" *ngIf="mediaSource">
<div class="media" >
<div class="media-elem">
<audio src="{{mediaSource}}"
#audioPlayer
preload
(play)="changeStateToPlay()"
(pause)="changeStateToPause()"
(timeupdate)="changeTimeupdate($event.currentTime)"
(durationchange)="changeDurationchange($event.duration)"
(loadedmetadata)="changeMetadata()"
autoplay
(ended)="onAudioEnded()"
><!-- controls > --> <!--preload="none"-->
<!--<p>Your browser does not support HTML5 media player. download media: <a href="{{mediaSource}}>link here</a>.</p>-->
</audio>
</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"
[value]="currentTime"
[max]="duration"
(input)="seek($event.target)">
</div>
<div class="timer-text">
<label class="unselectable">{{currentTimeDisplay}} / {{durationDisplay}}</label>
</div>
</div>
<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>
<button [disabled]="haveNext" (click)="onNext()"><i class="material-icons">navigate_next</i></button>
<button (click)="onPlayMode()"><i class="material-icons">{{playMode}}</i></button>
<!--<button (click)="onMore()" ><i class="material-icons">more_vert</i></button>-->
<!--<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>

View File

@ -0,0 +1,288 @@
.bottom {
/*
position: fixed;
bottom:0px;
left:0px;
display: block;
overflow: visible;
box-shadow: none;
min-height: 56px;
flex-direction: column;
flex-wrap: nowrap;
justify-content: flex-start;
box-sizing: border-box;
flex-shrink: 0;
width: 100%;
margin: 0;
padding: 0 12px 0 12px;
border: none;
max-height: 1000px;
z-index: 3;
box-shadow: 0 -4px 4px rgba(0, 0, 0, 0.6);
*/
.controls {
//visibility: hidden;
opacity: 0.5;
width: 96%;
height: 60px;
border-radius: 10px;
position: absolute;
bottom: 20px;
left: 2%;
//margin-left: -200px;
background-color: black;
box-shadow: 3px 3px 5px black;
transition: 1s all;
display: flex;
font-size: 40px;
.material-icons {
color: #FFF;
font-size: 40px;
}
button {
border: none;
background: none;
}
button:disabled,
button[disabled] {
.material-icons {
color: rgb(46, 46, 46);
}
}
.bigPause {
position: fixed;
top: 120px;
left: 40%;
width: 20%;
height: calc(90% - 120px*2);
border: none;
box-shadow: none;
cursor: pointer;
.material-icons {
color: #FFF;
font-size: 120px;
color: green;
}
&:focus {
outline: none;
}
opacity: 95%;
}
.bigRewind {
position: fixed;
top: 120px;
left: 20%;
width: 20%;
height: calc(90% - 120px*2);
border: none;
.material-icons {
color: #FFF;
font-size: 120px;
color: red;
}
&:focus {
outline: none;
}
opacity: 95%;
}
.bigForward {
position: fixed;
top: 120px;
left: 60%;
width: 20%;
height: calc(90% - 120px*2);
border: none;
.material-icons {
color: #FFF;
font-size: 120px;
color: blue;
}
&:focus {
outline: none;
}
opacity: 95%;
}
.slidecontainer {
line-height: 38px;
font-size: 10px;
font-family: monospace;
text-shadow: 1px 1px 0px black;
color: white;
flex: 5;
position: relative;
}
.slider {
position: relative;
-webkit-appearance: none;
width: 98%;
height: 10px;
top: 5px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
flex: 5;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 25px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
.timer-text {
position: absolute;
top: 25px;
left: 0px;
width: 100%;
line-height: 38px;
font-size: 30px;
font-weight:bold;
}
}
/*
:hover .controls, :focus .controls {
opacity: 1;
}
*/
button:before {
font-family: HeydingsControlsRegular;
font-size: 30px;
position: relative;
color: #FFF;
//text-shadow: 1px 1px 0px black;
}
.timer {
line-height: 38px;
font-size: 30px;
font-family: monospace;
text-shadow: 1px 1px 0px black;
color: white;
flex: 5;
position: relative;
}
.timer div {
width:100%;
line-height: 38px;
font-size: 10px;
font-family: monospace;
text-shadow: 1px 1px 0px black;
color: white;
flex: 5;
position: relative;
}
.timer span {
position: absolute;
z-index: 3;
left: 19px;
}
.volume-menu {
font-size: 40px;
opacity: 0.5;
width: 300px;
height: 60px;
border-radius: 10px;
position: absolute;
bottom: 90px;
right: 2%;
//margin-left: -200px;
background-color: black;
box-shadow: 3px 3px 5px black;
transition: 1s all;
display: flex;
.material-icons {
vertical-align: middle;
color: #FFF;
font-size: 40px;
}
/* Create an Arraw on the top ob the box ... */
&:after, &:before {
bottom: 100%;
right: 13px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-color: rgba(136, 183, 213, 0);
border-bottom-color: #263238;
border-width: 15px;
margin-left: -15px;
}
button {
border: none;
background: none;
border-radius: 50%;
}
.slidecontainer {
line-height: 38px;
font-size: 10px;
font-family: monospace;
text-shadow: 1px 1px 0px black;
color: white;
flex: 5;
position: relative;
}
.slider {
position: relative;
-webkit-appearance: none;
width: 98%;
height: 10px;
top: 15px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
flex: 5;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 25px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
}
}

View File

@ -0,0 +1,461 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';
import { isArrayOf, isNullOrUndefined, isNumberFinite } from 'common/utils';
import { NodeData } from 'common/model';
import { GenderService, DataService, PlayerService, TrackService } from 'app/service';
import { PlaylistCurrent } from 'app/service/player';
import { Media } from 'app/model';
import { HttpWrapperService } from 'common/service';
export enum PlayMode {
PLAY_ONE = "check",
PLAY_ALL = "trending_flat",
PLAY_ONE_LOOP = "repeat_one",
PLAY_ALL_LOOP = "repeat",
};
// note: all the input is managed with the player service ...
@Component({
selector: 'app-element-player-audio',
templateUrl: './element-player-audio.html',
styleUrls: [ './element-player-audio.less' ]
})
export class ElementPlayerAudioComponent implements OnInit {
audioPlayer: HTMLAudioElement;
duration: number;
durationDisplay: string;
@ViewChild('audioPlayer')
set mainVideoEl(el: ElementRef) {
if(el !== null && el !== undefined) {
this.audioPlayer = el.nativeElement;
}
}
public mediaSource: string = undefined;
public name: string = 'rr';
public description: string;
public counttrack: number;
public covers: string[];
playStream: boolean;
isPlaying: boolean;
currentTime: any;
currentTimeDisplay: string;
havePrevious: boolean = false;
haveNext: boolean = false;
playMode: PlayMode = PlayMode.PLAY_ALL;
onPlayMode() {
if (this.playMode === PlayMode.PLAY_ONE) {
this.playMode = PlayMode.PLAY_ALL;
} else if (this.playMode === PlayMode.PLAY_ALL) {
this.playMode = PlayMode.PLAY_ONE_LOOP;
} else if (this.playMode === PlayMode.PLAY_ONE_LOOP) {
this.playMode = PlayMode.PLAY_ALL_LOOP;
} else {
this.playMode = PlayMode.PLAY_ONE;
}
}
constructor(
private playerService: PlayerService,
private trackService: TrackService,
private httpService: HttpWrapperService,
private dataService: DataService) {
// nothing to do...
}
private currentLMedia: Media = undefined;
private localIdStreaming: number = undefined;
private localListStreaming: number[] = [];
ngOnInit() {
/*
export interface PlaylistCurrent {
playTrackList: number[];
trackLocalId?: number;
}
*/
let self = this;
this.playerService.playChange.subscribe((newProperty: PlaylistCurrent) => {
self.localIdStreaming = newProperty.trackLocalId;
self.localListStreaming = newProperty.playTrackList;
self.updateMediaStreamed();
});
}
updateMediaStreamed() {
if (isNullOrUndefined(this.localIdStreaming)) {
this.mediaSource = undefined;
return;
}
let self = this;
this.havePrevious = this.localIdStreaming <= 0;
this.haveNext = this.localIdStreaming >= this.localListStreaming.length-1;
this.trackService.get(this.localListStreaming[this.localIdStreaming])
.then((response: Media) => {
//console.log(`get response of video : ${ JSON.stringify(response, null, 2)}`);
this.currentLMedia = response;
if (isNullOrUndefined(self.currentLMedia)) {
console.log("Can not retreive the media ...")
return;
}
if (isNullOrUndefined(self.currentLMedia.dataId)) {
console.log("Can not retreive the media ... null or undefined data ID")
return;
}
self.mediaSource = self.httpService.createRESTCall2({
api: `data/${self.currentLMedia.dataId}/unknowMediaName.webm`, //${self.generatedName}`,
addURLToken: true,
});
}).catch(() => {
console.error("error not ùmanaged in audio player ... 111");
})
}
generateName() {
/*
this.generatedName = '';
if(this.seriesName !== undefined) {
this.generatedName = `${this.generatedName }${this.seriesName }-`;
}
if(this.seasonName !== undefined) {
if(this.seasonName.length < 2) {
this.generatedName = `${this.generatedName }s0${ this.seasonName }-`;
} else {
this.generatedName = `${this.generatedName }s${ this.seasonName }-`;
}
}
if(this.episode !== undefined) {
if(this.episode < 10) {
this.generatedName = `${this.generatedName }e0${ this.episode }-`;
} else {
this.generatedName = `${this.generatedName }e${ this.episode }-`;
}
}
this.generatedName = this.generatedName + this.name;
this.generatedName = this.generatedName.replace(new RegExp('&', 'g'), '_');
this.generatedName = this.generatedName.replace(new RegExp('/', 'g'), '_');
// update the path of the uri request
this.mediaSource = this.httpService.createRESTCall2({
api: `data/${ this.dataId}/${this.generatedName}`,
addURLToken: true,
});
*/
}
myPeriodicCheckFunction() {
console.log('check ... ');
}
changeMetadata() {
console.log('list of the stream:');
/*
let captureStream = this.audioPlayer.audioTracks;
for (let iii=0; iii < captureStream.length; iii++) {
console.log(" - " + captureStream[iii].language);
if (captureStream[iii].language.substring(0,2) === "fr") {
captureStream[iii].enabled = true;
} else {
captureStream[iii].enabled = false;
}
}
*/
}
/*
ngOnInit() {
let self = this;
this.arianeService.updateManual(this.route.snapshot.paramMap);
this.idVideo = this.arianeService.getVideoId();
this.arianeService.mediaChange.subscribe((mediaId) => {
console.log(`Detect mediaId change...${ mediaId}`);
self.idVideo = mediaId;
self.updateDisplay();
});
self.updateDisplay();
}
*/
updateDisplay():void {
let self = this;
/*
self.haveNext = null;
self.havePrevious = null;
this.mediaService.get(this.idVideo)
.then((response) => {
console.log(`get response of media : ${ JSON.stringify(response, null, 2)}`);
self.error = '';
self.name = response.name;
self.description = response.description;
self.episode = response.episode;
self.seriesId = response.seriesId;
self.seasonId = response.seasonId;
self.dataId = response.dataId;
self.time = response.time;
self.generatedName = "????????? TODO: ???????" //response.generatedName;
if(self.dataId !== -1) {
self.mediaSource = self.httpService.createRESTCall2({
api: `data/${ self.dataId}/${self.generatedName}`,
addURLToken: true,
});
} else {
self.mediaSource = '';
}
self.covers = self.dataService.getCoverListUrl(response.covers);
self.generateName();
if(self.seriesId !== undefined && self.seriesId !== null) {
self.seriesService.get(self.seriesId)
.then((response2) => {
self.seriesName = response2.name;
self.generateName();
}).catch((response3) => {
// nothing to do ...
});
}
if(self.seasonId !== undefined && self.seasonId !== null) {
self.seasonService.get(self.seasonId)
.then((response4) => {
self.seasonName = response4.name;
self.generateName();
}).catch((response5) => {
// nothing to do ...
});
self.seasonService.getVideo(self.seasonId)
.then((response6:any) => {
// console.log("saison property: " + JSON.stringify(response, null, 2));
self.haveNext = null;
self.havePrevious = null;
for(let iii = 0; iii < response6.length; iii++) {
if(isNullOrUndefined(response6[iii].episode)) {
continue;
}
if(response6[iii].episode < self.episode) {
if(self.havePrevious === null) {
self.havePrevious = response6[iii];
} else if(self.havePrevious.episode < response6[iii].episode) {
self.havePrevious = response6[iii];
}
} else if(response6[iii].episode > self.episode) {
if(self.haveNext === null) {
self.haveNext = response6[iii];
} else if(self.haveNext.episode > response6[iii].episode) {
self.haveNext = response6[iii];
}
}
self.covers.push(self.dataService.getCoverUrl(response6[iii]));
}
}).catch((response7:any) => {
});
}
self.mediaIsLoading = false;
// console.log("display source " + self.mediaSource);
// console.log("set transformed : " + JSON.stringify(self, null, 2));
}).catch((response8) => {
self.error = 'Can not get the data';
self.name = '';
self.description = '';
self.episode = undefined;
self.seriesId = undefined;
self.seasonId = undefined;
self.dataId = -1;
self.time = undefined;
self.generatedName = '';
self.mediaSource = '';
self.covers = undefined;
self.seriesName = undefined;
self.seasonName = undefined;
self.mediaIsNotFound = true;
self.mediaIsLoading = false;
});
*/
}
onRequirePlay() {
this.playStream = true;
}
onRequireStop() {
this.playStream = false;
}
onAudioEnded() {
if (this.playMode === PlayMode.PLAY_ONE) {
this.playStream = false;
} else if (this.playMode === PlayMode.PLAY_ALL) {
this.onNext();
} else if (this.playMode === PlayMode.PLAY_ONE_LOOP) {
this.audioPlayer.currentTime = 0;
this.onPlay();
} else {
if (this.localIdStreaming == this.localListStreaming.length-1) {
this.localIdStreaming = 0;
this.updateMediaStreamed();
if (this.localListStreaming.length == 1) {
this.audioPlayer.currentTime = 0;
this.onPlay();
}
} else {
this.onNext();
}
}
}
changeStateToPlay() {
this.isPlaying = true;
}
changeStateToPause() {
this.isPlaying = false;
}
convertIndisplayTime(time:number) : string {
let tmpp = parseInt(`${ time}`, 10);
let heures = parseInt(`${ tmpp / 3600}`, 10);
tmpp = tmpp - heures * 3600;
let minutes = parseInt(`${ tmpp / 60}`, 10);
let seconds = tmpp - minutes * 60;
let out = '';
if(heures !== 0) {
out = `${out }${heures }:`;
}
if(minutes >= 10) {
out = `${out }${minutes }:`;
} else {
out = `${out }0${ minutes }:`;
}
if(seconds >= 10) {
out = out + seconds;
} else {
out = `${out }0${ seconds}`;
}
return out;
}
changeTimeupdate(currentTime: any) {
// console.log("time change ");
// console.log(" ==> " + this.audioPlayer.currentTime);
this.currentTime = this.audioPlayer.currentTime;
this.currentTimeDisplay = this.convertIndisplayTime(this.currentTime);
// console.log(" ==> " + this.currentTimeDisplay);
}
changeDurationchange(duration: any) {
console.log('duration change ');
console.log(` ==> ${ this.audioPlayer.duration}`);
this.duration = this.audioPlayer.duration;
this.durationDisplay = this.convertIndisplayTime(this.duration);
}
onPlay() {
console.log('play');
if(this.audioPlayer === null ||
this.audioPlayer === undefined) {
console.log(`error element: ${ this.audioPlayer}`);
return;
}
this.audioPlayer.play();
}
onPause() {
console.log('pause');
if(this.audioPlayer === null ||
this.audioPlayer === undefined) {
console.log(`error element: ${ this.audioPlayer}`);
return;
}
this.audioPlayer.pause();
}
onPauseToggle() {
console.log('pause toggle ...');
if(this.isPlaying === true) {
this.onPause();
} else {
this.onPlay();
}
}
onStop() {
console.log('stop');
if(this.audioPlayer === null ||
this.audioPlayer === undefined) {
console.log(`error element: ${ this.audioPlayer}`);
return;
}
this.audioPlayer.pause();
this.audioPlayer.currentTime = 0;
}
onBefore() {
console.log('before');
if (this.localIdStreaming <= 0) {
console.error("have no previous !!!");
return;
}
this.localIdStreaming--;
this.updateMediaStreamed();
this.playerService.previous();
}
onNext() {
console.log('next');
if (this.localIdStreaming >= this.localListStreaming.length-1) {
console.error("have no next !!!");
return;
}
this.localIdStreaming++;
this.updateMediaStreamed();
this.playerService.next();
}
seek(newValue:any) {
console.log(`seek ${ newValue.value}`);
if(this.audioPlayer === null ||
this.audioPlayer === undefined) {
console.log(`error element: ${ this.audioPlayer}`);
return;
}
this.audioPlayer.currentTime = newValue.value;
}
onRewind() {
console.log('rewind');
if(this.audioPlayer === null ||
this.audioPlayer === undefined) {
console.log(`error element: ${ this.audioPlayer}`);
return;
}
this.audioPlayer.currentTime = this.currentTime - 10;
}
onForward() {
console.log('forward');
if(this.audioPlayer === null ||
this.audioPlayer === undefined) {
console.log(`error element: ${ this.audioPlayer}`);
return;
}
this.audioPlayer.currentTime = this.currentTime + 10;
}
onMore() {
console.log('more');
if(this.audioPlayer === null ||
this.audioPlayer === undefined) {
console.log(`error element: ${ this.audioPlayer}`);
return;
}
}
}

View File

@ -8,12 +8,12 @@
</div>
</div>
<div class="album-small">
Album {{numberAlbum}}
<div class="season-small">
{{prefixName}} {{numberAlbum}}
</div>
<div class="description-small" *ngIf="count > 1">
{{count}} Episodes
</div>
<div class="description-small" *ngIf="count == 1">
{{count}} Episode
</div>
</div>

View File

@ -17,8 +17,10 @@ import { isNullOrUndefined } from 'common/utils';
export class ElementSeasonComponent implements OnInit {
// input parameters
@Input() element:NodeData;
@Input() prefix:String;
numberAlbum: number;
prefixName: string = "";
numberAlbum: string;
count: number;
covers: string[];
description: string;
@ -29,12 +31,13 @@ export class ElementSeasonComponent implements OnInit {
}
ngOnInit() {
this.prefix = this.prefixName??"";
if (isNullOrUndefined(this.element)) {
this.numberAlbum = undefined;
this.covers = undefined;
this.description = undefined;
}
this.numberAlbum = this.element.id;
this.numberAlbum = this.element.name;
this.description = this.element.description;
this.covers = this.dataService.getCoverListThumbnailUrl(this.element.covers);
let self = this;

View File

@ -10,9 +10,9 @@ import { isNullOrUndefined } from 'common/utils';
import { ArtistService, DataService } from 'app/service';
@Component({
selector: 'app-element-artist',
templateUrl: './element-artist.html',
styleUrls: [ './element-artist.less' ]
selector: 'app-element-series',
templateUrl: './element-series.html',
styleUrls: [ './element-series.less' ]
})
export class ElementSeriesComponent implements OnInit {
// input parameters

View File

@ -1,8 +1,6 @@
<div>
<div class="count-base">
<span class="count" *ngIf="counttrack">
{{counttrack}}
</span>
<div class="count-base" *ngIf="counttrack">
<span class="count">{{counttrack}}</span>
</div>
<div class="imgContainer-small">
<div *ngIf="covers">

View File

@ -17,11 +17,12 @@ import { GenderService, DataService } from 'app/service';
export class ElementTypeComponent implements OnInit {
// input parameters
@Input() element:NodeData;
@Input() functionVignette:(number) => Promise<Number>;
public name: string = 'rr';
public description: string;
public counttrack:number;
public counttrack: number;
public covers: string[];
@ -44,11 +45,13 @@ export class ElementTypeComponent implements OnInit {
self.description = this.element.description;
self.covers = self.dataService.getCoverListThumbnailUrl(this.element.covers);
this.typeService.countTrack(this.element.id)
.then((response: number) => {
self.counttrack = response;
}).catch(() => {
self.counttrack = 0;
});
if (!isNullOrUndefined(this.functionVignette)) {
this.functionVignette(this.element.id)
.then((response: number) => {
self.counttrack = response;
}).catch(() => {
self.counttrack = 0;
});
}
}
}

View File

@ -1,5 +1,5 @@
<div>
<div class="trackImgContainer">
<div class="videoImgContainer">
<div *ngIf="covers">
<!--<data-image id="{{cover}}"></data-image>-->
<img src="{{covers[0]}}"/>
@ -19,4 +19,4 @@
{{description}}
</div>
-->
</div>
</div>

View File

@ -147,22 +147,22 @@ export class TopMenuComponent implements OnInit {
onArianeType(event: any): void {
console.log(`onArianeType(${ this.arianeTypeId })`);
this.arianeService.navigateType(this.arianeTypeId, event.which === 2);
//this.arianeService.navigateType(this.arianeTypeId, event.which === 2);
}
onArianePlaylist(event: any): void {
console.log(`onArianePlaylist(${ this.arianePlaylistId })`);
this.arianeService.navigatePlaylist(this.arianePlaylistId, event.which === 2);
//this.arianeService.navigatePlaylist(this.arianePlaylistId, event.which === 2);
}
onArianeArtist(event: any): void {
console.log(`onArianeArtist(${ this.arianeArtistId })`);
this.arianeService.navigateArtist(this.arianeArtistId, event.which === 2);
//this.arianeService.navigateArtist(this.arianeArtistId, event.which === 2);
}
onArianeAlbum(event: any): void {
console.log(`onArianeAlbum(${ this.arianeAlbumId })`);
this.arianeService.navigateAlbum(this.arianeAlbumId, event.which === 2);
//this.arianeService.navigateAlbum(this.arianeAlbumId, event.which === 2);
}
updateEditShow():void {
@ -181,31 +181,31 @@ export class TopMenuComponent implements OnInit {
console.log('onSubEdit()');
this.displayEditMenu = false;
this.displayUserMenu = false;
this.arianeService.navigateTrackEdit(this.arianeTrackId, event.which === 2);
//this.arianeService.navigateTrackEdit(this.arianeTrackId, event.which === 2);
}
onSubEditAlbum(event: any): void {
console.log('onSubEdit()');
this.displayEditMenu = false;
this.displayUserMenu = false;
this.arianeService.navigateAlbumEdit(this.arianeAlbumId, event.which === 2);
//this.arianeService.navigateAlbumEdit(this.arianeAlbumId, event.which === 2);
}
onSubEditArtist(event: any): void {
console.log('onSubEdit()');
this.displayEditMenu = false;
this.displayUserMenu = false;
this.arianeService.navigateArtistEdit(this.arianeArtistId, event.which === 2);
//this.arianeService.navigateArtistEdit(this.arianeArtistId, event.which === 2);
}
onSubEditPlaylist(event: any): void {
console.log('onSubEdit()');
this.displayEditMenu = false;
this.displayUserMenu = false;
this.arianeService.navigatePlaylistEdit(this.arianePlaylistId, event.which === 2);
//this.arianeService.navigatePlaylistEdit(this.arianePlaylistId, event.which === 2);
}
onSubEditType(event: any): void {
console.log('onSubEditType()');
this.displayEditMenu = false;
this.displayUserMenu = false;
this.arianeService.navigateTypeEdit(this.arianeTypeId, event.which === 2);
//this.arianeService.navigateTypeEdit(this.arianeTypeId, event.which === 2);
}
onAddMedia(event: any): void {
console.log('onAddMedia()');

View File

@ -0,0 +1,34 @@
import { isArrayOf, isNumberFinite, isObject, isOptionalOf, isOptionalArrayOf, isString } from "common/utils";
export interface AlbumModel {
id: number;
name: string;
description?: string;
covers?: number[];
tracks?: number[];
};
export function isAlbumModel(data: any): data is AlbumModel {
if (!isObject(data)) {
return false;
}
if (!isNumberFinite(data.id)) {
return false;
}
if (!isString(data.name)) {
return false;
}
if (!isOptionalOf(data.description, isString)) {
return false;
}
if (!isOptionalArrayOf(data.cover, isNumberFinite)) {
return false;
}
if (!isOptionalArrayOf(data.tracks, isNumberFinite)) {
return false;
}
return true;
}

View File

@ -80,6 +80,10 @@ export class AlbumScene implements OnInit {
}
onSelectTrack(event: any, idSelected: number):void {
this.arianeService.navigateTrack(idSelected, event.which === 2, event.ctrlKey);
if (event.ctrlKey === false) {
this.arianeService.navigateTrack({ trackId: idSelected, newWindows:event.which === 2} );
} else {
this.arianeService.navigateTrackEdit({ id: idSelected, newWindows:event.which === 2} );
}
}
}

View File

@ -0,0 +1,26 @@
<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}} / {{albumName}}
</div>
<div class="description" *ngIf="albumDescription">
{{albumDescription}}
</div>
</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-list" (click)="onSelectTrack($event, data.id)" (auxclick)="onSelectTrack($event, data.id)">
<app-element-season [element]="data"></app-element-season>
</div>
</div>
<div class="clear"></div>
</div>

View File

@ -0,0 +1,110 @@
/** @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 { AlbumModel, isAlbumModel } from 'app/model/album';
import { ArtistService, DataService, ArianeService, AlbumService, TrackService, PlayerService } from 'app/service';
import { NodeData } from 'common/model';
@Component({
selector: 'app-artist-album',
templateUrl: './artist-album.html'
})
export class ArtistAlbumScene 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: any[] = undefined;
constructor(
private route: ActivatedRoute,
private artistService: ArtistService,
private albumService: AlbumService,
private trackService: TrackService,
private arianeService: ArianeService,
private playerService: PlayerService,
private dataService: DataService) {
}
ngOnInit() {
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.artistService.get(this.idArtist)
.then((response) => {
self.name = response.name;
self.description = response.description;
self.covers = this.dataService.getCoverListUrl(response.covers);
}).catch((response) => {
self.description = undefined;
self.name = '???';
self.covers = undefined;
// no check just ==> an error occured on album
});
this.albumService.get(this.idAlbum)
.then((response) => {
self.albumName = response.name;
self.albumDescription = response.description;
self.albumCovers = this.dataService.getCoverListUrl(response.covers);
if (isAlbumModel(response)) {
//console.log("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT");
self.tracksIds = (response as AlbumModel).tracks;
}
//console.log("all the tracks: " + self.tracksIds);
this.trackService.getAll(self.tracksIds)
.then((response2: NodeData[]) => {
self.tracks = response2;
//console.log(`>>>>BBB get tracks : ${JSON.stringify(response2, null, 2)}`);
}).catch((response) => {
//console.log(`>>>>BBB plop`);
self.tracks = undefined;
});
}).catch((response) => {
self.albumDescription = undefined;
self.albumName = '???';
self.albumCovers = undefined;
// no check just ==> an error occured on album
});
}
onSelectTrack(event: any, idSelected: number):void {
if (event.ctrlKey === false) {
//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} );
}
}
}

View File

@ -1,11 +1,11 @@
<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 [className]="covers ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
<div class="title">
{{name}}
</div>
@ -14,7 +14,7 @@
</div>
</div>
</div>
<div class="fill-content colomn_mutiple" *ngIf="albums.length != 0">
<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>
@ -22,12 +22,12 @@
<app-element-season [element]="data"></app-element-season>
</div>
</div>
<div class="fill-content colomn_mutiple" *ngIf="tracks.length != 0">
<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 *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"></div>

View File

@ -0,0 +1,87 @@
/** @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 } from 'app/service';
import { NodeData } from 'common/model';
import { isNullOrUndefined } from 'common/utils';
@Component({
selector: 'app-artist',
templateUrl: './artist.html'
})
export class ArtistScene implements OnInit {
public idArtist = -1;
public name: string = '';
public description: string = undefined;
public covers: string[] = undefined;
public albums: NodeData[] = undefined;
public tracks: any[] = undefined;
constructor(
private route: ActivatedRoute,
private artistService: ArtistService,
private arianeService: ArianeService,
private dataService: DataService) {
}
ngOnInit() {
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();
let self = this;
this.artistService.get(this.idArtist)
.then((response) => {
self.name = response.name;
self.description = response.description;
self.covers = this.dataService.getCoverListUrl(response.covers);
}).catch((response) => {
self.name = '???';
self.description = undefined;
self.covers = undefined;
});
//console.log(`get parameter id: ${ this.idArtist}`);
this.artistService.getAlbum(this.idArtist)
.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.navigateArtist({artistId: this.idArtist, albumId: idSelected, newWindows: event.which === 2 } );
}
}
onSelectTrack(event: any, idSelected: number):void {
if (event.ctrlKey === false) {
this.arianeService.navigateTrack({trackId: idSelected, newWindows:event.which === 2} );
} else {
this.arianeService.navigateTrackEdit({ id: idSelected, newWindows:event.which === 2} );
}
}
}

View File

@ -0,0 +1,11 @@
<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">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>
</div>
</div>
<div class="clear"></div>
</div>

View File

@ -0,0 +1,53 @@
/** @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 } from 'app/service';
import { NodeData } from 'common/model';
import { isNullOrUndefined } from 'common/utils';
@Component({
selector: 'app-artists',
templateUrl: './artists.html',
})
export class ArtistsScene implements OnInit {
cover: string = '';
covers: Array<string> = [];
artists: NodeData[];
constructor(
private route: ActivatedRoute,
private artistService: ArtistService,
private arianeService: ArianeService) {
}
ngOnInit() {
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;
//console.log("get artists: " + JSON.stringify(self.artists));
}).catch((response) => {
self.artists = undefined;
});
}
onSelectAlbum(event: any, idSelected: number):void {
if (event.ctrlKey) {
this.arianeService.navigateArtistEdit({id: idSelected, newWindows:event.which === 2} );
} else {
this.arianeService.navigateArtist({artistId: idSelected, newWindows:event.which === 2} );
}
}
}

View File

@ -15,7 +15,7 @@ import { GenderService, DataService, ArianeService } from 'app/service';
styleUrls: [ './gender.less' ]
})
export class TypeScene implements OnInit {
export class GenderScene implements OnInit {
genderId = -1;
name: string = '';
description: string = '';
@ -80,10 +80,18 @@ export class TypeScene implements OnInit {
});
}
onSelectArtist(event: any, idSelected: number):void {
this.arianeService.navigateArtist(idSelected, event.which === 2, event.ctrlKey);
if (event.ctrlKey === false) {
this.arianeService.navigateArtist({ artistId: idSelected, newWindows:event.which === 2} );
} else {
this.arianeService.navigateArtistEdit({ id: idSelected, newWindows:event.which === 2} );
}
}
onSelectTrack(event: any, idSelected: number):void {
this.arianeService.navigateTrack(idSelected, event.which === 2, event.ctrlKey);
if (event.ctrlKey === false) {
this.arianeService.navigateTrack({ trackId: idSelected, newWindows:event.which === 2} );
} else {
this.arianeService.navigateTrackEdit({ id: idSelected, newWindows:event.which === 2} );
}
}
}

View File

@ -1,6 +1,6 @@
<div class="generic-page">
<div class="title">
Karideo
Karusic
</div>
<div class="fill-all colomn_mutiple">
<div *ngFor="let data of dataList" class="item-home" (click)="onSelectType($event, data.id)" (auxclick)="onSelectType($event, data.id)">

View File

@ -15,10 +15,27 @@ import { ArianeService, GenderService } from 'app/service';
styleUrls: [ './home.less' ]
})
export class HomeScene implements OnInit {
dataList = [];
dataList = [
{
id: 1,
name: "Genders",
}, {
id: 2,
name: "Artists",
}, {
id: 3,
name: "Album",
}, {
id: 4,
name: "Tracks",
}, {
id: 5,
name: "Playlist",
},
];
error = '';
constructor(private route: ActivatedRoute,
private typeService: GenderService,
private genderService: GenderService,
private arianeService: ArianeService) {
}
@ -26,7 +43,8 @@ export class HomeScene implements OnInit {
ngOnInit() {
this.arianeService.updateManual(this.route.snapshot.paramMap);
let self = this;
this.typeService.getData()
/*
this.genderService.getData()
.then((response) => {
self.error = '';
self.dataList = response;
@ -36,9 +54,20 @@ export class HomeScene implements OnInit {
console.log(`[E] ${ self.constructor.name }: Does not get a correct response from the server ...`);
self.dataList = [];
});
*/
this.arianeService.reset();
}
onSelectType(_event: any, _idSelected: number):void {
this.arianeService.navigateType(_idSelected, _event.which === 2);
onSelectType(event: any, idSelected: number):void {
if (idSelected === 1) {
this.arianeService.navigateGender({newWindows: event.which === 2});
} else if (idSelected === 2) {
this.arianeService.navigateArtist({newWindows: event.which === 2});
} else if (idSelected === 3) {
this.arianeService.navigateAlbum({newWindows: event.which === 2});
} else if (idSelected === 4) {
this.arianeService.navigateTrack({newWindows: event.which === 2});
} else if (idSelected === 5) {
this.arianeService.navigatePlaylist({newWindows: event.which === 2});
}
}
}

View File

@ -1,14 +1,17 @@
import { TypeScene } from "./gender/gender";
import { GenderScene } from "./gender/gender";
import { HelpScene } from "./help/help";
import { HomeScene } from "./home/home";
import { AlbumEditScene } from "./season-edit/season-edit";
import { AlbumScene } from "./season/season";
import { ArtistEditScene } from "./series-edit/series-edit";
import { ArtistScene } from "./series/series";
import { AlbumEditScene } from "./album-edit/album-edit";
import { AlbumScene } from "./album/album";
import { ArtistEditScene } from "./artist-edit/artist-edit";
import { ArtistScene } from "./artist/artist";
import { ArtistsScene } from "./artist/artists";
import { SettingsScene } from "./settings/settings";
import { PlaylistScene } from "./universe/universe";
import { TrackEditScene } from "./video-edit/video-edit";
import { TrackScene } from "./video/video";
import { PlaylistScene } from "./playlist/playlist";
import { TrackEditScene } from "./track-edit/track-edit";
import { TrackScene } from "./track/track";
import { UploadScene } from "./upload/upload";
import { ArtistAlbumScene } from "./artist/artist-album";
export {
@ -17,12 +20,15 @@ export {
SettingsScene,
AlbumScene,
AlbumEditScene,
ArtistsScene,
ArtistScene,
ArtistAlbumScene,
ArtistEditScene,
TypeScene,
GenderScene,
PlaylistScene,
TrackScene,
TrackEditScene,
UploadScene,
};

View File

@ -1,121 +0,0 @@
/** @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 } from 'app/service';
import { NodeData } from 'common/model';
@Component({
selector: 'app-artist',
templateUrl: './artist.html',
styleUrls: [ './artist.less' ]
})
export class ArtistScene implements OnInit {
idArtist = -1;
name: string = '';
description: string = '';
cover: string = '';
covers: Array<string> = [];
albumsError: string = '';
albums: NodeData[] = [];
tracksError: string = '';
tracks: Array<any> = [];
constructor(
private route: ActivatedRoute,
private artistService: ArtistService,
private arianeService: ArianeService,
private dataService: DataService) {
}
ngOnInit() {
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();
let self = this;
let updateEnded = {
artistMetadata: false,
subSaison: false,
subTrack: false,
};
this.artistService.get(this.idArtist)
.then((response) => {
self.name = response.name;
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]));
}
}
updateEnded.artistMetadata = true;
self.checkIfJumpIsNeeded(updateEnded);
}).catch((response) => {
self.description = '';
self.name = '???';
self.cover = null;
self.covers = [];
// no check just ==> an error occured on album
});
//console.log(`get parameter id: ${ this.idArtist}`);
this.artistService.getAlbum(this.idArtist)
.then((response: NodeData[]) => {
//console.log(`>>>> get album : ${JSON.stringify(response)}`)
self.albumsError = '';
self.albums = response;
updateEnded.subSaison = true;
self.checkIfJumpIsNeeded(updateEnded);
}).catch((response) => {
self.albumsError = 'Can not get the list of album in this artist';
self.albums = [];
updateEnded.subSaison = true;
self.checkIfJumpIsNeeded(updateEnded);
});
this.artistService.getTrack(this.idArtist)
.then((response: NodeData[]) => {
//console.log(`>>>> get track : ${JSON.stringify(response)}`)
self.tracksError = '';
self.tracks = response;
updateEnded.subTrack = true;
self.checkIfJumpIsNeeded(updateEnded);
}).catch((response) => {
self.tracksError = 'Can not get the List of track without album';
self.tracks = [];
updateEnded.subTrack = true;
self.checkIfJumpIsNeeded(updateEnded);
});
}
onSelectAlbum(event: any, idSelected: number):void {
this.arianeService.navigateAlbum(idSelected, event.which === 2, event.ctrlKey);
}
onSelectTrack(event: any, idSelected: number):void {
this.arianeService.navigateTrack(idSelected, event.which === 2, event.ctrlKey);
}
checkIfJumpIsNeeded(updateEnded: { artistMetadata: boolean; subSaison: boolean; subTrack: boolean; }): void {
// all update is ended
if(updateEnded.artistMetadata === false || updateEnded.subSaison === false || updateEnded.subTrack === false) {
return;
}
// no local track
if(this.tracks.length > 0) {
return;
}
// only one album:
if(this.albums.length !== 1) {
return;
}
this.arianeService.navigateAlbum(this.albums[0].id, false, false, true);
}
}

View File

@ -63,7 +63,7 @@
(mousemove)="startHideTimer()"
(fullscreenchange)="onFullscreenChange($event)">
<div class="track-elem">
<track src="{{trackSource}}"
<video src="{{trackSource}}"
#trackPlayer
preload
(play)="changeStateToPlay()"
@ -76,7 +76,7 @@
(ended)="onTrackEnded()"
><!-- controls > --> <!--preload="none"-->
<!--<p>Your browser does not support HTML5 track player. download track: <a href="{{trackSource}}>link here</a>.</p>-->
</track>
</video>
</div>
<div class="controls" *ngIf="!displayNeedHide || !isPlaying">
<button (click)="onPlay()" *ngIf="!isPlaying" ><i class="material-icons">play_arrow</i></button>

View File

@ -108,12 +108,20 @@ export class TrackScene implements OnInit {
}
onRequireNext(event: any) {
console.log(`generate next : ${ this.haveNext.id}`);
this.arianeService.navigateTrack(this.haveNext.id, event.which === 2, event.ctrlKey);
if (event.ctrlKey === false) {
this.arianeService.navigateTrack({ trackId: this.haveNext.id, newWindows:event.which === 2} );
} else {
this.arianeService.navigateTrackEdit({ id: this.haveNext.id, newWindows:event.which === 2} );
}
this.arianeService.setTrack(this.haveNext.id);
}
onRequirePrevious(event: any) {
console.log(`generate previous : ${ this.havePrevious.id}`);
this.arianeService.navigateTrack(this.havePrevious.id, event.which === 2, event.ctrlKey);
if (event.ctrlKey === false) {
this.arianeService.navigateTrack({ trackId: this.haveNext.id, newWindows:event.which === 2} );
} else {
this.arianeService.navigateTrackEdit({ id: this.haveNext.id, newWindows:event.which === 2} );
}
this.arianeService.setTrack(this.havePrevious.id);
}
generateName() {

View File

@ -14,8 +14,8 @@
<td class="left-colomn">format:</td>
<td class="right-colomn">
The format of the media permit to automatic find meta-data:<br/>
Univers:Artist name-sXX-eXX-my name of my media.mkv<br/>
<b>example:</b> Stargate:SG1-s55-e22-Asgard.mkv <br/>
Artist~album#idTrack-my name of my media.webm<br/>
<b>example:</b> Clarika~Moi En Mieux#22-des bulles.webm <br/>
</td>
</tr>
<tr>
@ -24,7 +24,7 @@
<input type="file"
(change)="onChangeFile($event.target)"
placeholder="Select a media file"
accept=".mkv,.webm"
accept=".webm"
width="90%"
multiple/>
</td>
@ -47,23 +47,29 @@
</colgroup>
<tbody>
<tr>
<td class="left-colomn">Type:</td>
<td class="left-colomn">Gender:</td>
<td class="right-colomn">
<select [ngModel]="typeId"
(ngModelChange)="onChangeType($event)"
[class.error]="typeId === undefined">
<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option>
</select>
<input type="text"
placeholder="Genre of the Media"
[value]="globalGender"
(input)="onGenre($event.target.value)"
/>
</td>
</tr>
<tr>
<td class="left-colomn">Playlist:</td>
<td class="left-colomn"></td>
<td class="right-colomn">
<input type="text"
placeholder="Playlist of the Media"
[value]="globalPlaylist"
(input)="onPlaylist($event.target.value)"
/>
<select [ngModel]="genreId"
(ngModelChange)="onChangeGenre($event)">
<option *ngFor="let element of listGender" [ngValue]="element.value">{{element.label}}</option>
</select>
</td>
<td class="tool-colomn">
<!--
<button class="button color-button-normal color-shadow-black" (click)="newArtist()" type="submit">
<i class="material-icons">add_circle_outline</i>
</button>
-->
</td>
</tr>
<tr>
@ -95,14 +101,29 @@
<tr>
<td class="left-colomn">Album:</td>
<td class="right-colomn">
<input type="number"
pattern="[0-9]{0-4}"
placeholder="album of the Media"
<input type="text"
placeholder="Album title"
[value]="globalAlbum"
(input)="onAlbum($event.target.value)"
/>
</td>
</tr>
<tr>
<td class="left-colomn"></td>
<td class="right-colomn">
<select [ngModel]="albumId"
(ngModelChange)="onChangeAlbum($event)">
<option *ngFor="let element of listAlbum" [ngValue]="element.value">{{element.label}}</option>
</select>
</td>
<td class="tool-colomn">
<!--
<button class="button color-button-normal color-shadow-black" (click)="newArtist()" type="submit">
<i class="material-icons">add_circle_outline</i>
</button>
-->
</td>
</tr>
</tbody>
</table>
</div>
@ -116,8 +137,8 @@
</colgroup>
<thead>
<tr>
<th>Episode ID:</th>
<th>Episode Title:</th>
<th>Track ID:</th>
<th>Title:</th>
</tr>
</thead>
<tbody>
@ -126,9 +147,9 @@
<input type="number"
pattern="[0-9]{0-4}"
placeholder="e?"
[value]="data.episode"
(input)="onEpisode(data, $event.target.value)"
[class.error]="data.episodeDetected === true"
[value]="data.trackId"
(input)="onTrackId(data, $event.target.value)"
[class.error]="data.trackIdDetected === true"
/>
</td>
<td class="right-colomn" >
@ -173,8 +194,8 @@
</colgroup>
<thead>
<tr>
<th>Episode ID:</th>
<th>Episode Title:</th>
<th>Track ID:</th>
<th>Title:</th>
</tr>
</thead>
<tbody>

View File

@ -21,13 +21,12 @@ export class ElementList {
export class FileParsedElement {
public isSended: boolean = false;
public nameDetected: boolean = false;
public episodeDetected: boolean = false;
public episodeDetected: boolean = false;s
constructor(
public file: File,
public playlist: string,
public artist: string,
public album: number,
public episode: number,
public album: string,
public trackId: number,
public title: string) {
// nothiing to do.
}
@ -51,7 +50,7 @@ export class UploadScene implements OnInit {
parsedFailedElement: FileFailParsedElement[] = [];
uploadFileValue: string = '';
selectedFiles: FileList;
typeId: number = null;
genderId: number = null;
artistId: number = null;
saisonId: number = null;
needSend: boolean = false;
@ -62,7 +61,7 @@ export class UploadScene implements OnInit {
// section tha define the upload value to display in the pop-in of upload
public upload:UploadProgress = new UploadProgress();
listType: ElementList[] = [
listGender: ElementList[] = [
{ value: null, label: '---' },
];
listPlaylist: ElementList[] = [
@ -95,11 +94,11 @@ export class UploadScene implements OnInit {
listAlbum: ElementList[] = [
{ value: null, label: '---' },
];
globalPlaylist: string = '';
globalGender: string = '';
globalArtist: string = '';
globalAlbum: number = null;
globalAlbum: string = null;
constructor(private route: ActivatedRoute,
private typeService: GenderService,
private genderService: GenderService,
private playlistService: PlaylistService,
private artistService: ArtistService,
private albumService: AlbumService,
@ -120,16 +119,18 @@ export class UploadScene implements OnInit {
this.needSend = false;
}
}
if(this.typeId === undefined || this.typeId === null) {
/*
if(this.genderId === undefined || this.genderId === null) {
this.needSend = false;
}
*/
return this.needSend;
}
ngOnInit() {
this.arianeService.updateManual(this.route.snapshot.paramMap);
let self = this;
this.listType = [ { value: null, label: '---' } ];
this.listGender = [ { value: null, label: '---' } ];
this.listPlaylist = [ { value: null, label: '---' } ];
this.listArtist = [ { value: null, label: '---' } ];
this.listAlbum = [ { value: null, label: '---' } ];
@ -141,10 +142,10 @@ export class UploadScene implements OnInit {
}).catch((response2) => {
console.log(`get response22 : ${ JSON.stringify(response2, null, 2)}`);
});
this.typeService.getData()
this.genderService.getData()
.then((response2) => {
for(let iii = 0; iii < response2.length; iii++) {
self.listType.push({ value: response2[iii].id, label: response2[iii].name });
self.listGender.push({ value: response2[iii].id, label: response2[iii].name });
}
}).catch((response2) => {
console.log(`get response22 : ${ JSON.stringify(response2, null, 2)}`);
@ -159,18 +160,18 @@ export class UploadScene implements OnInit {
private updateType(value: any): void {
console.log(`Change requested of type ... ${ value}`);
if(this.typeId === value) {
if(this.genderId === value) {
return;
}
this.typeId = value;
this.genderId = value;
// this.data.artist_id = null;
// this.data.album_id = null;
this.listArtist = [ { value: null, label: '---' } ];
this.listAlbum = [ { value: null, label: '---' } ];
let self = this;
this.updateNeedSend();
if(this.typeId !== null) {
self.typeService.getSubArtist(this.typeId)
if(this.genderId !== null) {
self.genderService.getSubArtist(this.genderId)
.then((response2) => {
for(let iii = 0; iii < response2.length; iii++) {
self.listArtist.push({ value: response2[iii].id, label: response2[iii].name });
@ -216,13 +217,13 @@ export class UploadScene implements OnInit {
this.updateNeedSend();
}
onPlaylist(value: any): void {
this.globalPlaylist = value;
onGender(value: any): void {
this.globalGender = value;
this.updateNeedSend();
}
onEpisode(data: FileParsedElement, value: any): void {
data.episode = value;
data.trackId = value;
// console.log("change episode ID: " + value + " ==> " + this.parseEpisode.toString());
this.updateNeedSend();
}
@ -253,89 +254,59 @@ export class UploadScene implements OnInit {
clearData() {
this.globalPlaylist = '';
this.globalGender = null;
this.globalArtist = '';
this.globalAlbum = null;
this.parsedElement = [];
this.parsedFailedElement = [];
this.listFileInBdd = null;
this.typeId = null;
this.genderId = null;
this.artistId = null;
this.saisonId = null;
this.listGender = [ { value: null, label: '---' } ];
this.listArtist = [ { value: null, label: '---' } ];
this.listAlbum = [ { value: null, label: '---' } ];
}
addFileWithMetaData(file: File) {
// parsedElement: FileParsedElement[] = [];
let playlist: string = null;
let artist: string = null;
let album: number | null = null;
let episode: number | null = null;
let album: string | null = null;
let trackIdNumber: number | null = null;
let title: string = '';
console.log(`select file ${ file.name}`);
let tmpName = file.name.replace(/[ \t]*-[ \t]*/g, '-');
tmpName = tmpName.replace(/[Ss]([0-9]+)[- \t]+[Ee]([0-9]+)/g, '-s$1-e$2-');
tmpName = tmpName.replace(/[Ee]([0-9]+)[- \t]+[Ss]([0-9]+)/g, '-s$2-e$1-');
tmpName = tmpName.replace(/_/g, '-');
tmpName = tmpName.replace(/--/g, '-');
//tmpName = tmpName.replace(/_/g, '-');
//tmpName = tmpName.replace(/--/g, '-');
console.log(`select file ${ tmpName}`);
const splitElement = tmpName.split('-');
if(splitElement.length === 1) {
title = splitElement[0];
} else {
if(splitElement.length >= 2) {
artist = splitElement[0];
}
splitElement.splice(0, 1);
if(splitElement.length === 1) {
title = splitElement[0];
} else {
while(splitElement.length > 0) {
let element = splitElement[0];
let find = false;
if(album === null) {
if(element.length >= 1 && (element[0] === 's' || element[0] === 'S')) {
element = element.substring(1);
album = parseInt(element, 10);
find = true;
}
}
if(episode === null && find === false) {
if(element.length >= 1 && (element[0] === 'e' || element[0] === 'E')) {
element = element.substring(1);
episode = parseInt(element, 10);
find = true;
}
}
if(find === false) {
if(album === null && episode === null) {
if(playlist === '') {
playlist = element;
} else {
playlist = `${playlist }-${ element}`;
}
} else if(title === '') {
title = element;
} else {
title = `${title }-${ element}`;
}
}
splitElement.splice(0, 1);
}
}
const splitElement = tmpName.split('~');
if(splitElement.length > 1) {
artist = splitElement[0];
tmpName = tmpName.substring(artist.length+1);
}
if(isNaN(episode)) {
episode = null;
const splitElement2 = tmpName.split('\#');
if(splitElement2.length > 1) {
album = splitElement2[0];
tmpName = tmpName.substring(album.length+1);
}
if(isNaN(album)) {
album = null;
console.log("ploppppp " + tmpName);
const splitElement3 = tmpName.split('-');
if(splitElement3.length > 1) {
trackIdNumber = parseInt(splitElement3[0], 10);
tmpName = tmpName.substring(splitElement3[0].length+1);
}
console.log("KKKppppp " + tmpName);
console.log(" ===> " + splitElement3[0]);
title = tmpName;
if(isNaN(trackIdNumber)) {
trackIdNumber = null;
}
// remove extention
title = title.replace(new RegExp('\\.(mkv|MKV|Mkv|webm|WEBM|Webm|mp4)'), '');
let tmp = new FileParsedElement(file, playlist, artist, album, episode, title);
let tmp = new FileParsedElement(file, artist, album, trackIdNumber, title);
console.log(`==>${ JSON.stringify(tmp)}`);
// add it in the list.
this.parsedElement.push(tmp);
@ -357,15 +328,16 @@ export class UploadScene implements OnInit {
}
// we verify fith the first value to remove all unknown ...
// clean different univers:
for(let iii = 1; iii < this.parsedElement.length; iii++) {
console.log(`check playlist [${ iii + 1 }/${ this.parsedElement.length }] '${ this.parsedElement[0].playlist } !== ${ this.parsedElement[iii].playlist }'`);
if(this.parsedElement[0].playlist !== this.parsedElement[iii].playlist) {
this.parsedFailedElement.push(new FileFailParsedElement(this.parsedElement[iii].file, 'Remove from list due to wrong playlist value'));
/*for(let iii = 1; iii < this.parsedElement.length; iii++) {
console.log(`check gender [${ iii + 1 }/${ this.parsedElement.length }] '${ this.parsedElement[0].gender } !== ${ this.parsedElement[iii].gender }'`);
if(this.parsedElement[0].gender !== this.parsedElement[iii].gender) {
this.parsedFailedElement.push(new FileFailParsedElement(this.parsedElement[iii].file, 'Remove from list due to wrong gender value'));
console.log(`Remove from list (!= playlist) : [${ iii + 1 }/${ this.parsedElement.length }] '${ this.parsedElement[iii].file.name }'`);
this.parsedElement.splice(iii, 1);
iii--;
}
}
*/
// clean different artist:
for(let iii = 1; iii < this.parsedElement.length; iii++) {
console.log(`check artist [${ iii + 1 }/${ this.parsedElement.length }] '${ this.parsedElement[0].artist } !== ${ this.parsedElement[iii].artist }'`);
@ -387,7 +359,6 @@ export class UploadScene implements OnInit {
}
}
console.log(`check : ${JSON.stringify(this.parsedElement[0])}`)
this.globalPlaylist = this.parsedElement[0].playlist ?? '';
this.globalArtist = this.parsedElement[0].artist ?? '';
this.globalAlbum = this.parsedElement[0].album ?? null;
@ -438,14 +409,16 @@ export class UploadScene implements OnInit {
self.upload.error = `Error in the upload of the data...${ value}`;
});
}
uploadFile(eleemnent: FileParsedElement, id: number, total: number, sendDone: any, errorOccured: any): void {
uploadFile(elemnent: FileParsedElement, id: number, total: number, sendDone: any, errorOccured: any): void {
let self = this;
self.upload.labelMediaTitle = '';
// add playlist
if(self.globalPlaylist !== null) {
self.upload.labelMediaTitle = self.upload.labelMediaTitle + self.globalPlaylist;
// add gender
/*
if(self.globalGender !== null) {
self.upload.labelMediaTitle = self.upload.labelMediaTitle + self.globalGender;
}
*/
// add artist
if(self.globalArtist !== null) {
if(self.upload.labelMediaTitle.length !== 0) {
@ -461,26 +434,24 @@ export class UploadScene implements OnInit {
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }s${ self.globalAlbum.toString()}`;
}
// add episode ID
if(eleemnent.episode !== null && eleemnent.episode !== undefined && eleemnent.episode.toString().length !== 0) {
if(elemnent.trackId !== null && elemnent.trackId !== undefined && elemnent.trackId.toString().length !== 0) {
if(self.upload.labelMediaTitle.length !== 0) {
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }-`;
}
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }e${ eleemnent.episode.toString()}`;
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }e${ elemnent.trackId.toString()}`;
}
// add title
if(self.upload.labelMediaTitle.length !== 0) {
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }-`;
}
self.upload.labelMediaTitle = `[${ id + 1 }/${ total }]${ self.upload.labelMediaTitle }${eleemnent.title}`;
self.upload.labelMediaTitle = `[${ id + 1 }/${ total }]${ self.upload.labelMediaTitle }${elemnent.title}`;
self.trackService.uploadFile(eleemnent.file,
self.globalPlaylist,
self.trackService.uploadFile(elemnent.file,
self.globalGender,
self.globalArtist,
self.artistId,
self.globalAlbum,
eleemnent.episode,
eleemnent.title,
self.typeId,
elemnent.trackId,
elemnent.title,
(count, totalTmp) => {
// console.log("upload : " + count*100/totalTmp);
self.upload.mediaSendSize = count;
@ -535,7 +506,7 @@ export class UploadScene implements OnInit {
this.parsedElement[iii].nameDetected = true;
this.listFileInBdd[jjj].nameDetected = true;
}
if(this.parsedElement[iii].episode === this.listFileInBdd[jjj].episode) {
if(this.parsedElement[iii].trackId === this.listFileInBdd[jjj].episode) {
this.parsedElement[iii].episodeDetected = true;
this.listFileInBdd[jjj].episodeDetected = true;
}

View File

@ -1,6 +1,7 @@
import { NodeData } from "common/model";
import { HttpWrapperService, BddService } from "common/service";
import { DataInterface, isNullOrUndefined } from "common/utils";
import { DataInterface, isNullOrUndefined, TypeCheck } from "common/utils";
export class GenericInterfaceModelDB {
constructor(
@ -10,6 +11,23 @@ export class GenericInterfaceModelDB {
// nothing to do ...
}
gets(): Promise<NodeData[]> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get(self.serviceName)
.then((response: DataInterface) => {
let data = response.gets();
if(isNullOrUndefined(data)) {
reject('Data does not exist in the local BDD');
return;
}
resolve(data);
return;
}).catch((response) => {
reject(response);
});
});
}
get(id:number): Promise<NodeData> {
let self = this;
return new Promise((resolve, reject) => {
@ -27,6 +45,26 @@ export class GenericInterfaceModelDB {
});
});
}
getAll(ids: number[]): Promise<NodeData[]> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get(self.serviceName)
.then((response: DataInterface) => {
let data = response.getsWhere([
{
check: TypeCheck.EQUAL,
key: 'id',
value: ids,
},
],
[ 'name', 'id' ]);
resolve(data);
return;
}).catch((response) => {
reject(response);
});
});
}
getData(): Promise<NodeData[]> {
let self = this;

View File

@ -5,6 +5,7 @@
*/
import { Injectable } from '@angular/core';
import { AlbumModel } from 'app/model/album';
import { NodeData } from 'common/model';
import { HttpWrapperService, BddService } from 'common/service';

View File

@ -15,6 +15,7 @@ import { AlbumService } from './album';
import { TrackService } from './track';
import { environment } from 'environments/environment';
import { NodeData } from 'common/model';
import { isNullOrUndefined, isUndefined } from 'common/utils';
export class InputOrders {
public genderId: number = null;
@ -313,26 +314,39 @@ export class ArianeService {
/**
* Generic navigation on the browser.
* @param destination - new destination url
* @param playlistId - univers ID
* @param genderId - type IF
* @param artistId - artist real ID
* @param albumId - album ID
* @param trackId - Track ID
* @param ids - list of successives ids
* @param newWindows - open in a new windows
* @param replaceCurrentPage - consider the curent page is removed from history
*/
genericNavigate(
destination:string,
playlistId:number,
genderId:number,
artistId:number,
albumId:number,
trackId:number,
newWindows:boolean = false,
ids:number[],
newWindows?:boolean,
replaceCurrentPage: boolean = false): void {
let addressOffset = `${destination }/${ playlistId }/${ genderId }/${ artistId }/${ albumId }/${ trackId}`;
if(newWindows === true) {
if(environment.frontBaseUrl === undefined || environment.frontBaseUrl === null || environment.frontBaseUrl === '') {
let addressOffset = `${destination }`;
ids.forEach(element => {
if (!isUndefined(element)) {
addressOffset += `/${element}`;
}
});
if(!isNullOrUndefined(newWindows) && newWindows === true) {
if(isNullOrUndefined(environment.frontBaseUrl) || environment.frontBaseUrl === '') {
window.open(`/${ addressOffset}`);
} else {
window.open(`/${ environment.frontBaseUrl }/${ addressOffset}`);
}
} else {
this.router.navigate([ addressOffset ], { replaceUrl: replaceCurrentPage });
}
}
genericNavigateEdit(
destination:string,
id:number,
newWindows?:boolean,
replaceCurrentPage: boolean = false): void {
let addressOffset = `${destination }-edit/${ id }`;
if(!isNullOrUndefined(newWindows) && newWindows === true) {
if(isNullOrUndefined(environment.frontBaseUrl) || environment.frontBaseUrl === '') {
window.open(`/${ addressOffset}`);
} else {
window.open(`/${ environment.frontBaseUrl }/${ addressOffset}`);
@ -342,50 +356,41 @@ export class ArianeService {
}
}
navigatePlaylist(id:number, newWindows:boolean):void {
this.genericNavigate('playlist', id, this.genderId, null, null, null, newWindows);
navigatePlaylist({ id, newWindows}: { id?: number; newWindows?: boolean; }):void {
this.genericNavigate('playlist', [ id ], newWindows);
}
navigatePlaylistEdit(id:number, newWindows:boolean):void {
this.genericNavigate('playlist-edit', id, this.genderId, null, null, null, newWindows);
}
navigateType(id:number, newWindows:boolean, ctrl:boolean = false):void {
if(ctrl === true) {
this.navigateTypeEdit(id, newWindows);
return;
}
this.genericNavigate('type', this.playlistId, id, null, null, null, newWindows);
}
navigateTypeEdit(id:number, newWindows:boolean):void {
this.genericNavigate('type-edit', this.playlistId, id, null, null, null, newWindows);
}
navigateArtist(id:number, newWindows:boolean, ctrl:boolean = false):void {
if(ctrl === true) {
this.navigateArtistEdit(id, newWindows);
return;
}
this.genericNavigate('artist', this.playlistId, this.genderId, id, null, null, newWindows);
}
navigateArtistEdit(id:number, newWindows:boolean):void {
this.genericNavigate('artist-edit', this.playlistId, this.genderId, id, null, null, newWindows);
}
navigateAlbum(id:number, newWindows:boolean, ctrl:boolean = false, replaceCurrentPage: boolean = false):void {
if(ctrl === true) {
this.navigateAlbumEdit(id, newWindows);
return;
}
this.genericNavigate('album', this.playlistId, this.genderId, this.artistId, id, null, newWindows, replaceCurrentPage);
}
navigateAlbumEdit(id:number, newWindows:boolean):void {
this.genericNavigate('album-edit', this.playlistId, this.genderId, this.artistId, id, null, newWindows);
}
navigateTrack(id:number, newWindows:boolean, ctrl:boolean = false):void {
if(ctrl === true) {
this.navigateTrackEdit(id, newWindows);
return;
}
this.genericNavigate('track', this.playlistId, this.genderId, this.artistId, this.albumId, id, newWindows);
}
navigateTrackEdit(id:number, newWindows:boolean):void {
this.genericNavigate('track-edit', this.playlistId, this.genderId, this.artistId, this.albumId, id, newWindows);
navigatePlaylistEdit({ id, newWindows }: { id: number; newWindows?: boolean; }):void {
this.genericNavigateEdit('playlist', id, newWindows);
}
navigateGender({ genderId, newWindows }: { genderId?: number; newWindows?: boolean; }):void {
this.genericNavigate('gender', [ genderId ], newWindows);
}
navigateGenderEdit({ id, newWindows }: { id: number; newWindows?: boolean; }):void {
this.genericNavigateEdit('gender', id, newWindows);
}
navigateAlbum({ genderId, artistId, newWindows }: { genderId?: number; artistId?: number; newWindows?: boolean; }):void {
this.genericNavigate('album', [ genderId, artistId ], newWindows);
}
navigateAlbumEdit({ id, newWindows }: { id: number; newWindows?: boolean; }):void {
this.genericNavigateEdit('album', id, newWindows);
}
navigateArtist({ artistId, albumId, newWindows }: { artistId?: number; albumId?:number, newWindows?: boolean; }):void {
this.genericNavigate('artist', [ artistId, albumId ], newWindows);
}
navigateArtistEdit({ id, newWindows }: { id: number; newWindows?: boolean; }):void {
this.genericNavigateEdit('artist', id, newWindows);
}
navigateTrack({ trackId, newWindows }: { trackId?: number; newWindows?: boolean; }):void {
this.genericNavigate('track', [ trackId ], newWindows);
}
navigateTrackEdit({ id, newWindows }: { id: number; newWindows?: boolean; }):void {
this.genericNavigateEdit('track', id, newWindows);
}
}

View File

@ -34,6 +34,7 @@ export class ArtistService extends GenericInterfaceModelDB {
},
],
[ 'name', 'id' ]);
//data = response.gets();
if (isArrayOf(data, isNodeData)) {
resolve(data);
}
@ -106,16 +107,35 @@ export class ArtistService extends GenericInterfaceModelDB {
getAlbum(id:number): Promise<NodeData[]> {
let self = this;
return new Promise((resolve, reject) => {
self.bdd.get('album')
self.bdd.get('track')
.then((response:DataInterface) => {
//console.log(" <<<========================================>>> " + id);
let data = response.getsWhere([
{
check: TypeCheck.EQUAL,
key: 'parentId',
check: TypeCheck.CONTAINS, //< this is for array containing
key: 'artists',
value: id,
},
], [ 'id' ]);
resolve(data);
//console.log("==> get all tracks of the artist: " + JSON.stringify(data, null, 2));
// extract a single time all value "id" in an array
const listTrack = DataInterface.extractLimitOne(data, "id");
//console.log("==> List Of ids: " + JSON.stringify(listTrack, null, 2));
self.bdd.get('album')
.then((response:DataInterface) => {
let dataAlbum = response.getsWhere([
{
check: TypeCheck.CONTAINS,
key: 'tracks',
value: listTrack,
},
], [ 'name', 'id' ]);
resolve(dataAlbum);
//console.log("==> get all albums: " + JSON.stringify(dataAlbum, null, 2));
return;
}).catch((response) => {
reject(response);
});
return;
}).catch((response) => {
reject(response);

View File

@ -5,6 +5,7 @@ import { ArtistService } from "./artist";
import { GenderService } from "./gender";
import { PlaylistService } from "./playlist";
import { TrackService } from "./track";
import { PlayerService } from "./player";
@ -17,6 +18,7 @@ export {
GenderService,
PlaylistService,
TrackService,
PlayerService,
};

View File

@ -0,0 +1,98 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable, Output, EventEmitter } from '@angular/core';
export function shuffle<T>(array: T[]): T[] {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
};
export interface PlaylistCurrent {
playTrackList: number[];
trackLocalId?: number;
}
@Injectable()
export class PlayerService {
public playTrackId: number = undefined;
public playTrackList: number[] = [];
@Output() playChange: EventEmitter<PlaylistCurrent> = new EventEmitter();
constructor() {
console.log('Start PlayerService');
}
clear(): void {
this.playTrackId = undefined;
this.playTrackList = [];
this.emit();
}
emit() {
console.log(`Emit new playlist local: ${this.playTrackId} in ${this.playTrackList}`)
this.playChange.emit({
trackLocalId: this.playTrackId,
playTrackList: this.playTrackList,
});
}
// Player call (back)
next() {
}
// Player call (back)
previous() {
}
play(id: number) {
this.playTrackList = [id];
this.playTrackId = 0;
this.emit();
}
playInList(id: number, listIds: number[]) {
this.playTrackList = listIds;
this.playTrackId = id;
this.emit();
}
setNewPlaylist(listIds: number[]) {
if (listIds.length == 0) {
this.clear();
return;
}
this.playTrackList = listIds;
this.playTrackId = 0;
this.emit();
}
setNewPlaylistShuffle(listIds: number[]) {
if (listIds.length == 0) {
this.clear();
return;
}
this.playTrackList = shuffle(listIds);
this.playTrackId = 0;
this.emit();
}
addAfterCurent(id: number) {
this.emit();
}
}

View File

@ -33,6 +33,7 @@ export class TrackService extends GenericInterfaceModelDB {
});
});
}
getData(): Promise<Media[]> {
return new Promise((resolve, reject) => {
@ -50,43 +51,26 @@ export class TrackService extends GenericInterfaceModelDB {
}
uploadFile(file:File,
playlist?:string,
gender?:string,
artist?:string,
artistId?:number,
album?:number,
episode?:number,
album?:string,
trackId?:number,
title?:string,
typeId?:number,
progress:any = null) {
const formData = new FormData();
formData.append('fileName', file.name);
// set the file at hte begining it will permit to abort the transmission
formData.append('file', file?? null);
formData.append('playlist', playlist?? null);
if(artistId !== null) {
formData.append('artistId', artistId.toString());
} else {
formData.append('artistId', null);
}
formData.append('gender', gender?? null);
formData.append('artist', artist?? null);
if(album !== null) {
formData.append('album', album.toString());
formData.append('album', album?? null);
if(trackId !== null) {
formData.append('trackId', trackId.toString());
} else {
formData.append('album', null);
}
if(episode !== null) {
formData.append('episode', episode.toString());
} else {
formData.append('episode', null);
formData.append('trackId', null);
}
formData.append('title', title?? null);
if(typeId !== null) {
formData.append('typeId', typeId.toString());
} else {
formData.append('typeId', null);
}
return this.http.uploadMultipart(`${this.serviceName }/upload/`, formData, progress);
}

View File

@ -8,6 +8,7 @@ import { NodeData } from "../model";
import { isArray, isNullOrUndefined } from "./validator";
export enum TypeCheck {
CONTAINS = 'C',
EQUAL = '==',
NOT_EQUAL = '!=',
LESS = '<',
@ -29,6 +30,17 @@ export interface SelectModel {
* @breif Generic interface to access to the BDD (no BDD, direct file IO)
*/
export class DataInterface {
static extractLimitOne(data: NodeData[], key: string): any[] {
const out = [];
for (let iii=0; iii<data.length; iii++) {
const value = data[iii][key];
if(DataInterface.existIn(value, out) === false) {
out.push(value);
}
}
return out;
}
constructor(
private name: string,
private bdd: NodeData[] ) {
@ -136,13 +148,27 @@ export class DataInterface {
return tmp.length;
}
public existIn(value, listValues: number[]|string[]): boolean {
for(let iii = 0; iii < listValues.length; iii++) {
if(value === listValues[iii]) {
return true;
public static existIn(value, listValues: number|string|boolean|number[]|string[]): boolean {
if (isArray(listValues)) {
for(let iii = 0; iii < listValues.length; iii++) {
if(value === listValues[iii]) {
return true;
}
}
return false;
}
return false;
return value === listValues;
}
public static containsOneIn(value: number|string|boolean|number[]|string[], listValues:number|string|boolean|number[]|string[]): boolean {
if (isArray(value)) {
for(let iii = 0; iii < value.length; iii++) {
if(this.existIn(value[iii], listValues) === true) {
return true;
}
}
return false;
}
return this.existIn(value, listValues);
}
public getSubList(values: NodeData[], select?: SelectModel[] ): NodeData[] {
@ -152,19 +178,27 @@ export class DataInterface {
if(select.length === 0) {
find = false;
}
// console.log("Check : " + JSON.stringify(_values[iii_elem], null, 2));
//console.log("Check : " + JSON.stringify(values[iiiElem], null, 2));
for(let iiiSelect = 0; iiiSelect < select.length; iiiSelect++) {
let control = select[iiiSelect];
let valueElement = values[iiiElem][control.key]
//console.log(" valueElement : " + JSON.stringify(valueElement, null, 2));
if(isArray(control.value)) {
if(control.check === TypeCheck.EQUAL) {
if(this.existIn(valueElement, control.value) === false) {
if(control.check === TypeCheck.CONTAINS) {
//console.log("check contains ... " + valueElement + " contains one element in " + control.value);
if(DataInterface.containsOneIn(valueElement, control.value) === false) {
find = false;
break;
}
} else if(control.check === TypeCheck.EQUAL) {
//console.log("check Equals ... " + valueElement + " === " + control.value);
if(DataInterface.existIn(valueElement, control.value) === false) {
find = false;
break;
}
} else if(control.check === TypeCheck.NOT_EQUAL) {
if(this.existIn(valueElement, control.value) === false) {
find = false;
if(DataInterface.existIn(valueElement, control.value) === false) {
find = true;
break;
}
} else {
@ -173,7 +207,13 @@ export class DataInterface {
}
} else {
//console.log(" [" + control.key + "] = " + valueElement);
if(control.check === TypeCheck.EQUAL) {
if(control.check === TypeCheck.CONTAINS) {
//console.log("check Equals ... " + valueElement + " === " + control.value + " #2");
if(DataInterface.containsOneIn(valueElement, control.value) === false) {
find = false;
break;
}
} else if(control.check === TypeCheck.EQUAL) {
if(valueElement !== control.value) {
find = false;
break;

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Karideo</title>
<title>Karusic</title>
<base href="/">
<!-- Some stupid things -->