Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
d44396ccee | |||
11b8b575e4 | |||
dfa245e842 | |||
ed94562372 | |||
5fee3a1390 | |||
96bc7ec052 | |||
94d2fd0fc8 | |||
d8ceaef3f9 | |||
334d68ac1f | |||
e4831e1a17 | |||
e0b81d2122 | |||
95c3c0f968 | |||
154c825499 | |||
5e8b244ebd | |||
48ad545da1 | |||
4b002aaee4 |
@ -1,7 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
version_file="../version.txt"
|
||||
|
||||
# update new release dependency
|
||||
cd back
|
||||
mvn versions:set -DnewVersion=$(cat ../version.txt)
|
||||
# update the Maven version number
|
||||
mvn versions:set -DnewVersion=$(sed 's/dev/SNAPSHOT/g' $version_file)
|
||||
if grep -q "DEV" "$version_file"; then
|
||||
# update all versions release of dependency
|
||||
mvn versions:use-latest-releases
|
||||
# update our manage dependency as snapshoot
|
||||
mvn versions:use-latest-versions -Dincludes=kangaroo-and-rabbit
|
||||
else
|
||||
# update our manage dependency as release (must be done before)
|
||||
mvn versions:use-latest-releases -Dincludes=kangaroo-and-rabbit
|
||||
fi
|
||||
cd -
|
||||
|
||||
|
||||
cd front
|
||||
if grep -q "dev" "$version_file"; then
|
||||
# update all dependency
|
||||
pnpm install
|
||||
pnpm run update_packages
|
||||
else
|
||||
# in case of release ==> can not do it automatically ...
|
||||
echo not implemented
|
||||
fi
|
||||
|
||||
cd -
|
||||
|
||||
|
18
Dockerfile
18
Dockerfile
@ -6,7 +6,7 @@
|
||||
FROM archlinux:base-devel AS builder
|
||||
# update system
|
||||
RUN pacman -Syu --noconfirm && pacman-db-upgrade \
|
||||
&& pacman -S --noconfirm jdk-openjdk maven npm \
|
||||
&& pacman -S --noconfirm jdk-openjdk maven npm pnpm \
|
||||
&& pacman -Scc --noconfirm
|
||||
|
||||
ENV PATH /tmp/node_modules/.bin:$PATH
|
||||
@ -29,14 +29,15 @@ RUN mvn clean compile assembly:single
|
||||
######################################################################################
|
||||
FROM builder AS buildFront
|
||||
|
||||
ADD front/package-lock.json \
|
||||
front/package.json \
|
||||
RUN echo "@kangaroo-and-rabbit:registry=https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/npm/" > /root/.npmrc
|
||||
|
||||
ADD front/package.json \
|
||||
front/karma.conf.js \
|
||||
front/protractor.conf.js \
|
||||
/tmp/
|
||||
|
||||
# install and cache app dependencies
|
||||
RUN npm install
|
||||
RUN pnpm install
|
||||
|
||||
ADD front/e2e \
|
||||
front/tsconfig.json \
|
||||
@ -58,15 +59,6 @@ FROM bellsoft/liberica-openjdk-alpine:latest
|
||||
# add wget to manage the health check...
|
||||
RUN apk add --no-cache wget
|
||||
|
||||
#FROM archlinux:base
|
||||
#RUN pacman -Syu --noconfirm && pacman-db-upgrade
|
||||
## install package
|
||||
#RUN pacman -S --noconfirm jdk-openjdk wget
|
||||
## intall npm
|
||||
#RUN pacman -S --noconfirm npm
|
||||
## clean all the caches Need only on the release environment
|
||||
#RUN pacman -Scc --noconfirm
|
||||
|
||||
ENV LANG=C.UTF-8
|
||||
|
||||
COPY --from=buildBack /tmp/out/maven/*.jar /application/application.jar
|
||||
|
57
back/pom.xml
57
back/pom.xml
@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.kar</groupId>
|
||||
<artifactId>karideo</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
<properties>
|
||||
<maven.compiler.version>3.1</maven.compiler.version>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
@ -20,12 +20,17 @@
|
||||
<dependency>
|
||||
<groupId>kangaroo-and-rabbit</groupId>
|
||||
<artifactId>archidata</artifactId>
|
||||
<version>0.6.1</version>
|
||||
<version>0.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>2.0.9</version>
|
||||
<version>2.1.0-alpha1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>2.17.1</version>
|
||||
</dependency>
|
||||
<!--
|
||||
************************************************************
|
||||
@ -35,15 +40,25 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.10.1</version>
|
||||
<version>5.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.10.1</version>
|
||||
<version>5.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.revelc.code.formatter</groupId>
|
||||
<artifactId>formatter-maven-plugin</artifactId>
|
||||
<version>2.24.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
@ -180,24 +195,10 @@
|
||||
<mainClass>org.kar.karideo.WebLauncher</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Check the style of the code -->
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<configLocation>CheckStyle.xml</configLocation>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failOnViolation>true</failOnViolation>
|
||||
<failsOnError>true</failsOnError>
|
||||
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>net.revelc.code.formatter</groupId>
|
||||
<artifactId>formatter-maven-plugin</artifactId>
|
||||
<version>2.12.2</version>
|
||||
<version>2.23.0</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<lineEnding>LF</lineEnding>
|
||||
@ -221,7 +222,23 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||
<version>4.8.5.0</version>
|
||||
<configuration>
|
||||
<includeFilterFile>spotbugs-security-include.xml</includeFilterFile>
|
||||
<excludeFilterFile>spotbugs-security-exclude.xml</excludeFilterFile>
|
||||
<!--<plugins>
|
||||
<plugin>
|
||||
<groupId>com.h3xstream.findsecbugs</groupId>
|
||||
<artifactId>findsecbugs-plugin</artifactId>
|
||||
<version>1.12.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
-->
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<!-- Generate Java-docs As Part Of Project Reports -->
|
||||
|
@ -10,10 +10,7 @@ import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.kar.archidata.GlobalConfiguration;
|
||||
import org.kar.archidata.UpdateJwtPublicKey;
|
||||
import org.kar.archidata.api.DataResource;
|
||||
import org.kar.archidata.catcher.ExceptionCatcher;
|
||||
import org.kar.archidata.catcher.FailExceptionCatcher;
|
||||
import org.kar.archidata.catcher.InputExceptionCatcher;
|
||||
import org.kar.archidata.catcher.SystemExceptionCatcher;
|
||||
import org.kar.archidata.catcher.GenericCatcher;
|
||||
import org.kar.archidata.db.DBConfig;
|
||||
import org.kar.archidata.filter.CORSFilter;
|
||||
import org.kar.archidata.filter.OptionFilter;
|
||||
@ -21,17 +18,18 @@ import org.kar.archidata.migration.MigrationEngine;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.karideo.api.Front;
|
||||
import org.kar.karideo.api.HealthCheck;
|
||||
import org.kar.karideo.api.MediaResource;
|
||||
import org.kar.karideo.api.SeasonResource;
|
||||
import org.kar.karideo.api.SeriesResource;
|
||||
import org.kar.karideo.api.TypeResource;
|
||||
import org.kar.karideo.api.UserMediaAdvancementResource;
|
||||
import org.kar.karideo.api.UserResource;
|
||||
import org.kar.karideo.api.VideoResource;
|
||||
import org.kar.karideo.filter.KarideoAuthenticationFilter;
|
||||
import org.kar.karideo.migration.Initialization;
|
||||
import org.kar.karideo.migration.Migration20230810;
|
||||
import org.kar.karideo.migration.Migration20231015;
|
||||
import org.kar.karideo.migration.Migration20231126;
|
||||
import org.kar.karideo.migration.Migration20240226;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -60,7 +58,7 @@ public class WebLauncher {
|
||||
migrationEngine.add(new Migration20230810());
|
||||
migrationEngine.add(new Migration20231015());
|
||||
migrationEngine.add(new Migration20231126());
|
||||
//migrationEngine.add(new Migration20231126());
|
||||
migrationEngine.add(new Migration20240226());
|
||||
WebLauncher.LOGGER.info("Migrate the DB [START]");
|
||||
migrationEngine.migrateWaitAdmin(GlobalConfiguration.dbConfig);
|
||||
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
|
||||
@ -94,17 +92,14 @@ public class WebLauncher {
|
||||
// global authentication system
|
||||
rc.register(KarideoAuthenticationFilter.class);
|
||||
// register exception catcher
|
||||
rc.register(InputExceptionCatcher.class);
|
||||
rc.register(SystemExceptionCatcher.class);
|
||||
rc.register(FailExceptionCatcher.class);
|
||||
rc.register(ExceptionCatcher.class);
|
||||
GenericCatcher.addAll(rc);
|
||||
// add default resource:
|
||||
rc.register(UserResource.class);
|
||||
rc.register(SeriesResource.class);
|
||||
rc.register(DataResource.class);
|
||||
rc.register(SeasonResource.class);
|
||||
rc.register(TypeResource.class);
|
||||
rc.register(VideoResource.class);
|
||||
rc.register(MediaResource.class);
|
||||
rc.register(UserMediaAdvancementResource.class);
|
||||
|
||||
rc.register(HealthCheck.class);
|
||||
|
@ -1,7 +1,20 @@
|
||||
|
||||
package org.kar.karideo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.api.DataResource;
|
||||
import org.kar.archidata.externalRestApi.AnalyzeApi;
|
||||
import org.kar.archidata.externalRestApi.TsGenerateApi;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.karideo.api.Front;
|
||||
import org.kar.karideo.api.HealthCheck;
|
||||
import org.kar.karideo.api.MediaResource;
|
||||
import org.kar.karideo.api.SeasonResource;
|
||||
import org.kar.karideo.api.SeriesResource;
|
||||
import org.kar.karideo.api.TypeResource;
|
||||
import org.kar.karideo.api.UserMediaAdvancementResource;
|
||||
import org.kar.karideo.api.UserResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -10,7 +23,18 @@ public class WebLauncherLocal extends WebLauncher {
|
||||
|
||||
private WebLauncherLocal() {}
|
||||
|
||||
public static void main(final String[] args) throws InterruptedException {
|
||||
public static void generateObjects() throws Exception {
|
||||
LOGGER.info("Generate APIs");
|
||||
final List<Class<?>> listOfResources = List.of(Front.class, HealthCheck.class, SeasonResource.class, SeriesResource.class, TypeResource.class, UserMediaAdvancementResource.class,
|
||||
UserResource.class, MediaResource.class, DataResource.class);
|
||||
final AnalyzeApi api = new AnalyzeApi();
|
||||
api.addAllApi(listOfResources);
|
||||
TsGenerateApi.generateApi(api, "../front/src/app/back-api/");
|
||||
LOGGER.info("Generate APIs (DONE)");
|
||||
}
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
generateObjects();
|
||||
final WebLauncherLocal launcher = new WebLauncherLocal();
|
||||
launcher.process();
|
||||
LOGGER.info("end-configure the server & wait finish process:");
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.kar.karideo.api;
|
||||
|
||||
|
||||
import org.kar.archidata.api.FrontGeneric;
|
||||
|
||||
import jakarta.ws.rs.Path;
|
||||
|
@ -6,6 +6,7 @@ import org.kar.archidata.tools.JWTWrapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
@ -18,11 +19,13 @@ import jakarta.ws.rs.core.Response;
|
||||
public class HealthCheck {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(HealthCheck.class);
|
||||
|
||||
public record HealthResult(
|
||||
String value) {};
|
||||
public record HealthResult(String value) {
|
||||
|
||||
};
|
||||
|
||||
@GET
|
||||
@PermitAll
|
||||
@Operation(description = "Get the server state (health)", tags = "SYSTEM")
|
||||
public HealthResult getHealth() throws FailException {
|
||||
if (JWTWrapper.getPublicKeyJson() == null && !ConfigBaseVariable.getTestMode()) {
|
||||
throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Missing Jwt public token");
|
||||
|
@ -4,12 +4,15 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
import org.kar.archidata.annotation.AsyncType;
|
||||
import org.kar.archidata.annotation.TypeScriptProgress;
|
||||
import org.kar.archidata.api.DataResource;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnDataJson;
|
||||
import org.kar.archidata.exception.FailException;
|
||||
import org.kar.archidata.exception.InputException;
|
||||
import org.kar.archidata.model.Data;
|
||||
@ -21,6 +24,7 @@ import org.kar.karideo.model.Type;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
@ -31,22 +35,23 @@ import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/video")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public class VideoResource {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(VideoResource.class);
|
||||
@Path("/media")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class MediaResource {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(MediaResource.class);
|
||||
|
||||
@GET
|
||||
@RolesAllowed("USER")
|
||||
public List<Media> get() throws Exception {
|
||||
@Operation(description = "Get all Media", tags = "GLOBAL")
|
||||
public List<Media> gets() throws Exception {
|
||||
return DataAccess.gets(Media.class);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
@Operation(description = "Get a specific Media with his ID", tags = "GLOBAL")
|
||||
public Media get(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Media.class, id);
|
||||
}
|
||||
@ -55,8 +60,9 @@ public class VideoResource {
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Media put(@PathParam("id") final Long id, final String jsonRequest) throws Exception {
|
||||
System.out.println("update video " + id + " ==> '" + jsonRequest + "'");
|
||||
@Operation(description = "Modify a specific Media", tags = "GLOBAL")
|
||||
public Media patch(@PathParam("id") final Long id, @AsyncType(Media.class) final String jsonRequest) throws Exception {
|
||||
LOGGER.info("update video {} ==> '{}'", id, jsonRequest);
|
||||
DataAccess.updateWithJson(Media.class, id, jsonRequest);
|
||||
return DataAccess.get(Media.class, id);
|
||||
}
|
||||
@ -75,13 +81,22 @@ public class VideoResource {
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/upload/")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
public Response uploadFile(@FormDataParam("fileName") String fileName, @FormDataParam("universe") String universe, @FormDataParam("series") String series,
|
||||
//@FormDataParam("seriesId") String seriesId, Not used ...
|
||||
@FormDataParam("season") String season, @FormDataParam("episode") String episode, @FormDataParam("title") String title, @FormDataParam("typeId") String typeId,
|
||||
@FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws FailException {
|
||||
@Operation(description = "Create a new Media", tags = "GLOBAL")
|
||||
@TypeScriptProgress
|
||||
public Media uploadFile( //
|
||||
@FormDataParam("fileName") String fileName, //
|
||||
@FormDataParam("universe") String universe, //
|
||||
@FormDataParam("series") String series, //
|
||||
// @FormDataParam("seriesId") String seriesId, // Not used ...
|
||||
@FormDataParam("season") String season, //
|
||||
@FormDataParam("episode") String episode, //
|
||||
@FormDataParam("title") String title, //
|
||||
@FormDataParam("typeId") String typeId, //
|
||||
@FormDataParam("file") final InputStream fileInputStream, //
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData //
|
||||
) throws FailException {
|
||||
try {
|
||||
// correct input string stream :
|
||||
fileName = multipartCorrection(fileName);
|
||||
@ -93,16 +108,16 @@ public class VideoResource {
|
||||
typeId = multipartCorrection(typeId);
|
||||
|
||||
// public NodeSmall uploadFile(final FormDataMultiPart form) {
|
||||
System.out.println("Upload media file: " + fileMetaData);
|
||||
System.out.println(" - fileName: " + fileName);
|
||||
System.out.println(" - universe: " + universe);
|
||||
System.out.println(" - series: " + series);
|
||||
System.out.println(" - season: " + season);
|
||||
System.out.println(" - episode: " + episode);
|
||||
System.out.println(" - title: " + title);
|
||||
System.out.println(" - type: " + typeId);
|
||||
System.out.println(" - fileInputStream: " + fileInputStream);
|
||||
System.out.println(" - fileMetaData: " + fileMetaData);
|
||||
LOGGER.info("Upload media file: {}", fileMetaData);
|
||||
LOGGER.info(" - fileName: {}", fileName);
|
||||
LOGGER.info(" - universe: {}", universe);
|
||||
LOGGER.info(" - series: {}", series);
|
||||
LOGGER.info(" - season: {}", season);
|
||||
LOGGER.info(" - episode: {}", episode);
|
||||
LOGGER.info(" - title: {}", title);
|
||||
LOGGER.info(" - type: {}", typeId);
|
||||
LOGGER.info(" - fileInputStream: {}", fileInputStream);
|
||||
LOGGER.info(" - fileMetaData: {}", fileMetaData);
|
||||
System.out.flush();
|
||||
if (typeId == null) {
|
||||
throw new InputException("typeId", "TypiId is not specified");
|
||||
@ -112,7 +127,7 @@ public class VideoResource {
|
||||
final 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 ... ");
|
||||
LOGGER.info("Need to add the data in the BDD ... ");
|
||||
System.out.flush();
|
||||
try {
|
||||
data = DataResource.createNewData(tmpUID, fileName, sha512);
|
||||
@ -121,33 +136,33 @@ public class VideoResource {
|
||||
ex.printStackTrace();
|
||||
throw new FailException("can not create input media (the data model has an internal error");
|
||||
}
|
||||
} else if (data.deleted) {
|
||||
System.out.println("Data already exist but deleted");
|
||||
} else if (data != null && data.deleted != null && data.deleted) {
|
||||
LOGGER.info("Data already exist but deleted");
|
||||
System.out.flush();
|
||||
DataResource.undelete(data.id);
|
||||
DataTools.undelete(data.uuid);
|
||||
data.deleted = false;
|
||||
} else {
|
||||
System.out.println("Data already exist ... all good");
|
||||
LOGGER.info("Data already exist ... all good");
|
||||
System.out.flush();
|
||||
}
|
||||
// Fist step: retive all the Id of each parents:...
|
||||
System.out.println("Find typeNode");
|
||||
// Fist step: retieve all the Id of each parents:...
|
||||
LOGGER.info("Find typeNode");
|
||||
// check if id of type exist:
|
||||
final Type typeNode = TypeResource.getId(Long.parseLong(typeId));
|
||||
if (typeNode == null) {
|
||||
DataResource.removeTemporaryFile(tmpUID);
|
||||
throw new InputException("typeId", "TypeId does not exist ...");
|
||||
}
|
||||
System.out.println(" ==> " + typeNode);
|
||||
System.out.println("Find seriesNode");
|
||||
LOGGER.info(" ==> {}", typeNode);
|
||||
LOGGER.info("Find seriesNode");
|
||||
// get uid of group:
|
||||
Series seriesNode = null;
|
||||
if (series != null) {
|
||||
seriesNode = SeriesResource.getOrCreate(series, typeNode.id);
|
||||
}
|
||||
|
||||
System.out.println(" ==> " + seriesNode);
|
||||
System.out.println("Find seasonNode");
|
||||
LOGGER.info(" ==> {}", seriesNode);
|
||||
LOGGER.info("Find seasonNode");
|
||||
// get uid of season:
|
||||
Season seasonNode = null;
|
||||
if (seriesNode == null && season != null) {
|
||||
@ -158,14 +173,13 @@ public class VideoResource {
|
||||
seasonNode = SeasonResource.getOrCreate(season, seriesNode.id);
|
||||
}
|
||||
|
||||
System.out.println(" ==> " + seasonNode);
|
||||
System.out.println("add media");
|
||||
LOGGER.info(" ==> {}", seasonNode);
|
||||
LOGGER.info("add media");
|
||||
|
||||
final long uniqueSQLID = -1;
|
||||
try {
|
||||
final Media media = new Media();
|
||||
media.name = title;
|
||||
media.dataId = data.id;
|
||||
media.dataId = data.uuid;
|
||||
media.typeId = typeNode.id;
|
||||
media.seriesId = null;
|
||||
if (seriesNode != null) {
|
||||
@ -180,44 +194,56 @@ public class VideoResource {
|
||||
media.episode = Integer.parseInt(episode);
|
||||
}
|
||||
final Media out = DataAccess.insert(media);
|
||||
DataResource.removeTemporaryFile(tmpUID);
|
||||
System.out.println("uploaded .... compleate: " + uniqueSQLID);
|
||||
final Media creation = get(uniqueSQLID);
|
||||
return Response.ok(creation).build();
|
||||
LOGGER.info("Generate new media {}", out);
|
||||
return out;
|
||||
} catch (final SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
System.out.println("Catch error:" + ex.getMessage());
|
||||
LOGGER.error("Catch error: {}", ex.getMessage());
|
||||
throw new FailException("Catch SQLerror ==> check server logs");
|
||||
} finally {
|
||||
DataResource.removeTemporaryFile(tmpUID);
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
System.out.println("Catch an unexpected error ... " + ex.getMessage());
|
||||
LOGGER.error("Catch an unexpected error ... {} ", ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
throw new FailException("Catch Exception ==> check server logs");
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{id}/add_cover")
|
||||
@Path("{id}/cover")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData) {
|
||||
return DataTools.uploadCover(Media.class, id, fileName, fileInputStream, fileMetaData);
|
||||
@AsyncType(Media.class)
|
||||
@Operation(description = "Upload a new season cover media", tags = "GLOBAL")
|
||||
@TypeScriptProgress
|
||||
public Media uploadCover( //
|
||||
@PathParam("id") final Long id, //
|
||||
@FormDataParam("fileName") final String fileName, //
|
||||
@FormDataParam("file") final InputStream fileInputStream, //
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData//
|
||||
) throws Exception {
|
||||
DataTools.uploadCover(Media.class, id, fileName, fileInputStream, fileMetaData);
|
||||
return DataAccess.get(Media.class, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/rm_cover/{coverId}")
|
||||
@DELETE
|
||||
@Path("{id}/cover/{coverId}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception {
|
||||
AddOnManyToMany.removeLink(Media.class, id, "cover", coverId);
|
||||
return Response.ok(DataAccess.get(Media.class, id)).build();
|
||||
@Operation(description = "Remove a specific cover of a media", tags = "GLOBAL")
|
||||
public Media removeCover( //
|
||||
@PathParam("id") final Long id, //
|
||||
@PathParam("coverId") final UUID coverId //
|
||||
) throws Exception {
|
||||
AddOnDataJson.removeLink(Media.class, id, "covers", coverId);
|
||||
return DataAccess.get(Media.class, id);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response delete(@PathParam("id") final Long id) throws Exception {
|
||||
@Operation(description = "Remove a specific Media", tags = "GLOBAL")
|
||||
public void remove(@PathParam("id") final Long id) throws Exception {
|
||||
DataAccess.delete(Media.class, id);
|
||||
return Response.ok().build();
|
||||
}
|
||||
}
|
@ -2,19 +2,23 @@ package org.kar.karideo.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
import org.kar.archidata.annotation.AsyncType;
|
||||
import org.kar.archidata.annotation.TypeScriptProgress;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryAnd;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnDataJson;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.tools.DataTools;
|
||||
import org.kar.karideo.model.Season;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
@ -25,23 +29,16 @@ import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/season")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class SeasonResource {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(SeasonResource.class);
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
public static Season getWithId(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Season.class, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@RolesAllowed("USER")
|
||||
public List<Season> get() throws Exception {
|
||||
@Operation(description = "Get a specific Season with his ID", tags = "GLOBAL")
|
||||
public List<Season> gets() throws Exception {
|
||||
return DataAccess.gets(Season.class);
|
||||
}
|
||||
|
||||
@ -49,26 +46,27 @@ public class SeasonResource {
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(description = "Get all season", tags = "GLOBAL")
|
||||
public Season get(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Season.class, id);
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
* ADMIN SECTION:
|
||||
* ============================================================================= */
|
||||
/* ============================================================================= ADMIN SECTION: ============================================================================= */
|
||||
|
||||
@POST
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Season put(final String jsonRequest) throws Exception {
|
||||
return DataAccess.insertWithJson(Season.class, jsonRequest);
|
||||
@Operation(description = "Create a new season", tags = "GLOBAL")
|
||||
public Season post(final Season jsonRequest) throws Exception {
|
||||
return DataAccess.insert(jsonRequest);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Season put(@PathParam("id") final Long id, final String jsonRequest) throws Exception {
|
||||
@Operation(description = "Modify a specific season", tags = "GLOBAL")
|
||||
public Season patch(@PathParam("id") final Long id, @AsyncType(Season.class) final String jsonRequest) throws Exception {
|
||||
DataAccess.updateWithJson(Season.class, id, jsonRequest);
|
||||
return DataAccess.get(Season.class, id);
|
||||
}
|
||||
@ -76,26 +74,30 @@ public class SeasonResource {
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response delete(@PathParam("id") final Long id) throws Exception {
|
||||
@Operation(description = "Remove a specific season", tags = "GLOBAL")
|
||||
public void remove(@PathParam("id") final Long id) throws Exception {
|
||||
DataAccess.delete(Season.class, id);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{id}/add_cover")
|
||||
@Path("{id}/cover")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData) {
|
||||
return DataTools.uploadCover(Season.class, id, fileName, fileInputStream, fileMetaData);
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Operation(description = "Upload a new season cover season", tags = "GLOBAL")
|
||||
@TypeScriptProgress
|
||||
public Season uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
|
||||
DataTools.uploadCover(Season.class, id, fileName, fileInputStream, fileMetaData);
|
||||
return DataAccess.get(Season.class, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/rm_cover/{coverId}")
|
||||
@DELETE
|
||||
@Path("{id}/cover/{coverId}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception {
|
||||
AddOnManyToMany.removeLink(Season.class, id, "cover", coverId);
|
||||
return Response.ok(DataAccess.get(Season.class, id)).build();
|
||||
@Operation(description = "Remove a specific cover of a season", tags = "GLOBAL")
|
||||
public Season removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
|
||||
AddOnDataJson.removeLink(Season.class, id, "covers", coverId);
|
||||
return DataAccess.get(Season.class, id);
|
||||
}
|
||||
|
||||
public static Season getOrCreate(final String name, final Long seriesId) {
|
||||
|
@ -2,19 +2,23 @@ package org.kar.karideo.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
import org.kar.archidata.annotation.AsyncType;
|
||||
import org.kar.archidata.annotation.TypeScriptProgress;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryAnd;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnDataJson;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.tools.DataTools;
|
||||
import org.kar.karideo.model.Series;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
@ -25,23 +29,16 @@ import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/series")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class SeriesResource {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(SeriesResource.class);
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
public static Series getWithId(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Series.class, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@RolesAllowed("USER")
|
||||
public List<Series> get() throws Exception {
|
||||
@Operation(description = "Get all Series", tags = "GLOBAL")
|
||||
public List<Series> gets() throws Exception {
|
||||
return DataAccess.gets(Series.class);
|
||||
}
|
||||
|
||||
@ -49,26 +46,27 @@ public class SeriesResource {
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(description = "Get a specific Series with his ID", tags = "GLOBAL")
|
||||
public Series get(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Series.class, id);
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
* ADMIN SECTION:
|
||||
* ============================================================================= */
|
||||
/* ============================================================================= ADMIN SECTION: ============================================================================= */
|
||||
|
||||
@POST
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Series put(final String jsonRequest) throws Exception {
|
||||
return DataAccess.insertWithJson(Series.class, jsonRequest);
|
||||
@Operation(description = "Create a new Series", tags = "GLOBAL")
|
||||
public Series post(final Series jsonRequest) throws Exception {
|
||||
return DataAccess.insert(jsonRequest);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Series put(@PathParam("id") final Long id, final String jsonRequest) throws Exception {
|
||||
@Operation(description = "Modify a specific Series", tags = "GLOBAL")
|
||||
public Series patch(@PathParam("id") final Long id, @AsyncType(Series.class) final String jsonRequest) throws Exception {
|
||||
DataAccess.updateWithJson(Series.class, id, jsonRequest);
|
||||
return DataAccess.get(Series.class, id);
|
||||
}
|
||||
@ -76,26 +74,30 @@ public class SeriesResource {
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response delete(@PathParam("id") final Long id) throws Exception {
|
||||
@Operation(description = "Remove a specific Series", tags = "GLOBAL")
|
||||
public void remove(@PathParam("id") final Long id) throws Exception {
|
||||
DataAccess.delete(Series.class, id);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{id}/add_cover")
|
||||
@Path("{id}/cover")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData) {
|
||||
return DataTools.uploadCover(Series.class, id, fileName, fileInputStream, fileMetaData);
|
||||
@Operation(description = "Upload a new season cover Series", tags = "GLOBAL")
|
||||
@TypeScriptProgress
|
||||
public Series uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
|
||||
DataTools.uploadCover(Series.class, id, fileName, fileInputStream, fileMetaData);
|
||||
return DataAccess.get(Series.class, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/rm_cover/{coverId}")
|
||||
@DELETE
|
||||
@Path("{id}/cover/{coverId}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception {
|
||||
AddOnManyToMany.removeLink(Series.class, id, "cover", coverId);
|
||||
return Response.ok(DataAccess.get(Series.class, id)).build();
|
||||
@Operation(description = "Remove a specific Series of a season", tags = "GLOBAL")
|
||||
public Series removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
|
||||
AddOnDataJson.removeLink(Series.class, id, "covers", coverId);
|
||||
return DataAccess.get(Series.class, id);
|
||||
}
|
||||
|
||||
public static Series getOrCreate(final String name, final Long typeId) {
|
||||
|
@ -2,18 +2,22 @@ package org.kar.karideo.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
import org.kar.archidata.annotation.AsyncType;
|
||||
import org.kar.archidata.annotation.TypeScriptProgress;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnDataJson;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.tools.DataTools;
|
||||
import org.kar.karideo.model.Type;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
@ -24,23 +28,16 @@ import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/type")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class TypeResource {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(TypeResource.class);
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
public static Type getWithId(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Type.class, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@RolesAllowed("USER")
|
||||
public List<Type> get() throws Exception {
|
||||
@Operation(description = "Get all Type", tags = "GLOBAL")
|
||||
public List<Type> gets() throws Exception {
|
||||
return DataAccess.gets(Type.class);
|
||||
}
|
||||
|
||||
@ -48,6 +45,7 @@ public class TypeResource {
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(description = "Get a specific Type with his ID", tags = "GLOBAL")
|
||||
public Type get(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Type.class, id);
|
||||
}
|
||||
@ -56,22 +54,22 @@ public class TypeResource {
|
||||
return DataAccess.get(Type.class, id);
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
* ADMIN SECTION:
|
||||
* ============================================================================= */
|
||||
/* ============================================================================= ADMIN SECTION: ============================================================================= */
|
||||
|
||||
@POST
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Type put(final String jsonRequest) throws Exception {
|
||||
return DataAccess.insertWithJson(Type.class, jsonRequest);
|
||||
@Operation(description = "Create a new Type", tags = "GLOBAL")
|
||||
public Type post(final Type jsonRequest) throws Exception {
|
||||
return DataAccess.insert(jsonRequest);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Type put(@PathParam("id") final Long id, final String jsonRequest) throws Exception {
|
||||
@Operation(description = "Modify a specific Type", tags = "GLOBAL")
|
||||
public Type patch(@PathParam("id") final Long id, @AsyncType(Type.class) final String jsonRequest) throws Exception {
|
||||
DataAccess.updateWithJson(Type.class, id, jsonRequest);
|
||||
return DataAccess.get(Type.class, id);
|
||||
}
|
||||
@ -79,26 +77,30 @@ public class TypeResource {
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response delete(@PathParam("id") final Long id) throws Exception {
|
||||
@Operation(description = "Remove a specific Type", tags = "GLOBAL")
|
||||
public void remove(@PathParam("id") final Long id) throws Exception {
|
||||
DataAccess.delete(Type.class, id);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{id}/add_cover")
|
||||
@Path("{id}/cover")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData) {
|
||||
return DataTools.uploadCover(Type.class, id, fileName, fileInputStream, fileMetaData);
|
||||
@Operation(description = "Upload a new season cover Type", tags = "GLOBAL")
|
||||
@TypeScriptProgress
|
||||
public Type uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
|
||||
DataTools.uploadCover(Type.class, id, fileName, fileInputStream, fileMetaData);
|
||||
return DataAccess.get(Type.class, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/rm_cover/{coverId}")
|
||||
@DELETE
|
||||
@Path("{id}/cover/{coverId}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception {
|
||||
AddOnManyToMany.removeLink(Type.class, id, "cover", coverId);
|
||||
return Response.ok(DataAccess.get(Type.class, id)).build();
|
||||
@Operation(description = "Remove a specific cover of a type", tags = "GLOBAL")
|
||||
public Type removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
|
||||
AddOnDataJson.removeLink(Type.class, id, "covers", coverId);
|
||||
return DataAccess.get(Type.class, id);
|
||||
}
|
||||
|
||||
public static Type getOrCreate(final String name) {
|
||||
|
@ -11,6 +11,7 @@ import org.kar.karideo.model.UserMediaAdvancement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
@ -21,37 +22,34 @@ import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
|
||||
@Path("/advancement")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class UserMediaAdvancementResource {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(UserMediaAdvancementResource.class);
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
public UserMediaAdvancement getWithId(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception {
|
||||
@Operation(description = "Get a specific user advancement with his ID", tags = "GLOBAL")
|
||||
public UserMediaAdvancement get(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception {
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
return DataAccess.getWhere(UserMediaAdvancement.class, new Condition(new QueryAnd(new QueryCondition("mediaId", "=", id), new QueryCondition("userId", "=", gc.userByToken.id))));
|
||||
}
|
||||
|
||||
@GET
|
||||
@RolesAllowed("USER")
|
||||
@Operation(description = "Get all user advancement", tags = "GLOBAL")
|
||||
public List<UserMediaAdvancement> gets(@Context final SecurityContext sc) throws Exception {
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
return DataAccess.getsWhere(UserMediaAdvancement.class, new Condition(new QueryCondition("userId", "=", gc.userByToken.id)));
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
* Modification SECTION:
|
||||
* ============================================================================= */
|
||||
/* ============================================================================= Modification SECTION: ============================================================================= */
|
||||
|
||||
public record MediaInformations(
|
||||
int time,
|
||||
float percent,
|
||||
int count) {}
|
||||
public record MediaInformations(int time, float percent, int count) {
|
||||
}
|
||||
|
||||
// @POST
|
||||
// @Path("{id}")
|
||||
@ -68,17 +66,16 @@ public class UserMediaAdvancementResource {
|
||||
return DataAccess.insert(elem);
|
||||
}
|
||||
|
||||
public record MediaInformationsDelta(
|
||||
int time,
|
||||
float percent,
|
||||
boolean addCount) {}
|
||||
public record MediaInformationsDelta(int time, float percent, boolean addCount) {
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public UserMediaAdvancement put(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformationsDelta data) throws Exception {
|
||||
final UserMediaAdvancement elem = getWithId(sc, id);
|
||||
@Operation(description = "Modify a user advancement", tags = "GLOBAL")
|
||||
public UserMediaAdvancement patch(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformationsDelta data) throws Exception {
|
||||
final UserMediaAdvancement elem = get(sc, id);
|
||||
if (elem == null) {
|
||||
// insert element
|
||||
if (data.addCount) {
|
||||
@ -100,10 +97,10 @@ public class UserMediaAdvancementResource {
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
public Response delete(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception {
|
||||
final UserMediaAdvancement elem = getWithId(sc, id);
|
||||
@Operation(description = "Remove a specific user advancement", tags = "GLOBAL")
|
||||
public void remove(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception {
|
||||
final UserMediaAdvancement elem = get(sc, id);
|
||||
DataAccess.delete(UserMediaAdvancement.class, elem.id);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
@ -20,7 +21,7 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
|
||||
@Path("/users")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class UserResource {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);
|
||||
|
||||
@ -41,7 +42,8 @@ public class UserResource {
|
||||
// curl http://localhost:9993/api/users
|
||||
@GET
|
||||
@RolesAllowed("ADMIN")
|
||||
public List<UserKarideo> getUsers() {
|
||||
@Operation(description = "Get all the users", tags = "SYSTEM")
|
||||
public List<UserKarideo> gets() {
|
||||
System.out.println("getUsers");
|
||||
try {
|
||||
return DataAccess.gets(UserKarideo.class);
|
||||
@ -56,7 +58,8 @@ public class UserResource {
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public UserKarideo getUsers(@Context final SecurityContext sc, @PathParam("id") final long userId) {
|
||||
@Operation(description = "Get a specific user data", tags = "SYSTEM")
|
||||
public UserKarideo get(@Context final SecurityContext sc, @PathParam("id") final long userId) {
|
||||
System.out.println("getUser " + userId);
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
System.out.println("===================================================");
|
||||
@ -74,6 +77,7 @@ public class UserResource {
|
||||
@GET
|
||||
@Path("me")
|
||||
@RolesAllowed("USER")
|
||||
@Operation(description = "Get the user personal data", tags = "SYSTEM")
|
||||
public UserOut getMe(@Context final SecurityContext sc) {
|
||||
LOGGER.debug("getMe()");
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
|
@ -1,5 +1,8 @@
|
||||
package org.kar.karideo.migration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
import org.kar.archidata.model.Data;
|
||||
import org.kar.archidata.model.User;
|
||||
@ -8,11 +11,16 @@ import org.kar.karideo.model.Season;
|
||||
import org.kar.karideo.model.Series;
|
||||
import org.kar.karideo.model.Type;
|
||||
import org.kar.karideo.model.UserMediaAdvancement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Initialization extends MigrationSqlStep {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Initialization.class);
|
||||
|
||||
public static final int KARSO_INITIALISATION_ID = 1;
|
||||
|
||||
public static final List<Class<?>> CLASSES_BASE = List.of(Data.class, Media.class, Type.class, Series.class, Season.class, User.class, UserMediaAdvancement.class);
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Initialization";
|
||||
@ -24,31 +32,24 @@ public class Initialization extends MigrationSqlStep {
|
||||
|
||||
@Override
|
||||
public void generateStep() throws Exception {
|
||||
addClass(Data.class);
|
||||
addClass(Media.class);
|
||||
addClass(Type.class);
|
||||
addClass(Series.class);
|
||||
addClass(Season.class);
|
||||
addClass(User.class);
|
||||
addClass(UserMediaAdvancement.class);
|
||||
for (final Class<?> clazz : CLASSES_BASE) {
|
||||
addClass(clazz);
|
||||
}
|
||||
|
||||
addAction("""
|
||||
INSERT INTO `type` (`id`, `name`, `description`) VALUES
|
||||
(1, 'Documentary', 'Documentary (animals, space, earth...)'),
|
||||
(2, 'Movie', 'Movie with real humans (film)'),
|
||||
(3, 'Animation', 'Animation movies (film)'),
|
||||
(4, 'Short movie', 'Small movies (less 2 minutes)'),
|
||||
(5, 'TV show', 'TV show for old peoples'),
|
||||
(6, 'Animation TV show', 'TV show for young peoples'),
|
||||
(7, 'Theater', 'Theater play'),
|
||||
(8, 'One man show', 'Recorded stand up'),
|
||||
(9, 'Concert', 'Recorded concert'),
|
||||
(10, 'Opera', 'Recorded opera');
|
||||
(UUID_TO_BIN('15237fd7-d4ee-11ee-a8dd-02420a030203'), 'Documentary', 'Documentary (animals, space, earth...)'),
|
||||
(UUID_TO_BIN('553146c1-d4ee-11ee-a8dd-02420a030203'), 'Movie', 'Movie with real humans (film)'),
|
||||
(UUID_TO_BIN('59c430a3-d4ee-11ee-a8dd-02420a030203'), 'Animation', 'Animation movies (film)'),
|
||||
(UUID_TO_BIN('5cd619e3-d4ee-11ee-a8dd-02420a030203'), 'Short movie', 'Small movies (less 2 minutes)'),
|
||||
(UUID_TO_BIN('5fbbf085-d4ee-11ee-a8dd-02420a030203'), 'TV show', 'TV show for old peoples'),
|
||||
(UUID_TO_BIN('66dcb6ba-d4ee-11ee-a8dd-02420a030203'), 'Animation TV show', 'TV show for young peoples'),
|
||||
(UUID_TO_BIN('69ee5c15-d4ee-11ee-a8dd-02420a030203'), 'Theater', 'Theater play'),
|
||||
(UUID_TO_BIN('6ce72530-d4ee-11ee-a8dd-02420a030203'), 'One man show', 'Recorded stand up'),
|
||||
(UUID_TO_BIN('6ff1691a-d4ee-11ee-a8dd-02420a030203'), 'Concert', 'Recorded concert'),
|
||||
(UUID_TO_BIN('730815ef-d4ee-11ee-a8dd-02420a030203'), 'Opera', 'Recorded opera');
|
||||
""");
|
||||
// set start increment element to permit to add after default elements
|
||||
addAction("""
|
||||
ALTER TABLE `data` AUTO_INCREMENT = 1000;
|
||||
""", "mysql");
|
||||
addAction("""
|
||||
ALTER TABLE `media` AUTO_INCREMENT = 1000;
|
||||
""", "mysql");
|
||||
@ -66,4 +67,25 @@ public class Initialization extends MigrationSqlStep {
|
||||
""", "mysql");
|
||||
}
|
||||
|
||||
public static void dropAll() {
|
||||
for (final Class<?> element : CLASSES_BASE) {
|
||||
try {
|
||||
DataAccess.drop(element);
|
||||
} catch (final Exception ex) {
|
||||
LOGGER.error("Fail to drop table !!!!!!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void cleanAll() {
|
||||
for (final Class<?> element : CLASSES_BASE) {
|
||||
try {
|
||||
DataAccess.cleanAll(element);
|
||||
} catch (final Exception ex) {
|
||||
LOGGER.error("Fail to clean table !!!!!!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
137
back/src/org/kar/karideo/migration/Migration20240226.java
Normal file
137
back/src/org/kar/karideo/migration/Migration20240226.java
Normal file
@ -0,0 +1,137 @@
|
||||
package org.kar.karideo.migration;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.kar.archidata.api.DataResource;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.addOn.model.LinkTableLongLong;
|
||||
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
|
||||
import org.kar.archidata.dataAccess.options.OverrideTableName;
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
import org.kar.archidata.tools.UuidUtils;
|
||||
import org.kar.karideo.migration.model.CoverConversion;
|
||||
import org.kar.karideo.migration.model.MediaConversion;
|
||||
import org.kar.karideo.migration.model.UUIDConversion;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Migration20240226 extends MigrationSqlStep {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Migration20240226.class);
|
||||
|
||||
public static final int KARSO_INITIALISATION_ID = 1;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "migration-2024-02-26: convert base with UUID";
|
||||
}
|
||||
|
||||
public Migration20240226() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateStep() throws Exception {
|
||||
addAction("""
|
||||
ALTER TABLE `data` ADD `uuid` binary(16) AFTER `id`;
|
||||
""");
|
||||
addAction(() -> {
|
||||
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
|
||||
for (final UUIDConversion elem : datas) {
|
||||
elem.uuid = UuidUtils.nextUUID();
|
||||
}
|
||||
for (final UUIDConversion elem : datas) {
|
||||
DataAccess.update(elem, elem.id, List.of("uuid"), new OverrideTableName("data"));
|
||||
}
|
||||
});
|
||||
addAction("""
|
||||
ALTER TABLE `data` CHANGE `uuid` `uuid` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE));
|
||||
""");
|
||||
final List<String> tableToTransform = List.of("media", "season", "series", "type", "user");
|
||||
for (final String tableName : tableToTransform) {
|
||||
addAction("ALTER TABLE `" + tableName + "` ADD `covers` text NULL;");
|
||||
addAction(() -> {
|
||||
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
|
||||
final List<CoverConversion> medias = DataAccess.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName));
|
||||
final List<LinkTableLongLong> links = DataAccess.gets(LinkTableLongLong.class, new OverrideTableName(tableName + "_link_cover"));
|
||||
LOGGER.info("Get somes data: {} {} {}", datas.size(), medias.size(), links.size());
|
||||
for (final CoverConversion media : medias) {
|
||||
final List<UUID> values = new ArrayList<>();
|
||||
for (final LinkTableLongLong link : links) {
|
||||
if (link.object1Id.equals(media.id)) {
|
||||
for (final UUIDConversion data : datas) {
|
||||
if (data.id.equals(link.object2Id)) {
|
||||
values.add(data.uuid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (values.size() != 0) {
|
||||
media.covers = values;
|
||||
LOGGER.info(" update: {} => {}", media.id, media.covers);
|
||||
DataAccess.update(media, media.id, List.of("covers"), new OverrideTableName(tableName));
|
||||
}
|
||||
}
|
||||
});
|
||||
addAction("DROP TABLE `" + tableName + "_link_cover`;");
|
||||
}
|
||||
addAction("""
|
||||
ALTER TABLE `media` ADD `dataUUID` binary(16) AFTER dataId;
|
||||
""");
|
||||
addAction(() -> {
|
||||
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
|
||||
final List<MediaConversion> medias = DataAccess.gets(MediaConversion.class, new AccessDeletedItems(), new OverrideTableName("media"));
|
||||
for (final MediaConversion media : medias) {
|
||||
for (final UUIDConversion data : datas) {
|
||||
if (data.id.equals(media.dataId)) {
|
||||
media.dataUUID = data.uuid;
|
||||
DataAccess.update(media, media.id, List.of("dataUUID"), new OverrideTableName("media"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
addAction("""
|
||||
ALTER TABLE `media` DROP `dataId`;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `media` CHANGE `dataUUID` `dataId` binary(16) NOT NULL;
|
||||
""");
|
||||
// Move the files...
|
||||
addAction(() -> {
|
||||
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
|
||||
for (final UUIDConversion data : datas) {
|
||||
final String origin = DataResource.getFileDataOld(data.id);
|
||||
final String destination = DataResource.getFileData(data.uuid);
|
||||
LOGGER.info("move file = {}", origin);
|
||||
LOGGER.info(" ==> {}", destination);
|
||||
try {
|
||||
Files.move(Paths.get(origin), Paths.get(destination), StandardCopyOption.ATOMIC_MOVE);
|
||||
} catch (final NoSuchFileException ex) {
|
||||
LOGGER.error("MOVE_ERROR : {} -> {}", origin, destination);
|
||||
}
|
||||
}
|
||||
});
|
||||
/* I am not sure then I prefer keep the primary key for the moment addAction(""" ALTER TABLE `data` DROP `id`; """); */
|
||||
addAction("""
|
||||
ALTER TABLE `data` CHANGE `id` `idOld` bigint NOT NULL DEFAULT 0;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `data` DROP PRIMARY KEY;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `data` CHANGE `uuid` `id` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE));
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `data` ADD PRIMARY KEY `id` (`id`);
|
||||
""");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package org.kar.karideo.migration.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
public class CoverConversion {
|
||||
@Id
|
||||
public Long id = null;
|
||||
@DataJson
|
||||
public List<UUID> covers = null;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package org.kar.karideo.migration.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
public class MediaConversion {
|
||||
@Id
|
||||
public Long id = null;
|
||||
public Long dataId = null;
|
||||
public UUID dataUUID = null;
|
||||
}
|
11
back/src/org/kar/karideo/migration/model/UUIDConversion.java
Normal file
11
back/src/org/kar/karideo/migration/model/UUIDConversion.java
Normal file
@ -0,0 +1,11 @@
|
||||
package org.kar.karideo.migration.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
public class UUIDConversion {
|
||||
@Id
|
||||
public Long id = null;
|
||||
public UUID uuid = null;
|
||||
}
|
@ -1,53 +1,60 @@
|
||||
package org.kar.karideo.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.model.Data;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "media")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
//@SQLDelete(sql = "UPDATE table_product SET deleted = true WHERE id=?")
|
||||
//@Where(clause = "deleted=false")
|
||||
public class Media extends GenericDataSoftDelete {
|
||||
// Name of the media (this represent the title)
|
||||
@Schema(description = "Name of the media (this represent the title)")
|
||||
@Column(nullable = false, length = 0)
|
||||
public String name;
|
||||
// Description of the media
|
||||
@Schema(description = "Description of the media")
|
||||
@Column(length = 0)
|
||||
public String description;
|
||||
// Foreign Key Id of the data
|
||||
@Schema(description = "Foreign Key Id of the data")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class)
|
||||
@Column(nullable = false)
|
||||
public Long dataId;
|
||||
// Type of the media")
|
||||
public UUID dataId;
|
||||
@Schema(description = "Type of the media")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
|
||||
public Long typeId;
|
||||
// Series reference of the media
|
||||
@Schema(description = "Series reference of the media")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
|
||||
public Long seriesId;
|
||||
// Saison reference of the media
|
||||
@Schema(description = "Season reference of the media")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Season.class)
|
||||
public Long seasonId;
|
||||
// Episide Id
|
||||
@Schema(description = "Episode Id")
|
||||
public Integer episode;
|
||||
// ")
|
||||
public Integer date;
|
||||
// Creation years of the media
|
||||
@Schema(description = "Creation years of the media")
|
||||
public Integer time;
|
||||
// Limitation Age of the media
|
||||
@Schema(description = "Limitation Age of the media")
|
||||
public Integer ageLimit;
|
||||
// List of Id of the specific covers
|
||||
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
|
||||
public List<Long> covers = null;
|
||||
@Schema(description = "List of Id of the specific covers")
|
||||
@DataJson(targetEntity = Data.class)
|
||||
public List<UUID> covers = null;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Media [name=" + this.name + ", description=" + this.description + ", dataId=" + this.dataId + ", typeId=" + this.typeId + ", seriesId=" + this.seriesId + ", seasonId=" + this.seasonId
|
||||
+ ", episode=" + this.episode + ", date=" + this.date + ", time=" + this.time + ", ageLimit=" + this.ageLimit + ", covers=" + this.covers + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package org.kar.karideo.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.Data;
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
@ -11,7 +12,6 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@ -29,7 +29,7 @@ public class Season extends GenericDataSoftDelete {
|
||||
@Schema(description = "series parent ID")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
|
||||
public Long parentId;
|
||||
@Schema(description = "List of Id of the sopecific covers")
|
||||
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
|
||||
public List<Long> covers = null;
|
||||
@Schema(description = "List of Id of the specific covers")
|
||||
@DataJson()
|
||||
public List<UUID> covers = null;
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
package org.kar.karideo.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.Data;
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
@ -11,7 +12,6 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@ -29,7 +29,7 @@ public class Series extends GenericDataSoftDelete {
|
||||
@Schema(description = "series parent ID")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
|
||||
public Long parentId;
|
||||
@Schema(description = "List of Id of the sopecific covers")
|
||||
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
|
||||
public List<Long> covers = null;
|
||||
@Schema(description = "List of Id of the specific covers")
|
||||
@DataJson()
|
||||
public List<UUID> covers = null;
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
package org.kar.karideo.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.Data;
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Table(name = "type")
|
||||
@ -24,7 +23,7 @@ public class Type extends GenericDataSoftDelete {
|
||||
@Column(length = 0)
|
||||
@Schema(description = "Description of the media")
|
||||
public String description;
|
||||
@Schema(description = "List of Id of the sopecific covers")
|
||||
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
|
||||
public List<Long> covers = null;
|
||||
@Schema(description = "List of Id of the specific covers")
|
||||
@DataJson()
|
||||
public List<UUID> covers = null;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.kar.karideo.model;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.annotation.DataNotRead;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
@ -15,21 +16,22 @@ import jakarta.persistence.Table;
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class UserMediaAdvancement extends GenericDataSoftDelete {
|
||||
@DataNotRead
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Foreign Key Id of the user")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = UserKarideo.class)
|
||||
public long userId;
|
||||
public Long userId;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Id of the media")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Media.class)
|
||||
public long mediaId;
|
||||
public Long mediaId;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Percent of admencement in the media")
|
||||
public float percent;
|
||||
@Schema(description = "Percent of advancement in the media")
|
||||
public Float percent;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Number of second of admencement in the media")
|
||||
public int time;
|
||||
@Schema(description = "Number of second of advancement in the media")
|
||||
public Integer time;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Number of time this media has been read")
|
||||
public int count;
|
||||
public Integer count;
|
||||
}
|
||||
|
@ -12,17 +12,23 @@ public class WebLauncherTest extends WebLauncher {
|
||||
public WebLauncherTest() {
|
||||
LOGGER.debug("Configure REST system");
|
||||
// for local test:
|
||||
ConfigBaseVariable.apiAdress = "http://127.0.0.1:12345/test/api/";
|
||||
ConfigBaseVariable.apiAdress = "http://127.0.0.1:12342/test/api/";
|
||||
// Enable the test mode permit to access to the test token (never use it in production).
|
||||
ConfigBaseVariable.testMode = "true";
|
||||
//ConfigBaseVariable.dbPort = "3306";
|
||||
// for the test we a in memory sqlite..
|
||||
if (true) {
|
||||
if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) {
|
||||
ConfigBaseVariable.dbType = "sqlite";
|
||||
ConfigBaseVariable.dbHost = "memory";
|
||||
// for test we need to connect all time the DB
|
||||
ConfigBaseVariable.dbKeepConnected = "true";
|
||||
|
||||
//ConfigBaseVariable.dbHost = "localhost";
|
||||
//ConfigBaseVariable.dbUser = "root";
|
||||
//ConfigBaseVariable.dbPassword = "ZERTYSDGFVHSDFGHJYZSDFGSQxfgsqdfgsqdrf4564654";
|
||||
}
|
||||
} else {
|
||||
// Enable this if you want to access to a local MySQL base to test with an adminer
|
||||
ConfigBaseVariable.bdDatabase = "test_db";
|
||||
ConfigBaseVariable.dbPort = "3309";
|
||||
ConfigBaseVariable.dbUser = "root";
|
||||
ConfigBaseVariable.dbPassword = "password";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"defaultProject" : "karideo",
|
||||
"projects": {
|
||||
"karideo": {
|
||||
"root": "",
|
||||
@ -16,9 +15,21 @@
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"tsConfig": "src/tsconfig.app.json",
|
||||
"polyfills" : "src/polyfills.ts",
|
||||
"assets" : [ "src/assets", "src/favicon.ico" ],
|
||||
"styles" : [ "src/styles.less", "src/generic_page.less", "src/theme.color.blue.less", "src/theme.checkbox.less", "src/theme.modal.less" ],
|
||||
"preserveSymlinks": true,
|
||||
"polyfills": [
|
||||
"zone.js"
|
||||
],
|
||||
"assets": [
|
||||
"src/assets",
|
||||
"src/favicon.ico"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.less",
|
||||
"src/generic_page.less",
|
||||
"src/theme.color.blue.less",
|
||||
"src/theme.checkbox.less",
|
||||
"src/theme.modal.less"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
@ -31,41 +42,48 @@
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"fileReplacements" : [ {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
} ]
|
||||
}
|
||||
]
|
||||
},
|
||||
"develop": {
|
||||
"optimization": false,
|
||||
"outputHashing": "none",
|
||||
"sourceMap" : true,
|
||||
"namedChunks": true,
|
||||
"aot" : true,
|
||||
"aot": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": true,
|
||||
"buildOptimizer" : false
|
||||
"buildOptimizer": false,
|
||||
"sourceMap": {
|
||||
"scripts": true,
|
||||
"styles": true,
|
||||
"hidden": false,
|
||||
"vendor": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget" : "karideo:build"
|
||||
"buildTarget": "karideo:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget" : "karideo:build:production"
|
||||
"buildTarget": "karideo:build:production"
|
||||
},
|
||||
"develop": {
|
||||
"browserTarget" : "karideo:build:develop"
|
||||
"buildTarget": "karideo:build:develop"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget" : "karideo:build"
|
||||
"buildTarget": "karideo:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
@ -73,11 +91,22 @@
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"karmaConfig": "./karma.conf.js",
|
||||
"polyfills" : "src/polyfills.ts",
|
||||
"polyfills": [
|
||||
"zone.js"
|
||||
],
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"scripts": [],
|
||||
"styles" : [ "src/styles.less", "src/generic_page.less", "src/theme.color.blue.less", "src/theme.checkbox.less", "src/theme.modal.less" ],
|
||||
"assets" : [ "src/assets", "src/favicon.ico" ]
|
||||
"styles": [
|
||||
"src/styles.less",
|
||||
"src/generic_page.less",
|
||||
"src/theme.color.blue.less",
|
||||
"src/theme.checkbox.less",
|
||||
"src/theme.modal.less"
|
||||
],
|
||||
"assets": [
|
||||
"src/assets",
|
||||
"src/favicon.ico"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
@ -94,8 +123,13 @@
|
||||
"TTTTTTlint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig" : [ "src/tsconfig.app.json", "src/tsconfig.spec.json" ],
|
||||
"exclude" : [ "**/node_modules/**" ]
|
||||
"tsConfig": [
|
||||
"src/tsconfig.app.json",
|
||||
"src/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,8 +149,12 @@
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig" : [ "e2e/tsconfig.e2e.json" ],
|
||||
"exclude" : [ "**/node_modules/**" ]
|
||||
"tsConfig": [
|
||||
"e2e/tsconfig.e2e.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21757
front/package-lock.json
generated
21757
front/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -6,36 +6,45 @@
|
||||
"all": "npm run build && npm run test",
|
||||
"ng": "ng",
|
||||
"dev": "ng serve --configuration=develop --watch --port 4202",
|
||||
"dev-hot-update": "ng serve --configuration=develop --watch --hmr --port 4202",
|
||||
"build": "ng build --prod",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"style": "prettier --write .",
|
||||
"e2e": "ng e2e"
|
||||
"e2e": "ng e2e",
|
||||
"update_packages": "ncu --upgrade",
|
||||
"install_dependency": "pnpm install --force",
|
||||
"link_kar_cw": "pnpm link ../../kar-cw/dist/kar-cw/",
|
||||
"unlink_kar_cw": "pnpm unlink ../../kar-cw/dist/kar-cw/"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^14.2.10",
|
||||
"@angular/cdk": "^14.2.7",
|
||||
"@angular/common": "^14.2.10",
|
||||
"@angular/compiler": "^14.2.10",
|
||||
"@angular/core": "^14.2.10",
|
||||
"@angular/forms": "^14.2.10",
|
||||
"@angular/material": "^14.2.7",
|
||||
"@angular/platform-browser": "^14.2.10",
|
||||
"@angular/platform-browser-dynamic": "^14.2.10",
|
||||
"@angular/router": "^14.2.10",
|
||||
"rxjs": "^7.5.7",
|
||||
"zone.js": "^0.12.0"
|
||||
"@angular/animations": "^18.0.2",
|
||||
"@angular/cdk": "^18.0.2",
|
||||
"@angular/common": "^18.0.2",
|
||||
"@angular/compiler": "^18.0.2",
|
||||
"@angular/core": "^18.0.2",
|
||||
"@angular/forms": "^18.0.2",
|
||||
"@angular/material": "^18.0.2",
|
||||
"@angular/platform-browser": "^18.0.2",
|
||||
"@angular/platform-browser-dynamic": "^18.0.2",
|
||||
"@angular/router": "^18.0.2",
|
||||
"rxjs": "^7.8.1",
|
||||
"zone.js": "^0.14.6",
|
||||
"zod": "3.23.8",
|
||||
"@kangaroo-and-rabbit/kar-cw": "^0.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^14.2.9",
|
||||
"@angular-eslint/builder": "14.2.0",
|
||||
"@angular-eslint/eslint-plugin": "14.2.0",
|
||||
"@angular-eslint/eslint-plugin-template": "14.2.0",
|
||||
"@angular-eslint/schematics": "14.2.0",
|
||||
"@angular-eslint/template-parser": "14.2.0",
|
||||
"@angular/cli": "^14.2.9",
|
||||
"@angular/compiler-cli": "^14.2.10",
|
||||
"@angular/language-service": "^14.2.10"
|
||||
"@angular-devkit/build-angular": "^18.0.3",
|
||||
"@angular-eslint/builder": "18.0.1",
|
||||
"@angular-eslint/eslint-plugin": "18.0.1",
|
||||
"@angular-eslint/eslint-plugin-template": "18.0.1",
|
||||
"@angular-eslint/schematics": "18.0.1",
|
||||
"@angular-eslint/template-parser": "18.0.1",
|
||||
"@angular/cli": "^18.0.3",
|
||||
"@angular/compiler-cli": "^18.0.2",
|
||||
"@angular/language-service": "^18.0.2",
|
||||
"npm-check-updates": "^16.14.20",
|
||||
"tslib": "^2.6.3"
|
||||
}
|
||||
}
|
9816
front/pnpm-lock.yaml
generated
Normal file
9816
front/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -6,11 +6,10 @@
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router'; // CLI imports router
|
||||
import { ForbiddenScene, HomeOutScene, NotFound404Scene, SsoScene } from 'common/scene';
|
||||
import { OnlyAdminGuard, OnlyUnregisteredGuardHome, OnlyUsersGuard, OnlyUsersGuardHome } from 'common/service';
|
||||
|
||||
import { HelpScene, HomeScene, SeasonEditScene, SeasonScene, SeriesEditScene, SeriesScene, SettingsScene, TypeScene, VideoEditScene, VideoScene } from './scene';
|
||||
import { UploadScene } from './scene/upload/upload';
|
||||
import { ForbiddenScene, OnlyUsersGuardHome, HomeOutScene, OnlyUnregisteredGuardHome, SsoScene, OnlyAdminGuard, OnlyUsersGuard, NotFound404Scene } from '@kangaroo-and-rabbit/kar-cw';
|
||||
// import { HelpComponent } from './help/help.component';
|
||||
|
||||
// see https://angular.io/guide/router
|
||||
|
@ -1,11 +1,14 @@
|
||||
|
||||
<!-- Generig global menu -->
|
||||
<app-top-menu [menu]="currentMenu" (callback)="eventOnMenu($event)"></app-top-menu>
|
||||
<karcw-top-menu [menu]="currentMenu" (callback)="eventOnMenu($event)" />
|
||||
<!-- all interfaced pages -->
|
||||
<div class="main-content" *ngIf="autoConnectedDone">
|
||||
@if(autoConnectedDone) {
|
||||
<div class="main-content">
|
||||
<router-outlet ></router-outlet>
|
||||
</div>
|
||||
<div class="main-content" *ngIf="!autoConnectedDone">
|
||||
}
|
||||
@else {
|
||||
<div class="main-content">
|
||||
<div class="generic-page">
|
||||
<div class="fill-all colomn_mutiple">
|
||||
<b style="color:red;">Auto-connection in progress</b>
|
||||
@ -13,3 +16,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
@ -5,12 +5,8 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { EventOnMenu } from 'common/component/top-menu/top-menu';
|
||||
import { MenuItem, MenuPosition } from 'common/model';
|
||||
import { UserService, SessionService, SSOService } from 'common/service';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
import { ArianeService } from './service';
|
||||
import { UserRoles222 } from 'common/service/session';
|
||||
import { ArianeService, MediaService, SeasonService, SeriesService, TypeService } from './service';
|
||||
import { EventOnMenu, MenuItem, MenuPosition, SSOService, SessionService, UserRoles222, UserService, isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw';
|
||||
|
||||
enum MenuEventType {
|
||||
SSO_LOGIN = "SSO_CALL_LOGIN",
|
||||
@ -38,6 +34,11 @@ export class AppComponent implements OnInit {
|
||||
location: string = "home";
|
||||
|
||||
constructor(
|
||||
private mediaService: MediaService,
|
||||
private seasonService: SeasonService,
|
||||
private seriesService: SeriesService,
|
||||
private typeService: TypeService,
|
||||
|
||||
private userService: UserService,
|
||||
private sessionService: SessionService,
|
||||
private ssoService: SSOService,
|
||||
@ -52,7 +53,7 @@ export class AppComponent implements OnInit {
|
||||
this.updateMainMenu();
|
||||
let self = this;
|
||||
this.sessionService.change.subscribe((isConnected) => {
|
||||
console.log(`receive event from session ...${isConnected}`);
|
||||
|
||||
self.isConnected = isConnected;
|
||||
self.autoConnectedDone = true;
|
||||
self.updateMainMenu();
|
||||
@ -67,13 +68,10 @@ export class AppComponent implements OnInit {
|
||||
});
|
||||
|
||||
this.userService.checkAutoConnect().then(() => {
|
||||
console.log(` ==>>>>> Autoconnect THEN !!!`);
|
||||
self.autoConnectedDone = true;
|
||||
}).catch(() => {
|
||||
console.log(` ==>>>>> Autoconnect CATCH !!!`);
|
||||
self.autoConnectedDone = true;
|
||||
}).finally(() => {
|
||||
console.log(` ==>>>>> Autoconnect FINALLY !!!`);
|
||||
self.autoConnectedDone = true;
|
||||
});
|
||||
this.arianeService.segmentChange.subscribe((_segmentName: string) => {
|
||||
@ -122,7 +120,6 @@ export class AppComponent implements OnInit {
|
||||
|
||||
}
|
||||
updateMainMenu(): void {
|
||||
console.log("update main menu :");
|
||||
if (this.isConnected) {
|
||||
this.currentMenu = [
|
||||
{
|
||||
@ -229,11 +226,9 @@ export class AppComponent implements OnInit {
|
||||
},
|
||||
];
|
||||
}
|
||||
console.log(" ==> DONE");
|
||||
|
||||
}
|
||||
getSegmentDisplayable(): string {
|
||||
let segment = this.arianeService.getCurrrentSegment();
|
||||
let segment = this.arianeService.getCurrentSegment();
|
||||
if (segment === "type") {
|
||||
return "Type";
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
@ -20,11 +20,24 @@ import { PopInCreateType } from './popin/create-type/create-type';
|
||||
import { AppComponent } from './app.component';
|
||||
import {
|
||||
HomeScene, HelpScene, TypeScene, SeriesScene, SeasonScene, VideoScene, SettingsScene,
|
||||
VideoEditScene, SeasonEditScene, SeriesEditScene
|
||||
VideoEditScene, SeasonEditScene, SeriesEditScene,
|
||||
} from './scene';
|
||||
import { TypeService, DataService, SeriesService, SeasonService, VideoService, ArianeService, AdvancementService } from './service';
|
||||
import {
|
||||
DataService,
|
||||
AdvancementService,
|
||||
MediaService,
|
||||
SeasonService,
|
||||
SeriesService,
|
||||
TypeService,
|
||||
ArianeService,
|
||||
} from './service';
|
||||
import { UploadScene } from './scene/upload/upload';
|
||||
import { common_module_declarations, common_module_imports, common_module_providers, common_module_exports } from 'common/module';
|
||||
import { KarCWModule } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FileDragNDropDirective } from './scene/upload/file-drag-n-drop.directive';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -47,24 +60,28 @@ import { common_module_declarations, common_module_imports, common_module_provid
|
||||
SeasonEditScene,
|
||||
SeriesEditScene,
|
||||
UploadScene,
|
||||
...common_module_declarations,
|
||||
FileDragNDropDirective,
|
||||
],
|
||||
imports: [
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
CommonModule,
|
||||
|
||||
BrowserModule,
|
||||
RouterModule,
|
||||
AppRoutingModule,
|
||||
HttpClientModule,
|
||||
...common_module_imports,
|
||||
KarCWModule,
|
||||
],
|
||||
providers: [
|
||||
TypeService,
|
||||
{ provide: 'ENVIRONMENT', useValue: environment },
|
||||
DataService,
|
||||
SeriesService,
|
||||
SeasonService,
|
||||
VideoService,
|
||||
ArianeService,
|
||||
AdvancementService,
|
||||
...common_module_providers,
|
||||
MediaService,
|
||||
SeasonService,
|
||||
SeriesService,
|
||||
TypeService,
|
||||
ArianeService,
|
||||
],
|
||||
exports: [
|
||||
AppComponent,
|
||||
@ -73,10 +90,10 @@ import { common_module_declarations, common_module_imports, common_module_provid
|
||||
ElementSeasonComponent,
|
||||
ElementVideoComponent,
|
||||
PopInCreateType,
|
||||
...common_module_exports,
|
||||
],
|
||||
bootstrap: [
|
||||
AppComponent
|
||||
]
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
|
||||
})
|
||||
export class AppModule { }
|
||||
|
128
front/src/app/back-api/api/data-resource.ts
Normal file
128
front/src/app/back-api/api/data-resource.ts
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import {
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
RESTConfig,
|
||||
RESTRequestJson,
|
||||
RESTRequestVoid,
|
||||
} from "../rest-tools";
|
||||
|
||||
import {
|
||||
UUID,
|
||||
} from "../model";
|
||||
|
||||
export namespace DataResource {
|
||||
|
||||
/**
|
||||
* Get back some data from the data environment (with a beautiful name (permit download with basic name)
|
||||
*/
|
||||
export function retrieveDataFull({
|
||||
restConfig,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
Authorization?: string,
|
||||
},
|
||||
params: {
|
||||
name: string,
|
||||
uuid: UUID,
|
||||
},
|
||||
data: string,
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/data/{uuid}/{name}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Get back some data from the data environment
|
||||
*/
|
||||
export function retrieveDataId({
|
||||
restConfig,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
Authorization?: string,
|
||||
},
|
||||
params: {
|
||||
uuid: UUID,
|
||||
},
|
||||
data: string,
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/data/{uuid}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Get a thumbnail of from the data environment (if resize is possible)
|
||||
*/
|
||||
export function retrieveDataThumbnailId({
|
||||
restConfig,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
Authorization?: string,
|
||||
},
|
||||
params: {
|
||||
uuid: UUID,
|
||||
},
|
||||
data: string,
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/data/thumbnail/{uuid}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Insert a new data in the data environment
|
||||
*/
|
||||
export function uploadFile({
|
||||
restConfig,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: {
|
||||
file: File,
|
||||
},
|
||||
}): Promise<void> {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
endPoint: "/data//upload/",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.MULTIPART,
|
||||
},
|
||||
restConfig,
|
||||
data,
|
||||
});
|
||||
};
|
||||
}
|
6
front/src/app/back-api/api/front.ts
Normal file
6
front/src/app/back-api/api/front.ts
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
export namespace Front {
|
||||
|
||||
}
|
35
front/src/app/back-api/api/health-check.ts
Normal file
35
front/src/app/back-api/api/health-check.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import {
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
RESTConfig,
|
||||
RESTRequestJson,
|
||||
} from "../rest-tools";
|
||||
|
||||
import {
|
||||
HealthResult,
|
||||
isHealthResult,
|
||||
} from "../model";
|
||||
|
||||
export namespace HealthCheck {
|
||||
|
||||
/**
|
||||
* Get the server state (health)
|
||||
*/
|
||||
export function getHealth({
|
||||
restConfig,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
}): Promise<HealthResult> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/health_check/",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
}, isHealthResult);
|
||||
};
|
||||
}
|
12
front/src/app/back-api/api/index.ts
Normal file
12
front/src/app/back-api/api/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
export * from "./data-resource"
|
||||
export * from "./front"
|
||||
export * from "./health-check"
|
||||
export * from "./media-resource"
|
||||
export * from "./season-resource"
|
||||
export * from "./series-resource"
|
||||
export * from "./type-resource"
|
||||
export * from "./user-media-advancement-resource"
|
||||
export * from "./user-resource"
|
215
front/src/app/back-api/api/media-resource.ts
Normal file
215
front/src/app/back-api/api/media-resource.ts
Normal file
@ -0,0 +1,215 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import {
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
RESTCallbacks,
|
||||
RESTConfig,
|
||||
RESTRequestJson,
|
||||
RESTRequestVoid,
|
||||
} from "../rest-tools";
|
||||
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Media,
|
||||
MediaWrite,
|
||||
UUID,
|
||||
ZodMedia,
|
||||
isMedia,
|
||||
} from "../model";
|
||||
|
||||
export namespace MediaResource {
|
||||
|
||||
/**
|
||||
* Get a specific Media with his ID
|
||||
*/
|
||||
export function get({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<Media> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/media/{id}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isMedia);
|
||||
};
|
||||
|
||||
export const ZodGetsTypeReturn = zod.array(ZodMedia);
|
||||
export type GetsTypeReturn = zod.infer<typeof ZodGetsTypeReturn>;
|
||||
|
||||
export function isGetsTypeReturn(data: any): data is GetsTypeReturn {
|
||||
try {
|
||||
ZodGetsTypeReturn.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGetsTypeReturn' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Media
|
||||
*/
|
||||
export function gets({
|
||||
restConfig,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
}): Promise<GetsTypeReturn> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/media/",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
}, isGetsTypeReturn);
|
||||
};
|
||||
/**
|
||||
* Modify a specific Media
|
||||
*/
|
||||
export function patch({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: MediaWrite,
|
||||
}): Promise<Media> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/media/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}, isMedia);
|
||||
};
|
||||
/**
|
||||
* Remove a specific Media
|
||||
*/
|
||||
export function remove({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<void> {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
endPoint: "/media/{id}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Remove a specific cover of a media
|
||||
*/
|
||||
export function removeCover({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
coverId: UUID,
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<Media> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/media/{id}/cover/{coverId}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isMedia);
|
||||
};
|
||||
/**
|
||||
* Upload a new season cover media
|
||||
*/
|
||||
export function uploadCover({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
callback,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: {
|
||||
fileName: string,
|
||||
file: File,
|
||||
},
|
||||
callback?: RESTCallbacks,
|
||||
}): Promise<Media> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/media/{id}/cover",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.MULTIPART,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
callback,
|
||||
}, isMedia);
|
||||
};
|
||||
/**
|
||||
* Create a new Media
|
||||
*/
|
||||
export function uploadFile({
|
||||
restConfig,
|
||||
data,
|
||||
callback,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: {
|
||||
fileName: string,
|
||||
file: File,
|
||||
series: string,
|
||||
universe: string,
|
||||
season: string,
|
||||
episode: string,
|
||||
typeId: string,
|
||||
title: string,
|
||||
},
|
||||
callback?: RESTCallbacks,
|
||||
}): Promise<Media> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/media/",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.MULTIPART,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
data,
|
||||
callback,
|
||||
}, isMedia);
|
||||
};
|
||||
}
|
204
front/src/app/back-api/api/season-resource.ts
Normal file
204
front/src/app/back-api/api/season-resource.ts
Normal file
@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import {
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
RESTCallbacks,
|
||||
RESTConfig,
|
||||
RESTRequestJson,
|
||||
RESTRequestVoid,
|
||||
} from "../rest-tools";
|
||||
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Season,
|
||||
SeasonWrite,
|
||||
UUID,
|
||||
ZodSeason,
|
||||
isSeason,
|
||||
} from "../model";
|
||||
|
||||
export namespace SeasonResource {
|
||||
|
||||
/**
|
||||
* Get all season
|
||||
*/
|
||||
export function get({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<Season> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/season/{id}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isSeason);
|
||||
};
|
||||
|
||||
export const ZodGetsTypeReturn = zod.array(ZodSeason);
|
||||
export type GetsTypeReturn = zod.infer<typeof ZodGetsTypeReturn>;
|
||||
|
||||
export function isGetsTypeReturn(data: any): data is GetsTypeReturn {
|
||||
try {
|
||||
ZodGetsTypeReturn.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGetsTypeReturn' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific Season with his ID
|
||||
*/
|
||||
export function gets({
|
||||
restConfig,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
}): Promise<GetsTypeReturn> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/season/",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
}, isGetsTypeReturn);
|
||||
};
|
||||
/**
|
||||
* Modify a specific season
|
||||
*/
|
||||
export function patch({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: SeasonWrite,
|
||||
}): Promise<Season> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/season/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}, isSeason);
|
||||
};
|
||||
/**
|
||||
* Create a new season
|
||||
*/
|
||||
export function post({
|
||||
restConfig,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: SeasonWrite,
|
||||
}): Promise<Season> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/season/",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
data,
|
||||
}, isSeason);
|
||||
};
|
||||
/**
|
||||
* Remove a specific season
|
||||
*/
|
||||
export function remove({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<void> {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
endPoint: "/season/{id}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Remove a specific cover of a season
|
||||
*/
|
||||
export function removeCover({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
coverId: UUID,
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<Season> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/season/{id}/cover/{coverId}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isSeason);
|
||||
};
|
||||
/**
|
||||
* Upload a new season cover season
|
||||
*/
|
||||
export function uploadCover({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
callback,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: {
|
||||
fileName: string,
|
||||
file: File,
|
||||
},
|
||||
callback?: RESTCallbacks,
|
||||
}): Promise<Season> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/season/{id}/cover",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.MULTIPART,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
callback,
|
||||
}, isSeason);
|
||||
};
|
||||
}
|
204
front/src/app/back-api/api/series-resource.ts
Normal file
204
front/src/app/back-api/api/series-resource.ts
Normal file
@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import {
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
RESTCallbacks,
|
||||
RESTConfig,
|
||||
RESTRequestJson,
|
||||
RESTRequestVoid,
|
||||
} from "../rest-tools";
|
||||
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Series,
|
||||
SeriesWrite,
|
||||
UUID,
|
||||
ZodSeries,
|
||||
isSeries,
|
||||
} from "../model";
|
||||
|
||||
export namespace SeriesResource {
|
||||
|
||||
/**
|
||||
* Get a specific Series with his ID
|
||||
*/
|
||||
export function get({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<Series> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/series/{id}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isSeries);
|
||||
};
|
||||
|
||||
export const ZodGetsTypeReturn = zod.array(ZodSeries);
|
||||
export type GetsTypeReturn = zod.infer<typeof ZodGetsTypeReturn>;
|
||||
|
||||
export function isGetsTypeReturn(data: any): data is GetsTypeReturn {
|
||||
try {
|
||||
ZodGetsTypeReturn.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGetsTypeReturn' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Series
|
||||
*/
|
||||
export function gets({
|
||||
restConfig,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
}): Promise<GetsTypeReturn> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/series/",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
}, isGetsTypeReturn);
|
||||
};
|
||||
/**
|
||||
* Modify a specific Series
|
||||
*/
|
||||
export function patch({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: SeriesWrite,
|
||||
}): Promise<Series> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/series/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}, isSeries);
|
||||
};
|
||||
/**
|
||||
* Create a new Series
|
||||
*/
|
||||
export function post({
|
||||
restConfig,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: SeriesWrite,
|
||||
}): Promise<Series> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/series/",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
data,
|
||||
}, isSeries);
|
||||
};
|
||||
/**
|
||||
* Remove a specific Series
|
||||
*/
|
||||
export function remove({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<void> {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
endPoint: "/series/{id}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Remove a specific Series of a season
|
||||
*/
|
||||
export function removeCover({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
coverId: UUID,
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<Series> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/series/{id}/cover/{coverId}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isSeries);
|
||||
};
|
||||
/**
|
||||
* Upload a new season cover Series
|
||||
*/
|
||||
export function uploadCover({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
callback,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: {
|
||||
fileName: string,
|
||||
file: File,
|
||||
},
|
||||
callback?: RESTCallbacks,
|
||||
}): Promise<Series> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/series/{id}/cover",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.MULTIPART,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
callback,
|
||||
}, isSeries);
|
||||
};
|
||||
}
|
204
front/src/app/back-api/api/type-resource.ts
Normal file
204
front/src/app/back-api/api/type-resource.ts
Normal file
@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import {
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
RESTCallbacks,
|
||||
RESTConfig,
|
||||
RESTRequestJson,
|
||||
RESTRequestVoid,
|
||||
} from "../rest-tools";
|
||||
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Type,
|
||||
TypeWrite,
|
||||
UUID,
|
||||
ZodType,
|
||||
isType,
|
||||
} from "../model";
|
||||
|
||||
export namespace TypeResource {
|
||||
|
||||
/**
|
||||
* Get a specific Type with his ID
|
||||
*/
|
||||
export function get({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<Type> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/type/{id}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isType);
|
||||
};
|
||||
|
||||
export const ZodGetsTypeReturn = zod.array(ZodType);
|
||||
export type GetsTypeReturn = zod.infer<typeof ZodGetsTypeReturn>;
|
||||
|
||||
export function isGetsTypeReturn(data: any): data is GetsTypeReturn {
|
||||
try {
|
||||
ZodGetsTypeReturn.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGetsTypeReturn' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Type
|
||||
*/
|
||||
export function gets({
|
||||
restConfig,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
}): Promise<GetsTypeReturn> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/type/",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
}, isGetsTypeReturn);
|
||||
};
|
||||
/**
|
||||
* Modify a specific Type
|
||||
*/
|
||||
export function patch({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: TypeWrite,
|
||||
}): Promise<Type> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/type/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}, isType);
|
||||
};
|
||||
/**
|
||||
* Create a new Type
|
||||
*/
|
||||
export function post({
|
||||
restConfig,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: TypeWrite,
|
||||
}): Promise<Type> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/type/",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
data,
|
||||
}, isType);
|
||||
};
|
||||
/**
|
||||
* Remove a specific Type
|
||||
*/
|
||||
export function remove({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<void> {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
endPoint: "/type/{id}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Remove a specific cover of a type
|
||||
*/
|
||||
export function removeCover({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
coverId: UUID,
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<Type> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/type/{id}/cover/{coverId}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isType);
|
||||
};
|
||||
/**
|
||||
* Upload a new season cover Type
|
||||
*/
|
||||
export function uploadCover({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
callback,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: {
|
||||
fileName: string,
|
||||
file: File,
|
||||
},
|
||||
callback?: RESTCallbacks,
|
||||
}): Promise<Type> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/type/{id}/cover",
|
||||
requestType: HTTPRequestModel.POST,
|
||||
contentType: HTTPMimeType.MULTIPART,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
callback,
|
||||
}, isType);
|
||||
};
|
||||
}
|
124
front/src/app/back-api/api/user-media-advancement-resource.ts
Normal file
124
front/src/app/back-api/api/user-media-advancement-resource.ts
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import {
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
RESTConfig,
|
||||
RESTRequestJson,
|
||||
RESTRequestVoid,
|
||||
} from "../rest-tools";
|
||||
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
MediaInformationsDeltaWrite,
|
||||
UserMediaAdvancement,
|
||||
ZodUserMediaAdvancement,
|
||||
isUserMediaAdvancement,
|
||||
} from "../model";
|
||||
|
||||
export namespace UserMediaAdvancementResource {
|
||||
|
||||
/**
|
||||
* Get a specific user advancement with his ID
|
||||
*/
|
||||
export function get({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<UserMediaAdvancement> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/advancement/{id}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isUserMediaAdvancement);
|
||||
};
|
||||
|
||||
export const ZodGetsTypeReturn = zod.array(ZodUserMediaAdvancement);
|
||||
export type GetsTypeReturn = zod.infer<typeof ZodGetsTypeReturn>;
|
||||
|
||||
export function isGetsTypeReturn(data: any): data is GetsTypeReturn {
|
||||
try {
|
||||
ZodGetsTypeReturn.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGetsTypeReturn' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all user advancement
|
||||
*/
|
||||
export function gets({
|
||||
restConfig,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
}): Promise<GetsTypeReturn> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/advancement/",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
}, isGetsTypeReturn);
|
||||
};
|
||||
/**
|
||||
* Modify a user advancement
|
||||
*/
|
||||
export function patch({
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: MediaInformationsDeltaWrite,
|
||||
}): Promise<UserMediaAdvancement> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/advancement/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
data,
|
||||
}, isUserMediaAdvancement);
|
||||
};
|
||||
/**
|
||||
* Remove a specific user advancement
|
||||
*/
|
||||
export function remove({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<void> {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
endPoint: "/advancement/{id}",
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
contentType: HTTPMimeType.TEXT_PLAIN,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
});
|
||||
};
|
||||
}
|
93
front/src/app/back-api/api/user-resource.ts
Normal file
93
front/src/app/back-api/api/user-resource.ts
Normal file
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import {
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
RESTConfig,
|
||||
RESTRequestJson,
|
||||
} from "../rest-tools";
|
||||
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
UserKarideo,
|
||||
UserOut,
|
||||
ZodUserKarideo,
|
||||
isUserKarideo,
|
||||
isUserOut,
|
||||
} from "../model";
|
||||
|
||||
export namespace UserResource {
|
||||
|
||||
/**
|
||||
* Get a specific user data
|
||||
*/
|
||||
export function get({
|
||||
restConfig,
|
||||
params,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
}): Promise<UserKarideo> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/users/{id}",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
params,
|
||||
}, isUserKarideo);
|
||||
};
|
||||
/**
|
||||
* Get the user personal data
|
||||
*/
|
||||
export function getMe({
|
||||
restConfig,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
}): Promise<UserOut> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/users/me",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
}, isUserOut);
|
||||
};
|
||||
|
||||
export const ZodGetsTypeReturn = zod.array(ZodUserKarideo);
|
||||
export type GetsTypeReturn = zod.infer<typeof ZodGetsTypeReturn>;
|
||||
|
||||
export function isGetsTypeReturn(data: any): data is GetsTypeReturn {
|
||||
try {
|
||||
ZodGetsTypeReturn.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGetsTypeReturn' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the users
|
||||
*/
|
||||
export function gets({
|
||||
restConfig,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
}): Promise<GetsTypeReturn> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/users/",
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
}, isGetsTypeReturn);
|
||||
};
|
||||
}
|
7
front/src/app/back-api/index.ts
Normal file
7
front/src/app/back-api/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
export * from "./model";
|
||||
export * from "./api";
|
||||
export * from "./rest-tools";
|
||||
|
8
front/src/app/back-api/model/float.ts
Normal file
8
front/src/app/back-api/model/float.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodFloat = zod.number();
|
||||
export type Float = zod.infer<typeof ZodFloat>;
|
46
front/src/app/back-api/model/generic-data-soft-delete.ts
Normal file
46
front/src/app/back-api/model/generic-data-soft-delete.ts
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodGenericData} from "./generic-data";
|
||||
|
||||
export const ZodGenericDataSoftDelete = ZodGenericData.extend({
|
||||
/**
|
||||
* Deleted state
|
||||
*/
|
||||
deleted: zod.boolean().readonly().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type GenericDataSoftDelete = zod.infer<typeof ZodGenericDataSoftDelete>;
|
||||
|
||||
export function isGenericDataSoftDelete(data: any): data is GenericDataSoftDelete {
|
||||
try {
|
||||
ZodGenericDataSoftDelete.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericDataSoftDelete' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodGenericDataSoftDeleteWrite = ZodGenericDataSoftDelete.omit({
|
||||
deleted: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type GenericDataSoftDeleteWrite = zod.infer<typeof ZodGenericDataSoftDeleteWrite>;
|
||||
|
||||
export function isGenericDataSoftDeleteWrite(data: any): data is GenericDataSoftDeleteWrite {
|
||||
try {
|
||||
ZodGenericDataSoftDeleteWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
46
front/src/app/back-api/model/generic-data.ts
Normal file
46
front/src/app/back-api/model/generic-data.ts
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodGenericTiming} from "./generic-timing";
|
||||
|
||||
export const ZodGenericData = ZodGenericTiming.extend({
|
||||
/**
|
||||
* Unique Id of the object
|
||||
*/
|
||||
id: ZodLong.readonly(),
|
||||
|
||||
});
|
||||
|
||||
export type GenericData = zod.infer<typeof ZodGenericData>;
|
||||
|
||||
export function isGenericData(data: any): data is GenericData {
|
||||
try {
|
||||
ZodGenericData.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericData' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodGenericDataWrite = ZodGenericData.omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type GenericDataWrite = zod.infer<typeof ZodGenericDataWrite>;
|
||||
|
||||
export function isGenericDataWrite(data: any): data is GenericDataWrite {
|
||||
try {
|
||||
ZodGenericDataWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericDataWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
48
front/src/app/back-api/model/generic-timing.ts
Normal file
48
front/src/app/back-api/model/generic-timing.ts
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodIsoDate} from "./iso-date";
|
||||
|
||||
export const ZodGenericTiming = zod.object({
|
||||
/**
|
||||
* Create time of the object
|
||||
*/
|
||||
createdAt: ZodIsoDate.readonly().optional(),
|
||||
/**
|
||||
* When update the object
|
||||
*/
|
||||
updatedAt: ZodIsoDate.readonly().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type GenericTiming = zod.infer<typeof ZodGenericTiming>;
|
||||
|
||||
export function isGenericTiming(data: any): data is GenericTiming {
|
||||
try {
|
||||
ZodGenericTiming.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericTiming' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodGenericTimingWrite = ZodGenericTiming.omit({
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type GenericTimingWrite = zod.infer<typeof ZodGenericTimingWrite>;
|
||||
|
||||
export function isGenericTimingWrite(data: any): data is GenericTimingWrite {
|
||||
try {
|
||||
ZodGenericTimingWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericTimingWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
35
front/src/app/back-api/model/health-result.ts
Normal file
35
front/src/app/back-api/model/health-result.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodHealthResult = zod.object({
|
||||
|
||||
});
|
||||
|
||||
export type HealthResult = zod.infer<typeof ZodHealthResult>;
|
||||
|
||||
export function isHealthResult(data: any): data is HealthResult {
|
||||
try {
|
||||
ZodHealthResult.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodHealthResult' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodHealthResultWrite = ZodHealthResult.partial();
|
||||
|
||||
export type HealthResultWrite = zod.infer<typeof ZodHealthResultWrite>;
|
||||
|
||||
export function isHealthResultWrite(data: any): data is HealthResultWrite {
|
||||
try {
|
||||
ZodHealthResultWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodHealthResultWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
24
front/src/app/back-api/model/index.ts
Normal file
24
front/src/app/back-api/model/index.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
export * from "./float"
|
||||
export * from "./generic-data"
|
||||
export * from "./generic-data-soft-delete"
|
||||
export * from "./generic-timing"
|
||||
export * from "./health-result"
|
||||
export * from "./int"
|
||||
export * from "./integer"
|
||||
export * from "./iso-date"
|
||||
export * from "./long"
|
||||
export * from "./media"
|
||||
export * from "./media-informations-delta"
|
||||
export * from "./rest-error-response"
|
||||
export * from "./season"
|
||||
export * from "./series"
|
||||
export * from "./timestamp"
|
||||
export * from "./type"
|
||||
export * from "./user"
|
||||
export * from "./user-karideo"
|
||||
export * from "./user-media-advancement"
|
||||
export * from "./user-out"
|
||||
export * from "./uuid"
|
35
front/src/app/back-api/model/int.ts
Normal file
35
front/src/app/back-api/model/int.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const Zodint = zod.object({
|
||||
|
||||
});
|
||||
|
||||
export type int = zod.infer<typeof Zodint>;
|
||||
|
||||
export function isint(data: any): data is int {
|
||||
try {
|
||||
Zodint.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='Zodint' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodintWrite = Zodint.partial();
|
||||
|
||||
export type intWrite = zod.infer<typeof ZodintWrite>;
|
||||
|
||||
export function isintWrite(data: any): data is intWrite {
|
||||
try {
|
||||
ZodintWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodintWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
8
front/src/app/back-api/model/integer.ts
Normal file
8
front/src/app/back-api/model/integer.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodInteger = zod.number().safe();
|
||||
export type Integer = zod.infer<typeof ZodInteger>;
|
8
front/src/app/back-api/model/iso-date.ts
Normal file
8
front/src/app/back-api/model/iso-date.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodIsoDate = zod.string().datetime({ precision: 3 });
|
||||
export type IsoDate = zod.infer<typeof ZodIsoDate>;
|
8
front/src/app/back-api/model/long.ts
Normal file
8
front/src/app/back-api/model/long.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodLong = zod.number();
|
||||
export type Long = zod.infer<typeof ZodLong>;
|
35
front/src/app/back-api/model/media-informations-delta.ts
Normal file
35
front/src/app/back-api/model/media-informations-delta.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodMediaInformationsDelta = zod.object({
|
||||
|
||||
});
|
||||
|
||||
export type MediaInformationsDelta = zod.infer<typeof ZodMediaInformationsDelta>;
|
||||
|
||||
export function isMediaInformationsDelta(data: any): data is MediaInformationsDelta {
|
||||
try {
|
||||
ZodMediaInformationsDelta.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodMediaInformationsDelta' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodMediaInformationsDeltaWrite = ZodMediaInformationsDelta.partial();
|
||||
|
||||
export type MediaInformationsDeltaWrite = zod.infer<typeof ZodMediaInformationsDeltaWrite>;
|
||||
|
||||
export function isMediaInformationsDeltaWrite(data: any): data is MediaInformationsDeltaWrite {
|
||||
try {
|
||||
ZodMediaInformationsDeltaWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodMediaInformationsDeltaWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
86
front/src/app/back-api/model/media.ts
Normal file
86
front/src/app/back-api/model/media.ts
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodUUID} from "./uuid";
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodInteger} from "./integer";
|
||||
import {ZodGenericDataSoftDelete} from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodMedia = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string(),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
/**
|
||||
* Foreign Key Id of the data
|
||||
*/
|
||||
dataId: ZodUUID,
|
||||
/**
|
||||
* Type of the media
|
||||
*/
|
||||
typeId: ZodLong.optional(),
|
||||
/**
|
||||
* Series reference of the media
|
||||
*/
|
||||
seriesId: ZodLong.optional(),
|
||||
/**
|
||||
* Season reference of the media
|
||||
*/
|
||||
seasonId: ZodLong.optional(),
|
||||
/**
|
||||
* Episode Id
|
||||
*/
|
||||
episode: ZodInteger.optional(),
|
||||
date: ZodInteger.optional(),
|
||||
/**
|
||||
* Creation years of the media
|
||||
*/
|
||||
time: ZodInteger.optional(),
|
||||
/**
|
||||
* Limitation Age of the media
|
||||
*/
|
||||
ageLimit: ZodInteger.optional(),
|
||||
/**
|
||||
* List of Id of the specific covers
|
||||
*/
|
||||
covers: zod.array(ZodUUID),
|
||||
|
||||
});
|
||||
|
||||
export type Media = zod.infer<typeof ZodMedia>;
|
||||
|
||||
export function isMedia(data: any): data is Media {
|
||||
try {
|
||||
ZodMedia.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodMedia' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodMediaWrite = ZodMedia.omit({
|
||||
deleted: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type MediaWrite = zod.infer<typeof ZodMediaWrite>;
|
||||
|
||||
export function isMediaWrite(data: any): data is MediaWrite {
|
||||
try {
|
||||
ZodMediaWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodMediaWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
43
front/src/app/back-api/model/rest-error-response.ts
Normal file
43
front/src/app/back-api/model/rest-error-response.ts
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodUUID} from "./uuid";
|
||||
import {Zodint} from "./int";
|
||||
|
||||
export const ZodRestErrorResponse = zod.object({
|
||||
uuid: ZodUUID.optional(),
|
||||
name: zod.string(),
|
||||
message: zod.string(),
|
||||
time: zod.string(),
|
||||
status: Zodint,
|
||||
statusMessage: zod.string(),
|
||||
|
||||
});
|
||||
|
||||
export type RestErrorResponse = zod.infer<typeof ZodRestErrorResponse>;
|
||||
|
||||
export function isRestErrorResponse(data: any): data is RestErrorResponse {
|
||||
try {
|
||||
ZodRestErrorResponse.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodRestErrorResponse' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodRestErrorResponseWrite = ZodRestErrorResponse.partial();
|
||||
|
||||
export type RestErrorResponseWrite = zod.infer<typeof ZodRestErrorResponseWrite>;
|
||||
|
||||
export function isRestErrorResponseWrite(data: any): data is RestErrorResponseWrite {
|
||||
try {
|
||||
ZodRestErrorResponseWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodRestErrorResponseWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
60
front/src/app/back-api/model/season.ts
Normal file
60
front/src/app/back-api/model/season.ts
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodUUID} from "./uuid";
|
||||
import {ZodGenericDataSoftDelete} from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodSeason = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string(),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
/**
|
||||
* series parent ID
|
||||
*/
|
||||
parentId: ZodLong,
|
||||
/**
|
||||
* List of Id of the specific covers
|
||||
*/
|
||||
covers: zod.array(ZodUUID),
|
||||
|
||||
});
|
||||
|
||||
export type Season = zod.infer<typeof ZodSeason>;
|
||||
|
||||
export function isSeason(data: any): data is Season {
|
||||
try {
|
||||
ZodSeason.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodSeason' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodSeasonWrite = ZodSeason.omit({
|
||||
deleted: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type SeasonWrite = zod.infer<typeof ZodSeasonWrite>;
|
||||
|
||||
export function isSeasonWrite(data: any): data is SeasonWrite {
|
||||
try {
|
||||
ZodSeasonWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodSeasonWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
60
front/src/app/back-api/model/series.ts
Normal file
60
front/src/app/back-api/model/series.ts
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodUUID} from "./uuid";
|
||||
import {ZodGenericDataSoftDelete} from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodSeries = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string(),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
/**
|
||||
* series parent ID
|
||||
*/
|
||||
parentId: ZodLong,
|
||||
/**
|
||||
* List of Id of the specific covers
|
||||
*/
|
||||
covers: zod.array(ZodUUID),
|
||||
|
||||
});
|
||||
|
||||
export type Series = zod.infer<typeof ZodSeries>;
|
||||
|
||||
export function isSeries(data: any): data is Series {
|
||||
try {
|
||||
ZodSeries.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodSeries' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodSeriesWrite = ZodSeries.omit({
|
||||
deleted: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type SeriesWrite = zod.infer<typeof ZodSeriesWrite>;
|
||||
|
||||
export function isSeriesWrite(data: any): data is SeriesWrite {
|
||||
try {
|
||||
ZodSeriesWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodSeriesWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
8
front/src/app/back-api/model/timestamp.ts
Normal file
8
front/src/app/back-api/model/timestamp.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodTimestamp = zod.string().datetime({ precision: 3 });
|
||||
export type Timestamp = zod.infer<typeof ZodTimestamp>;
|
55
front/src/app/back-api/model/type.ts
Normal file
55
front/src/app/back-api/model/type.ts
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodUUID} from "./uuid";
|
||||
import {ZodGenericDataSoftDelete} from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodType = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string(),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
/**
|
||||
* List of Id of the specific covers
|
||||
*/
|
||||
covers: zod.array(ZodUUID),
|
||||
|
||||
});
|
||||
|
||||
export type Type = zod.infer<typeof ZodType>;
|
||||
|
||||
export function isType(data: any): data is Type {
|
||||
try {
|
||||
ZodType.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodType' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodTypeWrite = ZodType.omit({
|
||||
deleted: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type TypeWrite = zod.infer<typeof ZodTypeWrite>;
|
||||
|
||||
export function isTypeWrite(data: any): data is TypeWrite {
|
||||
try {
|
||||
ZodTypeWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodTypeWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
42
front/src/app/back-api/model/user-karideo.ts
Normal file
42
front/src/app/back-api/model/user-karideo.ts
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodUser} from "./user";
|
||||
|
||||
export const ZodUserKarideo = ZodUser.extend({
|
||||
|
||||
});
|
||||
|
||||
export type UserKarideo = zod.infer<typeof ZodUserKarideo>;
|
||||
|
||||
export function isUserKarideo(data: any): data is UserKarideo {
|
||||
try {
|
||||
ZodUserKarideo.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserKarideo' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodUserKarideoWrite = ZodUserKarideo.omit({
|
||||
deleted: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type UserKarideoWrite = zod.infer<typeof ZodUserKarideoWrite>;
|
||||
|
||||
export function isUserKarideoWrite(data: any): data is UserKarideoWrite {
|
||||
try {
|
||||
ZodUserKarideoWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserKarideoWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
65
front/src/app/back-api/model/user-media-advancement.ts
Normal file
65
front/src/app/back-api/model/user-media-advancement.ts
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodFloat} from "./float";
|
||||
import {ZodInteger} from "./integer";
|
||||
import {ZodGenericDataSoftDelete} from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodUserMediaAdvancement = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
* Foreign Key Id of the user
|
||||
*/
|
||||
userId: ZodLong,
|
||||
/**
|
||||
* Id of the media
|
||||
*/
|
||||
mediaId: ZodLong,
|
||||
/**
|
||||
* Percent of advancement in the media
|
||||
*/
|
||||
percent: ZodFloat,
|
||||
/**
|
||||
* Number of second of advancement in the media
|
||||
*/
|
||||
time: ZodInteger,
|
||||
/**
|
||||
* Number of time this media has been read
|
||||
*/
|
||||
count: ZodInteger,
|
||||
|
||||
});
|
||||
|
||||
export type UserMediaAdvancement = zod.infer<typeof ZodUserMediaAdvancement>;
|
||||
|
||||
export function isUserMediaAdvancement(data: any): data is UserMediaAdvancement {
|
||||
try {
|
||||
ZodUserMediaAdvancement.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserMediaAdvancement' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodUserMediaAdvancementWrite = ZodUserMediaAdvancement.omit({
|
||||
deleted: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type UserMediaAdvancementWrite = zod.infer<typeof ZodUserMediaAdvancementWrite>;
|
||||
|
||||
export function isUserMediaAdvancementWrite(data: any): data is UserMediaAdvancementWrite {
|
||||
try {
|
||||
ZodUserMediaAdvancementWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserMediaAdvancementWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
38
front/src/app/back-api/model/user-out.ts
Normal file
38
front/src/app/back-api/model/user-out.ts
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
|
||||
export const ZodUserOut = zod.object({
|
||||
id: ZodLong,
|
||||
login: zod.string().max(255).optional(),
|
||||
|
||||
});
|
||||
|
||||
export type UserOut = zod.infer<typeof ZodUserOut>;
|
||||
|
||||
export function isUserOut(data: any): data is UserOut {
|
||||
try {
|
||||
ZodUserOut.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserOut' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodUserOutWrite = ZodUserOut.partial();
|
||||
|
||||
export type UserOutWrite = zod.infer<typeof ZodUserOutWrite>;
|
||||
|
||||
export function isUserOutWrite(data: any): data is UserOutWrite {
|
||||
try {
|
||||
ZodUserOutWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserOutWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
53
front/src/app/back-api/model/user.ts
Normal file
53
front/src/app/back-api/model/user.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodTimestamp} from "./timestamp";
|
||||
import {ZodUUID} from "./uuid";
|
||||
import {ZodGenericDataSoftDelete} from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodUser = ZodGenericDataSoftDelete.extend({
|
||||
login: zod.string().max(128).optional(),
|
||||
lastConnection: ZodTimestamp.optional(),
|
||||
admin: zod.boolean(),
|
||||
blocked: zod.boolean(),
|
||||
removed: zod.boolean(),
|
||||
/**
|
||||
* List of Id of the specific covers
|
||||
*/
|
||||
covers: zod.array(ZodUUID).optional(),
|
||||
|
||||
});
|
||||
|
||||
export type User = zod.infer<typeof ZodUser>;
|
||||
|
||||
export function isUser(data: any): data is User {
|
||||
try {
|
||||
ZodUser.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUser' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const ZodUserWrite = ZodUser.omit({
|
||||
deleted: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
|
||||
}).partial();
|
||||
|
||||
export type UserWrite = zod.infer<typeof ZodUserWrite>;
|
||||
|
||||
export function isUserWrite(data: any): data is UserWrite {
|
||||
try {
|
||||
ZodUserWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
8
front/src/app/back-api/model/uuid.ts
Normal file
8
front/src/app/back-api/model/uuid.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodUUID = zod.string().uuid();
|
||||
export type UUID = zod.infer<typeof ZodUUID>;
|
445
front/src/app/back-api/rest-tools.ts
Normal file
445
front/src/app/back-api/rest-tools.ts
Normal file
@ -0,0 +1,445 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2024, Edouard DUPIN, all right reserved
|
||||
* @license MPL-2
|
||||
*/
|
||||
|
||||
import { RestErrorResponse, isRestErrorResponse } from "./model";
|
||||
|
||||
export enum HTTPRequestModel {
|
||||
DELETE = "DELETE",
|
||||
GET = "GET",
|
||||
PATCH = "PATCH",
|
||||
POST = "POST",
|
||||
PUT = "PUT",
|
||||
}
|
||||
export enum HTTPMimeType {
|
||||
ALL = "*/*",
|
||||
CSV = "text/csv",
|
||||
IMAGE = "image/*",
|
||||
IMAGE_JPEG = "image/jpeg",
|
||||
IMAGE_PNG = "image/png",
|
||||
JSON = "application/json",
|
||||
MULTIPART = "multipart/form-data",
|
||||
OCTET_STREAM = "application/octet-stream",
|
||||
TEXT_PLAIN = "text/plain",
|
||||
}
|
||||
|
||||
export interface RESTConfig {
|
||||
// base of the server: http(s)://my.server.org/plop/api/
|
||||
server: string;
|
||||
// Token to access of the data.
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export interface RESTModel {
|
||||
// base of the local API request: "sheep/{id}".
|
||||
endPoint: string;
|
||||
// Type of the request.
|
||||
requestType?: HTTPRequestModel;
|
||||
// Input type requested.
|
||||
accept?: HTTPMimeType;
|
||||
// Content of the local data.
|
||||
contentType?: HTTPMimeType;
|
||||
// Mode of the TOKEN in URL or Header (?token:${tokenInUrl})
|
||||
tokenInUrl?: boolean;
|
||||
}
|
||||
|
||||
export interface ModelResponseHttp {
|
||||
status: number;
|
||||
data: any;
|
||||
}
|
||||
|
||||
function isNullOrUndefined(data: any): data is undefined | null {
|
||||
return data === undefined || data === null;
|
||||
}
|
||||
|
||||
// generic progression callback
|
||||
export type ProgressCallback = (count: number, total: number) => void;
|
||||
|
||||
export interface RESTAbort {
|
||||
abort?: () => boolean;
|
||||
}
|
||||
|
||||
// Rest generic callback have a basic model to upload and download advancement.
|
||||
export interface RESTCallbacks {
|
||||
progressUpload?: ProgressCallback;
|
||||
progressDownload?: ProgressCallback;
|
||||
abortHandle?: RESTAbort;
|
||||
}
|
||||
|
||||
export interface RESTRequestType {
|
||||
restModel: RESTModel;
|
||||
restConfig: RESTConfig;
|
||||
data?: any;
|
||||
params?: object;
|
||||
queries?: object;
|
||||
callback?: RESTCallbacks;
|
||||
}
|
||||
|
||||
function replaceAll(input, searchValue, replaceValue) {
|
||||
return input.split(searchValue).join(replaceValue);
|
||||
}
|
||||
|
||||
function removeTrailingSlashes(input: string): string {
|
||||
if (isNullOrUndefined(input)) {
|
||||
return "undefined";
|
||||
}
|
||||
return input.replace(/\/+$/, "");
|
||||
}
|
||||
function removeLeadingSlashes(input: string): string {
|
||||
if (isNullOrUndefined(input)) {
|
||||
return "";
|
||||
}
|
||||
return input.replace(/^\/+/, "");
|
||||
}
|
||||
|
||||
export function RESTUrl({
|
||||
restModel,
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
}: RESTRequestType): string {
|
||||
// Create the URL PATH:
|
||||
let generateUrl = `${removeTrailingSlashes(
|
||||
restConfig.server
|
||||
)}/${removeLeadingSlashes(restModel.endPoint)}`;
|
||||
if (params !== undefined) {
|
||||
for (let key of Object.keys(params)) {
|
||||
generateUrl = replaceAll(generateUrl, `{${key}}`, `${params[key]}`);
|
||||
}
|
||||
}
|
||||
if (
|
||||
queries === undefined &&
|
||||
(restConfig.token === undefined || restModel.tokenInUrl !== true)
|
||||
) {
|
||||
return generateUrl;
|
||||
}
|
||||
const searchParams = new URLSearchParams();
|
||||
if (queries !== undefined) {
|
||||
for (let key of Object.keys(queries)) {
|
||||
const value = queries[key];
|
||||
if (Array.isArray(value)) {
|
||||
for (const element of value) {
|
||||
searchParams.append(`${key}`, `${element}`);
|
||||
}
|
||||
} else {
|
||||
searchParams.append(`${key}`, `${value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (restConfig.token !== undefined && restModel.tokenInUrl === true) {
|
||||
searchParams.append("Authorization", `Bearer ${restConfig.token}`);
|
||||
}
|
||||
return generateUrl + "?" + searchParams.toString();
|
||||
}
|
||||
|
||||
export function fetchProgress(
|
||||
generateUrl: string,
|
||||
{
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
}: {
|
||||
method: HTTPRequestModel;
|
||||
headers: any;
|
||||
body: any;
|
||||
},
|
||||
{ progressUpload, progressDownload, abortHandle }: RESTCallbacks
|
||||
): Promise<Response> {
|
||||
const xhr: {
|
||||
io?: XMLHttpRequest;
|
||||
} = {
|
||||
io: new XMLHttpRequest(),
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
// Stream the upload progress
|
||||
if (progressUpload) {
|
||||
xhr.io?.upload.addEventListener("progress", (dataEvent) => {
|
||||
if (dataEvent.lengthComputable) {
|
||||
progressUpload(dataEvent.loaded, dataEvent.total);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Stream the download progress
|
||||
if (progressDownload) {
|
||||
xhr.io?.addEventListener("progress", (dataEvent) => {
|
||||
if (dataEvent.lengthComputable) {
|
||||
progressDownload(dataEvent.loaded, dataEvent.total);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (abortHandle) {
|
||||
abortHandle.abort = () => {
|
||||
if (xhr.io) {
|
||||
console.log(`Request abort on the XMLHttpRequest: ${generateUrl}`);
|
||||
xhr.io.abort();
|
||||
return true;
|
||||
}
|
||||
console.log(
|
||||
`Request abort (FAIL) on the XMLHttpRequest: ${generateUrl}`
|
||||
);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
// Check if we have an internal Fail:
|
||||
xhr.io?.addEventListener("error", () => {
|
||||
xhr.io = undefined;
|
||||
reject(new TypeError("Failed to fetch"));
|
||||
});
|
||||
|
||||
// Capture the end of the stream
|
||||
xhr.io?.addEventListener("loadend", () => {
|
||||
if (xhr.io?.readyState !== XMLHttpRequest.DONE) {
|
||||
return;
|
||||
}
|
||||
if (xhr.io?.status === 0) {
|
||||
//the stream has been aborted
|
||||
reject(new TypeError("Fetch has been aborted"));
|
||||
return;
|
||||
}
|
||||
// Stream is ended, transform in a generic response:
|
||||
const response = new Response(xhr.io.response, {
|
||||
status: xhr.io.status,
|
||||
statusText: xhr.io.statusText,
|
||||
});
|
||||
const headersArray = replaceAll(
|
||||
xhr.io.getAllResponseHeaders().trim(),
|
||||
"\r\n",
|
||||
"\n"
|
||||
).split("\n");
|
||||
headersArray.forEach(function (header) {
|
||||
const firstColonIndex = header.indexOf(":");
|
||||
if (firstColonIndex !== -1) {
|
||||
const key = header.substring(0, firstColonIndex).trim();
|
||||
const value = header.substring(firstColonIndex + 1).trim();
|
||||
response.headers.set(key, value);
|
||||
} else {
|
||||
response.headers.set(header, "");
|
||||
}
|
||||
});
|
||||
xhr.io = undefined;
|
||||
resolve(response);
|
||||
});
|
||||
xhr.io?.open(method, generateUrl, true);
|
||||
if (!isNullOrUndefined(headers)) {
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
xhr.io?.setRequestHeader(key, value as string);
|
||||
}
|
||||
}
|
||||
xhr.io?.send(body);
|
||||
});
|
||||
}
|
||||
|
||||
export function RESTRequest({
|
||||
restModel,
|
||||
restConfig,
|
||||
data,
|
||||
params,
|
||||
queries,
|
||||
callback,
|
||||
}: RESTRequestType): Promise<ModelResponseHttp> {
|
||||
// Create the URL PATH:
|
||||
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
||||
let headers: any = {};
|
||||
if (restConfig.token !== undefined && restModel.tokenInUrl !== true) {
|
||||
headers["Authorization"] = `Bearer ${restConfig.token}`;
|
||||
}
|
||||
if (restModel.accept !== undefined) {
|
||||
headers["Accept"] = restModel.accept;
|
||||
}
|
||||
if (restModel.requestType !== HTTPRequestModel.GET) {
|
||||
// if Get we have not a content type, the body is empty
|
||||
if (restModel.contentType !== HTTPMimeType.MULTIPART) {
|
||||
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
|
||||
headers["Content-Type"] = restModel.contentType;
|
||||
}
|
||||
}
|
||||
let body = data;
|
||||
if (restModel.contentType === HTTPMimeType.JSON) {
|
||||
body = JSON.stringify(data);
|
||||
} else if (restModel.contentType === HTTPMimeType.MULTIPART) {
|
||||
const formData = new FormData();
|
||||
for (const name in data) {
|
||||
formData.append(name, data[name]);
|
||||
}
|
||||
body = formData;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let action: undefined | Promise<Response> = undefined;
|
||||
if (
|
||||
isNullOrUndefined(callback) ||
|
||||
(isNullOrUndefined(callback.progressDownload) &&
|
||||
isNullOrUndefined(callback.progressUpload) &&
|
||||
isNullOrUndefined(callback.abortHandle))
|
||||
) {
|
||||
// No information needed: call the generic fetch interface
|
||||
action = fetch(generateUrl, {
|
||||
method: restModel.requestType,
|
||||
headers,
|
||||
body,
|
||||
});
|
||||
} else {
|
||||
// need progression information: call old fetch model (XMLHttpRequest) that permit to keep % upload and % download for HTTP1.x
|
||||
action = fetchProgress(
|
||||
generateUrl,
|
||||
{
|
||||
method: restModel.requestType ?? HTTPRequestModel.GET,
|
||||
headers,
|
||||
body,
|
||||
},
|
||||
callback
|
||||
);
|
||||
}
|
||||
action
|
||||
.then((response: Response) => {
|
||||
if (response.status >= 200 && response.status <= 299) {
|
||||
const contentType = response.headers.get("Content-Type");
|
||||
if (
|
||||
!isNullOrUndefined(restModel.accept) &&
|
||||
restModel.accept !== contentType
|
||||
) {
|
||||
reject({
|
||||
name: "Model accept type incompatible",
|
||||
time: Date().toString(),
|
||||
status: 901,
|
||||
message: `REST Content type are not compatible: ${restModel.accept} != ${contentType}`,
|
||||
statusMessage: "Fetch error",
|
||||
error: "rest-tools.ts Wrong type in the message return type",
|
||||
} as RestErrorResponse);
|
||||
} else if (contentType === HTTPMimeType.JSON) {
|
||||
response
|
||||
.json()
|
||||
.then((value: any) => {
|
||||
resolve({ status: response.status, data: value });
|
||||
})
|
||||
.catch((reason: Error) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
time: Date().toString(),
|
||||
status: 902,
|
||||
message: `REST parse json fail: ${reason}`,
|
||||
statusMessage: "Fetch parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
} else {
|
||||
resolve({ status: response.status, data: response.body });
|
||||
}
|
||||
} else {
|
||||
// the answer is not correct not a 2XX
|
||||
// clone the response to keep the raw data if case of error:
|
||||
response
|
||||
.clone()
|
||||
.json()
|
||||
.then((value: any) => {
|
||||
if (isRestErrorResponse(value)) {
|
||||
reject(value);
|
||||
} else {
|
||||
response
|
||||
.text()
|
||||
.then((dataError: string) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
time: Date().toString(),
|
||||
status: 903,
|
||||
message: `REST parse error json with wrong type fail. ${dataError}`,
|
||||
statusMessage: "Fetch parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
} as RestErrorResponse);
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
time: Date().toString(),
|
||||
status: response.status,
|
||||
message: `unmanaged error model: ??? with error: ${reason}`,
|
||||
statusMessage: "Fetch ERROR parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((reason: Error) => {
|
||||
response
|
||||
.text()
|
||||
.then((dataError: string) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
time: Date().toString(),
|
||||
status: response.status,
|
||||
message: `unmanaged error model: ${dataError} with error: ${reason}`,
|
||||
statusMessage: "Fetch ERROR TEXT parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
} as RestErrorResponse);
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
time: Date().toString(),
|
||||
status: response.status,
|
||||
message: `unmanaged error model: ??? with error: ${reason}`,
|
||||
statusMessage: "Fetch ERROR TEXT FAIL",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
if (isRestErrorResponse(error)) {
|
||||
reject(error);
|
||||
} else {
|
||||
reject({
|
||||
name: "Request fail",
|
||||
time: Date(),
|
||||
status: 999,
|
||||
message: error,
|
||||
statusMessage: "Fetch catch error",
|
||||
error: "rest-tools.ts detect an error in the fetch request",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function RESTRequestJson<TYPE>(
|
||||
request: RESTRequestType,
|
||||
checker?: (data: any) => data is TYPE
|
||||
): Promise<TYPE> {
|
||||
return new Promise((resolve, reject) => {
|
||||
RESTRequest(request)
|
||||
.then((value: ModelResponseHttp) => {
|
||||
if (isNullOrUndefined(checker)) {
|
||||
console.log(`Have no check of MODEL in API: ${RESTUrl(request)}`);
|
||||
resolve(value.data);
|
||||
} else if (checker === undefined || checker(value.data)) {
|
||||
resolve(value.data);
|
||||
} else {
|
||||
reject({
|
||||
name: "Model check fail",
|
||||
time: Date().toString(),
|
||||
status: 950,
|
||||
error: "REST Fail to verify the data",
|
||||
statusMessage: "API cast ERROR",
|
||||
message: "api.ts Check type as fail",
|
||||
} as RestErrorResponse);
|
||||
}
|
||||
})
|
||||
.catch((reason: RestErrorResponse) => {
|
||||
reject(reason);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function RESTRequestVoid(request: RESTRequestType): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
RESTRequest(request)
|
||||
.then((value: ModelResponseHttp) => {
|
||||
resolve();
|
||||
})
|
||||
.catch((reason: RestErrorResponse) => {
|
||||
reject(reason);
|
||||
});
|
||||
});
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { UUID } from 'app/back-api';
|
||||
//import { ModelResponseHttp } from '@app/service/http-wrapper';
|
||||
import { DataService } from 'app/service/data';
|
||||
|
||||
@ -14,7 +15,7 @@ import { DataService } from 'app/service/data';
|
||||
})
|
||||
export class ElementDataImageComponent implements OnInit {
|
||||
// input parameters
|
||||
@Input() id:number = -1;
|
||||
@Input() id?: UUID;
|
||||
cover: string = '';
|
||||
/*
|
||||
imageCanvas:any;
|
||||
@ -29,7 +30,7 @@ export class ElementDataImageComponent implements OnInit {
|
||||
|
||||
}
|
||||
ngOnInit() {
|
||||
this.cover = this.dataService.getCoverThumbnailUrl(this.id);
|
||||
this.cover = this.dataService.getThumbnailUrl(this.id);
|
||||
/*
|
||||
let canvas = this.imageCanvas.nativeElement;
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
@ -1,19 +1,26 @@
|
||||
|
||||
<div class="imgContainer-small">
|
||||
<div *ngIf="covers">
|
||||
@if(covers) {
|
||||
<div>
|
||||
<!--<data-image id="{{cover}}"></data-image>-->
|
||||
<img src="{{covers[0]}}"/>
|
||||
</div>
|
||||
<div *ngIf="!covers" class="noImage">
|
||||
|
||||
}
|
||||
@else {
|
||||
<div class="noImage">
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="season-small">
|
||||
Season {{numberSeason}}
|
||||
</div>
|
||||
<div class="description-small" *ngIf="count > 1">
|
||||
{{count}} Episodes
|
||||
@if(count > 0) {
|
||||
<div class="description-small">
|
||||
{{count}} épisode{{count > 1?"s":""}}
|
||||
</div>
|
||||
<div class="description-small" *ngIf="count == 1">
|
||||
{{count}} Episode
|
||||
}
|
||||
@else {
|
||||
<div class="description-small">
|
||||
Aucun épisode
|
||||
</div>
|
||||
}
|
@ -4,10 +4,10 @@
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Season } from 'app/back-api';
|
||||
|
||||
import { SeasonService, DataService } from 'app/service';
|
||||
import { NodeData } from 'common/model';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-element-season',
|
||||
@ -16,7 +16,7 @@ import { isNullOrUndefined } from 'common/utils';
|
||||
})
|
||||
export class ElementSeasonComponent implements OnInit {
|
||||
// input parameters
|
||||
@Input() element:NodeData;
|
||||
@Input() element: Season;
|
||||
|
||||
numberSeason: string;
|
||||
count: number;
|
||||
@ -24,8 +24,9 @@ export class ElementSeasonComponent implements OnInit {
|
||||
description: string;
|
||||
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private seasonService: SeasonService,
|
||||
private dataService: DataService) {
|
||||
) {
|
||||
|
||||
}
|
||||
ngOnInit() {
|
||||
@ -36,7 +37,7 @@ export class ElementSeasonComponent implements OnInit {
|
||||
}
|
||||
this.numberSeason = this.element.name;
|
||||
this.description = this.element.description;
|
||||
this.covers = this.dataService.getCoverListThumbnailUrl(this.element.covers);
|
||||
this.covers = this.dataService.getListThumbnailUrl(this.element.covers);
|
||||
let self = this;
|
||||
this.seasonService.countVideo(this.element.id)
|
||||
.then((response) => {
|
||||
|
@ -1,24 +1,24 @@
|
||||
<div>
|
||||
<div class="count-base">
|
||||
<div class="count" *ngIf="countvideo">
|
||||
{{countvideo}}
|
||||
@if(countVideo) {
|
||||
<div class="count">
|
||||
{{countVideo}}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="imgContainer-small">
|
||||
<div *ngIf="covers">
|
||||
@if(covers) {
|
||||
<div>
|
||||
<!--<data-image id="{{cover}}"></data-image>-->
|
||||
<img src="{{covers[0]}}"/>
|
||||
</div>
|
||||
<div *ngIf="!covers" class="noImage">
|
||||
|
||||
}
|
||||
@else {
|
||||
<div class="noImage">
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="title-small">
|
||||
{{name}}
|
||||
</div>
|
||||
<!--
|
||||
<div class="description-small" *ngIf="description">
|
||||
{{description}}
|
||||
</div>
|
||||
-->
|
||||
</div>
|
@ -4,8 +4,8 @@
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { NodeData } from 'common/model';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Series } from 'app/back-api';
|
||||
|
||||
import { SeriesService, DataService } from 'app/service';
|
||||
|
||||
@ -16,17 +16,18 @@ import { SeriesService, DataService } from 'app/service';
|
||||
})
|
||||
export class ElementSeriesComponent implements OnInit {
|
||||
// input parameters
|
||||
@Input() element:NodeData;
|
||||
@Input() element: Series;
|
||||
|
||||
name: string = 'plouf';
|
||||
description: string = '';
|
||||
countvideo:number = null;
|
||||
countVideo: number = null;
|
||||
|
||||
covers: string[];
|
||||
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private seriesService: SeriesService,
|
||||
private dataService: DataService) {
|
||||
) {
|
||||
|
||||
}
|
||||
ngOnInit() {
|
||||
@ -38,13 +39,13 @@ export class ElementSeriesComponent implements OnInit {
|
||||
let self = this;
|
||||
self.name = this.element.name;
|
||||
self.description = this.element.description;
|
||||
self.covers = self.dataService.getCoverListThumbnailUrl(this.element.covers);
|
||||
self.covers = self.dataService.getListThumbnailUrl(this.element.covers);
|
||||
|
||||
this.seriesService.countVideo(this.element.id)
|
||||
.then((response) => {
|
||||
self.countvideo = response;
|
||||
self.countVideo = response;
|
||||
}).catch((response) => {
|
||||
self.countvideo = 0;
|
||||
self.countVideo = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,24 @@
|
||||
<div>
|
||||
<div class="count-base">
|
||||
<span class="count" *ngIf="countvideo">
|
||||
{{countvideo}}
|
||||
@if(countVideo) {
|
||||
<span class="count">
|
||||
{{countVideo}}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<div class="imgContainer-small">
|
||||
<div *ngIf="covers">
|
||||
@if(covers) {
|
||||
<div>
|
||||
<img src="{{covers[0]}}" class="miniature-small"/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="title-small">
|
||||
{{name}}
|
||||
</div>
|
||||
<div class="description-small" *ngIf="description">
|
||||
@if(description) {
|
||||
<div class="description-small">
|
||||
{{description}}
|
||||
</div>
|
||||
}
|
||||
</div>
|
@ -4,8 +4,8 @@
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { isArrayOf, isNullOrUndefined, isNumberFinite } from 'common/utils';
|
||||
import { NodeData } from 'common/model';
|
||||
import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Type } from 'app/back-api';
|
||||
|
||||
import { TypeService, DataService } from 'app/service';
|
||||
|
||||
@ -16,39 +16,39 @@ import { TypeService, DataService } from 'app/service';
|
||||
})
|
||||
export class ElementTypeComponent implements OnInit {
|
||||
// input parameters
|
||||
@Input() element:NodeData;
|
||||
@Input() element: Type;
|
||||
|
||||
public name: string = 'rr';
|
||||
public description: string;
|
||||
|
||||
public countvideo:number;
|
||||
public countVideo: number;
|
||||
|
||||
public covers: string[];
|
||||
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private typeService: TypeService,
|
||||
private dataService: DataService) {
|
||||
) {
|
||||
|
||||
}
|
||||
ngOnInit() {
|
||||
if (isNullOrUndefined(this.element)) {
|
||||
this.name = 'Not a media';
|
||||
this.description = undefined;
|
||||
this.countvideo = undefined;
|
||||
this.countVideo = undefined;
|
||||
this.covers = undefined;
|
||||
return;
|
||||
}
|
||||
let self = this;
|
||||
console.log(" ??? Get element ! " + JSON.stringify(this.element));
|
||||
self.name = this.element.name;
|
||||
self.description = this.element.description;
|
||||
self.covers = self.dataService.getCoverListThumbnailUrl(this.element.covers);
|
||||
self.covers = self.dataService.getListThumbnailUrl(this.element.covers);
|
||||
|
||||
this.typeService.countVideo(this.element.id)
|
||||
.then((response: number) => {
|
||||
self.countvideo = response;
|
||||
self.countVideo = response;
|
||||
}).catch(() => {
|
||||
self.countvideo = 0;
|
||||
self.countVideo = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,31 @@
|
||||
<div>
|
||||
<div class="count-base">
|
||||
<span class="views" *ngIf="advancement">
|
||||
@if(advancement) {
|
||||
<span class="views">
|
||||
{{advancement.count}}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<div class="videoImgContainer">
|
||||
<div *ngIf="covers">
|
||||
@if(covers) {
|
||||
<div>
|
||||
<!--<data-image id="{{cover}}"></data-image>-->
|
||||
<img src="{{covers[0]}}" />
|
||||
</div>
|
||||
<div *ngIf="!covers" class="noImage">
|
||||
}
|
||||
@else {
|
||||
<div class="noImage">
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="view-progess" [ngStyle]="updateAdvancement()"></div>
|
||||
<div class="title-small" *ngIf="data">
|
||||
<div class="title-small">
|
||||
@if(data) {
|
||||
{{episodeDisplay}} {{name}}
|
||||
</div>
|
||||
<div class="title-small" *ngIf="!data">
|
||||
}
|
||||
@else {
|
||||
Error media: {{element?.id}}
|
||||
}
|
||||
</div>
|
||||
<!--
|
||||
<div class="description-small" *ngIf="description">
|
||||
{{description}}
|
||||
</div>
|
||||
-->
|
||||
</div>
|
@ -4,12 +4,10 @@
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Injectable, Component, OnInit, Input } from '@angular/core';
|
||||
import { isMedia, Media } from 'app/model';
|
||||
import { UserMediaAdvancement } from 'app/model/user-media-advancement';
|
||||
import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Media, UserMediaAdvancement } from 'app/back-api';
|
||||
|
||||
import { AdvancementService, DataService } from 'app/service';
|
||||
import { NodeData } from 'common/model';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-element-video',
|
||||
@ -20,7 +18,7 @@ import { isNullOrUndefined } from 'common/utils';
|
||||
@Injectable()
|
||||
export class ElementVideoComponent implements OnInit {
|
||||
// input parameters
|
||||
@Input() element: NodeData;
|
||||
@Input() element: Media;
|
||||
data: Media;
|
||||
|
||||
name: string = '';
|
||||
@ -38,12 +36,6 @@ export class ElementVideoComponent implements OnInit {
|
||||
// nothing to do.
|
||||
}
|
||||
ngOnInit() {
|
||||
if (!isMedia(this.element)) {
|
||||
this.data = undefined;
|
||||
this.name = 'Not a media';
|
||||
this.description = undefined;
|
||||
return;
|
||||
}
|
||||
this.data = this.element;
|
||||
this.name = this.element.name;
|
||||
this.description = this.element.description;
|
||||
@ -52,7 +44,7 @@ export class ElementVideoComponent implements OnInit {
|
||||
} else {
|
||||
this.episodeDisplay = `${this.element.episode} - `;
|
||||
}
|
||||
this.covers = this.dataService.getCoverListThumbnailUrl(this.element.covers);
|
||||
this.covers = this.dataService.getListThumbnailUrl(this.element.covers);
|
||||
|
||||
this.advancementService.get(this.element.id)
|
||||
.then((response: UserMediaAdvancement) => {
|
||||
|
@ -1,5 +0,0 @@
|
||||
import { Media, isMedia } from "./media";
|
||||
|
||||
export {
|
||||
Media, isMedia,
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
import { isNumberFinite, isString, isOptionalOf } from "common/utils";
|
||||
import { isNodeData, NodeData } from "common/model/node";
|
||||
|
||||
|
||||
export interface Media extends NodeData {
|
||||
dataId?: number;
|
||||
typeId?: number;
|
||||
seriesId?: number;
|
||||
seasonId?: number;
|
||||
episode?: number;
|
||||
date?: number;
|
||||
time?: number;
|
||||
ageLimit?: number;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export function isMedia(data: any): data is Media {
|
||||
if (!isNodeData(data) as any) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.dataId, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.typeId, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.seriesId, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.seasonId, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.episode, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.date, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.time, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.ageLimit, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
import { isNumberFinite, isString, isOptionalOf, isNumber } from "common/utils";
|
||||
import { isNodeData, NodeData } from "common/model/node";
|
||||
|
||||
|
||||
export interface UserMediaAdvancement {
|
||||
id: number;
|
||||
|
||||
// Id of the media
|
||||
mediaId?: number;
|
||||
// Percent of advancement in the media
|
||||
percent?: number;
|
||||
// "Number of second of advancement in the media
|
||||
time?: number;
|
||||
// Number of time this media has been read
|
||||
count?: number;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export function isUserMediaAdvancement(data: any): data is UserMediaAdvancement {
|
||||
if (!isNumberFinite(data.id)) {
|
||||
return false;
|
||||
}
|
||||
if (!isNumberFinite(data.mediaId)) {
|
||||
return false;
|
||||
}
|
||||
if (!isNumber(data.percent)) {
|
||||
return false;
|
||||
}
|
||||
if (!isNumberFinite(data.time)) {
|
||||
return false;
|
||||
}
|
||||
if (!isNumberFinite(data.count)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -4,8 +4,7 @@
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { PopInService } from 'common/service/popin';
|
||||
import { PopInService } from '@kangaroo-and-rabbit/kar-cw';
|
||||
|
||||
@Component({
|
||||
selector: 'create-type',
|
||||
|
@ -3,9 +3,11 @@
|
||||
Karideo
|
||||
</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)">
|
||||
@for (data of dataList; track data.id;) {
|
||||
<div class="item-home" (click)="onSelectType($event, data.id)" (auxclick)="onSelectType($event, data.id)">
|
||||
<app-element-type [element]="data"></app-element-type>
|
||||
</div>
|
||||
}
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
@ -24,14 +24,12 @@ export class HomeScene implements OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
let self = this;
|
||||
this.typeService.getData()
|
||||
this.typeService.gets()
|
||||
.then((response) => {
|
||||
self.error = '';
|
||||
self.dataList = response;
|
||||
console.log(`Get response: ${ JSON.stringify(response, null, 2)}`);
|
||||
}).catch((response) => {
|
||||
self.error = 'Wrong e-mail/login or password';
|
||||
console.log(`[E] ${ self.constructor.name }: Does not get a correct response from the server ...`);
|
||||
self.dataList = [];
|
||||
});
|
||||
this.arianeService.reset();
|
||||
|
@ -2,21 +2,26 @@
|
||||
<div class="title">
|
||||
Edit season
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsRemoved">
|
||||
@if(itemIsRemoved) {
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
The season has been removed
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsNotFound">
|
||||
}
|
||||
@else if (itemIsNotFound){
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
The season does not exist
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsLoading">
|
||||
}
|
||||
@else if (itemIsLoading){
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
Loading ...<br/>
|
||||
@ -24,7 +29,9 @@
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
}
|
||||
@else {
|
||||
<div class="fill-all">
|
||||
<div class="request_raw">
|
||||
<div class="label">
|
||||
Number:
|
||||
@ -54,10 +61,10 @@
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<!-- ------------------------- Cover section --------------------------------- -->
|
||||
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="title">
|
||||
Covers
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="fill-all">
|
||||
<div class="hide-element">
|
||||
<input type="file"
|
||||
#fileInput
|
||||
@ -67,16 +74,18 @@
|
||||
</div>
|
||||
<div class="request_raw">
|
||||
<div class="input">
|
||||
<div class="cover" *ngFor="let element of coversDisplay">
|
||||
@for (data of coversDisplay; track data.id;) {
|
||||
<div class="cover" >
|
||||
<div class="cover-image">
|
||||
<img src="{{element.url}}"/>
|
||||
<img src="{{data.url}}"/>
|
||||
</div>
|
||||
<div class="cover-button">
|
||||
<button (click)="removeCover(element.id)">
|
||||
<button (click)="removeCover(data.id)">
|
||||
<i class="material-icons button-remove">highlight_off</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="cover">
|
||||
<div class="cover-no-image">
|
||||
</div>
|
||||
@ -91,10 +100,10 @@
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<!-- ------------------------- ADMIN section --------------------------------- -->
|
||||
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="title">
|
||||
Administration
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="fill-all">
|
||||
<div class="request_raw">
|
||||
<div class="label">
|
||||
<i class="material-icons">data_usage</i> ID:
|
||||
@ -117,23 +126,29 @@
|
||||
<div class="label">
|
||||
<i class="material-icons">delete_forever</i> Trash:
|
||||
</div>
|
||||
<div class="input" *ngIf="(videoCount == '0')">
|
||||
@if(videoCount == '0') {
|
||||
<div class="input">
|
||||
<button class="button color-button-cancel color-shadow-black" (click)="removeItem()" type="submit">
|
||||
<i class="material-icons">delete</i> Remove season
|
||||
</button>
|
||||
</div>
|
||||
<div class="input" *ngIf="(videoCount != '0')">
|
||||
}
|
||||
@else {
|
||||
<div class="input">
|
||||
<i class="material-icons">new_releases</i> Can not remove season, video depending on it
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<upload-progress [mediaTitle]="upload.labelMediaTitle"
|
||||
[mediaUploaded]="upload.mediaSendSize"
|
||||
[mediaSize]="upload.mediaSize"
|
||||
[result]="upload.result"
|
||||
[error]="upload.error"></upload-progress>
|
||||
[error]="upload.error"
|
||||
(abort)="abortUpload()"></upload-progress>
|
||||
<delete-confirm
|
||||
[comment]="confirmDeleteComment"
|
||||
[imageUrl]=confirmDeleteImageUrl
|
||||
|
@ -5,13 +5,11 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PopInService, UploadProgress, isNumberFinite } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Season, UUID } from 'app/back-api';
|
||||
import { RESTAbort } from 'app/back-api/rest-tools';
|
||||
|
||||
import { SeasonService, ArianeService, DataService } from 'app/service';
|
||||
import { NodeData } from 'common/model';
|
||||
|
||||
import { UploadProgress } from 'common/popin/upload-progress/upload-progress';
|
||||
import { PopInService } from 'common/service';
|
||||
import { isNumberFinite } from 'common/utils';
|
||||
|
||||
export interface ElementList {
|
||||
value: number;
|
||||
@ -32,11 +30,11 @@ export class SeasonEditScene implements OnInit {
|
||||
|
||||
error: string = '';
|
||||
|
||||
numberVal: number = null;
|
||||
numberVal: string = null;
|
||||
description: string = '';
|
||||
coverFile: File;
|
||||
coverFile?: File;
|
||||
uploadFileValue: string = '';
|
||||
selectedFiles: FileList;
|
||||
selectedFiles?: FileList;
|
||||
videoCount: string = null;
|
||||
|
||||
|
||||
@ -46,8 +44,9 @@ export class SeasonEditScene implements OnInit {
|
||||
// --------------- confirm section ------------------
|
||||
public confirmDeleteComment: string = null;
|
||||
public confirmDeleteImageUrl: string = null;
|
||||
private deleteCoverId: number = null;
|
||||
private deleteCoverId: UUID = null;
|
||||
private deleteItemId: number = null;
|
||||
cancelHandle: RESTAbort = {};
|
||||
deleteConfirmed() {
|
||||
if (this.deleteCoverId !== null) {
|
||||
this.removeCoverAfterConfirm(this.deleteCoverId);
|
||||
@ -67,10 +66,11 @@ export class SeasonEditScene implements OnInit {
|
||||
|
||||
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private seasonService: SeasonService,
|
||||
private arianeService: ArianeService,
|
||||
private popInService: PopInService,
|
||||
private dataService: DataService) {
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ export class SeasonEditScene implements OnInit {
|
||||
this.idSeason = this.arianeService.getSeasonId();
|
||||
let self = this;
|
||||
this.seasonService.get(this.idSeason)
|
||||
.then((response: NodeData) => {
|
||||
.then((response: Season) => {
|
||||
console.log(`get response of season : ${JSON.stringify(response, null, 2)}`);
|
||||
if (isNumberFinite(response.name)) {
|
||||
self.numberVal = response.name;
|
||||
@ -108,7 +108,7 @@ export class SeasonEditScene implements OnInit {
|
||||
for (let iii = 0; iii < covers.length; iii++) {
|
||||
this.coversDisplay.push({
|
||||
id: covers[iii],
|
||||
url: this.dataService.getCoverThumbnailUrl(covers[iii])
|
||||
url: this.dataService.getThumbnailUrl(covers[iii])
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@ -126,7 +126,7 @@ export class SeasonEditScene implements OnInit {
|
||||
sendValues(): void {
|
||||
console.log('send new values....');
|
||||
let data = {
|
||||
name: this.numberVal,
|
||||
name: `${this.numberVal}`,
|
||||
description: this.description
|
||||
};
|
||||
if (this.description === undefined) {
|
||||
@ -149,6 +149,10 @@ export class SeasonEditScene implements OnInit {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
abortUpload(): void {
|
||||
this.cancelHandle.abort();
|
||||
}
|
||||
|
||||
// At the file input element
|
||||
// (change)="selectFile($event)"
|
||||
onChangeCover(value: any): void {
|
||||
@ -168,10 +172,10 @@ export class SeasonEditScene implements OnInit {
|
||||
this.upload.clear();
|
||||
// display the upload pop-in
|
||||
this.popInService.open('popin-upload-progress');
|
||||
this.seasonService.uploadCover(file, this.idSeason, (count, total) => {
|
||||
this.seasonService.uploadCover(this.idSeason, file, (count, total) => {
|
||||
self.upload.mediaSendSize = count;
|
||||
self.upload.mediaSize = total;
|
||||
})
|
||||
}, this.cancelHandle)
|
||||
.then((response: any) => {
|
||||
self.upload.result = 'Cover added done';
|
||||
// we retrive the whiole media ==> update data ...
|
||||
@ -182,14 +186,14 @@ export class SeasonEditScene implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
removeCover(id: number) {
|
||||
removeCover(id: UUID) {
|
||||
this.cleanConfirm();
|
||||
this.confirmDeleteComment = `Delete the cover ID: ${id}`;
|
||||
this.confirmDeleteImageUrl = this.dataService.getCoverThumbnailUrl(id);
|
||||
this.confirmDeleteImageUrl = this.dataService.getThumbnailUrl(id);
|
||||
this.deleteCoverId = id;
|
||||
this.popInService.open('popin-delete-confirm');
|
||||
}
|
||||
removeCoverAfterConfirm(id: number) {
|
||||
removeCoverAfterConfirm(id: UUID) {
|
||||
console.log(`Request remove cover: ${id}`);
|
||||
let self = this;
|
||||
this.seasonService.deleteCover(this.idSeason, id)
|
||||
|
@ -1,29 +1,36 @@
|
||||
<div class="generic-page">
|
||||
<div class="fill-title colomn_mutiple">
|
||||
<div class="cover-area">
|
||||
<div class="cover" *ngIf="cover != null" >
|
||||
@if(cover) {
|
||||
<div class="cover">
|
||||
<img src="{{cover}}"/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
|
||||
<div *ngIf="seriesName" class="title">
|
||||
@if(seriesName) {
|
||||
<div class="title">
|
||||
{{seriesName}}
|
||||
</div>
|
||||
}
|
||||
<div class="sub-title-main">
|
||||
Season {{name}}
|
||||
</div>
|
||||
<div class="description" *ngIf="description">
|
||||
@if(description) {
|
||||
<div class="description">
|
||||
{{description}}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-content colomn_mutiple">
|
||||
<div class="clear"></div>
|
||||
<div class="title" *ngIf="videos.length > 1">Videos:</div>
|
||||
<div class="title" *ngIf="videos.length == 1">Video:</div>
|
||||
<div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)">
|
||||
<div class="title">Video{{videos.length > 1?"s":""}}:</div>
|
||||
@for (data of videos; track data.id;) {
|
||||
<div class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)">
|
||||
<app-element-video [element]="data"></app-element-video>
|
||||
</div>
|
||||
}
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
@ -24,11 +24,12 @@ export class SeasonScene implements OnInit {
|
||||
videosError = '';
|
||||
videos = [];
|
||||
constructor(
|
||||
private advancementService: AdvancementService,
|
||||
private dataService: DataService,
|
||||
private seasonService: SeasonService,
|
||||
private seriesService: SeriesService,
|
||||
private arianeService: ArianeService,
|
||||
private dataService: DataService,
|
||||
private advancementService: AdvancementService) {
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@ -46,9 +47,9 @@ export class SeasonScene implements OnInit {
|
||||
self.cover = null;
|
||||
self.covers = [];
|
||||
} else {
|
||||
self.cover = self.dataService.getCoverUrl(response.covers[0]);
|
||||
self.cover = self.dataService.getThumbnailUrl(response.covers[0]);
|
||||
for (let iii = 0; iii < response.covers.length; iii++) {
|
||||
self.covers.push(self.dataService.getCoverUrl(response.covers[iii]));
|
||||
self.covers.push(self.dataService.getThumbnailUrl(response.covers[iii]));
|
||||
}
|
||||
}
|
||||
self.seriesService.get(self.seriesId)
|
||||
|
@ -2,21 +2,26 @@
|
||||
<div class="title">
|
||||
Edit series
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsRemoved">
|
||||
@if(itemIsRemoved) {
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
The series has been removed
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsNotFound">
|
||||
}
|
||||
@else if(itemIsNotFound) {
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
The series does not exist
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsLoading">
|
||||
}
|
||||
@else if(itemIsLoading) {
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
Loading ...<br/>
|
||||
@ -24,7 +29,9 @@
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
}
|
||||
@else {
|
||||
<div class="fill-all">
|
||||
<div class="request_raw">
|
||||
<div class="label">
|
||||
Type:
|
||||
@ -32,7 +39,9 @@
|
||||
<div class="input">
|
||||
<select [ngModel]="typeId"
|
||||
(ngModelChange)="onChangeType($event)">
|
||||
<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option>
|
||||
@for (data of listType; track data.value;) {
|
||||
<option [ngValue]="data.value">{{data.label}}</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -66,10 +75,10 @@
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<!-- ------------------------- Cover section --------------------------------- -->
|
||||
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="title">
|
||||
Covers
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="fill-all">
|
||||
<div class="hide-element">
|
||||
<input type="file"
|
||||
#fileInput
|
||||
@ -79,16 +88,18 @@
|
||||
</div>
|
||||
<div class="request_raw">
|
||||
<div class="input">
|
||||
<div class="cover" *ngFor="let element of coversDisplay">
|
||||
@for (data of coversDisplay; track data.id;) {
|
||||
<div class="cover">
|
||||
<div class="cover-image">
|
||||
<img src="{{element.url}}"/>
|
||||
<img src="{{data.url}}"/>
|
||||
</div>
|
||||
<div class="cover-button">
|
||||
<button (click)="removeCover(element.id)">
|
||||
<button (click)="removeCover(data.id)">
|
||||
<i class="material-icons button-remove">highlight_off</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="cover">
|
||||
<div class="cover-no-image">
|
||||
</div>
|
||||
@ -103,10 +114,10 @@
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<!-- ------------------------- ADMIN section --------------------------------- -->
|
||||
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="title">
|
||||
Administration
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="fill-all">
|
||||
<div class="request_raw">
|
||||
<div class="label">
|
||||
<i class="material-icons">data_usage</i> ID:
|
||||
@ -138,24 +149,30 @@
|
||||
<div class="label">
|
||||
<i class="material-icons">delete_forever</i> Trash:
|
||||
</div>
|
||||
<div class="input" *ngIf="(videoCount == '0' && seasonsCount == '0')">
|
||||
@if(videoCount == '0' && seasonsCount == '0') {
|
||||
<div class="input">
|
||||
<button class="button color-button-cancel color-shadow-black" (click)="removeItem()" type="submit">
|
||||
<i class="material-icons">delete</i> Remove Series
|
||||
</button>
|
||||
</div>
|
||||
<div class="input" *ngIf="(videoCount != '0' || seasonsCount != '0')">
|
||||
}
|
||||
@else {
|
||||
<div class="input">
|
||||
<i class="material-icons">new_releases</i> Can not remove season or video depending on it
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<upload-progress [mediaTitle]="upload.labelMediaTitle"
|
||||
[mediaUploaded]="upload.mediaSendSize"
|
||||
[mediaSize]="upload.mediaSize"
|
||||
[result]="upload.result"
|
||||
[error]="upload.error"></upload-progress>
|
||||
[error]="upload.error"
|
||||
(abort)="abortUpload()"></upload-progress>
|
||||
<delete-confirm
|
||||
[comment]="confirmDeleteComment"
|
||||
[imageUrl]=confirmDeleteImageUrl
|
||||
|
@ -5,10 +5,11 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PopInService, UploadProgress } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { UUID } from 'app/back-api';
|
||||
import { RESTAbort } from 'app/back-api/rest-tools';
|
||||
|
||||
import { SeriesService, DataService, TypeService, ArianeService } from 'app/service';
|
||||
import { UploadProgress } from 'common/popin/upload-progress/upload-progress';
|
||||
import { PopInService } from 'common/service';
|
||||
|
||||
export class ElementList {
|
||||
constructor(
|
||||
@ -53,8 +54,9 @@ export class SeriesEditScene implements OnInit {
|
||||
// --------------- confirm section ------------------
|
||||
public confirmDeleteComment: string = null;
|
||||
public confirmDeleteImageUrl: string = null;
|
||||
private deleteCoverId: number = null;
|
||||
private deleteCoverId: UUID = null;
|
||||
private deleteItemId: number = null;
|
||||
cancelHandle: RESTAbort = {};
|
||||
deleteConfirmed() {
|
||||
if (this.deleteCoverId !== null) {
|
||||
this.removeCoverAfterConfirm(this.deleteCoverId);
|
||||
@ -73,11 +75,13 @@ export class SeriesEditScene implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
constructor(private dataService: DataService,
|
||||
private typeService: TypeService,
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private seriesService: SeriesService,
|
||||
private typeService: TypeService,
|
||||
private arianeService: ArianeService,
|
||||
private popInService: PopInService) {
|
||||
private popInService: PopInService,
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@ -86,7 +90,7 @@ export class SeriesEditScene implements OnInit {
|
||||
let self = this;
|
||||
this.listType = [{ value: null, label: '---' }];
|
||||
|
||||
this.typeService.getData()
|
||||
this.typeService.gets()
|
||||
.then((response2) => {
|
||||
for (let iii = 0; iii < response2.length; iii++) {
|
||||
self.listType.push({ value: response2[iii].id, label: response2[iii].name });
|
||||
@ -127,13 +131,17 @@ export class SeriesEditScene implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
abortUpload(): void {
|
||||
this.cancelHandle.abort();
|
||||
}
|
||||
|
||||
updateCoverList(covers: any) {
|
||||
this.coversDisplay = [];
|
||||
if (covers !== undefined && covers !== null) {
|
||||
for (let iii = 0; iii < covers.length; iii++) {
|
||||
this.coversDisplay.push({
|
||||
id: covers[iii],
|
||||
url: this.dataService.getCoverThumbnailUrl(covers[iii])
|
||||
url: this.dataService.getThumbnailUrl(covers[iii])
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@ -203,10 +211,10 @@ export class SeriesEditScene implements OnInit {
|
||||
this.upload.clear();
|
||||
// display the upload pop-in
|
||||
this.popInService.open('popin-upload-progress');
|
||||
this.seriesService.uploadCover(file, this.idSeries, (count, total) => {
|
||||
this.seriesService.uploadCover(this.idSeries, file, (count, total) => {
|
||||
self.upload.mediaSendSize = count;
|
||||
self.upload.mediaSize = total;
|
||||
})
|
||||
}, this.cancelHandle)
|
||||
.then((response: any) => {
|
||||
self.upload.result = 'Cover added done';
|
||||
// we retrive the whiole media ==> update data ...
|
||||
@ -216,14 +224,14 @@ export class SeriesEditScene implements OnInit {
|
||||
console.log('Can not add the cover in the video...');
|
||||
});
|
||||
}
|
||||
removeCover(id: number) {
|
||||
removeCover(id: UUID) {
|
||||
this.cleanConfirm();
|
||||
this.confirmDeleteComment = `Delete the cover ID: ${id}`;
|
||||
this.confirmDeleteImageUrl = this.dataService.getCoverThumbnailUrl(id);
|
||||
this.confirmDeleteImageUrl = this.dataService.getThumbnailUrl(id);
|
||||
this.deleteCoverId = id;
|
||||
this.popInService.open('popin-delete-confirm');
|
||||
}
|
||||
removeCoverAfterConfirm(id: number) {
|
||||
removeCoverAfterConfirm(id: UUID) {
|
||||
console.log(`Request remove cover: ${id}`);
|
||||
let self = this;
|
||||
this.seriesService.deleteCover(this.idSeries, id)
|
||||
|
@ -1,34 +1,44 @@
|
||||
<div class="generic-page">
|
||||
<div class="fill-title colomn_mutiple">
|
||||
<div class="cover-area">
|
||||
<div class="cover" *ngIf="cover != null" >
|
||||
@if(cover) {
|
||||
<div class="cover" >
|
||||
<img src="{{cover}}"/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
|
||||
<div class="title">
|
||||
{{name}}
|
||||
</div>
|
||||
<div class="description" *ngIf="description">
|
||||
@if(description) {
|
||||
<div class="description">
|
||||
{{description}}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-content colomn_mutiple" *ngIf="seasons.length != 0">
|
||||
@if(seasons.length != 0) {
|
||||
<div class="fill-content colomn_mutiple">
|
||||
<div class="clear"></div>
|
||||
<div class="title" *ngIf="seasons.length > 1">Seasons:</div>
|
||||
<div class="title" *ngIf="seasons.length == 1">Season:</div>
|
||||
<div *ngFor="let data of seasons" class="item-list" (click)="onSelectSeason($event, data.id)" (auxclick)="onSelectSeason($event, data.id)">
|
||||
<div class="title">Season{{seasons.length > 1?"s":""}}:</div>
|
||||
@for (data of seasons; track data.id;) {
|
||||
<div class="item-list" (click)="onSelectSeason($event, data.id)" (auxclick)="onSelectSeason($event, data.id)">
|
||||
<app-element-season [element]="data"></app-element-season>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="fill-content colomn_mutiple" *ngIf="videos.length != 0">
|
||||
}
|
||||
@if(videos.length != 0) {
|
||||
<div class="fill-content colomn_mutiple">
|
||||
<div class="clear"></div>
|
||||
<div class="title" *ngIf="videos.length > 1">Videos:</div>
|
||||
<div class="title" *ngIf="videos.length == 1">Video:</div>
|
||||
<div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)">
|
||||
<div class="title">Video{{videos.length > 1?"s":""}}:</div>
|
||||
@for (data of videos; track data.id;) {
|
||||
<div class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)">
|
||||
<app-element-video [element]="data"></app-element-video>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div class="clear"></div>
|
||||
</div>
|
@ -5,9 +5,9 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Season } from 'app/back-api';
|
||||
|
||||
import { SeriesService, DataService, ArianeService, AdvancementService } from 'app/service';
|
||||
import { NodeData } from 'common/model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-series',
|
||||
@ -22,14 +22,15 @@ export class SeriesScene implements OnInit {
|
||||
cover: string = '';
|
||||
covers: Array<string> = [];
|
||||
seasonsError: string = '';
|
||||
seasons: NodeData[] = [];
|
||||
seasons: Season[] = [];
|
||||
videosError: string = '';
|
||||
videos: Array<any> = [];
|
||||
constructor(
|
||||
private advancementService: AdvancementService,
|
||||
private dataService: DataService,
|
||||
private seriesService: SeriesService,
|
||||
private arianeService: ArianeService,
|
||||
private dataService: DataService,
|
||||
private advancementService: AdvancementService) {
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@ -51,9 +52,9 @@ export class SeriesScene implements OnInit {
|
||||
self.cover = null;
|
||||
self.covers = [];
|
||||
} else {
|
||||
self.cover = self.dataService.getCoverUrl(response.covers[0]);
|
||||
self.cover = self.dataService.getThumbnailUrl(response.covers[0]);
|
||||
for (let iii = 0; iii < response.covers.length; iii++) {
|
||||
self.covers.push(self.dataService.getCoverUrl(response.covers[iii]));
|
||||
self.covers.push(self.dataService.getThumbnailUrl(response.covers[iii]));
|
||||
}
|
||||
}
|
||||
updateEnded.seriesMetadata = true;
|
||||
@ -63,30 +64,32 @@ export class SeriesScene implements OnInit {
|
||||
self.name = '???';
|
||||
self.cover = null;
|
||||
self.covers = [];
|
||||
// no check just ==> an error occured on season
|
||||
// no check just ==> an error occurred on season
|
||||
});
|
||||
//console.log(`get parameter id: ${ this.idSeries}`);
|
||||
console.log(`this.seriesService.getSeason(${this.idSeries})`);
|
||||
this.seriesService.getSeason(this.idSeries)
|
||||
.then((response: NodeData[]) => {
|
||||
//console.log(`>>>> get season : ${JSON.stringify(response)}`)
|
||||
.then((response: Season[]) => {
|
||||
console.log(`>>>> get season : ${JSON.stringify(response)}`)
|
||||
self.seasonsError = '';
|
||||
self.seasons = response;
|
||||
updateEnded.subSaison = true;
|
||||
self.checkIfJumpIsNeeded(updateEnded);
|
||||
}).catch((response) => {
|
||||
console.log(`>>>> get season (FAIL) : ${JSON.stringify(response)}`)
|
||||
self.seasonsError = 'Can not get the list of season in this series';
|
||||
self.seasons = [];
|
||||
updateEnded.subSaison = true;
|
||||
self.checkIfJumpIsNeeded(updateEnded);
|
||||
});
|
||||
this.seriesService.getVideo(this.idSeries)
|
||||
.then((response: NodeData[]) => {
|
||||
//console.log(`>>>> get video : ${JSON.stringify(response)}`)
|
||||
.then((response: Season[]) => {
|
||||
console.log(`>>>> get video : ${JSON.stringify(response)}`)
|
||||
self.videosError = '';
|
||||
self.videos = response;
|
||||
updateEnded.subVideo = true;
|
||||
self.checkIfJumpIsNeeded(updateEnded);
|
||||
}).catch((response) => {
|
||||
console.log(`>>>> get video (FAIL): ${JSON.stringify(response)}`)
|
||||
self.videosError = 'Can not get the List of video without season';
|
||||
self.videos = [];
|
||||
updateEnded.subVideo = true;
|
||||
|
@ -1,30 +1,38 @@
|
||||
<div class="generic-page">
|
||||
<div class="fill-title colomn_mutiple">
|
||||
<div class="cover-area">
|
||||
<div class="cover" *ngIf="cover != null" >
|
||||
@if(cover) {
|
||||
<div class="cover" >
|
||||
<img src="{{cover}}"/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
|
||||
<div class="title">
|
||||
{{name}}
|
||||
</div>
|
||||
<div class="description" *ngIf="description">
|
||||
@if(description) {
|
||||
<div class="description">
|
||||
{{description}}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-content colomn_mutiple">
|
||||
<div class="clear"></div>
|
||||
<div *ngFor="let data of series" class="item" (click)="onSelectSeries($event, data.id)" (auxclick)="onSelectSeries($event, data.id)">
|
||||
@for (data of series; track data.id;) {
|
||||
<div class="item" (click)="onSelectSeries($event, data.id)" (auxclick)="onSelectSeries($event, data.id)">
|
||||
<app-element-series [element]="data"></app-element-series>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="fill-content colomn_mutiple">
|
||||
<div class="clear"></div>
|
||||
<div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)">
|
||||
@for (data of videos; track data.id;) {
|
||||
<div class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)">
|
||||
<app-element-video [element]="data"></app-element-video>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
@ -5,9 +5,9 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Series } from 'app/back-api';
|
||||
|
||||
import { TypeService, DataService, ArianeService, AdvancementService } from 'app/service';
|
||||
import { TypeService, DataService, ArianeService, AdvancementService, SeriesService } from 'app/service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-type',
|
||||
@ -26,9 +26,10 @@ export class TypeScene implements OnInit {
|
||||
videosError = '';
|
||||
videos = [];
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private typeService: TypeService,
|
||||
private seriesService: SeriesService,
|
||||
private arianeService: ArianeService,
|
||||
private dateService: DataService,
|
||||
private advancementService: AdvancementService) {
|
||||
|
||||
/*
|
||||
@ -44,19 +45,19 @@ export class TypeScene implements OnInit {
|
||||
ngOnInit() {
|
||||
this.typeId = this.arianeService.getTypeId();
|
||||
let self = this;
|
||||
console.log(`get type global id: ${this.typeId}`);
|
||||
//console.log(`get type global id: ${this.typeId}`);
|
||||
this.typeService.get(this.typeId)
|
||||
.then((response) => {
|
||||
self.name = response.name;
|
||||
self.description = response.description;
|
||||
console.log(` ==> get answer type detail: ${JSON.stringify(response)}`);
|
||||
//console.log(` ==> get answer type detail: ${JSON.stringify(response)}`);
|
||||
if (response.covers === undefined || response.covers === null || response.covers.length === 0) {
|
||||
self.cover = null;
|
||||
self.covers = [];
|
||||
} else {
|
||||
self.cover = self.dateService.getCoverUrl(response.covers[0]);
|
||||
self.cover = self.dataService.getThumbnailUrl(response.covers[0]);
|
||||
for (let iii = 0; iii < response.covers.length; iii++) {
|
||||
self.covers.push(self.dateService.getCoverUrl(response.covers[iii]));
|
||||
self.covers.push(self.dataService.getThumbnailUrl(response.covers[iii]));
|
||||
}
|
||||
}
|
||||
}).catch((response) => {
|
||||
@ -65,23 +66,23 @@ export class TypeScene implements OnInit {
|
||||
self.covers = [];
|
||||
self.cover = null;
|
||||
});
|
||||
this.typeService.getSubSeries(this.typeId)
|
||||
.then((response) => {
|
||||
console.log(` ==> get answer sub-series: ${JSON.stringify(response)}`);
|
||||
this.seriesService.getSeriesWithType(this.typeId)
|
||||
.then((response: Series[]) => {
|
||||
//console.log(` ==> get answer sub-series: ${JSON.stringify(response)}`);
|
||||
self.seriessError = '';
|
||||
self.series = response;
|
||||
}).catch((response) => {
|
||||
console.log(` ==> get answer sub-series (ERROR): ${JSON.stringify(response)}`);
|
||||
//console.log(` ==> get answer sub-series (ERROR): ${JSON.stringify(response)}`);
|
||||
self.seriessError = 'Wrong e-mail/login or password';
|
||||
self.series = [];
|
||||
});
|
||||
this.typeService.getSubVideo(this.typeId)
|
||||
.then((response) => {
|
||||
console.log(` ==> get answer sub-video: ${JSON.stringify(response)}`);
|
||||
//console.log(` ==> get answer sub-video: ${JSON.stringify(response)}`);
|
||||
self.videosError = '';
|
||||
self.videos = response;
|
||||
}).catch((response) => {
|
||||
console.log(` ==> get answer sub-video (ERROR): ${JSON.stringify(response)}`);
|
||||
//console.log(` ==> get answer sub-video (ERROR): ${JSON.stringify(response)}`);
|
||||
self.videosError = 'Wrong e-mail/login or password';
|
||||
self.videos = [];
|
||||
});
|
||||
|
44
front/src/app/scene/upload/file-drag-n-drop.directive.ts
Normal file
44
front/src/app/scene/upload/file-drag-n-drop.directive.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { Directive, HostListener, HostBinding, Output, EventEmitter, Input } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[fileDragDrop]'
|
||||
})
|
||||
export class FileDragNDropDirective {
|
||||
//@Input() private allowed_extensions : Array<string> = ['png', 'jpg', 'bmp'];
|
||||
@Output() private filesChangeEmiter: EventEmitter<File[]> = new EventEmitter();
|
||||
//@Output() private filesInvalidEmiter : EventEmitter<File[]> = new EventEmitter();
|
||||
@HostBinding('style.background') private background = '#eee';
|
||||
@HostBinding('style.border') private borderStyle = '2px dashed';
|
||||
@HostBinding('style.border-color') private borderColor = '#696D7D';
|
||||
@HostBinding('style.border-radius') private borderRadius = '10px';
|
||||
|
||||
constructor() { }
|
||||
|
||||
@HostListener('dragover', ['$event']) public onDragOver(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
this.background = 'lightgray';
|
||||
this.borderColor = 'cadetblue';
|
||||
this.borderStyle = '3px solid';
|
||||
}
|
||||
|
||||
@HostListener('dragleave', ['$event']) public onDragLeave(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
this.background = '#eee';
|
||||
this.borderColor = '#696D7D';
|
||||
this.borderStyle = '2px dashed';
|
||||
}
|
||||
|
||||
@HostListener('drop', ['$event']) public onDrop(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
this.background = '#eee';
|
||||
this.borderColor = '#696D7D';
|
||||
this.borderStyle = '2px dashed';
|
||||
|
||||
let files = evt.dataTransfer.files;
|
||||
let valid_files: Array<File> = files;
|
||||
this.filesChangeEmiter.emit(valid_files);
|
||||
}
|
||||
}
|
@ -3,41 +3,26 @@
|
||||
Upload Media
|
||||
</div>
|
||||
<div class="clear"><br/></div>
|
||||
<div class="request_raw_table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width:10%">
|
||||
<col style="width:80%">
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="left-colomn">format:</td>
|
||||
<td class="right-colomn">
|
||||
<div class="request_raw_table drop-area" fileDragDrop
|
||||
(filesChangeEmiter)="onChangeFile($event)">
|
||||
<div class="clear"><br/></div>
|
||||
<div class="centered">
|
||||
<input type="file" name="file" id="file" (change)="onChangeFile($event.target.files)" multiple>
|
||||
<label for="file"><span class="textLink"><span class="material-icons">cloud_upload</span> Select your file</span> or <i>Drop it here!</i></label>
|
||||
</div>
|
||||
<div class="clear"><br/></div>
|
||||
<div class="centered">
|
||||
The format of the media permit to automatic find meta-data:<br/>
|
||||
Univers:Series name-sXX-eXX-my name of my media.mkv<br/>
|
||||
<b>example:</b> Stargate:SG1-s55-e22-Asgard.mkv <br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="left-colomn">Media:</td>
|
||||
<td class="right-colomn">
|
||||
<input type="file"
|
||||
(change)="onChangeFile($event.target)"
|
||||
placeholder="Select a media file"
|
||||
accept=".mkv,.webm"
|
||||
width="90%"
|
||||
multiple/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div *ngIf="this.parsedElement.length !== 0" class="title">
|
||||
</div>
|
||||
@if(parsedElement.length !== 0) {
|
||||
<div class="title">
|
||||
Meta-data:
|
||||
</div>
|
||||
<div class="clear"><br/></div>
|
||||
<div *ngIf="this.parsedElement.length !== 0" class="fill-all">
|
||||
<div class="fill-all">
|
||||
<div class="request_raw_table">
|
||||
<table>
|
||||
<colgroup>
|
||||
@ -52,7 +37,9 @@
|
||||
<select [ngModel]="typeId"
|
||||
(ngModelChange)="onChangeType($event)"
|
||||
[class.error]="typeId === undefined">
|
||||
<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option>
|
||||
@for (data of listType; track data.value;) {
|
||||
<option [ngValue]="data.value">{{data.label}}</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@ -71,7 +58,9 @@
|
||||
<td class="right-colomn">
|
||||
<select [ngModel]="seriesId"
|
||||
(ngModelChange)="onChangeSeries($event)">
|
||||
<option *ngFor="let element of listSeries" [ngValue]="element.value">{{element.label}}</option>
|
||||
@for (data of listSeries; track data.value;) {
|
||||
<option [ngValue]="data.value">{{data.label}}</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
<td class="tool-colomn">
|
||||
@ -111,7 +100,8 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let data of this.parsedElement">
|
||||
@for (data of parsedElement; track data.id;) {
|
||||
<tr>
|
||||
<td class="left-colomn">
|
||||
<input type="number"
|
||||
pattern="[0-9]{0-4}"
|
||||
@ -128,9 +118,11 @@
|
||||
(input)="onTitle(data, $event.target.value)"
|
||||
[class.error]="data.title === ''"
|
||||
/>
|
||||
<span *ngIf="data.nameDetected === true" class="error">
|
||||
@if(data.nameDetected === true) {
|
||||
<span class="error">
|
||||
^^^This title already exist !!!
|
||||
</span>
|
||||
}
|
||||
</td>
|
||||
<td class="tool-colomn" >
|
||||
<button class="button color-button-cancel color-shadow-black"
|
||||
@ -141,6 +133,7 @@
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -154,7 +147,8 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
<div class="request_raw_table" *ngIf="this.listFileInBdd !== undefined">
|
||||
@if(listFileInBdd !== undefined) {
|
||||
<div class="request_raw_table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width:10%">
|
||||
@ -168,15 +162,18 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let data of this.listFileInBdd">
|
||||
@for (data of listFileInBdd; track data.id;) {
|
||||
<tr>
|
||||
<td class="left-colomn" [class.error]="data.episodeDetected === true">{{data.episode}}</td>
|
||||
<td class="right-colomn" [class.error]="data.nameDetected === true">{{data.name}}</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div *ngIf="this.parsedElement.length !== 0" class="fill-all">
|
||||
<div class="fill-all">
|
||||
<div class="request_raw_table">
|
||||
<table>
|
||||
<colgroup>
|
||||
@ -184,30 +181,27 @@
|
||||
<col style="width:80%">
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<!-- no need
|
||||
<tr *ngFor="let data of this.parsedElement">
|
||||
<td class="left-colomn">Keep:</td>
|
||||
<td class="right-colomn">
|
||||
{{data.file.name}}
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
<tr *ngFor="let data of this.parsedFailedElement">
|
||||
@for (data of parsedFailedElement; track data.file;) {
|
||||
<tr>
|
||||
<td class="left-colomn">Rejected:</td>
|
||||
<td class="right-colomn">
|
||||
{{data.file.name}}<br/> ==> {{data.reason}}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<upload-progress [mediaTitle]="upload.labelMediaTitle"
|
||||
<upload-progress
|
||||
[mediaTitle]="upload.labelMediaTitle"
|
||||
[mediaUploaded]="upload.mediaSendSize"
|
||||
[mediaSize]="upload.mediaSize"
|
||||
[result]="upload.result"
|
||||
[error]="upload.error"></upload-progress>
|
||||
[error]="upload.error"
|
||||
(abort)="abortUpload()"></upload-progress>
|
||||
|
||||
<!--
|
||||
TODO: add a pop-in with:
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
.title {
|
||||
//background-color: green;
|
||||
font-size: 45px;
|
||||
@ -14,30 +12,68 @@
|
||||
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
.drop-area {
|
||||
height: 230px;
|
||||
display: table;
|
||||
width: 100%;
|
||||
background-color: #eee;
|
||||
border: dotted 1px #aaa;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.text-wrapper {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.centered {
|
||||
font-family: sans-serif;
|
||||
font-size: 1.3em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.textLink {
|
||||
background-color: #217500;
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
}
|
||||
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.request_raw_table {
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.left-colomn {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
|
||||
input {
|
||||
width: 95%;
|
||||
font-size: 20px;
|
||||
border: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-colomn {
|
||||
input {
|
||||
width: 95%;
|
||||
font-size: 20px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 95%;
|
||||
font-size: 20px;
|
||||
@ -45,11 +81,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
border-color: rgba(200, 0, 0, 1.0);
|
||||
background-color: rgba(256, 220, 220, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
.send_value {
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
|
@ -5,11 +5,11 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { PopInService, UploadProgress } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Series } from 'app/back-api';
|
||||
import { RESTAbort } from 'app/back-api/rest-tools';
|
||||
|
||||
import { TypeService, SeriesService, VideoService, ArianeService, SeasonService } from 'app/service';
|
||||
import { UploadProgress } from 'common/popin/upload-progress/upload-progress';
|
||||
import { PopInService } from 'common/service';
|
||||
import { TypeService, SeriesService, MediaService, SeasonService } from 'app/service';
|
||||
|
||||
export class ElementList {
|
||||
constructor(
|
||||
@ -23,6 +23,7 @@ export class FileParsedElement {
|
||||
public nameDetected: boolean = false;
|
||||
public episodeDetected: boolean = false;
|
||||
constructor(
|
||||
public id: number,
|
||||
public file: File,
|
||||
public series: string,
|
||||
public season: number,
|
||||
@ -52,10 +53,10 @@ export class UploadScene implements OnInit {
|
||||
selectedFiles: FileList;
|
||||
typeId: number = null;
|
||||
seriesId: number = null;
|
||||
saisonId: number = null;
|
||||
seasonId: number = null;
|
||||
needSend: boolean = false;
|
||||
|
||||
// list of all files already registered in the bdd to compare with the curent list of files.
|
||||
// list of all files already registered in the bdd to compare with the current list of files.
|
||||
listFileInBdd: any = null;
|
||||
|
||||
// section tha define the upload value to display in the pop-in of upload
|
||||
@ -78,7 +79,7 @@ export class UploadScene implements OnInit {
|
||||
*/
|
||||
config = {
|
||||
displayKey: 'description', // if objects array passed which key to be displayed defaults to description
|
||||
search: true, // true/false for the search functionlity defaults to false,
|
||||
search: true, // true/false for the search functionality defaults to false,
|
||||
height: 'auto', // height of the list so that if there are more no of items it can show a scroll defaults to auto. With auto height scroll will never appear
|
||||
placeholder: 'Select', // text to be displayed when no item is selected defaults to Select,
|
||||
customComparator: () => { }, // a custom function using which user wants to sort the items. default is undefined and Array.sort() will be used in that case,
|
||||
@ -93,11 +94,15 @@ export class UploadScene implements OnInit {
|
||||
];
|
||||
globalSeries: string = '';
|
||||
globalSeason: number = null;
|
||||
constructor(private typeService: TypeService,
|
||||
private seriesService: SeriesService,
|
||||
cancelHandle: RESTAbort = {};
|
||||
dataUniqueId: number = 0;
|
||||
constructor(
|
||||
private MediaService: MediaService,
|
||||
private seasonService: SeasonService,
|
||||
private videoService: VideoService,
|
||||
private popInService: PopInService) {
|
||||
private seriesService: SeriesService,
|
||||
private typeService: TypeService,
|
||||
private popInService: PopInService,
|
||||
) {
|
||||
// nothing to do.
|
||||
}
|
||||
|
||||
@ -123,7 +128,7 @@ export class UploadScene implements OnInit {
|
||||
this.listType = [{ value: null, label: '---' }];
|
||||
this.listSeries = [{ value: null, label: '---' }];
|
||||
this.listSeason = [{ value: null, label: '---' }];
|
||||
this.typeService.getData()
|
||||
this.typeService.gets()
|
||||
.then((response2) => {
|
||||
for (let iii = 0; iii < response2.length; iii++) {
|
||||
self.listType.push({ value: response2[iii].id, label: response2[iii].name });
|
||||
@ -152,8 +157,8 @@ export class UploadScene implements OnInit {
|
||||
let self = this;
|
||||
this.updateNeedSend();
|
||||
if (this.typeId !== null) {
|
||||
self.typeService.getSubSeries(this.typeId)
|
||||
.then((response2) => {
|
||||
self.seriesService.getSeriesWithType(this.typeId)
|
||||
.then((response2: Series[]) => {
|
||||
for (let iii = 0; iii < response2.length; iii++) {
|
||||
self.listSeries.push({ value: response2[iii].id, label: response2[iii].name });
|
||||
}
|
||||
@ -238,7 +243,7 @@ export class UploadScene implements OnInit {
|
||||
|
||||
this.typeId = null;
|
||||
this.seriesId = null;
|
||||
this.saisonId = null;
|
||||
this.seasonId = null;
|
||||
this.listSeries = [{ value: null, label: '---' }];
|
||||
this.listSeason = [{ value: null, label: '---' }];
|
||||
}
|
||||
@ -302,22 +307,21 @@ export class UploadScene implements OnInit {
|
||||
if (isNaN(season)) {
|
||||
season = null;
|
||||
}
|
||||
// remove extention
|
||||
// remove extension
|
||||
title = title.replace(new RegExp('\\.(mkv|MKV|Mkv|webm|WEBM|Webm|mp4)'), '');
|
||||
let tmp = new FileParsedElement(file, series, season, episode, title);
|
||||
const tmp = new FileParsedElement(this.dataUniqueId++, file, series, season, episode, title);
|
||||
console.log(`==>${JSON.stringify(tmp)}`);
|
||||
// add it in the list.
|
||||
this.parsedElement.push(tmp);
|
||||
}
|
||||
|
||||
|
||||
// At the file input element
|
||||
// (change)="selectFile($event)"
|
||||
onChangeFile(value: any): void {
|
||||
onChangeFile(files: File[]): void {
|
||||
this.clearData();
|
||||
|
||||
for(let iii = 0; iii < value.files.length; iii++) {
|
||||
this.addFileWithMetaData(value.files[iii]);
|
||||
for (let iii = 0; iii < files.length; iii++) {
|
||||
this.addFileWithMetaData(files[iii]);
|
||||
}
|
||||
// check if all global parameters are generic:
|
||||
if (this.parsedElement.length === 0) {
|
||||
@ -350,7 +354,7 @@ export class UploadScene implements OnInit {
|
||||
|
||||
this.updateNeedSend();
|
||||
this.seriesId = null;
|
||||
this.saisonId = null;
|
||||
this.seasonId = null;
|
||||
let self = this;
|
||||
if (this.globalSeries !== '') {
|
||||
this.seriesService.getLike(this.globalSeries)
|
||||
@ -362,9 +366,9 @@ export class UploadScene implements OnInit {
|
||||
if (response.length === 0) {
|
||||
self.seriesId = null;
|
||||
} else if (response.length === 1) {
|
||||
let serieElem = response[0];
|
||||
self.seriesId = serieElem.id;
|
||||
self.updateType(serieElem.parentId);
|
||||
let seriesElem = response[0];
|
||||
self.seriesId = seriesElem.id;
|
||||
self.updateType(seriesElem.parentId);
|
||||
}
|
||||
self.updateListOfVideoToCheck();
|
||||
}).catch((response) => {
|
||||
@ -392,10 +396,11 @@ export class UploadScene implements OnInit {
|
||||
self.upload.result = 'Media creation done';
|
||||
}
|
||||
}, (value: string) => {
|
||||
console.log("Detect error from serveur ...********************");
|
||||
self.upload.error = `Error in the upload of the data...${value}`;
|
||||
});
|
||||
}
|
||||
uploadFile(eleemnent: FileParsedElement, id: number, total: number, sendDone: any, errorOccured: any): void {
|
||||
uploadFile(element: FileParsedElement, id: number, total: number, sendDone: () => void, errorOccurred: (string) => void): void {
|
||||
let self = this;
|
||||
|
||||
self.upload.labelMediaTitle = '';
|
||||
@ -414,37 +419,38 @@ export class UploadScene implements OnInit {
|
||||
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}s${self.globalSeason.toString()}`;
|
||||
}
|
||||
// add episode ID
|
||||
if(eleemnent.episode !== null && eleemnent.episode !== undefined && eleemnent.episode.toString().length !== 0) {
|
||||
if (element.episode !== null && element.episode !== undefined && element.episode.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${element.episode.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}${element.title}`;
|
||||
|
||||
self.videoService.uploadFile(eleemnent.file,
|
||||
self.MediaService.uploadFile(element.file,
|
||||
self.globalSeries,
|
||||
self.seriesId,
|
||||
self.globalSeason,
|
||||
eleemnent.episode,
|
||||
eleemnent.title,
|
||||
element.episode,
|
||||
element.title,
|
||||
self.typeId,
|
||||
(count, totalTmp) => {
|
||||
// console.log("upload : " + count*100/totalTmp);
|
||||
self.upload.mediaSendSize = count;
|
||||
self.upload.mediaSize = totalTmp;
|
||||
})
|
||||
}, this.cancelHandle)
|
||||
.then((response) => {
|
||||
console.log(`get response of video : ${JSON.stringify(response, null, 2)}`);
|
||||
sendDone();
|
||||
}).catch((response) => {
|
||||
})
|
||||
.catch((response) => {
|
||||
// self.error = "Can not get the data";
|
||||
console.log('Can not add the data in the system...');
|
||||
errorOccured(JSON.stringify(response, null, 2));
|
||||
errorOccurred(JSON.stringify(response, null, 2));
|
||||
});
|
||||
}
|
||||
|
||||
@ -518,7 +524,7 @@ export class UploadScene implements OnInit {
|
||||
return;
|
||||
}
|
||||
|
||||
self.saisonId = null;
|
||||
self.seasonId = null;
|
||||
// set 1 find the ID of the season:
|
||||
this.seriesService.getSeason(this.seriesId)
|
||||
.then((response: any[]) => {
|
||||
@ -526,14 +532,14 @@ export class UploadScene implements OnInit {
|
||||
for (let iii = 0; iii < response.length; iii++) {
|
||||
// console.log(" - " + JSON.stringify(response[iii]) + 'compare with : ' + JSON.stringify(self.globalSeason));
|
||||
if (response[iii].name === `${self.globalSeason}`) {
|
||||
self.saisonId = response[iii].id;
|
||||
self.seasonId = response[iii].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(self.saisonId === null) {
|
||||
if (self.seasonId === null) {
|
||||
return;
|
||||
}
|
||||
self.seasonService.getVideo(self.saisonId)
|
||||
self.seasonService.getVideo(self.seasonId)
|
||||
.then((response2: any[]) => {
|
||||
self.listFileInBdd = response2;
|
||||
// console.log("find video: " + response2.length);
|
||||
@ -549,6 +555,10 @@ export class UploadScene implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
abortUpload(): void {
|
||||
this.cancelHandle.abort();
|
||||
}
|
||||
|
||||
eventPopUpSeason(event: string): void {
|
||||
console.log(`GET event: ${event}`);
|
||||
this.popInService.close('popin-new-season');
|
||||
@ -575,3 +585,7 @@ export class UploadScene implements OnInit {
|
||||
this.popInService.open('popin-create-type');
|
||||
}
|
||||
}
|
||||
function isNullOrUndefined(abort: () => boolean) {
|
||||
throw new Error('Function not implemented.');
|
||||
}
|
||||
|
||||
|
@ -2,21 +2,26 @@
|
||||
<div class="title">
|
||||
Edit Media
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsRemoved">
|
||||
@if(itemIsRemoved) {
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
The media has been removed
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsNotFound">
|
||||
}
|
||||
@else if(itemIsNotFound) {
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
The media does not exist
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="itemIsLoading">
|
||||
}
|
||||
@else if(itemIsLoading) {
|
||||
<div class="fill-all">
|
||||
<div class="message-big">
|
||||
<br/><br/><br/>
|
||||
Loading ...<br/>
|
||||
@ -24,8 +29,9 @@
|
||||
<br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
}
|
||||
@else {
|
||||
<div class="fill-all">
|
||||
<div class="request_raw">
|
||||
<div class="label">
|
||||
Title:
|
||||
@ -69,7 +75,9 @@
|
||||
<div class="input">
|
||||
<select [ngModel]="data.typeId"
|
||||
(ngModelChange)="onChangeType($event)">
|
||||
<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option>
|
||||
@for (data of listType; track data.value;) {
|
||||
<option [ngValue]="data.value">{{data.label}}</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input_add">
|
||||
@ -85,7 +93,9 @@
|
||||
<div class="input">
|
||||
<select [ngModel]="data.seriesId"
|
||||
(ngModelChange)="onChangeSeries($event)">
|
||||
<option *ngFor="let element of listSeries" [ngValue]="element.value">{{element.label}}</option>
|
||||
@for (data of listSeries; track data.value;) {
|
||||
<option [ngValue]="data.value">{{data.label}}</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input_add">
|
||||
@ -101,7 +111,9 @@
|
||||
<div class="input">
|
||||
<select [ngModel]="data.seasonId"
|
||||
(ngModelChange)="onChangeSeason($event)">
|
||||
<option *ngFor="let element of listSeason" [ngValue]="element.value">{{element.label}}</option>
|
||||
@for (data of listSeason; track data.value;) {
|
||||
<option [ngValue]="data.value">{{data.label}}</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input_add">
|
||||
@ -128,10 +140,10 @@
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<!-- ------------------------- Cover section --------------------------------- -->
|
||||
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="title">
|
||||
Covers
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="fill-all">
|
||||
<div class="hide-element">
|
||||
<input type="file"
|
||||
#fileInput
|
||||
@ -141,16 +153,18 @@
|
||||
</div>
|
||||
<div class="request_raw">
|
||||
<div class="input">
|
||||
<div class="cover" *ngFor="let element of coversDisplay">
|
||||
@for (data of coversDisplay; track data.id;) {
|
||||
<div class="cover">
|
||||
<div class="cover-image">
|
||||
<img src="{{element.url}}"/>
|
||||
<img src="{{data.url}}"/>
|
||||
</div>
|
||||
<div class="cover-button">
|
||||
<button (click)="removeCover(element.id)">
|
||||
<button (click)="removeCover(data.id)">
|
||||
<i class="material-icons button-remove">highlight_off</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="cover">
|
||||
<div class="cover-no-image">
|
||||
</div>
|
||||
@ -165,10 +179,10 @@
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<!-- ------------------------- ADMIN section --------------------------------- -->
|
||||
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="title">
|
||||
Administration
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
|
||||
<div class="fill-all">
|
||||
<div class="request_raw">
|
||||
<div class="label">
|
||||
<i class="material-icons">data_usage</i> ID:
|
||||
@ -190,6 +204,7 @@
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<create-type ></create-type>
|
||||
@ -198,7 +213,8 @@
|
||||
[mediaUploaded]="upload.mediaSendSize"
|
||||
[mediaSize]="upload.mediaSize"
|
||||
[result]="upload.result"
|
||||
[error]="upload.error"></upload-progress>
|
||||
[error]="upload.error"
|
||||
(abort)="abortUpload()"></upload-progress>
|
||||
|
||||
<delete-confirm
|
||||
[comment]="confirmDeleteComment"
|
||||
|
@ -5,14 +5,11 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
|
||||
import { DataService, TypeService, SeriesService, VideoService, ArianeService } from 'app/service';
|
||||
import { UploadProgress } from 'common/popin/upload-progress/upload-progress';
|
||||
import { NodeData } from 'common/model';
|
||||
import { PopInService } from 'common/service';
|
||||
import { Media } from 'app/model';
|
||||
import { DataService, TypeService, SeriesService, MediaService, ArianeService } from 'app/service';
|
||||
import { PopInService, UploadProgress } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Media, Season, Series, UUID } from 'app/back-api';
|
||||
import { RESTAbort } from 'app/back-api/rest-tools';
|
||||
|
||||
export interface ElementList {
|
||||
value?: number;
|
||||
@ -24,27 +21,13 @@ class DataToSend {
|
||||
name: string = '';
|
||||
description: string = '';
|
||||
episode?: number;
|
||||
seriesId: number = null;
|
||||
seasonId: number = null;
|
||||
dataId: number = -1;
|
||||
seriesId?: number;
|
||||
seasonId?: number;
|
||||
dataId?: UUID;
|
||||
time?: number;
|
||||
typeId: number = null;
|
||||
typeId?: number;
|
||||
covers: number[] = [];
|
||||
generatedName: string = '';
|
||||
clone() {
|
||||
let tmp = new DataToSend();
|
||||
tmp.name = this.name;
|
||||
tmp.description = this.description;
|
||||
tmp.episode = this.episode;
|
||||
tmp.seriesId = this.seriesId;
|
||||
tmp.seasonId = this.seasonId;
|
||||
tmp.dataId = this.dataId;
|
||||
tmp.time = this.time;
|
||||
tmp.typeId = this.typeId;
|
||||
tmp.covers = this.covers;
|
||||
tmp.generatedName = this.generatedName;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -74,7 +57,7 @@ export class VideoEditScene implements OnInit {
|
||||
// --------------- confirm section ------------------
|
||||
public confirmDeleteComment: string = null;
|
||||
public confirmDeleteImageUrl: string = null;
|
||||
private deleteCoverId: number = null;
|
||||
private deleteCoverId: UUID = null;
|
||||
private deleteMediaId: number = null;
|
||||
deleteConfirmed() {
|
||||
if (this.deleteCoverId !== null) {
|
||||
@ -108,16 +91,22 @@ export class VideoEditScene implements OnInit {
|
||||
listSeason: ElementList[] = [
|
||||
{ value: undefined, label: '---' },
|
||||
];
|
||||
cancelHandle: RESTAbort = {};
|
||||
constructor(
|
||||
private typeService: TypeService,
|
||||
private dataService: DataService,
|
||||
private MediaService: MediaService,
|
||||
private seriesService: SeriesService,
|
||||
private videoService: VideoService,
|
||||
private typeService: TypeService,
|
||||
private arianeService: ArianeService,
|
||||
private popInService: PopInService,
|
||||
private dataService: DataService) {
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
abortUpload(): void {
|
||||
this.cancelHandle.abort();
|
||||
}
|
||||
|
||||
updateNeedSend(): boolean {
|
||||
this.needSend = false;
|
||||
if (this.data.name !== this.dataOri.name) {
|
||||
@ -152,7 +141,7 @@ export class VideoEditScene implements OnInit {
|
||||
this.data.covers.push(covers[iii]);
|
||||
this.coversDisplay.push({
|
||||
id: covers[iii],
|
||||
url: this.dataService.getCoverThumbnailUrl(covers[iii])
|
||||
url: this.dataService.getThumbnailUrl(covers[iii])
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@ -166,7 +155,7 @@ export class VideoEditScene implements OnInit {
|
||||
this.listUniverse = [{ value: null, label: '---' }];
|
||||
this.listSeries = [{ value: null, label: '---' }];
|
||||
this.listSeason = [{ value: null, label: '---' }];
|
||||
this.typeService.getData()
|
||||
this.typeService.gets()
|
||||
.then((response2) => {
|
||||
for (let iii = 0; iii < response2.length; iii++) {
|
||||
self.listType.push({ value: response2[iii].id, label: response2[iii].name });
|
||||
@ -175,7 +164,7 @@ export class VideoEditScene implements OnInit {
|
||||
console.log(`get response22 : ${JSON.stringify(response2, null, 2)}`);
|
||||
});
|
||||
// this.seriesService.getOrder()
|
||||
this.seriesService.getData()
|
||||
this.seriesService.gets()
|
||||
.then((response3) => {
|
||||
for (let iii = 0; iii < response3.length; iii++) {
|
||||
self.listSeries.push({ value: response3[iii].id, label: response3[iii].name });
|
||||
@ -184,7 +173,7 @@ export class VideoEditScene implements OnInit {
|
||||
}).catch((response3) => {
|
||||
console.log(`get response3 : ${JSON.stringify(response3, null, 2)}`);
|
||||
});
|
||||
this.videoService.get(this.idVideo)
|
||||
this.MediaService.get(this.idVideo)
|
||||
.then((response: Media) => {
|
||||
console.log(`get response of video : ${JSON.stringify(response, null, 2)}`);
|
||||
self.data.name = response.name;
|
||||
@ -199,7 +188,7 @@ export class VideoEditScene implements OnInit {
|
||||
if (self.data.seasonId === undefined) {
|
||||
self.data.seasonId = null;
|
||||
}
|
||||
self.dataOri = self.data.clone();
|
||||
self.dataOri = { ...self.data };
|
||||
self.updateCoverList(response.covers);
|
||||
self.updateNeedSend();
|
||||
console.log(`coversList : ${JSON.stringify(self.coversDisplay, null, 2)}`);
|
||||
@ -208,7 +197,7 @@ export class VideoEditScene implements OnInit {
|
||||
self.error = 'Can not get the data';
|
||||
self.data = new DataToSend();
|
||||
self.coversDisplay = [];
|
||||
self.dataOri = self.data.clone();
|
||||
self.dataOri = { ...self.data };
|
||||
self.updateNeedSend();
|
||||
self.itemIsNotFound = true;
|
||||
self.itemIsLoading = false;
|
||||
@ -228,8 +217,8 @@ export class VideoEditScene implements OnInit {
|
||||
let self = this;
|
||||
this.updateNeedSend();
|
||||
if (this.data.typeId !== undefined) {
|
||||
self.typeService.getSubSeries(this.data.typeId)
|
||||
.then((response2: NodeData[]) => {
|
||||
self.seriesService.getSeriesWithType(this.data.typeId)
|
||||
.then((response2: Series[]) => {
|
||||
for (let iii = 0; iii < response2.length; iii++) {
|
||||
self.listSeries.push({ value: response2[iii].id, label: response2[iii].name });
|
||||
}
|
||||
@ -249,7 +238,7 @@ export class VideoEditScene implements OnInit {
|
||||
let self = this;
|
||||
if (this.data.seriesId !== undefined) {
|
||||
self.seriesService.getSeason(this.data.seriesId)
|
||||
.then((response3: NodeData[]) => {
|
||||
.then((response3: Season[]) => {
|
||||
for (let iii = 0; iii < response3.length; iii++) {
|
||||
self.listSeason.push({ value: response3[iii].id, label: `season ${response3[iii].name}` });
|
||||
}
|
||||
@ -338,9 +327,9 @@ export class VideoEditScene implements OnInit {
|
||||
data.seasonId = this.data.seasonId;
|
||||
}
|
||||
}
|
||||
let tmpp = this.data.clone();
|
||||
const tmpp = { ...this.data };
|
||||
let self = this;
|
||||
this.videoService.patch(this.idVideo, data)
|
||||
this.MediaService.patch(this.idVideo, data)
|
||||
.then((response3) => {
|
||||
self.dataOri = tmpp;
|
||||
self.updateNeedSend();
|
||||
@ -385,14 +374,14 @@ export class VideoEditScene implements OnInit {
|
||||
this.upload.clear();
|
||||
// display the upload pop-in
|
||||
this.popInService.open('popin-upload-progress');
|
||||
this.videoService.uploadCover(file, this.idVideo, (count, total) => {
|
||||
this.MediaService.uploadCover(this.idVideo, file, (count, total) => {
|
||||
self.upload.mediaSendSize = count;
|
||||
self.upload.mediaSize = total;
|
||||
})
|
||||
}, this.cancelHandle)
|
||||
.then((response: any) => {
|
||||
console.log(`get response of cover : ${JSON.stringify(response, null, 2)}`);
|
||||
self.upload.result = 'Cover added done';
|
||||
// we retrive the whiole media ==> update data ...
|
||||
// we retrieve the while media ==> update data ...
|
||||
self.updateCoverList(response.covers);
|
||||
}).catch((response: any) => {
|
||||
// self.error = "Can not get the data";
|
||||
@ -401,21 +390,21 @@ export class VideoEditScene implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
removeCover(id: number) {
|
||||
removeCover(id: UUID) {
|
||||
this.cleanConfirm();
|
||||
this.confirmDeleteComment = `Delete the cover ID: ${id}`;
|
||||
this.confirmDeleteImageUrl = this.dataService.getCoverThumbnailUrl(id);
|
||||
this.confirmDeleteImageUrl = this.dataService.getThumbnailUrl(id);
|
||||
this.deleteCoverId = id;
|
||||
this.popInService.open('popin-delete-confirm');
|
||||
}
|
||||
removeCoverAfterConfirm(id: number) {
|
||||
removeCoverAfterConfirm(id: UUID) {
|
||||
console.log(`Request remove cover: ${id}`);
|
||||
let self = this;
|
||||
this.videoService.deleteCover(this.idVideo, id)
|
||||
this.MediaService.deleteCover(this.idVideo, id)
|
||||
.then((response: any) => {
|
||||
console.log(`get response of remove cover : ${JSON.stringify(response, null, 2)}`);
|
||||
self.upload.result = 'Cover remove done';
|
||||
// we retrive the whiole media ==> update data ...
|
||||
// we retrieve the while media ==> update data ...
|
||||
self.updateCoverList(response.covers);
|
||||
}).catch((response: any) => {
|
||||
// self.error = "Can not get the data";
|
||||
@ -432,7 +421,7 @@ export class VideoEditScene implements OnInit {
|
||||
}
|
||||
removeItemAfterConfirm(id: number) {
|
||||
let self = this;
|
||||
this.videoService.delete(id)
|
||||
this.MediaService.delete(id)
|
||||
.then((response3) => {
|
||||
// self.dataOri = tmpp;
|
||||
// self.updateNeedSend();
|
||||
|
@ -1,69 +1,91 @@
|
||||
<div class="main-reduce">
|
||||
<div class="fill-all" *ngIf="mediaIsNotFound">
|
||||
@if(mediaIsNotFound) {
|
||||
<div class="fill-all">
|
||||
<div class="title">
|
||||
Play media<br /><br /><br /><br /><br />
|
||||
The media does not exist
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="mediaIsLoading">
|
||||
}
|
||||
@else if(mediaIsLoading) {
|
||||
<div class="fill-all">
|
||||
<div class="title">
|
||||
Play media<br /><br /><br /><br /><br />
|
||||
Loading ...<br />
|
||||
Please wait.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fill-all" *ngIf="!mediaIsNotFound && !mediaIsLoading && !playVideo">
|
||||
}
|
||||
@else if(!playVideo) {
|
||||
<div class="fill-all">
|
||||
<div class="title">
|
||||
{{name}}
|
||||
</div>
|
||||
<div class="cover-full">
|
||||
<div class="cover">
|
||||
<div class="cover-image" *ngIf="covers">
|
||||
@if(covers) {
|
||||
<div class="cover-image">
|
||||
<img src="{{covers[0]}}" />
|
||||
</div>
|
||||
<div class="cover-no-image" *ngIf="covers"></div>
|
||||
}
|
||||
@else {
|
||||
<div class="cover-no-image"></div>
|
||||
}
|
||||
<div class="cover-button">
|
||||
<button (click)="onRequirePlay()">
|
||||
<i class="material-icons big-button">play_circle_outline</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cover-button-next" *ngIf="haveNext !== null">
|
||||
@if(haveNext) {
|
||||
<div class="cover-button-next">
|
||||
<button (click)="onRequireNext($event)" (auxclick)="onRequireNext($event)">
|
||||
<i class="material-icons big-button">arrow_forward_ios</i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="cover-button-previous" *ngIf="havePrevious !== null">
|
||||
}
|
||||
@if(havePrevious) {
|
||||
<div class="cover-button-previous">
|
||||
<button (click)="onRequirePrevious($event)" (auxclick)="onRequirePrevious($event)">
|
||||
<i class="material-icons big-button">arrow_back_ios</i>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
<div class="episode" *ngIf="seriesName!=null">
|
||||
@if(seriesName) {
|
||||
<div class="episode">
|
||||
<b>Series:</b> {{seriesName}}
|
||||
</div>
|
||||
<div class="episode" *ngIf="seasonName!=null">
|
||||
}
|
||||
@if(seasonName) {
|
||||
<div class="episode">
|
||||
<b>Season:</b> {{seasonName}}
|
||||
</div>
|
||||
<div class="episode" *ngIf="episode!=null">
|
||||
}
|
||||
@if(episode) {
|
||||
<div class="episode">
|
||||
<b>Episode:</b> {{episode}}
|
||||
</div>
|
||||
}
|
||||
<div class="episode">
|
||||
<b>generatedName:</b> {{generatedName}}
|
||||
</div>
|
||||
<div class="episode" *ngIf="userMetaData">
|
||||
@if(userMetaData) {
|
||||
<div class="episode">
|
||||
<b>Number of view:</b> {{userMetaData.count}}<br />
|
||||
<b>Position:</b> {{userMetaData.percentDisplay}} % ==> {{convertIndisplayTime(userMetaData.time)}}
|
||||
</div>
|
||||
}
|
||||
<div class="description">
|
||||
{{description}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all bg-black" *ngIf="playVideo">
|
||||
}
|
||||
@else {
|
||||
<div class="fill-all bg-black">
|
||||
<div class="video" #globalVideoElement (mousemove)="startHideTimer()"
|
||||
(fullscreenchange)="onFullscreenChange($event)">
|
||||
(fullscreenchange)="onFullscreenChange()">
|
||||
<div class="video-elem">
|
||||
<video src="{{videoSource}}" #videoPlayer preload (play)="changeStateToPlay()"
|
||||
(pause)="changeStateToPause()" (timeupdate)="changeTimeupdate($event.currentTime)"
|
||||
@ -73,9 +95,14 @@
|
||||
<!--<p>Your browser does not support HTML5 video player. download video: <a href="{{videoSource}}>link here</a>.</p>-->
|
||||
</video>
|
||||
</div>
|
||||
<div class="controls" *ngIf="!displayNeedHide || !isPlaying">
|
||||
<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>
|
||||
@if(!displayNeedHide || !isPlaying) {
|
||||
<div class="controls">
|
||||
@if(isPlaying) {
|
||||
<button (click)="onPause()"><i class="material-icons">pause</i></button>
|
||||
}
|
||||
@else {
|
||||
<button (click)="onPlay()"><i class="material-icons">play_arrow</i></button>
|
||||
}
|
||||
<button (click)="onStop()"><i class="material-icons">stop</i></button>
|
||||
<div class="timer">
|
||||
<div>
|
||||
@ -91,41 +118,61 @@
|
||||
<button (click)="onForward()"><i class="material-icons">fast_forward</i></button>
|
||||
<!--<button (click)="onNext()"><i class="material-icons">navigate_next</i></button>-->
|
||||
<!--<button (click)="onMore()" ><i class="material-icons">more_vert</i></button>-->
|
||||
<button (click)="onFullscreen()" *ngIf="!isFullScreen"><i class="material-icons">fullscreen</i></button>
|
||||
<button (click)="onFullscreenExit()" *ngIf="isFullScreen"><i
|
||||
class="material-icons">fullscreen_exit</i></button>
|
||||
@if(isFullScreen) {
|
||||
<button (click)="onFullscreenExit()"><i class="material-icons">fullscreen_exit</i></button>
|
||||
}
|
||||
@else {
|
||||
<button (click)="onFullscreen()"><i class="material-icons">fullscreen</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>
|
||||
|
||||
<button class="bigPause" (click)="onPauseToggle()"><i *ngIf="!isPlaying"
|
||||
class="material-icons">play_circle_outline</i></button>
|
||||
<button class="bigRewind" (click)="onRewind()"><i *ngIf="!isPlaying"
|
||||
class="material-icons">fast_rewind</i></button>
|
||||
<button class="bigForward" (click)="onForward()"><i *ngIf="!isPlaying"
|
||||
class="material-icons">fast_forward</i></button>
|
||||
<button class="bigPause" (click)="onPauseToggle()">
|
||||
@if(!isPlaying) {
|
||||
<i class="material-icons">play_circle_outline</i>
|
||||
}
|
||||
</button>
|
||||
<button class="bigRewind" (click)="onRewind()">
|
||||
@if(!isPlaying) {
|
||||
<i class="material-icons">fast_rewind</i>
|
||||
}
|
||||
</button>
|
||||
<button class="bigForward" (click)="onForward()">
|
||||
@if(!isPlaying) {
|
||||
<i class="material-icons">fast_forward</i>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="title-inline" *ngIf="!isFullScreen || !isPlaying">
|
||||
}
|
||||
@if(!isFullScreen || !isPlaying) {
|
||||
<div class="title-inline">
|
||||
{{generatedName}}
|
||||
</div>
|
||||
<div class="video-button" *ngIf="!isFullScreen || !isPlaying">
|
||||
<div class="video-button">
|
||||
<button (click)="onRequireStop()">
|
||||
<i class="material-icons big-button">highlight_off</i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="volume" *ngIf="displayVolumeMenu && (!displayNeedHide || !isPlaying)">
|
||||
}
|
||||
@if(displayVolumeMenu && (!displayNeedHide || !isPlaying)) {
|
||||
<div class="volume">
|
||||
<div class="volume-menu">
|
||||
<div class="slidecontainer">
|
||||
<input type="range" min="0" max="100" class="slider" [value]="volumeValue"
|
||||
(input)="onVolume($event.target)">
|
||||
</div>
|
||||
<button (click)="onVolumeMute()" *ngIf="!videoPlayer.muted"><i
|
||||
class="material-icons">volume_mute</i></button>
|
||||
<button (click)="onVolumeUnMute()" *ngIf="videoPlayer.muted"><i
|
||||
@if(videoPlayer.muted) {
|
||||
<button (click)="onVolumeUnMute()"><i
|
||||
class="material-icons">volume_off</i></button>
|
||||
}
|
||||
@else {
|
||||
<button (click)="onVolumeMute()"><i
|
||||
class="material-icons">volume_mute</i></button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<canvas #canvascreenshoot style="overflow:auto"></canvas>
|
||||
</div>
|
@ -5,10 +5,10 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
|
||||
import { UserMediaAdvancement } from 'app/model/user-media-advancement';
|
||||
import { DataService, VideoService, SeriesService, SeasonService, ArianeService, AdvancementService } from 'app/service';
|
||||
import { HttpWrapperService } from 'common/service';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { UUID, UserMediaAdvancement } from 'app/back-api';
|
||||
import { DataService, MediaService, SeriesService, SeasonService, ArianeService, AdvancementService } from 'app/service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-video',
|
||||
@ -53,7 +53,7 @@ export class VideoScene implements OnInit {
|
||||
seriesName: string = undefined;
|
||||
seasonId: number = undefined;
|
||||
seasonName: string = undefined;
|
||||
dataId: number = -1;
|
||||
dataId: UUID;
|
||||
time: number = undefined;
|
||||
typeId: number = undefined;
|
||||
generatedName: string = '';
|
||||
@ -88,13 +88,13 @@ export class VideoScene implements OnInit {
|
||||
registered: false
|
||||
};
|
||||
|
||||
constructor(private videoService: VideoService,
|
||||
private seriesService: SeriesService,
|
||||
private seasonService: SeasonService,
|
||||
private httpService: HttpWrapperService,
|
||||
private arianeService: ArianeService,
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private advancementService: AdvancementService) {
|
||||
private advancementService: AdvancementService,
|
||||
private MediaService: MediaService,
|
||||
private seasonService: SeasonService,
|
||||
private seriesService: SeriesService,
|
||||
private arianeService: ArianeService,) {
|
||||
|
||||
}
|
||||
|
||||
@ -154,10 +154,10 @@ export class VideoScene implements OnInit {
|
||||
this.generatedName = this.generatedName.replace(new RegExp('&', 'g'), '_');
|
||||
this.generatedName = this.generatedName.replace(new RegExp('/', 'g'), '_');
|
||||
// update the path of the uri request
|
||||
this.videoSource = this.httpService.createRESTCall2({
|
||||
api: `data/${this.dataId}/${this.generatedName}`,
|
||||
addURLToken: true,
|
||||
});
|
||||
this.videoSource = this.dataService.getUrl(
|
||||
this.dataId,
|
||||
this.generatedName,
|
||||
);
|
||||
}
|
||||
|
||||
myPeriodicCheckFunction() {
|
||||
@ -209,7 +209,7 @@ export class VideoScene implements OnInit {
|
||||
let self = this;
|
||||
self.haveNext = null;
|
||||
self.havePrevious = null;
|
||||
this.videoService.get(this.idVideo)
|
||||
this.MediaService.get(this.idVideo)
|
||||
.then((response) => {
|
||||
console.log(`get response of video : ${JSON.stringify(response, null, 2)}`);
|
||||
self.error = '';
|
||||
@ -221,15 +221,12 @@ export class VideoScene implements OnInit {
|
||||
self.dataId = response.dataId;
|
||||
self.time = response.time;
|
||||
self.generatedName = "????????? TODO: ???????" //response.generatedName;
|
||||
if (self.dataId !== -1) {
|
||||
self.videoSource = self.httpService.createRESTCall2({
|
||||
api: `data/${self.dataId}/${self.generatedName}`,
|
||||
addURLToken: true,
|
||||
});
|
||||
if (!isNullOrUndefined(self.dataId)) {
|
||||
self.videoSource = self.dataService.getUrl(self.dataId, self.generatedName);
|
||||
} else {
|
||||
self.videoSource = '';
|
||||
}
|
||||
self.covers = self.dataService.getCoverListUrl(response.covers);
|
||||
self.covers = self.dataService.getListThumbnailUrl(response.covers);
|
||||
|
||||
self.generateName();
|
||||
if (self.seriesId !== undefined && self.seriesId !== null) {
|
||||
@ -271,7 +268,7 @@ export class VideoScene implements OnInit {
|
||||
self.haveNext = response6[iii];
|
||||
}
|
||||
}
|
||||
//self.covers.push(self.dataService.getCoverUrl(response6[iii]));
|
||||
//self.covers.push(self.dataService.getThumbnailUrl(response6[iii]));
|
||||
}
|
||||
}).catch((response7: any) => {
|
||||
|
||||
@ -287,7 +284,7 @@ export class VideoScene implements OnInit {
|
||||
self.episode = undefined;
|
||||
self.seriesId = undefined;
|
||||
self.seasonId = undefined;
|
||||
self.dataId = -1;
|
||||
self.dataId = undefined;
|
||||
self.time = undefined;
|
||||
self.generatedName = '';
|
||||
self.videoSource = '';
|
||||
@ -457,8 +454,7 @@ export class VideoScene implements OnInit {
|
||||
onStop() {
|
||||
console.log('stop');
|
||||
this.startHideTimer();
|
||||
if (this.videoPlayer === null ||
|
||||
this.videoPlayer === undefined) {
|
||||
if (isNullOrUndefined(this.videoPlayer)) {
|
||||
console.log(`error element: ${this.videoPlayer}`);
|
||||
return;
|
||||
}
|
||||
@ -479,8 +475,7 @@ export class VideoScene implements OnInit {
|
||||
seek(newValue: any) {
|
||||
console.log(`seek ${newValue.value}`);
|
||||
this.startHideTimer();
|
||||
if (this.videoPlayer === null ||
|
||||
this.videoPlayer === undefined) {
|
||||
if (isNullOrUndefined(this.videoPlayer)) {
|
||||
console.log(`error element: ${this.videoPlayer}`);
|
||||
return;
|
||||
}
|
||||
@ -490,8 +485,7 @@ export class VideoScene implements OnInit {
|
||||
onRewind() {
|
||||
console.log('rewind');
|
||||
this.startHideTimer();
|
||||
if (this.videoPlayer === null ||
|
||||
this.videoPlayer === undefined) {
|
||||
if (isNullOrUndefined(this.videoPlayer)) {
|
||||
console.log(`error element: ${this.videoPlayer}`);
|
||||
return;
|
||||
}
|
||||
@ -501,8 +495,7 @@ export class VideoScene implements OnInit {
|
||||
onForward() {
|
||||
console.log('forward');
|
||||
this.startHideTimer();
|
||||
if (this.videoPlayer === null ||
|
||||
this.videoPlayer === undefined) {
|
||||
if (isNullOrUndefined(this.videoPlayer)) {
|
||||
console.log(`error element: ${this.videoPlayer}`);
|
||||
return;
|
||||
}
|
||||
@ -512,8 +505,7 @@ export class VideoScene implements OnInit {
|
||||
onMore() {
|
||||
console.log('more');
|
||||
this.startHideTimer();
|
||||
if (this.videoPlayer === null ||
|
||||
this.videoPlayer === undefined) {
|
||||
if (isNullOrUndefined(this.videoPlayer)) {
|
||||
console.log(`error element: ${this.videoPlayer}`);
|
||||
return;
|
||||
}
|
||||
@ -521,8 +513,7 @@ export class VideoScene implements OnInit {
|
||||
onFullscreen() {
|
||||
console.log('fullscreen');
|
||||
this.startHideTimer();
|
||||
if (this.videoGlobal === null ||
|
||||
this.videoGlobal === undefined) {
|
||||
if (isNullOrUndefined(this.videoGlobal)) {
|
||||
console.log(`error element: ${this.videoGlobal}`);
|
||||
return;
|
||||
}
|
||||
@ -543,8 +534,7 @@ export class VideoScene implements OnInit {
|
||||
onFullscreenExit22(docc: any) {
|
||||
console.log('fullscreen EXIT');
|
||||
this.startHideTimer();
|
||||
if (this.videoGlobal === null ||
|
||||
this.videoGlobal === undefined) {
|
||||
if (isNullOrUndefined(this.videoGlobal)) {
|
||||
console.log(`error element: ${this.videoGlobal}`);
|
||||
return;
|
||||
}
|
||||
@ -620,17 +610,18 @@ export class VideoScene implements OnInit {
|
||||
// canvas.crossorigin="anonymous"
|
||||
// convert it and send it to the server
|
||||
let self = this;
|
||||
|
||||
/*
|
||||
this.videoCanva.toBlob((blob) => {
|
||||
self.videoService.uploadCoverBlob(blob, this.idVideo);
|
||||
self.MediaService.uploadCoverBlob(blob, this.idVideo);
|
||||
}, 'image/jpeg', 0.95);
|
||||
|
||||
*/
|
||||
console.log("not implement upload as row data...");
|
||||
/*
|
||||
let tmpUrl = this.videoCanva.toDataURL('image/jpeg', 0.95);
|
||||
fetch(tmpUrl)
|
||||
.then(res => res.blob()) // Gets the response and returns it as a blob
|
||||
.then(blob => {
|
||||
self.videoService.uploadCoverBlob(blob, this.idVideo);
|
||||
self.MediaService.uploadCoverBlob(blob, this.idVideo);
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
123
front/src/app/service/GenericDataService.ts
Normal file
123
front/src/app/service/GenericDataService.ts
Normal file
@ -0,0 +1,123 @@
|
||||
import { DataStore, DataTools, TypeCheck, isNullOrUndefined } from "@kangaroo-and-rabbit/kar-cw";
|
||||
import { SelectModel } from "@kangaroo-and-rabbit/kar-cw/utils/data-tools";
|
||||
|
||||
export class GenericDataService<TYPE> {
|
||||
protected dataStore: DataStore<TYPE>;
|
||||
|
||||
setStore(dataStore: DataStore<TYPE>) {
|
||||
this.dataStore = dataStore;
|
||||
}
|
||||
|
||||
|
||||
gets(): Promise<TYPE[]> {
|
||||
return this.dataStore.getData();
|
||||
}
|
||||
|
||||
get(id: number): Promise<TYPE> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.gets()
|
||||
.then((response: TYPE[]) => {
|
||||
let data = DataTools.get(response, id);
|
||||
if (isNullOrUndefined(data)) {
|
||||
reject('Data does not exist in the local BDD');
|
||||
return;
|
||||
}
|
||||
resolve(data);
|
||||
return;
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getAll(ids: number[]): Promise<TYPE[]> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.gets()
|
||||
.then((response: TYPE[]) => {
|
||||
let data = DataTools.getsWhere(response,
|
||||
[
|
||||
{
|
||||
check: TypeCheck.EQUAL,
|
||||
key: 'id',
|
||||
value: ids,
|
||||
},
|
||||
]);
|
||||
resolve(data);
|
||||
return;
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getFilter(filter: (subData: any) => boolean): Promise<TYPE[]> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.gets()
|
||||
.then((data: TYPE[]) => {
|
||||
if (isNullOrUndefined(data)) {
|
||||
reject('Data does not exist in the local BDD');
|
||||
return;
|
||||
}
|
||||
let out: TYPE[] = [];
|
||||
for (const elem of data) {
|
||||
if (filter(elem)) {
|
||||
out.push(elem);
|
||||
}
|
||||
}
|
||||
resolve(out);
|
||||
return;
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getLike(value: string): Promise<TYPE[]> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.gets()
|
||||
.then((response: TYPE[]) => {
|
||||
let data = DataTools.getNameLike(response, value);
|
||||
if (isNullOrUndefined(data) || data.length === 0) {
|
||||
reject('Data does not exist in the local BDD');
|
||||
return;
|
||||
}
|
||||
resolve(data);
|
||||
return;
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getOrder(): Promise<TYPE[]> {
|
||||
return this.getsWhere(
|
||||
[
|
||||
{
|
||||
check: TypeCheck.NOT_EQUAL,
|
||||
key: 'id',
|
||||
value: [undefined, null],
|
||||
},
|
||||
],
|
||||
["name", "id"],
|
||||
);
|
||||
}
|
||||
|
||||
getsWhere(select: SelectModel[], orderByData?: string[]): Promise<TYPE[]> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.gets()
|
||||
.then((response: TYPE[]) => {
|
||||
let data = DataTools.getsWhere(response, select, orderByData);
|
||||
resolve(data);
|
||||
}).catch((response) => {
|
||||
console.log(`[E] ${self.constructor.name}: can not retrieve BDD values`);
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user