Compare commits

..

No commits in common. "main" and "v0.2.0" have entirely different histories.
main ... v0.2.0

125 changed files with 24677 additions and 15781 deletions

View File

@ -1,32 +1,7 @@
#!/bin/bash #!/bin/bash
version_file="../version.txt"
# update new release dependency
cd back cd back
# update the Maven version number mvn versions:set -DnewVersion=$(cat ../version.txt)
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 -
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 -

View File

@ -6,7 +6,7 @@
FROM archlinux:base-devel AS builder FROM archlinux:base-devel AS builder
# update system # update system
RUN pacman -Syu --noconfirm && pacman-db-upgrade \ RUN pacman -Syu --noconfirm && pacman-db-upgrade \
&& pacman -S --noconfirm jdk-openjdk maven npm pnpm \ && pacman -S --noconfirm jdk-openjdk maven npm \
&& pacman -Scc --noconfirm && pacman -Scc --noconfirm
ENV PATH /tmp/node_modules/.bin:$PATH ENV PATH /tmp/node_modules/.bin:$PATH
@ -29,15 +29,14 @@ RUN mvn clean compile assembly:single
###################################################################################### ######################################################################################
FROM builder AS buildFront FROM builder AS buildFront
RUN echo "@kangaroo-and-rabbit:registry=https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/npm/" > /root/.npmrc ADD front/package-lock.json \
front/package.json \
ADD front/package.json \
front/karma.conf.js \ front/karma.conf.js \
front/protractor.conf.js \ front/protractor.conf.js \
/tmp/ /tmp/
# install and cache app dependencies # install and cache app dependencies
RUN pnpm install RUN npm install
ADD front/e2e \ ADD front/e2e \
front/tsconfig.json \ front/tsconfig.json \
@ -59,6 +58,15 @@ FROM bellsoft/liberica-openjdk-alpine:latest
# add wget to manage the health check... # add wget to manage the health check...
RUN apk add --no-cache wget 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 ENV LANG=C.UTF-8
COPY --from=buildBack /tmp/out/maven/*.jar /application/application.jar COPY --from=buildBack /tmp/out/maven/*.jar /application/application.jar

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.kar</groupId> <groupId>org.kar</groupId>
<artifactId>karideo</artifactId> <artifactId>karideo</artifactId>
<version>0.3.0</version> <version>0.2.0</version>
<properties> <properties>
<maven.compiler.version>3.1</maven.compiler.version> <maven.compiler.version>3.1</maven.compiler.version>
<maven.compiler.source>21</maven.compiler.source> <maven.compiler.source>21</maven.compiler.source>
@ -20,17 +20,12 @@
<dependency> <dependency>
<groupId>kangaroo-and-rabbit</groupId> <groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId> <artifactId>archidata</artifactId>
<version>0.12.0</version> <version>0.6.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId> <artifactId>slf4j-simple</artifactId>
<version>2.1.0-alpha1</version> <version>2.0.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.17.1</version>
</dependency> </dependency>
<!-- <!--
************************************************************ ************************************************************
@ -40,25 +35,15 @@
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId> <artifactId>junit-jupiter-api</artifactId>
<version>5.11.0-M2</version> <version>5.10.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId> <artifactId>junit-jupiter-engine</artifactId>
<version>5.11.0-M2</version> <version>5.10.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </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> </dependencies>
<build> <build>
<sourceDirectory>src</sourceDirectory> <sourceDirectory>src</sourceDirectory>
@ -195,10 +180,24 @@
<mainClass>org.kar.karideo.WebLauncher</mainClass> <mainClass>org.kar.karideo.WebLauncher</mainClass>
</configuration> </configuration>
</plugin> </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> <plugin>
<groupId>net.revelc.code.formatter</groupId> <groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId> <artifactId>formatter-maven-plugin</artifactId>
<version>2.23.0</version> <version>2.12.2</version>
<configuration> <configuration>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<lineEnding>LF</lineEnding> <lineEnding>LF</lineEnding>
@ -222,23 +221,7 @@
</execution> </execution>
</executions> </executions>
</plugin> </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> </plugins>
</build> </build>
<!-- Generate Java-docs As Part Of Project Reports --> <!-- Generate Java-docs As Part Of Project Reports -->

View File

@ -10,7 +10,10 @@ import org.glassfish.jersey.server.ResourceConfig;
import org.kar.archidata.GlobalConfiguration; import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.UpdateJwtPublicKey; import org.kar.archidata.UpdateJwtPublicKey;
import org.kar.archidata.api.DataResource; import org.kar.archidata.api.DataResource;
import org.kar.archidata.catcher.GenericCatcher; 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.db.DBConfig; import org.kar.archidata.db.DBConfig;
import org.kar.archidata.filter.CORSFilter; import org.kar.archidata.filter.CORSFilter;
import org.kar.archidata.filter.OptionFilter; import org.kar.archidata.filter.OptionFilter;
@ -18,18 +21,17 @@ import org.kar.archidata.migration.MigrationEngine;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.karideo.api.Front; import org.kar.karideo.api.Front;
import org.kar.karideo.api.HealthCheck; import org.kar.karideo.api.HealthCheck;
import org.kar.karideo.api.MediaResource;
import org.kar.karideo.api.SeasonResource; import org.kar.karideo.api.SeasonResource;
import org.kar.karideo.api.SeriesResource; import org.kar.karideo.api.SeriesResource;
import org.kar.karideo.api.TypeResource; import org.kar.karideo.api.TypeResource;
import org.kar.karideo.api.UserMediaAdvancementResource; import org.kar.karideo.api.UserMediaAdvancementResource;
import org.kar.karideo.api.UserResource; import org.kar.karideo.api.UserResource;
import org.kar.karideo.api.VideoResource;
import org.kar.karideo.filter.KarideoAuthenticationFilter; import org.kar.karideo.filter.KarideoAuthenticationFilter;
import org.kar.karideo.migration.Initialization; import org.kar.karideo.migration.Initialization;
import org.kar.karideo.migration.Migration20230810; import org.kar.karideo.migration.Migration20230810;
import org.kar.karideo.migration.Migration20231015; import org.kar.karideo.migration.Migration20231015;
import org.kar.karideo.migration.Migration20231126; import org.kar.karideo.migration.Migration20231126;
import org.kar.karideo.migration.Migration20240226;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -58,7 +60,7 @@ public class WebLauncher {
migrationEngine.add(new Migration20230810()); migrationEngine.add(new Migration20230810());
migrationEngine.add(new Migration20231015()); migrationEngine.add(new Migration20231015());
migrationEngine.add(new Migration20231126()); migrationEngine.add(new Migration20231126());
migrationEngine.add(new Migration20240226()); //migrationEngine.add(new Migration20231126());
WebLauncher.LOGGER.info("Migrate the DB [START]"); WebLauncher.LOGGER.info("Migrate the DB [START]");
migrationEngine.migrateWaitAdmin(GlobalConfiguration.dbConfig); migrationEngine.migrateWaitAdmin(GlobalConfiguration.dbConfig);
WebLauncher.LOGGER.info("Migrate the DB [STOP]"); WebLauncher.LOGGER.info("Migrate the DB [STOP]");
@ -92,14 +94,17 @@ public class WebLauncher {
// global authentication system // global authentication system
rc.register(KarideoAuthenticationFilter.class); rc.register(KarideoAuthenticationFilter.class);
// register exception catcher // register exception catcher
GenericCatcher.addAll(rc); rc.register(InputExceptionCatcher.class);
rc.register(SystemExceptionCatcher.class);
rc.register(FailExceptionCatcher.class);
rc.register(ExceptionCatcher.class);
// add default resource: // add default resource:
rc.register(UserResource.class); rc.register(UserResource.class);
rc.register(SeriesResource.class); rc.register(SeriesResource.class);
rc.register(DataResource.class); rc.register(DataResource.class);
rc.register(SeasonResource.class); rc.register(SeasonResource.class);
rc.register(TypeResource.class); rc.register(TypeResource.class);
rc.register(MediaResource.class); rc.register(VideoResource.class);
rc.register(UserMediaAdvancementResource.class); rc.register(UserMediaAdvancementResource.class);
rc.register(HealthCheck.class); rc.register(HealthCheck.class);
@ -108,7 +113,7 @@ public class WebLauncher {
// add jackson to be discover when we are ins stand-alone server // add jackson to be discover when we are ins stand-alone server
rc.register(JacksonFeature.class); rc.register(JacksonFeature.class);
// enable this to show low level request // enable this to show low level request
// rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName()); //rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName());
this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
final HttpServer serverLink = this.server; final HttpServer serverLink = this.server;

View File

@ -1,20 +1,7 @@
package org.kar.karideo; 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.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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -23,18 +10,7 @@ public class WebLauncherLocal extends WebLauncher {
private WebLauncherLocal() {} private WebLauncherLocal() {}
public static void generateObjects() throws Exception { public static void main(final String[] args) throws InterruptedException {
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(); final WebLauncherLocal launcher = new WebLauncherLocal();
launcher.process(); launcher.process();
LOGGER.info("end-configure the server & wait finish process:"); LOGGER.info("end-configure the server & wait finish process:");

View File

@ -1,5 +1,6 @@
package org.kar.karideo.api; package org.kar.karideo.api;
import org.kar.archidata.api.FrontGeneric; import org.kar.archidata.api.FrontGeneric;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;

View File

@ -6,7 +6,6 @@ import org.kar.archidata.tools.JWTWrapper;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
@ -19,13 +18,11 @@ import jakarta.ws.rs.core.Response;
public class HealthCheck { public class HealthCheck {
static final Logger LOGGER = LoggerFactory.getLogger(HealthCheck.class); static final Logger LOGGER = LoggerFactory.getLogger(HealthCheck.class);
public record HealthResult(String value) { public record HealthResult(
String value) {};
};
@GET @GET
@PermitAll @PermitAll
@Operation(description = "Get the server state (health)", tags = "SYSTEM")
public HealthResult getHealth() throws FailException { public HealthResult getHealth() throws FailException {
if (JWTWrapper.getPublicKeyJson() == null && !ConfigBaseVariable.getTestMode()) { if (JWTWrapper.getPublicKeyJson() == null && !ConfigBaseVariable.getTestMode()) {
throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Missing Jwt public token"); throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Missing Jwt public token");

View File

@ -2,23 +2,19 @@ package org.kar.karideo.api;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; 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.DataAccess;
import org.kar.archidata.dataAccess.QueryAnd; import org.kar.archidata.dataAccess.QueryAnd;
import org.kar.archidata.dataAccess.QueryCondition; import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
import org.kar.archidata.dataAccess.options.Condition; import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.tools.DataTools; import org.kar.archidata.tools.DataTools;
import org.kar.karideo.model.Season; import org.kar.karideo.model.Season;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@ -29,16 +25,23 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam; import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("/season") @Path("/season")
@Produces(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_JSON })
public class SeasonResource { public class SeasonResource {
static final Logger LOGGER = LoggerFactory.getLogger(SeasonResource.class); static final Logger LOGGER = LoggerFactory.getLogger(SeasonResource.class);
@GET @GET
@Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get a specific Season with his ID", tags = "GLOBAL") public static Season getWithId(@PathParam("id") final Long id) throws Exception {
public List<Season> gets() throws Exception { return DataAccess.get(Season.class, id);
}
@GET
@RolesAllowed("USER")
public List<Season> get() throws Exception {
return DataAccess.gets(Season.class); return DataAccess.gets(Season.class);
} }
@ -46,27 +49,26 @@ public class SeasonResource {
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Get all season", tags = "GLOBAL")
public Season get(@PathParam("id") final Long id) throws Exception { public Season get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Season.class, id); return DataAccess.get(Season.class, id);
} }
/* ============================================================================= ADMIN SECTION: ============================================================================= */ /* =============================================================================
* ADMIN SECTION:
* ============================================================================= */
@POST @POST
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Create a new season", tags = "GLOBAL") public Season put(final String jsonRequest) throws Exception {
public Season post(final Season jsonRequest) throws Exception { return DataAccess.insertWithJson(Season.class, jsonRequest);
return DataAccess.insert(jsonRequest);
} }
@PATCH @PATCH
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Modify a specific season", tags = "GLOBAL") public Season put(@PathParam("id") final Long id, final String jsonRequest) throws Exception {
public Season patch(@PathParam("id") final Long id, @AsyncType(Season.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Season.class, id, jsonRequest); DataAccess.updateWithJson(Season.class, id, jsonRequest);
return DataAccess.get(Season.class, id); return DataAccess.get(Season.class, id);
} }
@ -74,30 +76,26 @@ public class SeasonResource {
@DELETE @DELETE
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific season", tags = "GLOBAL") public Response delete(@PathParam("id") final Long id) throws Exception {
public void remove(@PathParam("id") final Long id) throws Exception {
DataAccess.delete(Season.class, id); DataAccess.delete(Season.class, id);
return Response.ok().build();
} }
@POST @POST
@Path("{id}/cover") @Path("{id}/add_cover")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Upload a new season cover season", tags = "GLOBAL") public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
@TypeScriptProgress @FormDataParam("file") final FormDataContentDisposition fileMetaData) {
public Season uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, return DataTools.uploadCover(Season.class, id, fileName, fileInputStream, fileMetaData);
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
DataTools.uploadCover(Season.class, id, fileName, fileInputStream, fileMetaData);
return DataAccess.get(Season.class, id);
} }
@DELETE @GET
@Path("{id}/cover/{coverId}") @Path("{id}/rm_cover/{coverId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific cover of a season", tags = "GLOBAL") public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception {
public Season removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { AddOnManyToMany.removeLink(Season.class, id, "cover", coverId);
AddOnDataJson.removeLink(Season.class, id, "covers", coverId); return Response.ok(DataAccess.get(Season.class, id)).build();
return DataAccess.get(Season.class, id);
} }
public static Season getOrCreate(final String name, final Long seriesId) { public static Season getOrCreate(final String name, final Long seriesId) {

View File

@ -2,23 +2,19 @@ package org.kar.karideo.api;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; 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.DataAccess;
import org.kar.archidata.dataAccess.QueryAnd; import org.kar.archidata.dataAccess.QueryAnd;
import org.kar.archidata.dataAccess.QueryCondition; import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
import org.kar.archidata.dataAccess.options.Condition; import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.tools.DataTools; import org.kar.archidata.tools.DataTools;
import org.kar.karideo.model.Series; import org.kar.karideo.model.Series;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@ -29,16 +25,23 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam; import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("/series") @Path("/series")
@Produces(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_JSON })
public class SeriesResource { public class SeriesResource {
static final Logger LOGGER = LoggerFactory.getLogger(SeriesResource.class); static final Logger LOGGER = LoggerFactory.getLogger(SeriesResource.class);
@GET @GET
@Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get all Series", tags = "GLOBAL") public static Series getWithId(@PathParam("id") final Long id) throws Exception {
public List<Series> gets() throws Exception { return DataAccess.get(Series.class, id);
}
@GET
@RolesAllowed("USER")
public List<Series> get() throws Exception {
return DataAccess.gets(Series.class); return DataAccess.gets(Series.class);
} }
@ -46,27 +49,26 @@ public class SeriesResource {
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Consumes(MediaType.APPLICATION_JSON) @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 { public Series get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Series.class, id); return DataAccess.get(Series.class, id);
} }
/* ============================================================================= ADMIN SECTION: ============================================================================= */ /* =============================================================================
* ADMIN SECTION:
* ============================================================================= */
@POST @POST
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Create a new Series", tags = "GLOBAL") public Series put(final String jsonRequest) throws Exception {
public Series post(final Series jsonRequest) throws Exception { return DataAccess.insertWithJson(Series.class, jsonRequest);
return DataAccess.insert(jsonRequest);
} }
@PATCH @PATCH
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Modify a specific Series", tags = "GLOBAL") public Series put(@PathParam("id") final Long id, final String jsonRequest) throws Exception {
public Series patch(@PathParam("id") final Long id, @AsyncType(Series.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Series.class, id, jsonRequest); DataAccess.updateWithJson(Series.class, id, jsonRequest);
return DataAccess.get(Series.class, id); return DataAccess.get(Series.class, id);
} }
@ -74,30 +76,26 @@ public class SeriesResource {
@DELETE @DELETE
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific Series", tags = "GLOBAL") public Response delete(@PathParam("id") final Long id) throws Exception {
public void remove(@PathParam("id") final Long id) throws Exception {
DataAccess.delete(Series.class, id); DataAccess.delete(Series.class, id);
return Response.ok().build();
} }
@POST @POST
@Path("{id}/cover") @Path("{id}/add_cover")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Upload a new season cover Series", tags = "GLOBAL") public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
@TypeScriptProgress @FormDataParam("file") final FormDataContentDisposition fileMetaData) {
public Series uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, return DataTools.uploadCover(Series.class, id, fileName, fileInputStream, fileMetaData);
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
DataTools.uploadCover(Series.class, id, fileName, fileInputStream, fileMetaData);
return DataAccess.get(Series.class, id);
} }
@DELETE @GET
@Path("{id}/cover/{coverId}") @Path("{id}/rm_cover/{coverId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific Series of a season", tags = "GLOBAL") public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception {
public Series removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { AddOnManyToMany.removeLink(Series.class, id, "cover", coverId);
AddOnDataJson.removeLink(Series.class, id, "covers", coverId); return Response.ok(DataAccess.get(Series.class, id)).build();
return DataAccess.get(Series.class, id);
} }
public static Series getOrCreate(final String name, final Long typeId) { public static Series getOrCreate(final String name, final Long typeId) {

View File

@ -2,22 +2,18 @@ package org.kar.karideo.api;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; 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.DataAccess;
import org.kar.archidata.dataAccess.QueryCondition; import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
import org.kar.archidata.dataAccess.options.Condition; import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.tools.DataTools; import org.kar.archidata.tools.DataTools;
import org.kar.karideo.model.Type; import org.kar.karideo.model.Type;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@ -28,16 +24,23 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam; import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("/type") @Path("/type")
@Produces(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public class TypeResource { public class TypeResource {
static final Logger LOGGER = LoggerFactory.getLogger(TypeResource.class); static final Logger LOGGER = LoggerFactory.getLogger(TypeResource.class);
@GET @GET
@Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get all Type", tags = "GLOBAL") public static Type getWithId(@PathParam("id") final Long id) throws Exception {
public List<Type> gets() throws Exception { return DataAccess.get(Type.class, id);
}
@GET
@RolesAllowed("USER")
public List<Type> get() throws Exception {
return DataAccess.gets(Type.class); return DataAccess.gets(Type.class);
} }
@ -45,7 +48,6 @@ public class TypeResource {
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Consumes(MediaType.APPLICATION_JSON) @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 { public Type get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Type.class, id); return DataAccess.get(Type.class, id);
} }
@ -54,22 +56,22 @@ public class TypeResource {
return DataAccess.get(Type.class, id); return DataAccess.get(Type.class, id);
} }
/* ============================================================================= ADMIN SECTION: ============================================================================= */ /* =============================================================================
* ADMIN SECTION:
* ============================================================================= */
@POST @POST
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Create a new Type", tags = "GLOBAL") public Type put(final String jsonRequest) throws Exception {
public Type post(final Type jsonRequest) throws Exception { return DataAccess.insertWithJson(Type.class, jsonRequest);
return DataAccess.insert(jsonRequest);
} }
@PATCH @PATCH
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Modify a specific Type", tags = "GLOBAL") public Type put(@PathParam("id") final Long id, final String jsonRequest) throws Exception {
public Type patch(@PathParam("id") final Long id, @AsyncType(Type.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Type.class, id, jsonRequest); DataAccess.updateWithJson(Type.class, id, jsonRequest);
return DataAccess.get(Type.class, id); return DataAccess.get(Type.class, id);
} }
@ -77,30 +79,26 @@ public class TypeResource {
@DELETE @DELETE
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific Type", tags = "GLOBAL") public Response delete(@PathParam("id") final Long id) throws Exception {
public void remove(@PathParam("id") final Long id) throws Exception {
DataAccess.delete(Type.class, id); DataAccess.delete(Type.class, id);
return Response.ok().build();
} }
@POST @POST
@Path("{id}/cover") @Path("{id}/add_cover")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Upload a new season cover Type", tags = "GLOBAL") public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
@TypeScriptProgress @FormDataParam("file") final FormDataContentDisposition fileMetaData) {
public Type uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, return DataTools.uploadCover(Type.class, id, fileName, fileInputStream, fileMetaData);
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
DataTools.uploadCover(Type.class, id, fileName, fileInputStream, fileMetaData);
return DataAccess.get(Type.class, id);
} }
@DELETE @GET
@Path("{id}/cover/{coverId}") @Path("{id}/rm_cover/{coverId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific cover of a type", tags = "GLOBAL") public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception {
public Type removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { AddOnManyToMany.removeLink(Type.class, id, "cover", coverId);
AddOnDataJson.removeLink(Type.class, id, "covers", coverId); return Response.ok(DataAccess.get(Type.class, id)).build();
return DataAccess.get(Type.class, id);
} }
public static Type getOrCreate(final String name) { public static Type getOrCreate(final String name) {

View File

@ -11,7 +11,6 @@ import org.kar.karideo.model.UserMediaAdvancement;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@ -22,39 +21,42 @@ import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.SecurityContext;
@Path("/advancement") @Path("/advancement")
@Produces(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public class UserMediaAdvancementResource { public class UserMediaAdvancementResource {
static final Logger LOGGER = LoggerFactory.getLogger(UserMediaAdvancementResource.class); static final Logger LOGGER = LoggerFactory.getLogger(UserMediaAdvancementResource.class);
@GET @GET
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get a specific user advancement with his ID", tags = "GLOBAL") public UserMediaAdvancement getWithId(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception {
public UserMediaAdvancement get(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception {
final GenericContext gc = (GenericContext) sc.getUserPrincipal(); 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)))); return DataAccess.getWhere(UserMediaAdvancement.class, new Condition(new QueryAnd(new QueryCondition("mediaId", "=", id), new QueryCondition("userId", "=", gc.userByToken.id))));
} }
@GET @GET
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get all user advancement", tags = "GLOBAL")
public List<UserMediaAdvancement> gets(@Context final SecurityContext sc) throws Exception { public List<UserMediaAdvancement> gets(@Context final SecurityContext sc) throws Exception {
final GenericContext gc = (GenericContext) sc.getUserPrincipal(); final GenericContext gc = (GenericContext) sc.getUserPrincipal();
return DataAccess.getsWhere(UserMediaAdvancement.class, new Condition(new QueryCondition("userId", "=", gc.userByToken.id))); 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 //@POST
// @Path("{id}") //@Path("{id}")
// @RolesAllowed("USER") //@RolesAllowed("USER")
// @Consumes(MediaType.APPLICATION_JSON) //@Consumes(MediaType.APPLICATION_JSON)
public UserMediaAdvancement post(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformations data) throws Exception { public UserMediaAdvancement post(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformations data) throws Exception {
final GenericContext gc = (GenericContext) sc.getUserPrincipal(); final GenericContext gc = (GenericContext) sc.getUserPrincipal();
final UserMediaAdvancement elem = new UserMediaAdvancement(); final UserMediaAdvancement elem = new UserMediaAdvancement();
@ -66,16 +68,17 @@ public class UserMediaAdvancementResource {
return DataAccess.insert(elem); return DataAccess.insert(elem);
} }
public record MediaInformationsDelta(int time, float percent, boolean addCount) { public record MediaInformationsDelta(
} int time,
float percent,
boolean addCount) {}
@PATCH @PATCH
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Modify a user advancement", tags = "GLOBAL") public UserMediaAdvancement put(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformationsDelta data) throws Exception {
public UserMediaAdvancement patch(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformationsDelta data) throws Exception { final UserMediaAdvancement elem = getWithId(sc, id);
final UserMediaAdvancement elem = get(sc, id);
if (elem == null) { if (elem == null) {
// insert element // insert element
if (data.addCount) { if (data.addCount) {
@ -97,10 +100,10 @@ public class UserMediaAdvancementResource {
@DELETE @DELETE
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Remove a specific user advancement", tags = "GLOBAL") public Response delete(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception {
public void remove(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception { final UserMediaAdvancement elem = getWithId(sc, id);
final UserMediaAdvancement elem = get(sc, id);
DataAccess.delete(UserMediaAdvancement.class, elem.id); DataAccess.delete(UserMediaAdvancement.class, elem.id);
return Response.ok().build();
} }
} }

View File

@ -10,7 +10,6 @@ import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
@ -21,7 +20,7 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.SecurityContext;
@Path("/users") @Path("/users")
@Produces(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public class UserResource { public class UserResource {
static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class); static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);
@ -42,8 +41,7 @@ public class UserResource {
// curl http://localhost:9993/api/users // curl http://localhost:9993/api/users
@GET @GET
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Get all the users", tags = "SYSTEM") public List<UserKarideo> getUsers() {
public List<UserKarideo> gets() {
System.out.println("getUsers"); System.out.println("getUsers");
try { try {
return DataAccess.gets(UserKarideo.class); return DataAccess.gets(UserKarideo.class);
@ -58,8 +56,7 @@ public class UserResource {
@GET @GET
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Get a specific user data", tags = "SYSTEM") public UserKarideo getUsers(@Context final SecurityContext sc, @PathParam("id") final long userId) {
public UserKarideo get(@Context final SecurityContext sc, @PathParam("id") final long userId) {
System.out.println("getUser " + userId); System.out.println("getUser " + userId);
final GenericContext gc = (GenericContext) sc.getUserPrincipal(); final GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("==================================================="); System.out.println("===================================================");
@ -77,7 +74,6 @@ public class UserResource {
@GET @GET
@Path("me") @Path("me")
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get the user personal data", tags = "SYSTEM")
public UserOut getMe(@Context final SecurityContext sc) { public UserOut getMe(@Context final SecurityContext sc) {
LOGGER.debug("getMe()"); LOGGER.debug("getMe()");
final GenericContext gc = (GenericContext) sc.getUserPrincipal(); final GenericContext gc = (GenericContext) sc.getUserPrincipal();

View File

@ -4,15 +4,12 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; 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.api.DataResource;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
import org.kar.archidata.exception.FailException; import org.kar.archidata.exception.FailException;
import org.kar.archidata.exception.InputException; import org.kar.archidata.exception.InputException;
import org.kar.archidata.model.Data; import org.kar.archidata.model.Data;
@ -24,7 +21,6 @@ import org.kar.karideo.model.Type;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@ -35,23 +31,22 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam; import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("/media") @Path("/video")
@Produces(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_JSON })
public class MediaResource { public class VideoResource {
static final Logger LOGGER = LoggerFactory.getLogger(MediaResource.class); static final Logger LOGGER = LoggerFactory.getLogger(VideoResource.class);
@GET @GET
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get all Media", tags = "GLOBAL") public List<Media> get() throws Exception {
public List<Media> gets() throws Exception {
return DataAccess.gets(Media.class); return DataAccess.gets(Media.class);
} }
@GET @GET
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get a specific Media with his ID", tags = "GLOBAL")
public Media get(@PathParam("id") final Long id) throws Exception { public Media get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Media.class, id); return DataAccess.get(Media.class, id);
} }
@ -60,9 +55,8 @@ public class MediaResource {
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Modify a specific Media", tags = "GLOBAL") public Media put(@PathParam("id") final Long id, final String jsonRequest) throws Exception {
public Media patch(@PathParam("id") final Long id, @AsyncType(Media.class) final String jsonRequest) throws Exception { System.out.println("update video " + id + " ==> '" + jsonRequest + "'");
LOGGER.info("update video {} ==> '{}'", id, jsonRequest);
DataAccess.updateWithJson(Media.class, id, jsonRequest); DataAccess.updateWithJson(Media.class, id, jsonRequest);
return DataAccess.get(Media.class, id); return DataAccess.get(Media.class, id);
} }
@ -81,22 +75,13 @@ public class MediaResource {
} }
@POST @POST
@Path("/upload/")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Create a new Media", tags = "GLOBAL") public Response uploadFile(@FormDataParam("fileName") String fileName, @FormDataParam("universe") String universe, @FormDataParam("series") String series,
@TypeScriptProgress //@FormDataParam("seriesId") String seriesId, Not used ...
public Media uploadFile( // @FormDataParam("season") String season, @FormDataParam("episode") String episode, @FormDataParam("title") String title, @FormDataParam("typeId") String typeId,
@FormDataParam("fileName") String fileName, // @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws FailException {
@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 { try {
// correct input string stream : // correct input string stream :
fileName = multipartCorrection(fileName); fileName = multipartCorrection(fileName);
@ -107,17 +92,17 @@ public class MediaResource {
title = multipartCorrection(title); title = multipartCorrection(title);
typeId = multipartCorrection(typeId); typeId = multipartCorrection(typeId);
// public NodeSmall uploadFile(final FormDataMultiPart form) { //public NodeSmall uploadFile(final FormDataMultiPart form) {
LOGGER.info("Upload media file: {}", fileMetaData); System.out.println("Upload media file: " + fileMetaData);
LOGGER.info(" - fileName: {}", fileName); System.out.println(" - fileName: " + fileName);
LOGGER.info(" - universe: {}", universe); System.out.println(" - universe: " + universe);
LOGGER.info(" - series: {}", series); System.out.println(" - series: " + series);
LOGGER.info(" - season: {}", season); System.out.println(" - season: " + season);
LOGGER.info(" - episode: {}", episode); System.out.println(" - episode: " + episode);
LOGGER.info(" - title: {}", title); System.out.println(" - title: " + title);
LOGGER.info(" - type: {}", typeId); System.out.println(" - type: " + typeId);
LOGGER.info(" - fileInputStream: {}", fileInputStream); System.out.println(" - fileInputStream: " + fileInputStream);
LOGGER.info(" - fileMetaData: {}", fileMetaData); System.out.println(" - fileMetaData: " + fileMetaData);
System.out.flush(); System.out.flush();
if (typeId == null) { if (typeId == null) {
throw new InputException("typeId", "TypiId is not specified"); throw new InputException("typeId", "TypiId is not specified");
@ -127,7 +112,7 @@ public class MediaResource {
final String sha512 = DataResource.saveTemporaryFile(fileInputStream, tmpUID); final String sha512 = DataResource.saveTemporaryFile(fileInputStream, tmpUID);
Data data = DataResource.getWithSha512(sha512); Data data = DataResource.getWithSha512(sha512);
if (data == null) { if (data == null) {
LOGGER.info("Need to add the data in the BDD ... "); System.out.println("Need to add the data in the BDD ... ");
System.out.flush(); System.out.flush();
try { try {
data = DataResource.createNewData(tmpUID, fileName, sha512); data = DataResource.createNewData(tmpUID, fileName, sha512);
@ -136,33 +121,33 @@ public class MediaResource {
ex.printStackTrace(); ex.printStackTrace();
throw new FailException("can not create input media (the data model has an internal error"); throw new FailException("can not create input media (the data model has an internal error");
} }
} else if (data != null && data.deleted != null && data.deleted) { } else if (data.deleted) {
LOGGER.info("Data already exist but deleted"); System.out.println("Data already exist but deleted");
System.out.flush(); System.out.flush();
DataTools.undelete(data.uuid); DataResource.undelete(data.id);
data.deleted = false; data.deleted = false;
} else { } else {
LOGGER.info("Data already exist ... all good"); System.out.println("Data already exist ... all good");
System.out.flush(); System.out.flush();
} }
// Fist step: retieve all the Id of each parents:... // Fist step: retive all the Id of each parents:...
LOGGER.info("Find typeNode"); System.out.println("Find typeNode");
// check if id of type exist: // check if id of type exist:
final Type typeNode = TypeResource.getId(Long.parseLong(typeId)); final Type typeNode = TypeResource.getId(Long.parseLong(typeId));
if (typeNode == null) { if (typeNode == null) {
DataResource.removeTemporaryFile(tmpUID); DataResource.removeTemporaryFile(tmpUID);
throw new InputException("typeId", "TypeId does not exist ..."); throw new InputException("typeId", "TypeId does not exist ...");
} }
LOGGER.info(" ==> {}", typeNode); System.out.println(" ==> " + typeNode);
LOGGER.info("Find seriesNode"); System.out.println("Find seriesNode");
// get uid of group: // get uid of group:
Series seriesNode = null; Series seriesNode = null;
if (series != null) { if (series != null) {
seriesNode = SeriesResource.getOrCreate(series, typeNode.id); seriesNode = SeriesResource.getOrCreate(series, typeNode.id);
} }
LOGGER.info(" ==> {}", seriesNode); System.out.println(" ==> " + seriesNode);
LOGGER.info("Find seasonNode"); System.out.println("Find seasonNode");
// get uid of season: // get uid of season:
Season seasonNode = null; Season seasonNode = null;
if (seriesNode == null && season != null) { if (seriesNode == null && season != null) {
@ -173,13 +158,14 @@ public class MediaResource {
seasonNode = SeasonResource.getOrCreate(season, seriesNode.id); seasonNode = SeasonResource.getOrCreate(season, seriesNode.id);
} }
LOGGER.info(" ==> {}", seasonNode); System.out.println(" ==> " + seasonNode);
LOGGER.info("add media"); System.out.println("add media");
final long uniqueSQLID = -1;
try { try {
final Media media = new Media(); final Media media = new Media();
media.name = title; media.name = title;
media.dataId = data.uuid; media.dataId = data.id;
media.typeId = typeNode.id; media.typeId = typeNode.id;
media.seriesId = null; media.seriesId = null;
if (seriesNode != null) { if (seriesNode != null) {
@ -194,56 +180,44 @@ public class MediaResource {
media.episode = Integer.parseInt(episode); media.episode = Integer.parseInt(episode);
} }
final Media out = DataAccess.insert(media); final Media out = DataAccess.insert(media);
LOGGER.info("Generate new media {}", out); DataResource.removeTemporaryFile(tmpUID);
return out; System.out.println("uploaded .... compleate: " + uniqueSQLID);
final Media creation = get(uniqueSQLID);
return Response.ok(creation).build();
} catch (final SQLException ex) { } catch (final SQLException ex) {
ex.printStackTrace(); ex.printStackTrace();
LOGGER.error("Catch error: {}", ex.getMessage()); System.out.println("Catch error:" + ex.getMessage());
throw new FailException("Catch SQLerror ==> check server logs"); throw new FailException("Catch SQLerror ==> check server logs");
} finally {
DataResource.removeTemporaryFile(tmpUID);
} }
} catch (final Exception ex) { } catch (final Exception ex) {
LOGGER.error("Catch an unexpected error ... {} ", ex.getMessage()); System.out.println("Catch an unexpected error ... " + ex.getMessage());
ex.printStackTrace(); ex.printStackTrace();
throw new FailException("Catch Exception ==> check server logs"); throw new FailException("Catch Exception ==> check server logs");
} }
} }
@POST @POST
@Path("{id}/cover") @Path("{id}/add_cover")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
@AsyncType(Media.class) public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream,
@Operation(description = "Upload a new season cover media", tags = "GLOBAL") @FormDataParam("file") final FormDataContentDisposition fileMetaData) {
@TypeScriptProgress return DataTools.uploadCover(Media.class, id, fileName, fileInputStream, fileMetaData);
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);
} }
@DELETE @GET
@Path("{id}/cover/{coverId}") @Path("{id}/rm_cover/{coverId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific cover of a media", tags = "GLOBAL") public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception {
public Media removeCover( // AddOnManyToMany.removeLink(Media.class, id, "cover", coverId);
@PathParam("id") final Long id, // return Response.ok(DataAccess.get(Media.class, id)).build();
@PathParam("coverId") final UUID coverId //
) throws Exception {
AddOnDataJson.removeLink(Media.class, id, "covers", coverId);
return DataAccess.get(Media.class, id);
} }
@DELETE @DELETE
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific Media", tags = "GLOBAL") public Response delete(@PathParam("id") final Long id) throws Exception {
public void remove(@PathParam("id") final Long id) throws Exception {
DataAccess.delete(Media.class, id); DataAccess.delete(Media.class, id);
return Response.ok().build();
} }
} }

View File

@ -16,7 +16,7 @@ import jakarta.annotation.Priority;
public class KarideoAuthenticationFilter extends AuthenticationFilter { public class KarideoAuthenticationFilter extends AuthenticationFilter {
final Logger logger = LoggerFactory.getLogger(KarideoAuthenticationFilter.class); final Logger logger = LoggerFactory.getLogger(KarideoAuthenticationFilter.class);
public KarideoAuthenticationFilter() { public KarideoAuthenticationFilter() {
super("karideo"); super("karideo");
} }

View File

@ -4,57 +4,57 @@ package org.kar.karideo.internal;
//import io.scenarium.logger.Logger; //import io.scenarium.logger.Logger;
public class Log { public class Log {
// private static final String LIB_NAME = "logger"; // private static final String LIB_NAME = "logger";
// private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); // private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME);
// private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); // private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL);
// private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR); // private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR);
// private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING); // private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING);
// private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO); // private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO);
// private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG); // private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG);
// private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); // private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE);
// private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); // private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO);
// private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); // private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT);
// //
// private Log() {} // private Log() {}
// //
// public static void print(String data) { // public static void print(String data) {
// if (PRINT_PRINT) // if (PRINT_PRINT)
// Logger.print(LIB_NAME_DRAW, data); // Logger.print(LIB_NAME_DRAW, data);
// } // }
// //
// public static void todo(String data) { // public static void todo(String data) {
// if (PRINT_TODO) // if (PRINT_TODO)
// Logger.todo(LIB_NAME_DRAW, data); // Logger.todo(LIB_NAME_DRAW, data);
// } // }
// //
// public static void critical(String data) { // public static void critical(String data) {
// if (PRINT_CRITICAL) // if (PRINT_CRITICAL)
// Logger.critical(LIB_NAME_DRAW, data); // Logger.critical(LIB_NAME_DRAW, data);
// } // }
// //
// public static void error(String data) { // public static void error(String data) {
// if (PRINT_ERROR) // if (PRINT_ERROR)
// Logger.error(LIB_NAME_DRAW, data); // Logger.error(LIB_NAME_DRAW, data);
// } // }
// //
// public static void warning(String data) { // public static void warning(String data) {
// if (PRINT_WARNING) // if (PRINT_WARNING)
// Logger.warning(LIB_NAME_DRAW, data); // Logger.warning(LIB_NAME_DRAW, data);
// } // }
// //
// public static void info(String data) { // public static void info(String data) {
// if (PRINT_INFO) // if (PRINT_INFO)
// Logger.info(LIB_NAME_DRAW, data); // Logger.info(LIB_NAME_DRAW, data);
// } // }
// //
// public static void debug(String data) { // public static void debug(String data) {
// if (PRINT_DEBUG) // if (PRINT_DEBUG)
// Logger.debug(LIB_NAME_DRAW, data); // Logger.debug(LIB_NAME_DRAW, data);
// } // }
// //
// public static void verbose(String data) { // public static void verbose(String data) {
// if (PRINT_VERBOSE) // if (PRINT_VERBOSE)
// Logger.verbose(LIB_NAME_DRAW, data); // Logger.verbose(LIB_NAME_DRAW, data);
// } // }
} }

View File

@ -1,8 +1,5 @@
package org.kar.karideo.migration; 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.migration.MigrationSqlStep;
import org.kar.archidata.model.Data; import org.kar.archidata.model.Data;
import org.kar.archidata.model.User; import org.kar.archidata.model.User;
@ -11,16 +8,11 @@ import org.kar.karideo.model.Season;
import org.kar.karideo.model.Series; import org.kar.karideo.model.Series;
import org.kar.karideo.model.Type; import org.kar.karideo.model.Type;
import org.kar.karideo.model.UserMediaAdvancement; import org.kar.karideo.model.UserMediaAdvancement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Initialization extends MigrationSqlStep { 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 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 @Override
public String getName() { public String getName() {
return "Initialization"; return "Initialization";
@ -32,24 +24,31 @@ public class Initialization extends MigrationSqlStep {
@Override @Override
public void generateStep() throws Exception { public void generateStep() throws Exception {
for (final Class<?> clazz : CLASSES_BASE) { addClass(Data.class);
addClass(clazz); addClass(Media.class);
} addClass(Type.class);
addClass(Series.class);
addClass(Season.class);
addClass(User.class);
addClass(UserMediaAdvancement.class);
addAction(""" addAction("""
INSERT INTO `type` (`id`, `name`, `description`) VALUES INSERT INTO `type` (`id`, `name`, `description`) VALUES
(UUID_TO_BIN('15237fd7-d4ee-11ee-a8dd-02420a030203'), 'Documentary', 'Documentary (animals, space, earth...)'), (1, 'Documentary', 'Documentary (animals, space, earth...)'),
(UUID_TO_BIN('553146c1-d4ee-11ee-a8dd-02420a030203'), 'Movie', 'Movie with real humans (film)'), (2, 'Movie', 'Movie with real humans (film)'),
(UUID_TO_BIN('59c430a3-d4ee-11ee-a8dd-02420a030203'), 'Animation', 'Animation movies (film)'), (3, 'Animation', 'Animation movies (film)'),
(UUID_TO_BIN('5cd619e3-d4ee-11ee-a8dd-02420a030203'), 'Short movie', 'Small movies (less 2 minutes)'), (4, 'Short movie', 'Small movies (less 2 minutes)'),
(UUID_TO_BIN('5fbbf085-d4ee-11ee-a8dd-02420a030203'), 'TV show', 'TV show for old peoples'), (5, 'TV show', 'TV show for old peoples'),
(UUID_TO_BIN('66dcb6ba-d4ee-11ee-a8dd-02420a030203'), 'Animation TV show', 'TV show for young peoples'), (6, 'Animation TV show', 'TV show for young peoples'),
(UUID_TO_BIN('69ee5c15-d4ee-11ee-a8dd-02420a030203'), 'Theater', 'Theater play'), (7, 'Theater', 'Theater play'),
(UUID_TO_BIN('6ce72530-d4ee-11ee-a8dd-02420a030203'), 'One man show', 'Recorded stand up'), (8, 'One man show', 'Recorded stand up'),
(UUID_TO_BIN('6ff1691a-d4ee-11ee-a8dd-02420a030203'), 'Concert', 'Recorded concert'), (9, 'Concert', 'Recorded concert'),
(UUID_TO_BIN('730815ef-d4ee-11ee-a8dd-02420a030203'), 'Opera', 'Recorded opera'); (10, 'Opera', 'Recorded opera');
"""); """);
// set start increment element to permit to add after default elements // set start increment element to permit to add after default elements
addAction("""
ALTER TABLE `data` AUTO_INCREMENT = 1000;
""", "mysql");
addAction(""" addAction("""
ALTER TABLE `media` AUTO_INCREMENT = 1000; ALTER TABLE `media` AUTO_INCREMENT = 1000;
""", "mysql"); """, "mysql");
@ -67,25 +66,4 @@ public class Initialization extends MigrationSqlStep {
""", "mysql"); """, "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();
}
}
}
} }

View File

@ -1,137 +0,0 @@
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`);
""");
}
}

View File

@ -1,15 +0,0 @@
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;
}

View File

@ -1,12 +0,0 @@
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;
}

View File

@ -1,11 +0,0 @@
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;
}

View File

@ -1,60 +1,53 @@
package org.kar.karideo.model; package org.kar.karideo.model;
import java.util.List; 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.Data;
import org.kar.archidata.model.GenericDataSoftDelete; import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.FetchType; import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Entity @Entity
@Table(name = "media") @Table(name = "media")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
//@SQLDelete(sql = "UPDATE table_product SET deleted = true WHERE id=?")
//@Where(clause = "deleted=false")
public class Media extends GenericDataSoftDelete { public class Media extends GenericDataSoftDelete {
@Schema(description = "Name of the media (this represent the title)") // Name of the media (this represent the title)
@Column(nullable = false, length = 0) @Column(nullable = false, length = 0)
public String name; public String name;
@Schema(description = "Description of the media") // Description of the media
@Column(length = 0) @Column(length = 0)
public String description; public String description;
@Schema(description = "Foreign Key Id of the data") // Foreign Key Id of the data
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class)
@Column(nullable = false) @Column(nullable = false)
public UUID dataId; public Long dataId;
@Schema(description = "Type of the media") // Type of the media")
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
public Long typeId; public Long typeId;
@Schema(description = "Series reference of the media") // Series reference of the media
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
public Long seriesId; public Long seriesId;
@Schema(description = "Season reference of the media") // Saison reference of the media
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Season.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Season.class)
public Long seasonId; public Long seasonId;
@Schema(description = "Episode Id") // Episide Id
public Integer episode; public Integer episode;
// ") // ")
public Integer date; public Integer date;
@Schema(description = "Creation years of the media") // Creation years of the media
public Integer time; public Integer time;
@Schema(description = "Limitation Age of the media") // Limitation Age of the media
public Integer ageLimit; public Integer ageLimit;
@Schema(description = "List of Id of the specific covers") // List of Id of the specific covers
@DataJson(targetEntity = Data.class) @ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
public List<UUID> covers = null; public List<Long> 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 + "]";
}
} }

View File

@ -1,10 +1,9 @@
package org.kar.karideo.model; package org.kar.karideo.model;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete; import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
@ -12,6 +11,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.FetchType; import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@ -29,7 +29,7 @@ public class Season extends GenericDataSoftDelete {
@Schema(description = "series parent ID") @Schema(description = "series parent ID")
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
public Long parentId; public Long parentId;
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the sopecific covers")
@DataJson() @ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
public List<UUID> covers = null; public List<Long> covers = null;
} }

View File

@ -1,10 +1,9 @@
package org.kar.karideo.model; package org.kar.karideo.model;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete; import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
@ -12,6 +11,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.FetchType; import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@ -29,7 +29,7 @@ public class Series extends GenericDataSoftDelete {
@Schema(description = "series parent ID") @Schema(description = "series parent ID")
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
public Long parentId; public Long parentId;
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the sopecific covers")
@DataJson() @ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
public List<UUID> covers = null; public List<Long> covers = null;
} }

View File

@ -1,16 +1,17 @@
package org.kar.karideo.model; package org.kar.karideo.model;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete; import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Table(name = "type") @Table(name = "type")
@ -23,7 +24,7 @@ public class Type extends GenericDataSoftDelete {
@Column(length = 0) @Column(length = 0)
@Schema(description = "Description of the media") @Schema(description = "Description of the media")
public String description; public String description;
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the sopecific covers")
@DataJson() @ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
public List<UUID> covers = null; public List<Long> covers = null;
} }

View File

@ -1,7 +1,6 @@
package org.kar.karideo.model; package org.kar.karideo.model;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataNotRead;
import org.kar.archidata.model.GenericDataSoftDelete; import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
@ -16,22 +15,21 @@ import jakarta.persistence.Table;
@DataIfNotExists @DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class UserMediaAdvancement extends GenericDataSoftDelete { public class UserMediaAdvancement extends GenericDataSoftDelete {
@DataNotRead
@Column(nullable = false) @Column(nullable = false)
@Schema(description = "Foreign Key Id of the user") @Schema(description = "Foreign Key Id of the user")
@ManyToOne(fetch = FetchType.LAZY, targetEntity = UserKarideo.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = UserKarideo.class)
public Long userId; public long userId;
@Column(nullable = false) @Column(nullable = false)
@Schema(description = "Id of the media") @Schema(description = "Id of the media")
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Media.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Media.class)
public Long mediaId; public long mediaId;
@Column(nullable = false) @Column(nullable = false)
@Schema(description = "Percent of advancement in the media") @Schema(description = "Percent of admencement in the media")
public Float percent; public float percent;
@Column(nullable = false) @Column(nullable = false)
@Schema(description = "Number of second of advancement in the media") @Schema(description = "Number of second of admencement in the media")
public Integer time; public int time;
@Column(nullable = false) @Column(nullable = false)
@Schema(description = "Number of time this media has been read") @Schema(description = "Number of time this media has been read")
public Integer count; public int count;
} }

View File

@ -3,11 +3,11 @@ package org.kar.karideo.util;
public class ConfigVariable { public class ConfigVariable {
public static final String BASE_NAME = "ORG_KARIDEO_"; public static final String BASE_NAME = "ORG_KARIDEO_";
public static String getFrontFolder() { public static String getFrontFolder() {
String out = System.getenv(BASE_NAME + "FRONT_FOLDER"); String out = System.getenv(BASE_NAME + "FRONT_FOLDER");
if (out == null) { if (out == null) {
return "/application/front"; return "/application/front";
} }
return out; return out;
} }
} }

View File

@ -55,7 +55,7 @@ public class TestHealthCheck {
@Order(1) @Order(1)
@Test @Test
// @RepeatedTest(10) //@RepeatedTest(10)
public void checkHealthCheck() throws Exception { public void checkHealthCheck() throws Exception {
final HealthResult result = api.get(HealthResult.class, "health_check"); final HealthResult result = api.get(HealthResult.class, "health_check");
Assertions.assertEquals(result.value(), "alive and kicking"); Assertions.assertEquals(result.value(), "alive and kicking");

View File

@ -12,23 +12,17 @@ public class WebLauncherTest extends WebLauncher {
public WebLauncherTest() { public WebLauncherTest() {
LOGGER.debug("Configure REST system"); LOGGER.debug("Configure REST system");
// for local test: // for local test:
ConfigBaseVariable.apiAdress = "http://127.0.0.1:12342/test/api/"; ConfigBaseVariable.apiAdress = "http://127.0.0.1:12345/test/api/";
// Enable the test mode permit to access to the test token (never use it in production).
ConfigBaseVariable.testMode = "true"; ConfigBaseVariable.testMode = "true";
//ConfigBaseVariable.dbPort = "3306";
// for the test we a in memory sqlite.. // for the test we a in memory sqlite..
if (true) { ConfigBaseVariable.dbType = "sqlite";
if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { ConfigBaseVariable.dbHost = "memory";
ConfigBaseVariable.dbType = "sqlite"; // for test we need to connect all time the DB
ConfigBaseVariable.dbHost = "memory"; ConfigBaseVariable.dbKeepConnected = "true";
// for test we need to connect all time the DB
ConfigBaseVariable.dbKeepConnected = "true"; //ConfigBaseVariable.dbHost = "localhost";
} //ConfigBaseVariable.dbUser = "root";
} else { //ConfigBaseVariable.dbPassword = "ZERTYSDGFVHSDFGHJYZSDFGSQxfgsqdfgsqdrf4564654";
// 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";
}
} }
} }

View File

@ -1,117 +1,88 @@
{ {
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", "$schema" : "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1, "version" : 1,
"newProjectRoot": "projects", "newProjectRoot" : "projects",
"projects": { "defaultProject" : "karideo",
"karideo": { "projects" : {
"root": "", "karideo" : {
"sourceRoot": "src", "root" : "",
"projectType": "application", "sourceRoot" : "src",
"architect": { "projectType" : "application",
"build": { "architect" : {
"builder": "@angular-devkit/build-angular:browser", "build" : {
"options": { "builder" : "@angular-devkit/build-angular:browser",
"outputPath": "dist", "options" : {
"index": "src/index.html", "outputPath" : "dist",
"main": "src/main.ts", "index" : "src/index.html",
"tsConfig": "src/tsconfig.app.json", "main" : "src/main.ts",
"preserveSymlinks": true, "tsConfig" : "src/tsconfig.app.json",
"polyfills": [ "polyfills" : "src/polyfills.ts",
"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" ],
"assets": [ "scripts" : [ ]
"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": { "configurations" : {
"production": { "production" : {
"optimization": true, "optimization" : true,
"outputHashing": "all", "outputHashing" : "all",
"sourceMap": false, "sourceMap" : false,
"namedChunks": false, "namedChunks" : false,
"aot": true, "aot" : true,
"extractLicenses": true, "extractLicenses" : true,
"vendorChunk": false, "vendorChunk" : false,
"buildOptimizer": true, "buildOptimizer" : true,
"fileReplacements": [ "fileReplacements" : [ {
{ "replace" : "src/environments/environment.ts",
"replace": "src/environments/environment.ts", "with" : "src/environments/environment.prod.ts"
"with": "src/environments/environment.prod.ts" } ]
}
]
}, },
"develop": { "develop" : {
"optimization": false, "optimization" : false,
"outputHashing": "none", "outputHashing" : "none",
"namedChunks": true, "sourceMap" : true,
"aot": false, "namedChunks" : true,
"extractLicenses": true, "aot" : true,
"vendorChunk": true, "extractLicenses" : true,
"buildOptimizer": false, "vendorChunk" : true,
"sourceMap": { "buildOptimizer" : false
"scripts": true,
"styles": true,
"hidden": false,
"vendor": true
}
} }
} }
}, },
"serve": { "serve" : {
"builder": "@angular-devkit/build-angular:dev-server", "builder" : "@angular-devkit/build-angular:dev-server",
"options": { "options" : {
"buildTarget": "karideo:build" "browserTarget" : "karideo:build"
}, },
"configurations": { "configurations" : {
"production": { "production" : {
"buildTarget": "karideo:build:production" "browserTarget" : "karideo:build:production"
}, },
"develop": { "develop" : {
"buildTarget": "karideo:build:develop" "browserTarget" : "karideo:build:develop"
} }
} }
}, },
"extract-i18n": { "extract-i18n" : {
"builder": "@angular-devkit/build-angular:extract-i18n", "builder" : "@angular-devkit/build-angular:extract-i18n",
"options": { "options" : {
"buildTarget": "karideo:build" "browserTarget" : "karideo:build"
} }
}, },
"test": { "test" : {
"builder": "@angular-devkit/build-angular:karma", "builder" : "@angular-devkit/build-angular:karma",
"options": { "options" : {
"main": "src/test.ts", "main" : "src/test.ts",
"karmaConfig": "./karma.conf.js", "karmaConfig" : "./karma.conf.js",
"polyfills": [ "polyfills" : "src/polyfills.ts",
"zone.js" "tsConfig" : "src/tsconfig.spec.json",
], "scripts" : [ ],
"tsConfig": "src/tsconfig.spec.json", "styles" : [ "src/styles.less", "src/generic_page.less", "src/theme.color.blue.less", "src/theme.checkbox.less", "src/theme.modal.less" ],
"scripts": [], "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": { "lint" : {
"builder": "@angular-eslint/builder:lint", "builder" : "@angular-eslint/builder:lint",
"options": { "options" : {
"fix": true, "fix": true,
"eslintConfig": ".eslintrc.js", "eslintConfig": ".eslintrc.js",
"lintFilePatterns": [ "lintFilePatterns": [
@ -120,53 +91,44 @@
] ]
} }
}, },
"TTTTTTlint": { "TTTTTTlint" : {
"builder": "@angular-devkit/build-angular:tslint", "builder" : "@angular-devkit/build-angular:tslint",
"options": { "options" : {
"tsConfig": [ "tsConfig" : [ "src/tsconfig.app.json", "src/tsconfig.spec.json" ],
"src/tsconfig.app.json", "exclude" : [ "**/node_modules/**" ]
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
} }
} }
} }
}, },
"karideo-e2e": { "karideo-e2e" : {
"root": "e2e", "root" : "e2e",
"sourceRoot": "e2e", "sourceRoot" : "e2e",
"projectType": "application", "projectType" : "application",
"architect": { "architect" : {
"e2e": { "e2e" : {
"builder": "@angular-devkit/build-angular:protractor", "builder" : "@angular-devkit/build-angular:protractor",
"options": { "options" : {
"protractorConfig": "./protractor.conf.js", "protractorConfig" : "./protractor.conf.js",
"devServerTarget": "karideo:serve" "devServerTarget" : "karideo:serve"
} }
}, },
"lint": { "lint" : {
"builder": "@angular-devkit/build-angular:tslint", "builder" : "@angular-devkit/build-angular:tslint",
"options": { "options" : {
"tsConfig": [ "tsConfig" : [ "e2e/tsconfig.e2e.json" ],
"e2e/tsconfig.e2e.json" "exclude" : [ "**/node_modules/**" ]
],
"exclude": [
"**/node_modules/**"
]
} }
} }
} }
} }
}, },
"schematics": { "schematics" : {
"@schematics/angular:component": { "@schematics/angular:component" : {
"prefix": "app", "prefix" : "app",
"style": "less" "style" : "less"
}, },
"@schematics/angular:directive": { "@schematics/angular:directive" : {
"prefix": "app" "prefix" : "app"
} }
} }
} }

21757
front/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,45 +6,36 @@
"all": "npm run build && npm run test", "all": "npm run build && npm run test",
"ng": "ng", "ng": "ng",
"dev": "ng serve --configuration=develop --watch --port 4202", "dev": "ng serve --configuration=develop --watch --port 4202",
"dev-hot-update": "ng serve --configuration=develop --watch --hmr --port 4202",
"build": "ng build --prod", "build": "ng build --prod",
"test": "ng test", "test": "ng test",
"lint": "ng lint", "lint": "ng lint",
"style": "prettier --write .", "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, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^18.0.2", "@angular/animations": "^14.2.10",
"@angular/cdk": "^18.0.2", "@angular/cdk": "^14.2.7",
"@angular/common": "^18.0.2", "@angular/common": "^14.2.10",
"@angular/compiler": "^18.0.2", "@angular/compiler": "^14.2.10",
"@angular/core": "^18.0.2", "@angular/core": "^14.2.10",
"@angular/forms": "^18.0.2", "@angular/forms": "^14.2.10",
"@angular/material": "^18.0.2", "@angular/material": "^14.2.7",
"@angular/platform-browser": "^18.0.2", "@angular/platform-browser": "^14.2.10",
"@angular/platform-browser-dynamic": "^18.0.2", "@angular/platform-browser-dynamic": "^14.2.10",
"@angular/router": "^18.0.2", "@angular/router": "^14.2.10",
"rxjs": "^7.8.1", "rxjs": "^7.5.7",
"zone.js": "^0.14.6", "zone.js": "^0.12.0"
"zod": "3.23.8",
"@kangaroo-and-rabbit/kar-cw": "^0.4.1"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^18.0.3", "@angular-devkit/build-angular": "^14.2.9",
"@angular-eslint/builder": "18.0.1", "@angular-eslint/builder": "14.2.0",
"@angular-eslint/eslint-plugin": "18.0.1", "@angular-eslint/eslint-plugin": "14.2.0",
"@angular-eslint/eslint-plugin-template": "18.0.1", "@angular-eslint/eslint-plugin-template": "14.2.0",
"@angular-eslint/schematics": "18.0.1", "@angular-eslint/schematics": "14.2.0",
"@angular-eslint/template-parser": "18.0.1", "@angular-eslint/template-parser": "14.2.0",
"@angular/cli": "^18.0.3", "@angular/cli": "^14.2.9",
"@angular/compiler-cli": "^18.0.2", "@angular/compiler-cli": "^14.2.10",
"@angular/language-service": "^18.0.2", "@angular/language-service": "^14.2.10"
"npm-check-updates": "^16.14.20",
"tslib": "^2.6.3"
} }
} }

9816
front/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -6,10 +6,11 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; // CLI imports router 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 { HelpScene, HomeScene, SeasonEditScene, SeasonScene, SeriesEditScene, SeriesScene, SettingsScene, TypeScene, VideoEditScene, VideoScene } from './scene';
import { UploadScene } from './scene/upload/upload'; 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'; // import { HelpComponent } from './help/help.component';
// see https://angular.io/guide/router // see https://angular.io/guide/router

View File

@ -1,19 +1,15 @@
<!-- Generig global menu --> <!-- Generig global menu -->
<karcw-top-menu [menu]="currentMenu" (callback)="eventOnMenu($event)" /> <app-top-menu [menu]="currentMenu" (callback)="eventOnMenu($event)"></app-top-menu>
<!-- all interfaced pages --> <!-- all interfaced pages -->
@if(autoConnectedDone) { <div class="main-content" *ngIf="autoConnectedDone">
<div class="main-content"> <router-outlet ></router-outlet>
<router-outlet ></router-outlet> </div>
</div> <div class="main-content" *ngIf="!autoConnectedDone">
} <div class="generic-page">
@else { <div class="fill-all colomn_mutiple">
<div class="main-content"> <b style="color:red;">Auto-connection in progress</b>
<div class="generic-page"> <div class="clear"></div>
<div class="fill-all colomn_mutiple">
<b style="color:red;">Auto-connection in progress</b>
<div class="clear"></div>
</div>
</div> </div>
</div> </div>
} </div>

View File

@ -5,8 +5,12 @@
*/ */
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ArianeService, MediaService, SeasonService, SeriesService, TypeService } from './service'; import { EventOnMenu } from 'common/component/top-menu/top-menu';
import { EventOnMenu, MenuItem, MenuPosition, SSOService, SessionService, UserRoles222, UserService, isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw'; 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';
enum MenuEventType { enum MenuEventType {
SSO_LOGIN = "SSO_CALL_LOGIN", SSO_LOGIN = "SSO_CALL_LOGIN",
@ -34,11 +38,6 @@ export class AppComponent implements OnInit {
location: string = "home"; location: string = "home";
constructor( constructor(
private mediaService: MediaService,
private seasonService: SeasonService,
private seriesService: SeriesService,
private typeService: TypeService,
private userService: UserService, private userService: UserService,
private sessionService: SessionService, private sessionService: SessionService,
private ssoService: SSOService, private ssoService: SSOService,
@ -53,7 +52,7 @@ export class AppComponent implements OnInit {
this.updateMainMenu(); this.updateMainMenu();
let self = this; let self = this;
this.sessionService.change.subscribe((isConnected) => { this.sessionService.change.subscribe((isConnected) => {
console.log(`receive event from session ...${isConnected}`);
self.isConnected = isConnected; self.isConnected = isConnected;
self.autoConnectedDone = true; self.autoConnectedDone = true;
self.updateMainMenu(); self.updateMainMenu();
@ -68,10 +67,13 @@ export class AppComponent implements OnInit {
}); });
this.userService.checkAutoConnect().then(() => { this.userService.checkAutoConnect().then(() => {
console.log(` ==>>>>> Autoconnect THEN !!!`);
self.autoConnectedDone = true; self.autoConnectedDone = true;
}).catch(() => { }).catch(() => {
console.log(` ==>>>>> Autoconnect CATCH !!!`);
self.autoConnectedDone = true; self.autoConnectedDone = true;
}).finally(() => { }).finally(() => {
console.log(` ==>>>>> Autoconnect FINALLY !!!`);
self.autoConnectedDone = true; self.autoConnectedDone = true;
}); });
this.arianeService.segmentChange.subscribe((_segmentName: string) => { this.arianeService.segmentChange.subscribe((_segmentName: string) => {
@ -120,6 +122,7 @@ export class AppComponent implements OnInit {
} }
updateMainMenu(): void { updateMainMenu(): void {
console.log("update main menu :");
if (this.isConnected) { if (this.isConnected) {
this.currentMenu = [ this.currentMenu = [
{ {
@ -226,9 +229,11 @@ export class AppComponent implements OnInit {
}, },
]; ];
} }
console.log(" ==> DONE");
} }
getSegmentDisplayable(): string { getSegmentDisplayable(): string {
let segment = this.arianeService.getCurrentSegment(); let segment = this.arianeService.getCurrrentSegment();
if (segment === "type") { if (segment === "type") {
return "Type"; return "Type";
} }

View File

@ -5,7 +5,7 @@
*/ */
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
@ -20,24 +20,11 @@ import { PopInCreateType } from './popin/create-type/create-type';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { import {
HomeScene, HelpScene, TypeScene, SeriesScene, SeasonScene, VideoScene, SettingsScene, HomeScene, HelpScene, TypeScene, SeriesScene, SeasonScene, VideoScene, SettingsScene,
VideoEditScene, SeasonEditScene, SeriesEditScene, VideoEditScene, SeasonEditScene, SeriesEditScene
} from './scene'; } from './scene';
import { import { TypeService, DataService, SeriesService, SeasonService, VideoService, ArianeService, AdvancementService } from './service';
DataService,
AdvancementService,
MediaService,
SeasonService,
SeriesService,
TypeService,
ArianeService,
} from './service';
import { UploadScene } from './scene/upload/upload'; import { UploadScene } from './scene/upload/upload';
import { KarCWModule } from '@kangaroo-and-rabbit/kar-cw'; import { common_module_declarations, common_module_imports, common_module_providers, common_module_exports } from 'common/module';
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({ @NgModule({
declarations: [ declarations: [
@ -60,28 +47,24 @@ import { FileDragNDropDirective } from './scene/upload/file-drag-n-drop.directiv
SeasonEditScene, SeasonEditScene,
SeriesEditScene, SeriesEditScene,
UploadScene, UploadScene,
FileDragNDropDirective, ...common_module_declarations,
], ],
imports: [ imports: [
FormsModule,
ReactiveFormsModule,
CommonModule,
BrowserModule, BrowserModule,
RouterModule, RouterModule,
AppRoutingModule, AppRoutingModule,
HttpClientModule, HttpClientModule,
KarCWModule, ...common_module_imports,
], ],
providers: [ providers: [
{ provide: 'ENVIRONMENT', useValue: environment },
DataService,
AdvancementService,
MediaService,
SeasonService,
SeriesService,
TypeService, TypeService,
DataService,
SeriesService,
SeasonService,
VideoService,
ArianeService, ArianeService,
AdvancementService,
...common_module_providers,
], ],
exports: [ exports: [
AppComponent, AppComponent,
@ -90,10 +73,10 @@ import { FileDragNDropDirective } from './scene/upload/file-drag-n-drop.directiv
ElementSeasonComponent, ElementSeasonComponent,
ElementVideoComponent, ElementVideoComponent,
PopInCreateType, PopInCreateType,
...common_module_exports,
], ],
bootstrap: [ bootstrap: [
AppComponent AppComponent
], ]
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
}) })
export class AppModule { } export class AppModule { }

View File

@ -1,128 +0,0 @@
/**
* 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,
});
};
}

View File

@ -1,6 +0,0 @@
/**
* Interface of the server (auto-generated code)
*/
export namespace Front {
}

View File

@ -1,35 +0,0 @@
/**
* 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);
};
}

View File

@ -1,12 +0,0 @@
/**
* 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"

View File

@ -1,215 +0,0 @@
/**
* 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);
};
}

View File

@ -1,204 +0,0 @@
/**
* 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);
};
}

View File

@ -1,204 +0,0 @@
/**
* 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);
};
}

View File

@ -1,204 +0,0 @@
/**
* 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);
};
}

View File

@ -1,124 +0,0 @@
/**
* 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,
});
};
}

View File

@ -1,93 +0,0 @@
/**
* 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);
};
}

View File

@ -1,7 +0,0 @@
/**
* Interface of the server (auto-generated code)
*/
export * from "./model";
export * from "./api";
export * from "./rest-tools";

View File

@ -1,8 +0,0 @@
/**
* 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>;

View File

@ -1,46 +0,0 @@
/**
* 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;
}
}

View File

@ -1,46 +0,0 @@
/**
* 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;
}
}

View File

@ -1,48 +0,0 @@
/**
* 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;
}
}

View File

@ -1,35 +0,0 @@
/**
* 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;
}
}

View File

@ -1,24 +0,0 @@
/**
* 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"

View File

@ -1,35 +0,0 @@
/**
* 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;
}
}

View File

@ -1,8 +0,0 @@
/**
* 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>;

View File

@ -1,8 +0,0 @@
/**
* 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>;

View File

@ -1,8 +0,0 @@
/**
* 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>;

View File

@ -1,35 +0,0 @@
/**
* 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;
}
}

View File

@ -1,86 +0,0 @@
/**
* 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;
}
}

View File

@ -1,43 +0,0 @@
/**
* 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;
}
}

View File

@ -1,60 +0,0 @@
/**
* 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;
}
}

View File

@ -1,60 +0,0 @@
/**
* 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;
}
}

View File

@ -1,8 +0,0 @@
/**
* 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>;

View File

@ -1,55 +0,0 @@
/**
* 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;
}
}

View File

@ -1,42 +0,0 @@
/**
* 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;
}
}

View File

@ -1,65 +0,0 @@
/**
* 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;
}
}

View File

@ -1,38 +0,0 @@
/**
* 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;
}
}

View File

@ -1,53 +0,0 @@
/**
* 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;
}
}

View File

@ -1,8 +0,0 @@
/**
* 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>;

View File

@ -1,445 +0,0 @@
/** @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);
});
});
}

View File

@ -4,33 +4,32 @@
* @license PROPRIETARY (see license file) * @license PROPRIETARY (see license file)
*/ */
import { Component, OnInit, Input } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { UUID } from 'app/back-api';
//import { ModelResponseHttp } from '@app/service/http-wrapper'; //import { ModelResponseHttp } from '@app/service/http-wrapper';
import { DataService } from 'app/service/data'; import { DataService } from 'app/service/data';
@Component({ @Component({
selector: 'data-image', selector: 'data-image',
templateUrl: './data-image.html', templateUrl: './data-image.html',
styleUrls: ['./data-image.less'] styleUrls: [ './data-image.less' ]
}) })
export class ElementDataImageComponent implements OnInit { export class ElementDataImageComponent implements OnInit {
// input parameters // input parameters
@Input() id?: UUID; @Input() id:number = -1;
cover: string = ''; cover: string = '';
/* /*
imageCanvas:any; imageCanvas:any;
@ViewChild('imageCanvas') @ViewChild('imageCanvas')
set mainDivEl(el: ElementRef) { set mainDivEl(el: ElementRef) {
if(el !== null && el !== undefined) { if(el !== null && el !== undefined) {
this.imageCanvas = el.nativeElement; this.imageCanvas = el.nativeElement;
}
} }
*/ }
*/
constructor(private dataService: DataService) { constructor(private dataService: DataService) {
} }
ngOnInit() { ngOnInit() {
this.cover = this.dataService.getThumbnailUrl(this.id); this.cover = this.dataService.getCoverThumbnailUrl(this.id);
/* /*
let canvas = this.imageCanvas.nativeElement; let canvas = this.imageCanvas.nativeElement;
let ctx = canvas.getContext("2d"); let ctx = canvas.getContext("2d");

View File

@ -1,26 +1,19 @@
<div class="imgContainer-small"> <div class="imgContainer-small">
@if(covers) { <div *ngIf="covers">
<div> <!--<data-image id="{{cover}}"></data-image>-->
<!--<data-image id="{{cover}}"></data-image>--> <img src="{{covers[0]}}"/>
<img src="{{covers[0]}}"/> </div>
</div> <div *ngIf="!covers" class="noImage">
}
@else { </div>
<div class="noImage">
</div>
}
</div> </div>
<div class="season-small"> <div class="season-small">
Season {{numberSeason}} Season {{numberSeason}}
</div> </div>
@if(count > 0) { <div class="description-small" *ngIf="count > 1">
<div class="description-small"> {{count}} Episodes
{{count}} épisode{{count > 1?"s":""}} </div>
</div> <div class="description-small" *ngIf="count == 1">
} {{count}} Episode
@else { </div>
<div class="description-small">
Aucun épisode
</div>
}

View File

@ -3,20 +3,20 @@
* @copyright 2018, Edouard DUPIN, all right reserved * @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file) * @license PROPRIETARY (see license file)
*/ */
import { Component, OnInit, Input } from '@angular/core'; 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 { SeasonService, DataService } from 'app/service';
import { NodeData } from 'common/model';
import { isNullOrUndefined } from 'common/utils';
@Component({ @Component({
selector: 'app-element-season', selector: 'app-element-season',
templateUrl: './element-season.html', templateUrl: './element-season.html',
styleUrls: ['./element-season.less'] styleUrls: [ './element-season.less' ]
}) })
export class ElementSeasonComponent implements OnInit { export class ElementSeasonComponent implements OnInit {
// input parameters // input parameters
@Input() element: Season; @Input() element:NodeData;
numberSeason: string; numberSeason: string;
count: number; count: number;
@ -24,9 +24,8 @@ export class ElementSeasonComponent implements OnInit {
description: string; description: string;
constructor( constructor(
private dataService: DataService,
private seasonService: SeasonService, private seasonService: SeasonService,
) { private dataService: DataService) {
} }
ngOnInit() { ngOnInit() {
@ -37,7 +36,7 @@ export class ElementSeasonComponent implements OnInit {
} }
this.numberSeason = this.element.name; this.numberSeason = this.element.name;
this.description = this.element.description; this.description = this.element.description;
this.covers = this.dataService.getListThumbnailUrl(this.element.covers); this.covers = this.dataService.getCoverListThumbnailUrl(this.element.covers);
let self = this; let self = this;
this.seasonService.countVideo(this.element.id) this.seasonService.countVideo(this.element.id)
.then((response) => { .then((response) => {

View File

@ -1,24 +1,24 @@
<div> <div>
<div class="count-base"> <div class="count-base">
@if(countVideo) { <div class="count" *ngIf="countvideo">
<div class="count"> {{countvideo}}
{{countVideo}} </div>
</div>
}
</div> </div>
<div class="imgContainer-small"> <div class="imgContainer-small">
@if(covers) { <div *ngIf="covers">
<div> <!--<data-image id="{{cover}}"></data-image>-->
<!--<data-image id="{{cover}}"></data-image>--> <img src="{{covers[0]}}"/>
<img src="{{covers[0]}}"/> </div>
</div> <div *ngIf="!covers" class="noImage">
}
@else { </div>
<div class="noImage">
</div>
}
</div> </div>
<div class="title-small"> <div class="title-small">
{{name}} {{name}}
</div> </div>
<!--
<div class="description-small" *ngIf="description">
{{description}}
</div>
-->
</div> </div>

View File

@ -4,30 +4,29 @@
* @license PROPRIETARY (see license file) * @license PROPRIETARY (see license file)
*/ */
import { Component, OnInit, Input } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw'; import { NodeData } from 'common/model';
import { Series } from 'app/back-api'; import { isNullOrUndefined } from 'common/utils';
import { SeriesService, DataService } from 'app/service'; import { SeriesService, DataService } from 'app/service';
@Component({ @Component({
selector: 'app-element-series', selector: 'app-element-series',
templateUrl: './element-series.html', templateUrl: './element-series.html',
styleUrls: ['./element-series.less'] styleUrls: [ './element-series.less' ]
}) })
export class ElementSeriesComponent implements OnInit { export class ElementSeriesComponent implements OnInit {
// input parameters // input parameters
@Input() element: Series; @Input() element:NodeData;
name: string = 'plouf'; name:string = 'plouf';
description: string = ''; description:string = '';
countVideo: number = null; countvideo:number = null;
covers: string[]; covers:string[];
constructor( constructor(
private dataService: DataService,
private seriesService: SeriesService, private seriesService: SeriesService,
) { private dataService: DataService) {
} }
ngOnInit() { ngOnInit() {
@ -39,13 +38,13 @@ export class ElementSeriesComponent implements OnInit {
let self = this; let self = this;
self.name = this.element.name; self.name = this.element.name;
self.description = this.element.description; self.description = this.element.description;
self.covers = self.dataService.getListThumbnailUrl(this.element.covers); self.covers = self.dataService.getCoverListThumbnailUrl(this.element.covers);
this.seriesService.countVideo(this.element.id) this.seriesService.countVideo(this.element.id)
.then((response) => { .then((response) => {
self.countVideo = response; self.countvideo = response;
}).catch((response) => { }).catch((response) => {
self.countVideo = 0; self.countvideo = 0;
}); });
} }
} }

View File

@ -1,24 +1,18 @@
<div> <div>
<div class="count-base"> <div class="count-base">
@if(countVideo) { <span class="count" *ngIf="countvideo">
<span class="count"> {{countvideo}}
{{countVideo}} </span>
</span>
}
</div> </div>
<div class="imgContainer-small"> <div class="imgContainer-small">
@if(covers) { <div *ngIf="covers">
<div> <img src="{{covers[0]}}" class="miniature-small"/>
<img src="{{covers[0]}}" class="miniature-small"/> </div>
</div>
}
</div> </div>
<div class="title-small"> <div class="title-small">
{{name}} {{name}}
</div> </div>
@if(description) { <div class="description-small" *ngIf="description">
<div class="description-small"> {{description}}
{{description}} </div>
</div>
}
</div> </div>

View File

@ -4,51 +4,51 @@
* @license PROPRIETARY (see license file) * @license PROPRIETARY (see license file)
*/ */
import { Component, OnInit, Input } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw'; import { isArrayOf, isNullOrUndefined, isNumberFinite } from 'common/utils';
import { Type } from 'app/back-api'; import { NodeData } from 'common/model';
import { TypeService, DataService } from 'app/service'; import { TypeService, DataService } from 'app/service';
@Component({ @Component({
selector: 'app-element-type', selector: 'app-element-type',
templateUrl: './element-type.html', templateUrl: './element-type.html',
styleUrls: ['./element-type.less'] styleUrls: [ './element-type.less' ]
}) })
export class ElementTypeComponent implements OnInit { export class ElementTypeComponent implements OnInit {
// input parameters // input parameters
@Input() element: Type; @Input() element:NodeData;
public name: string = 'rr'; public name: string = 'rr';
public description: string; public description: string;
public countVideo: number; public countvideo:number;
public covers: string[]; public covers: string[];
constructor( constructor(
private dataService: DataService,
private typeService: TypeService, private typeService: TypeService,
) { private dataService: DataService) {
} }
ngOnInit() { ngOnInit() {
if (isNullOrUndefined(this.element)) { if (isNullOrUndefined(this.element)) {
this.name = 'Not a media'; this.name = 'Not a media';
this.description = undefined; this.description = undefined;
this.countVideo = undefined; this.countvideo = undefined;
this.covers = undefined; this.covers = undefined;
return; return;
} }
let self = this; let self = this;
console.log(" ??? Get element ! " + JSON.stringify(this.element));
self.name = this.element.name; self.name = this.element.name;
self.description = this.element.description; self.description = this.element.description;
self.covers = self.dataService.getListThumbnailUrl(this.element.covers); self.covers = self.dataService.getCoverListThumbnailUrl(this.element.covers);
this.typeService.countVideo(this.element.id) this.typeService.countVideo(this.element.id)
.then((response: number) => { .then((response: number) => {
self.countVideo = response; self.countvideo = response;
}).catch(() => { }).catch(() => {
self.countVideo = 0; self.countvideo = 0;
}); });
} }
} }

View File

@ -1,31 +1,28 @@
<div> <div>
<div class="count-base"> <div class="count-base">
@if(advancement) { <span class="views" *ngIf="advancement">
<span class="views"> {{advancement.count}}
{{advancement.count}} </span>
</span>
}
</div> </div>
<div class="videoImgContainer"> <div class="videoImgContainer">
@if(covers) { <div *ngIf="covers">
<div> <!--<data-image id="{{cover}}"></data-image>-->
<!--<data-image id="{{cover}}"></data-image>--> <img src="{{covers[0]}}" />
<img src="{{covers[0]}}" /> </div>
</div> <div *ngIf="!covers" class="noImage">
}
@else {
<div class="noImage">
</div> </div>
}
</div> </div>
<div class="view-progess" [ngStyle]="updateAdvancement()"></div> <div class="view-progess" [ngStyle]="updateAdvancement()"></div>
<div class="title-small"> <div class="title-small" *ngIf="data">
@if(data) { {{episodeDisplay}} {{name}}
{{episodeDisplay}} {{name}}
}
@else {
Error media: {{element?.id}}
}
</div> </div>
<div class="title-small" *ngIf="!data">
Error media: {{element?.id}}
</div>
<!--
<div class="description-small" *ngIf="description">
{{description}}
</div>
-->
</div> </div>

View File

@ -4,10 +4,12 @@
* @license PROPRIETARY (see license file) * @license PROPRIETARY (see license file)
*/ */
import { Injectable, Component, OnInit, Input } from '@angular/core'; import { Injectable, Component, OnInit, Input } from '@angular/core';
import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw'; import { isMedia, Media } from 'app/model';
import { Media, UserMediaAdvancement } from 'app/back-api'; import { UserMediaAdvancement } from 'app/model/user-media-advancement';
import { AdvancementService, DataService } from 'app/service'; import { AdvancementService, DataService } from 'app/service';
import { NodeData } from 'common/model';
import { isNullOrUndefined } from 'common/utils';
@Component({ @Component({
selector: 'app-element-video', selector: 'app-element-video',
@ -18,7 +20,7 @@ import { AdvancementService, DataService } from 'app/service';
@Injectable() @Injectable()
export class ElementVideoComponent implements OnInit { export class ElementVideoComponent implements OnInit {
// input parameters // input parameters
@Input() element: Media; @Input() element: NodeData;
data: Media; data: Media;
name: string = ''; name: string = '';
@ -36,6 +38,12 @@ export class ElementVideoComponent implements OnInit {
// nothing to do. // nothing to do.
} }
ngOnInit() { ngOnInit() {
if (!isMedia(this.element)) {
this.data = undefined;
this.name = 'Not a media';
this.description = undefined;
return;
}
this.data = this.element; this.data = this.element;
this.name = this.element.name; this.name = this.element.name;
this.description = this.element.description; this.description = this.element.description;
@ -44,7 +52,7 @@ export class ElementVideoComponent implements OnInit {
} else { } else {
this.episodeDisplay = `${this.element.episode} - `; this.episodeDisplay = `${this.element.episode} - `;
} }
this.covers = this.dataService.getListThumbnailUrl(this.element.covers); this.covers = this.dataService.getCoverListThumbnailUrl(this.element.covers);
this.advancementService.get(this.element.id) this.advancementService.get(this.element.id)
.then((response: UserMediaAdvancement) => { .then((response: UserMediaAdvancement) => {

View File

@ -0,0 +1,5 @@
import { Media, isMedia } from "./media";
export {
Media, isMedia,
}

View File

@ -0,0 +1,47 @@
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;
}

View File

@ -0,0 +1,37 @@
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;
}

View File

@ -4,12 +4,13 @@
* @license PROPRIETARY (see license file) * @license PROPRIETARY (see license file)
*/ */
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { PopInService } from '@kangaroo-and-rabbit/kar-cw';
import { PopInService } from 'common/service/popin';
@Component({ @Component({
selector: 'create-type', selector: 'create-type',
templateUrl: './create-type.html', templateUrl: './create-type.html',
styleUrls: ['./create-type.less'] styleUrls: [ './create-type.less' ]
}) })
export class PopInCreateType implements OnInit { export class PopInCreateType implements OnInit {
name: string = ''; name: string = '';
@ -25,14 +26,14 @@ export class PopInCreateType implements OnInit {
} }
eventPopUp(event: string): void { eventPopUp(event: string): void {
console.log(`GET event: ${event}`); console.log(`GET event: ${ event}`);
this.popInService.close('popin-create-type'); this.popInService.close('popin-create-type');
} }
updateNeedSend(): void { updateNeedSend():void {
} }
onName(value: any): void { onName(value:any):void {
if (value.length === 0) { if(value.length === 0) {
this.name = ''; this.name = '';
} else { } else {
this.name = value; this.name = value;
@ -40,8 +41,8 @@ export class PopInCreateType implements OnInit {
this.updateNeedSend(); this.updateNeedSend();
} }
onDescription(value: any): void { onDescription(value:any):void {
if (value.length === 0) { if(value.length === 0) {
this.description = ''; this.description = '';
} else { } else {
this.description = value; this.description = value;

View File

@ -3,11 +3,9 @@
Karideo Karideo
</div> </div>
<div class="fill-all colomn_mutiple"> <div class="fill-all colomn_mutiple">
@for (data of dataList; track data.id;) { <div *ngFor="let data of dataList" class="item-home" (click)="onSelectType($event, data.id)" (auxclick)="onSelectType($event, data.id)">
<div class="item-home" (click)="onSelectType($event, data.id)" (auxclick)="onSelectType($event, data.id)"> <app-element-type [element]="data"></app-element-type>
<app-element-type [element]="data"></app-element-type> </div>
</div>
}
<div class="clear"></div> <div class="clear"></div>
</div> </div>
</div> </div>

View File

@ -12,29 +12,31 @@ import { ArianeService } from 'app/service/ariane';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
templateUrl: './home.html', templateUrl: './home.html',
styleUrls: ['./home.less'] styleUrls: [ './home.less' ]
}) })
export class HomeScene implements OnInit { export class HomeScene implements OnInit {
dataList = []; dataList = [];
error = ''; error = '';
constructor(private typeService: TypeService, constructor(private typeService: TypeService,
private arianeService: ArianeService) { private arianeService: ArianeService) {
} }
ngOnInit() { ngOnInit() {
let self = this; let self = this;
this.typeService.gets() this.typeService.getData()
.then((response) => { .then((response) => {
self.error = ''; self.error = '';
self.dataList = response; self.dataList = response;
console.log(`Get response: ${ JSON.stringify(response, null, 2)}`);
}).catch((response) => { }).catch((response) => {
self.error = 'Wrong e-mail/login or password'; 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 = []; self.dataList = [];
}); });
this.arianeService.reset(); this.arianeService.reset();
} }
onSelectType(_event: any, _idSelected: number): void { onSelectType(_event: any, _idSelected: number):void {
this.arianeService.navigateType(_idSelected, _event.which === 2); this.arianeService.navigateType(_idSelected, _event.which === 2);
} }
} }

View File

@ -2,153 +2,138 @@
<div class="title"> <div class="title">
Edit season Edit season
</div> </div>
@if(itemIsRemoved) { <div class="fill-all" *ngIf="itemIsRemoved">
<div class="fill-all"> <div class="message-big">
<div class="message-big"> <br/><br/><br/>
<br/><br/><br/> The season has been removed
The season has been removed <br/><br/><br/>
<br/><br/><br/> </div>
</div>
<div class="fill-all" *ngIf="itemIsNotFound">
<div class="message-big">
<br/><br/><br/>
The season does not exist
<br/><br/><br/>
</div>
</div>
<div class="fill-all" *ngIf="itemIsLoading">
<div class="message-big">
<br/><br/><br/>
Loading ...<br/>
Please wait.
<br/><br/><br/>
</div>
</div>
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="request_raw">
<div class="label">
Number:
</div>
<div class="input">
<input type="number"
placeholder="Id of the season"
[value]="numberVal"
(input)="onNumber($event.target.value)"
/>
</div> </div>
</div> </div>
} <div class="request_raw">
@else if (itemIsNotFound){ <div class="label">
<div class="fill-all"> Description:
<div class="message-big"> </div>
<br/><br/><br/> <div class="input">
The season does not exist <input type="text"
<br/><br/><br/> placeholder="Description of the Media"
[value]="description"
(input)="onDescription($event.target.value)"/>
</div> </div>
</div> </div>
} <div class="send_value">
@else if (itemIsLoading){ <button class="button fill-x color-button-validate color-shadow-black" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button>
<div class="fill-all">
<div class="message-big">
<br/><br/><br/>
Loading ...<br/>
Please wait.
<br/><br/><br/>
</div>
</div> </div>
} <div class="clear"></div>
@else { </div>
<div class="fill-all"> <!-- ------------------------- Cover section --------------------------------- -->
<div class="request_raw"> <div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="label"> Covers
Number: </div>
</div> <div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="input"> <div class="hide-element">
<input type="number" <input type="file"
placeholder="Id of the season" #fileInput
[value]="numberVal" (change)="onChangeCover($event.target)"
(input)="onNumber($event.target.value)" placeholder="Select a cover file"
/> accept=".png,.jpg,.jpeg,.webp"/>
</div>
</div>
<div class="request_raw">
<div class="label">
Description:
</div>
<div class="input">
<input type="text"
placeholder="Description of the Media"
[value]="description"
(input)="onDescription($event.target.value)"/>
</div>
</div>
<div class="send_value">
<button class="button fill-x color-button-validate color-shadow-black" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button>
</div>
<div class="clear"></div>
</div> </div>
<!-- ------------------------- Cover section --------------------------------- --> <div class="request_raw">
<div class="title"> <div class="input">
Covers <div class="cover" *ngFor="let element of coversDisplay">
</div> <div class="cover-image">
<div class="fill-all"> <img src="{{element.url}}"/>
<div class="hide-element">
<input type="file"
#fileInput
(change)="onChangeCover($event.target)"
placeholder="Select a cover file"
accept=".png,.jpg,.jpeg,.webp"/>
</div>
<div class="request_raw">
<div class="input">
@for (data of coversDisplay; track data.id;) {
<div class="cover" >
<div class="cover-image">
<img src="{{data.url}}"/>
</div>
<div class="cover-button">
<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>
<div class="cover-button">
<button (click)="fileInput.click()">
<i class="material-icons button-add">add_circle_outline</i>
</button>
</div>
</div> </div>
</div> <div class="cover-button">
</div> <button (click)="removeCover(element.id)">
<div class="clear"></div> <i class="material-icons button-remove">highlight_off</i>
</div>
<!-- ------------------------- ADMIN section --------------------------------- -->
<div class="title">
Administration
</div>
<div class="fill-all">
<div class="request_raw">
<div class="label">
<i class="material-icons">data_usage</i> ID:
</div>
<div class="input">
{{idSeason}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
Videos:
</div>
<div class="input">
{{videoCount}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
<i class="material-icons">delete_forever</i> Trash:
</div>
@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> </button>
</div> </div>
} </div>
@else { <div class="cover">
<div class="input"> <div class="cover-no-image">
<i class="material-icons">new_releases</i> Can not remove season, video depending on it
</div> </div>
} <div class="cover-button">
<button (click)="fileInput.click()">
<i class="material-icons button-add">add_circle_outline</i>
</button>
</div>
</div>
</div> </div>
<div class="clear"></div>
</div> </div>
} <div class="clear"></div>
</div>
<!-- ------------------------- ADMIN section --------------------------------- -->
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
Administration
</div>
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="request_raw">
<div class="label">
<i class="material-icons">data_usage</i> ID:
</div>
<div class="input">
{{idSeason}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
Videos:
</div>
<div class="input">
{{videoCount}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
<i class="material-icons">delete_forever</i> Trash:
</div>
<div class="input" *ngIf="(videoCount == '0')">
<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')">
<i class="material-icons">new_releases</i> Can not remove season, video depending on it
</div>
</div>
<div class="clear"></div>
</div>
</div> </div>
<upload-progress [mediaTitle]="upload.labelMediaTitle" <upload-progress [mediaTitle]="upload.labelMediaTitle"
[mediaUploaded]="upload.mediaSendSize" [mediaUploaded]="upload.mediaSendSize"
[mediaSize]="upload.mediaSize" [mediaSize]="upload.mediaSize"
[result]="upload.result" [result]="upload.result"
[error]="upload.error" [error]="upload.error"></upload-progress>
(abort)="abortUpload()"></upload-progress>
<delete-confirm <delete-confirm
[comment]="confirmDeleteComment" [comment]="confirmDeleteComment"
[imageUrl]=confirmDeleteImageUrl [imageUrl]=confirmDeleteImageUrl

View File

@ -5,11 +5,13 @@
*/ */
import { Component, OnInit } from '@angular/core'; 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 { 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 { export interface ElementList {
value: number; value: number;
@ -30,11 +32,11 @@ export class SeasonEditScene implements OnInit {
error: string = ''; error: string = '';
numberVal: string = null; numberVal: number = null;
description: string = ''; description: string = '';
coverFile?: File; coverFile: File;
uploadFileValue: string = ''; uploadFileValue: string = '';
selectedFiles?: FileList; selectedFiles: FileList;
videoCount: string = null; videoCount: string = null;
@ -44,9 +46,8 @@ export class SeasonEditScene implements OnInit {
// --------------- confirm section ------------------ // --------------- confirm section ------------------
public confirmDeleteComment: string = null; public confirmDeleteComment: string = null;
public confirmDeleteImageUrl: string = null; public confirmDeleteImageUrl: string = null;
private deleteCoverId: UUID = null; private deleteCoverId: number = null;
private deleteItemId: number = null; private deleteItemId: number = null;
cancelHandle: RESTAbort = {};
deleteConfirmed() { deleteConfirmed() {
if (this.deleteCoverId !== null) { if (this.deleteCoverId !== null) {
this.removeCoverAfterConfirm(this.deleteCoverId); this.removeCoverAfterConfirm(this.deleteCoverId);
@ -66,11 +67,10 @@ export class SeasonEditScene implements OnInit {
constructor( constructor(
private dataService: DataService,
private seasonService: SeasonService, private seasonService: SeasonService,
private arianeService: ArianeService, private arianeService: ArianeService,
private popInService: PopInService, private popInService: PopInService,
) { private dataService: DataService) {
} }
@ -78,7 +78,7 @@ export class SeasonEditScene implements OnInit {
this.idSeason = this.arianeService.getSeasonId(); this.idSeason = this.arianeService.getSeasonId();
let self = this; let self = this;
this.seasonService.get(this.idSeason) this.seasonService.get(this.idSeason)
.then((response: Season) => { .then((response: NodeData) => {
console.log(`get response of season : ${JSON.stringify(response, null, 2)}`); console.log(`get response of season : ${JSON.stringify(response, null, 2)}`);
if (isNumberFinite(response.name)) { if (isNumberFinite(response.name)) {
self.numberVal = response.name; self.numberVal = response.name;
@ -108,7 +108,7 @@ export class SeasonEditScene implements OnInit {
for (let iii = 0; iii < covers.length; iii++) { for (let iii = 0; iii < covers.length; iii++) {
this.coversDisplay.push({ this.coversDisplay.push({
id: covers[iii], id: covers[iii],
url: this.dataService.getThumbnailUrl(covers[iii]) url: this.dataService.getCoverThumbnailUrl(covers[iii])
}); });
} }
} else { } else {
@ -126,7 +126,7 @@ export class SeasonEditScene implements OnInit {
sendValues(): void { sendValues(): void {
console.log('send new values....'); console.log('send new values....');
let data = { let data = {
name: `${this.numberVal}`, name: this.numberVal,
description: this.description description: this.description
}; };
if (this.description === undefined) { if (this.description === undefined) {
@ -149,10 +149,6 @@ export class SeasonEditScene implements OnInit {
event.preventDefault(); event.preventDefault();
} }
abortUpload(): void {
this.cancelHandle.abort();
}
// At the file input element // At the file input element
// (change)="selectFile($event)" // (change)="selectFile($event)"
onChangeCover(value: any): void { onChangeCover(value: any): void {
@ -172,10 +168,10 @@ export class SeasonEditScene implements OnInit {
this.upload.clear(); this.upload.clear();
// display the upload pop-in // display the upload pop-in
this.popInService.open('popin-upload-progress'); this.popInService.open('popin-upload-progress');
this.seasonService.uploadCover(this.idSeason, file, (count, total) => { this.seasonService.uploadCover(file, this.idSeason, (count, total) => {
self.upload.mediaSendSize = count; self.upload.mediaSendSize = count;
self.upload.mediaSize = total; self.upload.mediaSize = total;
}, this.cancelHandle) })
.then((response: any) => { .then((response: any) => {
self.upload.result = 'Cover added done'; self.upload.result = 'Cover added done';
// we retrive the whiole media ==> update data ... // we retrive the whiole media ==> update data ...
@ -186,14 +182,14 @@ export class SeasonEditScene implements OnInit {
}); });
} }
removeCover(id: UUID) { removeCover(id: number) {
this.cleanConfirm(); this.cleanConfirm();
this.confirmDeleteComment = `Delete the cover ID: ${id}`; this.confirmDeleteComment = `Delete the cover ID: ${id}`;
this.confirmDeleteImageUrl = this.dataService.getThumbnailUrl(id); this.confirmDeleteImageUrl = this.dataService.getCoverThumbnailUrl(id);
this.deleteCoverId = id; this.deleteCoverId = id;
this.popInService.open('popin-delete-confirm'); this.popInService.open('popin-delete-confirm');
} }
removeCoverAfterConfirm(id: UUID) { removeCoverAfterConfirm(id: number) {
console.log(`Request remove cover: ${id}`); console.log(`Request remove cover: ${id}`);
let self = this; let self = this;
this.seasonService.deleteCover(this.idSeason, id) this.seasonService.deleteCover(this.idSeason, id)

View File

@ -1,36 +1,29 @@
<div class="generic-page"> <div class="generic-page">
<div class="fill-title colomn_mutiple"> <div class="fill-title colomn_mutiple">
<div class="cover-area"> <div class="cover-area">
@if(cover) { <div class="cover" *ngIf="cover != null" >
<div class="cover"> <img src="{{cover}}"/>
<img src="{{cover}}"/> </div>
</div>
}
</div> </div>
<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'"> <div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
@if(seriesName) { <div *ngIf="seriesName" class="title">
<div class="title"> {{seriesName}}
{{seriesName}} </div>
</div>
}
<div class="sub-title-main"> <div class="sub-title-main">
Season {{name}} Season {{name}}
</div> </div>
@if(description) { <div class="description" *ngIf="description">
<div class="description"> {{description}}
{{description}} </div>
</div>
}
</div> </div>
</div> </div>
<div class="fill-content colomn_mutiple"> <div class="fill-content colomn_mutiple">
<div class="clear"></div> <div class="clear"></div>
<div class="title">Video{{videos.length > 1?"s":""}}:</div> <div class="title" *ngIf="videos.length > 1">Videos:</div>
@for (data of videos; track data.id;) { <div class="title" *ngIf="videos.length == 1">Video:</div>
<div class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)"> <div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)">
<app-element-video [element]="data"></app-element-video> <app-element-video [element]="data"></app-element-video>
</div> </div>
}
<div class="clear"></div> <div class="clear"></div>
</div> </div>
</div> </div>

View File

@ -24,12 +24,11 @@ export class SeasonScene implements OnInit {
videosError = ''; videosError = '';
videos = []; videos = [];
constructor( constructor(
private advancementService: AdvancementService,
private dataService: DataService,
private seasonService: SeasonService, private seasonService: SeasonService,
private seriesService: SeriesService, private seriesService: SeriesService,
private arianeService: ArianeService, private arianeService: ArianeService,
) { private dataService: DataService,
private advancementService: AdvancementService) {
} }
@ -47,9 +46,9 @@ export class SeasonScene implements OnInit {
self.cover = null; self.cover = null;
self.covers = []; self.covers = [];
} else { } else {
self.cover = self.dataService.getThumbnailUrl(response.covers[0]); self.cover = self.dataService.getCoverUrl(response.covers[0]);
for (let iii = 0; iii < response.covers.length; iii++) { for (let iii = 0; iii < response.covers.length; iii++) {
self.covers.push(self.dataService.getThumbnailUrl(response.covers[iii])); self.covers.push(self.dataService.getCoverUrl(response.covers[iii]));
} }
} }
self.seriesService.get(self.seriesId) self.seriesService.get(self.seriesId)

View File

@ -2,177 +2,160 @@
<div class="title"> <div class="title">
Edit series Edit series
</div> </div>
@if(itemIsRemoved) { <div class="fill-all" *ngIf="itemIsRemoved">
<div class="fill-all"> <div class="message-big">
<div class="message-big"> <br/><br/><br/>
<br/><br/><br/> The series has been removed
The series has been removed <br/><br/><br/>
<br/><br/><br/> </div>
</div>
<div class="fill-all" *ngIf="itemIsNotFound">
<div class="message-big">
<br/><br/><br/>
The series does not exist
<br/><br/><br/>
</div>
</div>
<div class="fill-all" *ngIf="itemIsLoading">
<div class="message-big">
<br/><br/><br/>
Loading ...<br/>
Please wait.
<br/><br/><br/>
</div>
</div>
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="request_raw">
<div class="label">
Type:
</div>
<div class="input">
<select [ngModel]="typeId"
(ngModelChange)="onChangeType($event)">
<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option>
</select>
</div> </div>
</div> </div>
} <div class="request_raw">
@else if(itemIsNotFound) { <div class="label">
<div class="fill-all"> Name:
<div class="message-big"> </div>
<br/><br/><br/> <div class="input">
The series does not exist <input type="text"
<br/><br/><br/> placeholder="Name of the Series"
[value]="name"
(input)="onName($event.target.value)"
/>
</div> </div>
</div> </div>
} <div class="request_raw">
@else if(itemIsLoading) { <div class="label">
<div class="fill-all"> Description:
<div class="message-big"> </div>
<br/><br/><br/> <div class="input">
Loading ...<br/> <input type="text"
Please wait. placeholder="Description of the Media"
<br/><br/><br/> [value]="description"
(input)="onDescription($event.target.value)"/>
</div> </div>
</div> </div>
} <div class="clear"></div>
@else { <div class="send_value">
<div class="fill-all"> <button class="button fill-x color-button-validate color-shadow-black" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button>
<div class="request_raw">
<div class="label">
Type:
</div>
<div class="input">
<select [ngModel]="typeId"
(ngModelChange)="onChangeType($event)">
@for (data of listType; track data.value;) {
<option [ngValue]="data.value">{{data.label}}</option>
}
</select>
</div>
</div>
<div class="request_raw">
<div class="label">
Name:
</div>
<div class="input">
<input type="text"
placeholder="Name of the Series"
[value]="name"
(input)="onName($event.target.value)"
/>
</div>
</div>
<div class="request_raw">
<div class="label">
Description:
</div>
<div class="input">
<input type="text"
placeholder="Description of the Media"
[value]="description"
(input)="onDescription($event.target.value)"/>
</div>
</div>
<div class="clear"></div>
<div class="send_value">
<button class="button fill-x color-button-validate color-shadow-black" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button>
</div>
<div class="clear"></div>
</div> </div>
<!-- ------------------------- Cover section --------------------------------- --> <div class="clear"></div>
<div class="title"> </div>
Covers <!-- ------------------------- Cover section --------------------------------- -->
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
Covers
</div>
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="hide-element">
<input type="file"
#fileInput
(change)="onChangeCover($event.target)"
placeholder="Select a cover file"
accept=".png,.jpg,.jpeg,.webp"/>
</div> </div>
<div class="fill-all"> <div class="request_raw">
<div class="hide-element"> <div class="input">
<input type="file" <div class="cover" *ngFor="let element of coversDisplay">
#fileInput <div class="cover-image">
(change)="onChangeCover($event.target)" <img src="{{element.url}}"/>
placeholder="Select a cover file"
accept=".png,.jpg,.jpeg,.webp"/>
</div>
<div class="request_raw">
<div class="input">
@for (data of coversDisplay; track data.id;) {
<div class="cover">
<div class="cover-image">
<img src="{{data.url}}"/>
</div>
<div class="cover-button">
<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>
<div class="cover-button">
<button (click)="fileInput.click()">
<i class="material-icons button-add">add_circle_outline</i>
</button>
</div>
</div> </div>
</div> <div class="cover-button">
</div> <button (click)="removeCover(element.id)">
<div class="clear"></div> <i class="material-icons button-remove">highlight_off</i>
</div>
<!-- ------------------------- ADMIN section --------------------------------- -->
<div class="title">
Administration
</div>
<div class="fill-all">
<div class="request_raw">
<div class="label">
<i class="material-icons">data_usage</i> ID:
</div>
<div class="input">
{{idSeries}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
Seasons:
</div>
<div class="input">
{{seasonsCount}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
Videos:
</div>
<div class="input">
{{videoCount}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
<i class="material-icons">delete_forever</i> Trash:
</div>
@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> </button>
</div> </div>
} </div>
@else { <div class="cover">
<div class="input"> <div class="cover-no-image">
<i class="material-icons">new_releases</i> Can not remove season or video depending on it
</div> </div>
} <div class="cover-button">
<button (click)="fileInput.click()">
<i class="material-icons button-add">add_circle_outline</i>
</button>
</div>
</div>
</div> </div>
<div class="clear"></div>
</div> </div>
} <div class="clear"></div>
</div>
<!-- ------------------------- ADMIN section --------------------------------- -->
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
Administration
</div>
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="request_raw">
<div class="label">
<i class="material-icons">data_usage</i> ID:
</div>
<div class="input">
{{idSeries}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
Seasons:
</div>
<div class="input">
{{seasonsCount}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
Videos:
</div>
<div class="input">
{{videoCount}}
</div>
</div>
<div class="clear"></div>
<div class="request_raw">
<div class="label">
<i class="material-icons">delete_forever</i> Trash:
</div>
<div class="input" *ngIf="(videoCount == '0' && seasonsCount == '0')">
<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')">
<i class="material-icons">new_releases</i> Can not remove season or video depending on it
</div>
</div>
<div class="clear"></div>
</div>
</div> </div>
<upload-progress [mediaTitle]="upload.labelMediaTitle" <upload-progress [mediaTitle]="upload.labelMediaTitle"
[mediaUploaded]="upload.mediaSendSize" [mediaUploaded]="upload.mediaSendSize"
[mediaSize]="upload.mediaSize" [mediaSize]="upload.mediaSize"
[result]="upload.result" [result]="upload.result"
[error]="upload.error" [error]="upload.error"></upload-progress>
(abort)="abortUpload()"></upload-progress>
<delete-confirm <delete-confirm
[comment]="confirmDeleteComment" [comment]="confirmDeleteComment"
[imageUrl]=confirmDeleteImageUrl [imageUrl]=confirmDeleteImageUrl

View File

@ -5,11 +5,10 @@
*/ */
import { Component, OnInit } from '@angular/core'; 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 { SeriesService, DataService, TypeService, ArianeService } from 'app/service';
import { UploadProgress } from 'common/popin/upload-progress/upload-progress';
import { PopInService } from 'common/service';
export class ElementList { export class ElementList {
constructor( constructor(
@ -54,9 +53,8 @@ export class SeriesEditScene implements OnInit {
// --------------- confirm section ------------------ // --------------- confirm section ------------------
public confirmDeleteComment: string = null; public confirmDeleteComment: string = null;
public confirmDeleteImageUrl: string = null; public confirmDeleteImageUrl: string = null;
private deleteCoverId: UUID = null; private deleteCoverId: number = null;
private deleteItemId: number = null; private deleteItemId: number = null;
cancelHandle: RESTAbort = {};
deleteConfirmed() { deleteConfirmed() {
if (this.deleteCoverId !== null) { if (this.deleteCoverId !== null) {
this.removeCoverAfterConfirm(this.deleteCoverId); this.removeCoverAfterConfirm(this.deleteCoverId);
@ -75,13 +73,11 @@ export class SeriesEditScene implements OnInit {
} }
constructor( constructor(private dataService: DataService,
private dataService: DataService,
private seriesService: SeriesService,
private typeService: TypeService, private typeService: TypeService,
private seriesService: SeriesService,
private arianeService: ArianeService, private arianeService: ArianeService,
private popInService: PopInService, private popInService: PopInService) {
) {
} }
@ -90,7 +86,7 @@ export class SeriesEditScene implements OnInit {
let self = this; let self = this;
this.listType = [{ value: null, label: '---' }]; this.listType = [{ value: null, label: '---' }];
this.typeService.gets() this.typeService.getData()
.then((response2) => { .then((response2) => {
for (let iii = 0; iii < response2.length; iii++) { for (let iii = 0; iii < response2.length; iii++) {
self.listType.push({ value: response2[iii].id, label: response2[iii].name }); self.listType.push({ value: response2[iii].id, label: response2[iii].name });
@ -131,17 +127,13 @@ export class SeriesEditScene implements OnInit {
}); });
} }
abortUpload(): void {
this.cancelHandle.abort();
}
updateCoverList(covers: any) { updateCoverList(covers: any) {
this.coversDisplay = []; this.coversDisplay = [];
if (covers !== undefined && covers !== null) { if (covers !== undefined && covers !== null) {
for (let iii = 0; iii < covers.length; iii++) { for (let iii = 0; iii < covers.length; iii++) {
this.coversDisplay.push({ this.coversDisplay.push({
id: covers[iii], id: covers[iii],
url: this.dataService.getThumbnailUrl(covers[iii]) url: this.dataService.getCoverThumbnailUrl(covers[iii])
}); });
} }
} else { } else {
@ -211,10 +203,10 @@ export class SeriesEditScene implements OnInit {
this.upload.clear(); this.upload.clear();
// display the upload pop-in // display the upload pop-in
this.popInService.open('popin-upload-progress'); this.popInService.open('popin-upload-progress');
this.seriesService.uploadCover(this.idSeries, file, (count, total) => { this.seriesService.uploadCover(file, this.idSeries, (count, total) => {
self.upload.mediaSendSize = count; self.upload.mediaSendSize = count;
self.upload.mediaSize = total; self.upload.mediaSize = total;
}, this.cancelHandle) })
.then((response: any) => { .then((response: any) => {
self.upload.result = 'Cover added done'; self.upload.result = 'Cover added done';
// we retrive the whiole media ==> update data ... // we retrive the whiole media ==> update data ...
@ -224,14 +216,14 @@ export class SeriesEditScene implements OnInit {
console.log('Can not add the cover in the video...'); console.log('Can not add the cover in the video...');
}); });
} }
removeCover(id: UUID) { removeCover(id: number) {
this.cleanConfirm(); this.cleanConfirm();
this.confirmDeleteComment = `Delete the cover ID: ${id}`; this.confirmDeleteComment = `Delete the cover ID: ${id}`;
this.confirmDeleteImageUrl = this.dataService.getThumbnailUrl(id); this.confirmDeleteImageUrl = this.dataService.getCoverThumbnailUrl(id);
this.deleteCoverId = id; this.deleteCoverId = id;
this.popInService.open('popin-delete-confirm'); this.popInService.open('popin-delete-confirm');
} }
removeCoverAfterConfirm(id: UUID) { removeCoverAfterConfirm(id: number) {
console.log(`Request remove cover: ${id}`); console.log(`Request remove cover: ${id}`);
let self = this; let self = this;
this.seriesService.deleteCover(this.idSeries, id) this.seriesService.deleteCover(this.idSeries, id)

View File

@ -1,44 +1,34 @@
<div class="generic-page"> <div class="generic-page">
<div class="fill-title colomn_mutiple"> <div class="fill-title colomn_mutiple">
<div class="cover-area"> <div class="cover-area">
@if(cover) { <div class="cover" *ngIf="cover != null" >
<div class="cover" > <img src="{{cover}}"/>
<img src="{{cover}}"/> </div>
</div>
}
</div> </div>
<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'"> <div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
<div class="title"> <div class="title">
{{name}} {{name}}
</div> </div>
@if(description) { <div class="description" *ngIf="description">
<div class="description"> {{description}}
{{description}} </div>
</div>
}
</div> </div>
</div> </div>
@if(seasons.length != 0) { <div class="fill-content colomn_mutiple" *ngIf="seasons.length != 0">
<div class="fill-content colomn_mutiple"> <div class="clear"></div>
<div class="clear"></div> <div class="title" *ngIf="seasons.length > 1">Seasons:</div>
<div class="title">Season{{seasons.length > 1?"s":""}}:</div> <div class="title" *ngIf="seasons.length == 1">Season:</div>
@for (data of seasons; track data.id;) { <div *ngFor="let data of seasons" class="item-list" (click)="onSelectSeason($event, data.id)" (auxclick)="onSelectSeason($event, data.id)">
<div class="item-list" (click)="onSelectSeason($event, data.id)" (auxclick)="onSelectSeason($event, data.id)"> <app-element-season [element]="data"></app-element-season>
<app-element-season [element]="data"></app-element-season>
</div>
}
</div> </div>
} </div>
@if(videos.length != 0) { <div class="fill-content colomn_mutiple" *ngIf="videos.length != 0">
<div class="fill-content colomn_mutiple"> <div class="clear"></div>
<div class="clear"></div> <div class="title" *ngIf="videos.length > 1">Videos:</div>
<div class="title">Video{{videos.length > 1?"s":""}}:</div> <div class="title" *ngIf="videos.length == 1">Video:</div>
@for (data of videos; track data.id;) { <div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, 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>
<app-element-video [element]="data"></app-element-video>
</div>
}
</div> </div>
} </div>
<div class="clear"></div> <div class="clear"></div>
</div> </div>

View File

@ -5,9 +5,9 @@
*/ */
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Season } from 'app/back-api';
import { SeriesService, DataService, ArianeService, AdvancementService } from 'app/service'; import { SeriesService, DataService, ArianeService, AdvancementService } from 'app/service';
import { NodeData } from 'common/model';
@Component({ @Component({
selector: 'app-series', selector: 'app-series',
@ -22,15 +22,14 @@ export class SeriesScene implements OnInit {
cover: string = ''; cover: string = '';
covers: Array<string> = []; covers: Array<string> = [];
seasonsError: string = ''; seasonsError: string = '';
seasons: Season[] = []; seasons: NodeData[] = [];
videosError: string = ''; videosError: string = '';
videos: Array<any> = []; videos: Array<any> = [];
constructor( constructor(
private advancementService: AdvancementService,
private dataService: DataService,
private seriesService: SeriesService, private seriesService: SeriesService,
private arianeService: ArianeService, private arianeService: ArianeService,
) { private dataService: DataService,
private advancementService: AdvancementService) {
} }
@ -52,9 +51,9 @@ export class SeriesScene implements OnInit {
self.cover = null; self.cover = null;
self.covers = []; self.covers = [];
} else { } else {
self.cover = self.dataService.getThumbnailUrl(response.covers[0]); self.cover = self.dataService.getCoverUrl(response.covers[0]);
for (let iii = 0; iii < response.covers.length; iii++) { for (let iii = 0; iii < response.covers.length; iii++) {
self.covers.push(self.dataService.getThumbnailUrl(response.covers[iii])); self.covers.push(self.dataService.getCoverUrl(response.covers[iii]));
} }
} }
updateEnded.seriesMetadata = true; updateEnded.seriesMetadata = true;
@ -64,32 +63,30 @@ export class SeriesScene implements OnInit {
self.name = '???'; self.name = '???';
self.cover = null; self.cover = null;
self.covers = []; self.covers = [];
// no check just ==> an error occurred on season // no check just ==> an error occured on season
}); });
console.log(`this.seriesService.getSeason(${this.idSeries})`); //console.log(`get parameter id: ${ this.idSeries}`);
this.seriesService.getSeason(this.idSeries) this.seriesService.getSeason(this.idSeries)
.then((response: Season[]) => { .then((response: NodeData[]) => {
console.log(`>>>> get season : ${JSON.stringify(response)}`) //console.log(`>>>> get season : ${JSON.stringify(response)}`)
self.seasonsError = ''; self.seasonsError = '';
self.seasons = response; self.seasons = response;
updateEnded.subSaison = true; updateEnded.subSaison = true;
self.checkIfJumpIsNeeded(updateEnded); self.checkIfJumpIsNeeded(updateEnded);
}).catch((response) => { }).catch((response) => {
console.log(`>>>> get season (FAIL) : ${JSON.stringify(response)}`)
self.seasonsError = 'Can not get the list of season in this series'; self.seasonsError = 'Can not get the list of season in this series';
self.seasons = []; self.seasons = [];
updateEnded.subSaison = true; updateEnded.subSaison = true;
self.checkIfJumpIsNeeded(updateEnded); self.checkIfJumpIsNeeded(updateEnded);
}); });
this.seriesService.getVideo(this.idSeries) this.seriesService.getVideo(this.idSeries)
.then((response: Season[]) => { .then((response: NodeData[]) => {
console.log(`>>>> get video : ${JSON.stringify(response)}`) //console.log(`>>>> get video : ${JSON.stringify(response)}`)
self.videosError = ''; self.videosError = '';
self.videos = response; self.videos = response;
updateEnded.subVideo = true; updateEnded.subVideo = true;
self.checkIfJumpIsNeeded(updateEnded); self.checkIfJumpIsNeeded(updateEnded);
}).catch((response) => { }).catch((response) => {
console.log(`>>>> get video (FAIL): ${JSON.stringify(response)}`)
self.videosError = 'Can not get the List of video without season'; self.videosError = 'Can not get the List of video without season';
self.videos = []; self.videos = [];
updateEnded.subVideo = true; updateEnded.subVideo = true;

View File

@ -1,38 +1,30 @@
<div class="generic-page"> <div class="generic-page">
<div class="fill-title colomn_mutiple"> <div class="fill-title colomn_mutiple">
<div class="cover-area"> <div class="cover-area">
@if(cover) { <div class="cover" *ngIf="cover != null" >
<div class="cover" > <img src="{{cover}}"/>
<img src="{{cover}}"/> </div>
</div>
}
</div> </div>
<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'"> <div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'">
<div class="title"> <div class="title">
{{name}} {{name}}
</div> </div>
@if(description) { <div class="description" *ngIf="description">
<div class="description"> {{description}}
{{description}} </div>
</div>
}
</div> </div>
</div> </div>
<div class="fill-content colomn_mutiple"> <div class="fill-content colomn_mutiple">
<div class="clear"></div> <div class="clear"></div>
@for (data of series; track data.id;) { <div *ngFor="let data of series" class="item" (click)="onSelectSeries($event, data.id)" (auxclick)="onSelectSeries($event, data.id)">
<div class="item" (click)="onSelectSeries($event, data.id)" (auxclick)="onSelectSeries($event, data.id)"> <app-element-series [element]="data"></app-element-series>
<app-element-series [element]="data"></app-element-series> </div>
</div>
}
</div> </div>
<div class="fill-content colomn_mutiple"> <div class="fill-content colomn_mutiple">
<div class="clear"></div> <div class="clear"></div>
@for (data of videos; track data.id;) { <div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, 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>
<app-element-video [element]="data"></app-element-video> </div>
</div>
}
</div> </div>
<div class="clear"></div> <div class="clear"></div>
</div> </div>

View File

@ -5,9 +5,9 @@
*/ */
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Series } from 'app/back-api'; import { ActivatedRoute } from '@angular/router';
import { TypeService, DataService, ArianeService, AdvancementService, SeriesService } from 'app/service'; import { TypeService, DataService, ArianeService, AdvancementService } from 'app/service';
@Component({ @Component({
selector: 'app-type', selector: 'app-type',
@ -26,10 +26,9 @@ export class TypeScene implements OnInit {
videosError = ''; videosError = '';
videos = []; videos = [];
constructor( constructor(
private dataService: DataService,
private typeService: TypeService, private typeService: TypeService,
private seriesService: SeriesService,
private arianeService: ArianeService, private arianeService: ArianeService,
private dateService: DataService,
private advancementService: AdvancementService) { private advancementService: AdvancementService) {
/* /*
@ -45,19 +44,19 @@ export class TypeScene implements OnInit {
ngOnInit() { ngOnInit() {
this.typeId = this.arianeService.getTypeId(); this.typeId = this.arianeService.getTypeId();
let self = this; let self = this;
//console.log(`get type global id: ${this.typeId}`); console.log(`get type global id: ${this.typeId}`);
this.typeService.get(this.typeId) this.typeService.get(this.typeId)
.then((response) => { .then((response) => {
self.name = response.name; self.name = response.name;
self.description = response.description; 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) { if (response.covers === undefined || response.covers === null || response.covers.length === 0) {
self.cover = null; self.cover = null;
self.covers = []; self.covers = [];
} else { } else {
self.cover = self.dataService.getThumbnailUrl(response.covers[0]); self.cover = self.dateService.getCoverUrl(response.covers[0]);
for (let iii = 0; iii < response.covers.length; iii++) { for (let iii = 0; iii < response.covers.length; iii++) {
self.covers.push(self.dataService.getThumbnailUrl(response.covers[iii])); self.covers.push(self.dateService.getCoverUrl(response.covers[iii]));
} }
} }
}).catch((response) => { }).catch((response) => {
@ -66,23 +65,23 @@ export class TypeScene implements OnInit {
self.covers = []; self.covers = [];
self.cover = null; self.cover = null;
}); });
this.seriesService.getSeriesWithType(this.typeId) this.typeService.getSubSeries(this.typeId)
.then((response: Series[]) => { .then((response) => {
//console.log(` ==> get answer sub-series: ${JSON.stringify(response)}`); console.log(` ==> get answer sub-series: ${JSON.stringify(response)}`);
self.seriessError = ''; self.seriessError = '';
self.series = response; self.series = response;
}).catch((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.seriessError = 'Wrong e-mail/login or password';
self.series = []; self.series = [];
}); });
this.typeService.getSubVideo(this.typeId) this.typeService.getSubVideo(this.typeId)
.then((response) => { .then((response) => {
//console.log(` ==> get answer sub-video: ${JSON.stringify(response)}`); console.log(` ==> get answer sub-video: ${JSON.stringify(response)}`);
self.videosError = ''; self.videosError = '';
self.videos = response; self.videos = response;
}).catch((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.videosError = 'Wrong e-mail/login or password';
self.videos = []; self.videos = [];
}); });

View File

@ -1,44 +0,0 @@
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);
}
}

View File

@ -3,205 +3,211 @@
Upload Media Upload Media
</div> </div>
<div class="clear"><br/></div> <div class="clear"><br/></div>
<div class="request_raw_table drop-area" fileDragDrop <div class="request_raw_table">
(filesChangeEmiter)="onChangeFile($event)"> <table>
<div class="clear"><br/></div> <colgroup>
<div class="centered"> <col style="width:10%">
<input type="file" name="file" id="file" (change)="onChangeFile($event.target.files)" multiple> <col style="width:80%">
<label for="file"><span class="textLink"><span class="material-icons">cloud_upload</span> Select your file</span> or <i>Drop it here!</i></label> </colgroup>
</div> <tbody>
<div class="clear"><br/></div> <tr>
<div class="centered"> <td class="left-colomn">format:</td>
The format of the media permit to automatic find meta-data:<br/> <td class="right-colomn">
Univers:Series name-sXX-eXX-my name of my media.mkv<br/> The format of the media permit to automatic find meta-data:<br/>
<b>example:</b> Stargate:SG1-s55-e22-Asgard.mkv <br/> Univers:Series name-sXX-eXX-my name of my media.mkv<br/>
</div> <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>
@if(parsedElement.length !== 0) {
<div class="title"> <div *ngIf="this.parsedElement.length !== 0" class="title">
Meta-data: Meta-data:
</div>
<div class="clear"><br/></div>
<div *ngIf="this.parsedElement.length !== 0" class="fill-all">
<div class="request_raw_table">
<table>
<colgroup>
<col style="width:10%">
<col style="width:70%">
<col style="width:10%">
</colgroup>
<tbody>
<tr>
<td class="left-colomn">Type:</td>
<td class="right-colomn">
<select [ngModel]="typeId"
(ngModelChange)="onChangeType($event)"
[class.error]="typeId === undefined">
<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option>
</select>
</td>
</tr>
<tr>
<td class="left-colomn">Series:</td>
<td class="right-colomn">
<input type="text"
placeholder="Series of the Media"
[value]="globalSeries"
(input)="onSeries($event.target.value)"
/>
</td>
</tr>
<tr>
<td class="left-colomn"></td>
<td class="right-colomn">
<select [ngModel]="seriesId"
(ngModelChange)="onChangeSeries($event)">
<option *ngFor="let element of listSeries" [ngValue]="element.value">{{element.label}}</option>
</select>
</td>
<td class="tool-colomn">
<!--
<button class="button color-button-normal color-shadow-black" (click)="newSeries()" type="submit">
<i class="material-icons">add_circle_outline</i>
</button>
-->
</td>
</tr>
<tr>
<td class="left-colomn">Season:</td>
<td class="right-colomn">
<input type="number"
pattern="[0-9]{0-4}"
placeholder="season of the Media"
[value]="globalSeason"
(input)="onSeason($event.target.value)"
/>
</td>
</tr>
</tbody>
</table>
</div> </div>
<div class="clear"><br/></div> <div class="clear"></div>
<div class="fill-all"> <div class="request_raw_table">
<div class="request_raw_table"> <table>
<table> <colgroup>
<colgroup>
<col style="width:10%"> <col style="width:10%">
<col style="width:70%"> <col style="width:70%">
<col style="width:10%"> <col style="width:10%">
</colgroup> </colgroup>
<tbody> <thead>
<tr> <tr>
<td class="left-colomn">Type:</td> <th>Episode ID:</th>
<td class="right-colomn"> <th>Episode Title:</th>
<select [ngModel]="typeId" </tr>
(ngModelChange)="onChangeType($event)" </thead>
[class.error]="typeId === undefined"> <tbody>
@for (data of listType; track data.value;) { <tr *ngFor="let data of this.parsedElement">
<option [ngValue]="data.value">{{data.label}}</option> <td class="left-colomn">
} <input type="number"
</select> pattern="[0-9]{0-4}"
</td> placeholder="e?"
</tr> [value]="data.episode"
<tr> (input)="onEpisode(data, $event.target.value)"
<td class="left-colomn">Series:</td> [class.error]="data.episodeDetected === true"
<td class="right-colomn"> />
<input type="text" </td>
placeholder="Series of the Media" <td class="right-colomn" >
[value]="globalSeries" <input type="text"
(input)="onSeries($event.target.value)" placeholder="Name of the Media"
/> [value]="data.title"
</td> (input)="onTitle(data, $event.target.value)"
</tr> [class.error]="data.title === ''"
<tr> />
<td class="left-colomn"></td> <span *ngIf="data.nameDetected === true" class="error">
<td class="right-colomn"> ^^^This title already exist !!!
<select [ngModel]="seriesId" </span>
(ngModelChange)="onChangeSeries($event)"> </td>
@for (data of listSeries; track data.value;) { <td class="tool-colomn" >
<option [ngValue]="data.value">{{data.label}}</option> <button class="button color-button-cancel color-shadow-black"
} (click)="removeElmentFromList(data, $event.target.value)"
</select> type="submit"
</td> alt="Delete">
<td class="tool-colomn"> <i class="material-icons">delete</i>
<!-- </button>
<button class="button color-button-normal color-shadow-black" (click)="newSeries()" type="submit"> </td>
<i class="material-icons">add_circle_outline</i> </tr>
</button> </tbody>
--> </table>
</td>
</tr>
<tr>
<td class="left-colomn">Season:</td>
<td class="right-colomn">
<input type="number"
pattern="[0-9]{0-4}"
placeholder="season of the Media"
[value]="globalSeason"
(input)="onSeason($event.target.value)"
/>
</td>
</tr>
</tbody>
</table>
</div>
<div class="clear"></div>
<div class="request_raw_table">
<table>
<colgroup>
<col style="width:10%">
<col style="width:70%">
<col style="width:10%">
</colgroup>
<thead>
<tr>
<th>Episode ID:</th>
<th>Episode Title:</th>
</tr>
</thead>
<tbody>
@for (data of parsedElement; track data.id;) {
<tr>
<td class="left-colomn">
<input type="number"
pattern="[0-9]{0-4}"
placeholder="e?"
[value]="data.episode"
(input)="onEpisode(data, $event.target.value)"
[class.error]="data.episodeDetected === true"
/>
</td>
<td class="right-colomn" >
<input type="text"
placeholder="Name of the Media"
[value]="data.title"
(input)="onTitle(data, $event.target.value)"
[class.error]="data.title === ''"
/>
@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"
(click)="removeElmentFromList(data, $event.target.value)"
type="submit"
alt="Delete">
<i class="material-icons">delete</i>
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="clear"></div>
<div class="send_value">
<button class="button fill-x color-button-validate color-shadow-black"
[disabled]="!needSend"
(click)="sendFile()"
type="submit">
<i class="material-icons">cloud_upload</i> Upload
</button>
</div>
<div class="clear"></div>
@if(listFileInBdd !== undefined) {
<div class="request_raw_table">
<table>
<colgroup>
<col style="width:10%">
<col style="width:70%">
<col style="width:10%">
</colgroup>
<thead>
<tr>
<th>Episode ID:</th>
<th>Episode Title:</th>
</tr>
</thead>
<tbody>
@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>
<div class="fill-all"> <div class="clear"></div>
<div class="request_raw_table"> <div class="send_value">
<table> <button class="button fill-x color-button-validate color-shadow-black"
<colgroup> [disabled]="!needSend"
(click)="sendFile()"
type="submit">
<i class="material-icons">cloud_upload</i> Upload
</button>
</div>
<div class="clear"></div>
<div class="request_raw_table" *ngIf="this.listFileInBdd !== undefined">
<table>
<colgroup>
<col style="width:10%"> <col style="width:10%">
<col style="width:80%"> <col style="width:70%">
</colgroup> <col style="width:10%">
<tbody> </colgroup>
@for (data of parsedFailedElement; track data.file;) { <thead>
<tr> <tr>
<td class="left-colomn">Rejected:</td> <th>Episode ID:</th>
<td class="right-colomn"> <th>Episode Title:</th>
{{data.file.name}}<br/> ==&gt; {{data.reason}} </tr>
</td> </thead>
</tr> <tbody>
} <tr *ngFor="let data of this.listFileInBdd">
</tbody> <td class="left-colomn" [class.error]="data.episodeDetected === true">{{data.episode}}</td>
</table> <td class="right-colomn" [class.error]="data.nameDetected === true">{{data.name}}</td>
</div> </tr>
</tbody>
</table>
</div> </div>
} </div>
<div *ngIf="this.parsedElement.length !== 0" class="fill-all">
<div class="request_raw_table">
<table>
<colgroup>
<col style="width:10%">
<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">
<td class="left-colomn">Rejected:</td>
<td class="right-colomn">
{{data.file.name}}<br/> ==&gt; {{data.reason}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div> </div>
<upload-progress <upload-progress [mediaTitle]="upload.labelMediaTitle"
[mediaTitle]="upload.labelMediaTitle"
[mediaUploaded]="upload.mediaSendSize" [mediaUploaded]="upload.mediaSendSize"
[mediaSize]="upload.mediaSize" [mediaSize]="upload.mediaSize"
[result]="upload.result" [result]="upload.result"
[error]="upload.error" [error]="upload.error"></upload-progress>
(abort)="abortUpload()"></upload-progress>
<!-- <!--
TODO: add a pop-in with: TODO: add a pop-in with:

View File

@ -1,79 +1,43 @@
.title { .title {
//background-color: green; //background-color: green;
font-size: 45px; font-size: 45px;
font-weight: bold; font-weight: bold;
line-height: 60px; line-height: 60px;
width: 100%; width:100%;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
margin: 10px 0 10px 0; margin: 10px 0 10px 0;
text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white; text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white;
text-transform: uppercase; text-transform: uppercase;
font-family: "Roboto", "Helvetica", "Arial", sans-serif; 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 { .request_raw_table {
display: block; display: block;
width: 90%; width: 90%;
margin: 0 auto; margin: 0 auto;
table { table {
width: 100%; width: 100%;
th { th {
text-align: left; text-align: left;
} }
.left-colomn { .left-colomn {
text-align: right; text-align: right;
font-weight: bold; font-weight: bold;
input { input {
width: 95%; width: 95%;
font-size: 20px; font-size: 20px;
border: 0px; border: 0px;
} }
} }
.right-colomn { .right-colomn {
input { input {
width: 95%; width: 95%;
font-size: 20px; font-size: 20px;
border: 0px; border: 0px;
} }
select { select {
width: 95%; width: 95%;
font-size: 20px; font-size: 20px;
@ -81,13 +45,11 @@ input[type="file"] {
} }
} }
} }
.error { .error {
border-color: rgba(200, 0, 0, 1.0); border-color: rgba(200,0,0,1.0);
background-color: rgba(256, 220, 220, 1.0); background-color: rgba(256,220,220,1.0);
} }
} }
.send_value { .send_value {
width: 300px; width: 300px;
margin: 0 auto; margin: 0 auto;

View File

@ -5,11 +5,11 @@
*/ */
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { PopInService, UploadProgress } from '@kangaroo-and-rabbit/kar-cw'; import { ActivatedRoute } from '@angular/router';
import { Series } from 'app/back-api';
import { RESTAbort } from 'app/back-api/rest-tools';
import { TypeService, SeriesService, MediaService, SeasonService } from 'app/service'; import { TypeService, SeriesService, VideoService, ArianeService, SeasonService } from 'app/service';
import { UploadProgress } from 'common/popin/upload-progress/upload-progress';
import { PopInService } from 'common/service';
export class ElementList { export class ElementList {
constructor( constructor(
@ -23,7 +23,6 @@ export class FileParsedElement {
public nameDetected: boolean = false; public nameDetected: boolean = false;
public episodeDetected: boolean = false; public episodeDetected: boolean = false;
constructor( constructor(
public id: number,
public file: File, public file: File,
public series: string, public series: string,
public season: number, public season: number,
@ -43,7 +42,7 @@ export class FileFailParsedElement {
@Component({ @Component({
selector: 'app-video-edit', selector: 'app-video-edit',
templateUrl: './upload.html', templateUrl: './upload.html',
styleUrls: ['./upload.less'] styleUrls: [ './upload.less' ]
}) })
export class UploadScene implements OnInit { export class UploadScene implements OnInit {
@ -53,14 +52,14 @@ export class UploadScene implements OnInit {
selectedFiles: FileList; selectedFiles: FileList;
typeId: number = null; typeId: number = null;
seriesId: number = null; seriesId: number = null;
seasonId: number = null; saisonId: number = null;
needSend: boolean = false; needSend: boolean = false;
// list of all files already registered in the bdd to compare with the current list of files. // list of all files already registered in the bdd to compare with the curent list of files.
listFileInBdd: any = null; listFileInBdd: any = null;
// section tha define the upload value to display in the pop-in of upload // section tha define the upload value to display in the pop-in of upload
public upload: UploadProgress = new UploadProgress(); public upload:UploadProgress = new UploadProgress();
listType: ElementList[] = [ listType: ElementList[] = [
{ value: null, label: '---' }, { value: null, label: '---' },
@ -68,21 +67,21 @@ export class UploadScene implements OnInit {
listSeries: ElementList[] = [ listSeries: ElementList[] = [
{ value: null, label: '---' }, { value: null, label: '---' },
]; ];
listSeries2 = [{ id: null, description: '---' }]; listSeries2 = [ { id: null, description: '---' } ];
/* /*
config = { config = {
displayKey: "label", // if objects array passed which key to be displayed defaults to description displayKey: "label", // if objects array passed which key to be displayed defaults to description
search: true, search: true,
limitTo: 3, limitTo: 3,
}; };
*/ */
config = { config = {
displayKey: 'description', // if objects array passed which key to be displayed defaults to description displayKey: 'description', // if objects array passed which key to be displayed defaults to description
search: true, // true/false for the search functionality defaults to false, search: true, // true/false for the search functionlity 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 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, 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, customComparator: () => {}, // a custom function using which user wants to sort the items. default is undefined and Array.sort() will be used in that case,
limitTo: 10, // number thats limits the no of options displayed in the UI (if zero, options will not be limited) limitTo: 10, // number thats limits the no of options displayed in the UI (if zero, options will not be limited)
moreText: 'more', // text to be displayed whenmore than one items are selected like Option 1 + 5 more moreText: 'more', // text to be displayed whenmore than one items are selected like Option 1 + 5 more
noResultsFound: 'No results found!', // text to be displayed when no items are found while searching noResultsFound: 'No results found!', // text to be displayed when no items are found while searching
@ -94,30 +93,26 @@ export class UploadScene implements OnInit {
]; ];
globalSeries: string = ''; globalSeries: string = '';
globalSeason: number = null; globalSeason: number = null;
cancelHandle: RESTAbort = {}; constructor(private typeService: TypeService,
dataUniqueId: number = 0;
constructor(
private MediaService: MediaService,
private seasonService: SeasonService,
private seriesService: SeriesService, private seriesService: SeriesService,
private typeService: TypeService, private seasonService: SeasonService,
private popInService: PopInService, private videoService: VideoService,
) { private popInService: PopInService) {
// nothing to do. // nothing to do.
} }
updateNeedSend(): boolean { updateNeedSend(): boolean {
if (this.parsedElement.length === 0) { if(this.parsedElement.length === 0) {
this.needSend = false; this.needSend = false;
return; return;
} }
this.needSend = true; this.needSend = true;
for (let iii = 0; iii < this.parsedElement.length; iii++) { for(let iii = 0; iii < this.parsedElement.length; iii++) {
if (this.parsedElement[iii].title === undefined || this.parsedElement[iii].title === null || this.parsedElement[iii].title === '') { if(this.parsedElement[iii].title === undefined || this.parsedElement[iii].title === null || this.parsedElement[iii].title === '') {
this.needSend = false; this.needSend = false;
} }
} }
if (this.typeId === undefined || this.typeId === null) { if(this.typeId === undefined || this.typeId === null) {
this.needSend = false; this.needSend = false;
} }
return this.needSend; return this.needSend;
@ -125,16 +120,16 @@ export class UploadScene implements OnInit {
ngOnInit() { ngOnInit() {
let self = this; let self = this;
this.listType = [{ value: null, label: '---' }]; this.listType = [ { value: null, label: '---' } ];
this.listSeries = [{ value: null, label: '---' }]; this.listSeries = [ { value: null, label: '---' } ];
this.listSeason = [{ value: null, label: '---' }]; this.listSeason = [ { value: null, label: '---' } ];
this.typeService.gets() this.typeService.getData()
.then((response2) => { .then((response2) => {
for (let iii = 0; iii < response2.length; iii++) { for(let iii = 0; iii < response2.length; iii++) {
self.listType.push({ value: response2[iii].id, label: response2[iii].name }); self.listType.push({ value: response2[iii].id, label: response2[iii].name });
} }
}).catch((response2) => { }).catch((response2) => {
console.log(`get response22 : ${JSON.stringify(response2, null, 2)}`); console.log(`get response22 : ${ JSON.stringify(response2, null, 2)}`);
}); });
console.log(' END INIT '); console.log(' END INIT ');
} }
@ -145,34 +140,34 @@ export class UploadScene implements OnInit {
} }
private updateType(value: any): void { private updateType(value: any): void {
console.log(`Change requested of type ... ${value}`); console.log(`Change requested of type ... ${ value}`);
if (this.typeId === value) { if(this.typeId === value) {
return; return;
} }
this.typeId = value; this.typeId = value;
// this.data.series_id = null; // this.data.series_id = null;
// this.data.season_id = null; // this.data.season_id = null;
this.listSeries = [{ value: null, label: '---' }]; this.listSeries = [ { value: null, label: '---' } ];
this.listSeason = [{ value: null, label: '---' }]; this.listSeason = [ { value: null, label: '---' } ];
let self = this; let self = this;
this.updateNeedSend(); this.updateNeedSend();
if (this.typeId !== null) { if(this.typeId !== null) {
self.seriesService.getSeriesWithType(this.typeId) self.typeService.getSubSeries(this.typeId)
.then((response2: Series[]) => { .then((response2) => {
for (let iii = 0; iii < response2.length; iii++) { for(let iii = 0; iii < response2.length; iii++) {
self.listSeries.push({ value: response2[iii].id, label: response2[iii].name }); self.listSeries.push({ value: response2[iii].id, label: response2[iii].name });
} }
}).catch((response2) => { }).catch((response2) => {
console.log(`get response22 : ${JSON.stringify(response2, null, 2)}`); console.log(`get response22 : ${ JSON.stringify(response2, null, 2)}`);
}); });
} }
} }
onChangeSeries(value: any): void { onChangeSeries(value: any): void {
this.seriesId = value; this.seriesId = value;
if (!(value === undefined || value === null)) { if(!(value === undefined || value === null)) {
for (let iii = 0; iii < this.listSeries.length; iii++) { for(let iii = 0; iii < this.listSeries.length; iii++) {
if (this.listSeries[iii].value === value) { if(this.listSeries[iii].value === value) {
this.globalSeries = this.listSeries[iii].label; this.globalSeries = this.listSeries[iii].label;
break; break;
} }
@ -193,8 +188,8 @@ export class UploadScene implements OnInit {
this.updateNeedSend(); this.updateNeedSend();
} }
removeElmentFromList(data: FileParsedElement, value: any): void { removeElmentFromList(data: FileParsedElement, value: any): void {
for (let iii = 0; iii < this.parsedElement.length; iii++) { for(let iii = 0; iii < this.parsedElement.length; iii++) {
if (this.parsedElement[iii] === data) { if(this.parsedElement[iii] === data) {
this.parsedElement.splice(iii, 1); this.parsedElement.splice(iii, 1);
break; break;
} }
@ -212,16 +207,16 @@ export class UploadScene implements OnInit {
onSeries(value: any): void { onSeries(value: any): void {
this.globalSeries = value; this.globalSeries = value;
let self = this; let self = this;
if (this.globalSeries !== '') { if(this.globalSeries !== '') {
this.seriesService.getLike(this.globalSeries) this.seriesService.getLike(this.globalSeries)
.then((response: any[]) => { .then((response: any[]) => {
console.log(`find element: ${response.length}`); console.log(`find element: ${ response.length}`);
for (let iii = 0; iii < response.length; iii++) { for(let iii = 0; iii < response.length; iii++) {
console.log(` - ${JSON.stringify(response[iii])}`); console.log(` - ${ JSON.stringify(response[iii])}`);
} }
if (response.length === 0) { if(response.length === 0) {
self.seriesId = null; self.seriesId = null;
} else if (response.length === 1) { } else if(response.length === 1) {
self.seriesId = response[0].id; self.seriesId = response[0].id;
} }
self.updateListOfVideoToCheck(); self.updateListOfVideoToCheck();
@ -243,9 +238,9 @@ export class UploadScene implements OnInit {
this.typeId = null; this.typeId = null;
this.seriesId = null; this.seriesId = null;
this.seasonId = null; this.saisonId = null;
this.listSeries = [{ value: null, label: '---' }]; this.listSeries = [ { value: null, label: '---' } ];
this.listSeason = [{ value: null, label: '---' }]; this.listSeason = [ { value: null, label: '---' } ];
} }
addFileWithMetaData(file: File) { addFileWithMetaData(file: File) {
@ -255,95 +250,96 @@ export class UploadScene implements OnInit {
let episode: number | null = null; let episode: number | null = null;
let title: string = ''; let title: string = '';
console.log(`select file ${file.name}`); console.log(`select file ${ file.name}`);
let tmpName = file.name.replace(/[ \t]*-[ \t]*/g, '-'); let tmpName = file.name.replace(/[ \t]*-[ \t]*/g, '-');
tmpName = tmpName.replace(/[Ss]([0-9]+)[- \t]+[Ee]([0-9]+)/g, '-s$1-e$2-'); tmpName = tmpName.replace(/[Ss]([0-9]+)[- \t]+[Ee]([0-9]+)/g, '-s$1-e$2-');
tmpName = tmpName.replace(/[Ee]([0-9]+)[- \t]+[Ss]([0-9]+)/g, '-s$2-e$1-'); tmpName = tmpName.replace(/[Ee]([0-9]+)[- \t]+[Ss]([0-9]+)/g, '-s$2-e$1-');
tmpName = tmpName.replace(/_/g, '-'); tmpName = tmpName.replace(/_/g, '-');
tmpName = tmpName.replace(/--/g, '-'); tmpName = tmpName.replace(/--/g, '-');
console.log(`select file ${tmpName}`); console.log(`select file ${ tmpName}`);
const splitElement = tmpName.split('-'); const splitElement = tmpName.split('-');
if (splitElement.length === 1) { if(splitElement.length === 1) {
title = splitElement[0]; title = splitElement[0];
} else { } else {
if (splitElement.length >= 2) { if(splitElement.length >= 2) {
series = splitElement[0]; series = splitElement[0];
} }
splitElement.splice(0, 1); splitElement.splice(0, 1);
if (splitElement.length === 1) { if(splitElement.length === 1) {
title = splitElement[0]; title = splitElement[0];
} else { } else {
while (splitElement.length > 0) { while(splitElement.length > 0) {
let element = splitElement[0]; let element = splitElement[0];
let find = false; let find = false;
if (season === null) { if(season === null) {
if (element.length >= 1 && (element[0] === 's' || element[0] === 'S')) { if(element.length >= 1 && (element[0] === 's' || element[0] === 'S')) {
element = element.substring(1); element = element.substring(1);
season = parseInt(element, 10); season = parseInt(element, 10);
find = true; find = true;
} }
} }
if (episode === null && find === false) { if(episode === null && find === false) {
if (element.length >= 1 && (element[0] === 'e' || element[0] === 'E')) { if(element.length >= 1 && (element[0] === 'e' || element[0] === 'E')) {
element = element.substring(1); element = element.substring(1);
episode = parseInt(element, 10); episode = parseInt(element, 10);
find = true; find = true;
} }
} }
if (find === false) { if(find === false) {
if (title === '') { if(title === '') {
title = element; title = element;
} else { } else {
title = `${title}-${element}`; title = `${title }-${ element}`;
} }
} }
splitElement.splice(0, 1); splitElement.splice(0, 1);
} }
} }
} }
if (isNaN(episode)) { if(isNaN(episode)) {
episode = null; episode = null;
} }
if (isNaN(season)) { if(isNaN(season)) {
season = null; season = null;
} }
// remove extension // remove extention
title = title.replace(new RegExp('\\.(mkv|MKV|Mkv|webm|WEBM|Webm|mp4)'), ''); title = title.replace(new RegExp('\\.(mkv|MKV|Mkv|webm|WEBM|Webm|mp4)'), '');
const tmp = new FileParsedElement(this.dataUniqueId++, file, series, season, episode, title); let tmp = new FileParsedElement(file, series, season, episode, title);
console.log(`==>${JSON.stringify(tmp)}`); console.log(`==>${ JSON.stringify(tmp)}`);
// add it in the list. // add it in the list.
this.parsedElement.push(tmp); this.parsedElement.push(tmp);
} }
// At the file input element // At the file input element
// (change)="selectFile($event)" // (change)="selectFile($event)"
onChangeFile(files: File[]): void { onChangeFile(value: any): void {
this.clearData(); this.clearData();
for (let iii = 0; iii < files.length; iii++) { for(let iii = 0; iii < value.files.length; iii++) {
this.addFileWithMetaData(files[iii]); this.addFileWithMetaData(value.files[iii]);
} }
// check if all global parameters are generic: // check if all global parameters are generic:
if (this.parsedElement.length === 0) { if(this.parsedElement.length === 0) {
this.updateNeedSend(); this.updateNeedSend();
return; return;
} }
// clean different series: // clean different series:
for (let iii = 1; iii < this.parsedElement.length; iii++) { for(let iii = 1; iii < this.parsedElement.length; iii++) {
console.log(`check series [${iii + 1}/${this.parsedElement.length}] '${this.parsedElement[0].series} !== ${this.parsedElement[iii].series}'`); console.log(`check series [${ iii + 1 }/${ this.parsedElement.length }] '${ this.parsedElement[0].series } !== ${ this.parsedElement[iii].series }'`);
if (this.parsedElement[0].series !== this.parsedElement[iii].series) { if(this.parsedElement[0].series !== this.parsedElement[iii].series) {
this.parsedFailedElement.push(new FileFailParsedElement(this.parsedElement[iii].file, 'Remove from list due to wrong series value')); this.parsedFailedElement.push(new FileFailParsedElement(this.parsedElement[iii].file, 'Remove from list due to wrong series value'));
console.log(`Remove from list (!= series) : [${iii + 1}/${this.parsedElement.length}] '${this.parsedElement[iii].file.name}'`); console.log(`Remove from list (!= series) : [${ iii + 1 }/${ this.parsedElement.length }] '${ this.parsedElement[iii].file.name }'`);
this.parsedElement.splice(iii, 1); this.parsedElement.splice(iii, 1);
iii--; iii--;
} }
} }
// clean different season: // clean different season:
for (let iii = 1; iii < this.parsedElement.length; iii++) { for(let iii = 1; iii < this.parsedElement.length; iii++) {
console.log(`check season [${iii + 1}/${this.parsedElement.length}] '${this.parsedElement[0].season} !== ${this.parsedElement[iii].season}'`); console.log(`check season [${ iii + 1 }/${ this.parsedElement.length }] '${ this.parsedElement[0].season } !== ${ this.parsedElement[iii].season }'`);
if (this.parsedElement[0].season !== this.parsedElement[iii].season) { if(this.parsedElement[0].season !== this.parsedElement[iii].season) {
this.parsedFailedElement.push(new FileFailParsedElement(this.parsedElement[iii].file, 'Remove from list due to wrong season value')); this.parsedFailedElement.push(new FileFailParsedElement(this.parsedElement[iii].file, 'Remove from list due to wrong season value'));
console.log(`Remove from list (!= season) : [${iii + 1}/${this.parsedElement.length}] '${this.parsedElement[iii].file.name}'`); console.log(`Remove from list (!= season) : [${ iii + 1 }/${ this.parsedElement.length }] '${ this.parsedElement[iii].file.name }'`);
this.parsedElement.splice(iii, 1); this.parsedElement.splice(iii, 1);
iii--; iii--;
} }
@ -354,21 +350,21 @@ export class UploadScene implements OnInit {
this.updateNeedSend(); this.updateNeedSend();
this.seriesId = null; this.seriesId = null;
this.seasonId = null; this.saisonId = null;
let self = this; let self = this;
if (this.globalSeries !== '') { if(this.globalSeries !== '') {
this.seriesService.getLike(this.globalSeries) this.seriesService.getLike(this.globalSeries)
.then((response: any[]) => { .then((response: any[]) => {
console.log(`find element: ${response.length}`); console.log(`find element: ${ response.length}`);
for (let iii = 0; iii < response.length; iii++) { for(let iii = 0; iii < response.length; iii++) {
console.log(` - ${JSON.stringify(response[iii])}`); console.log(` - ${ JSON.stringify(response[iii])}`);
} }
if (response.length === 0) { if(response.length === 0) {
self.seriesId = null; self.seriesId = null;
} else if (response.length === 1) { } else if(response.length === 1) {
let seriesElem = response[0]; let serieElem = response[0];
self.seriesId = seriesElem.id; self.seriesId = serieElem.id;
self.updateType(seriesElem.parentId); self.updateType(serieElem.parentId);
} }
self.updateListOfVideoToCheck(); self.updateListOfVideoToCheck();
}).catch((response) => { }).catch((response) => {
@ -379,7 +375,7 @@ export class UploadScene implements OnInit {
sendFile(): void { sendFile(): void {
console.log(`Send file requested ... ${this.parsedElement.length}`); console.log(`Send file requested ... ${ this.parsedElement.length}`);
this.upload = new UploadProgress(); this.upload = new UploadProgress();
// display the upload pop-in // display the upload pop-in
this.popInService.open('popin-upload-progress'); this.popInService.open('popin-upload-progress');
@ -390,110 +386,108 @@ export class UploadScene implements OnInit {
let self = this; let self = this;
this.uploadFile(this.parsedElement[id], id, total, () => { this.uploadFile(this.parsedElement[id], id, total, () => {
let id2 = id + 1; let id2 = id + 1;
if (id2 < total) { if(id2 < total) {
self.globalUpLoad(id2, total); self.globalUpLoad(id2, total);
} else { } else {
self.upload.result = 'Media creation done'; self.upload.result = 'Media creation done';
} }
}, (value: string) => { }, (value:string) => {
console.log("Detect error from serveur ...********************"); self.upload.error = `Error in the upload of the data...${ value}`;
self.upload.error = `Error in the upload of the data...${value}`;
}); });
} }
uploadFile(element: FileParsedElement, id: number, total: number, sendDone: () => void, errorOccurred: (string) => void): void { uploadFile(eleemnent: FileParsedElement, id: number, total: number, sendDone: any, errorOccured: any): void {
let self = this; let self = this;
self.upload.labelMediaTitle = ''; self.upload.labelMediaTitle = '';
// add series // add series
if (self.globalSeries !== null) { if(self.globalSeries !== null) {
if (self.upload.labelMediaTitle.length !== 0) { if(self.upload.labelMediaTitle.length !== 0) {
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}:`; self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }:`;
} }
self.upload.labelMediaTitle = self.upload.labelMediaTitle + self.globalSeries; self.upload.labelMediaTitle = self.upload.labelMediaTitle + self.globalSeries;
} }
// add season // add season
if (self.globalSeason !== null && self.globalSeason !== undefined && self.globalSeason.toString().length !== 0) { if(self.globalSeason !== null && self.globalSeason !== undefined && self.globalSeason.toString().length !== 0) {
if (self.upload.labelMediaTitle.length !== 0) { if(self.upload.labelMediaTitle.length !== 0) {
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}-`; self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }-`;
} }
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}s${self.globalSeason.toString()}`; self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }s${ self.globalSeason.toString()}`;
} }
// add episode ID // add episode ID
if (element.episode !== null && element.episode !== undefined && element.episode.toString().length !== 0) { if(eleemnent.episode !== null && eleemnent.episode !== undefined && eleemnent.episode.toString().length !== 0) {
if (self.upload.labelMediaTitle.length !== 0) { if(self.upload.labelMediaTitle.length !== 0) {
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}-`; self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }-`;
} }
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}e${element.episode.toString()}`; self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }e${ eleemnent.episode.toString()}`;
} }
// add title // add title
if (self.upload.labelMediaTitle.length !== 0) { if(self.upload.labelMediaTitle.length !== 0) {
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}-`; self.upload.labelMediaTitle = `${self.upload.labelMediaTitle }-`;
} }
self.upload.labelMediaTitle = `[${id + 1}/${total}]${self.upload.labelMediaTitle}${element.title}`; self.upload.labelMediaTitle = `[${ id + 1 }/${ total }]${ self.upload.labelMediaTitle }${eleemnent.title}`;
self.MediaService.uploadFile(element.file, self.videoService.uploadFile(eleemnent.file,
self.globalSeries, self.globalSeries,
self.seriesId, self.seriesId,
self.globalSeason, self.globalSeason,
element.episode, eleemnent.episode,
element.title, eleemnent.title,
self.typeId, self.typeId,
(count, totalTmp) => { (count, totalTmp) => {
// console.log("upload : " + count*100/totalTmp); // console.log("upload : " + count*100/totalTmp);
self.upload.mediaSendSize = count; self.upload.mediaSendSize = count;
self.upload.mediaSize = totalTmp; self.upload.mediaSize = totalTmp;
}, this.cancelHandle)
.then((response) => {
console.log(`get response of video : ${JSON.stringify(response, null, 2)}`);
sendDone();
}) })
.catch((response) => { .then((response) => {
// self.error = "Can not get the data"; console.log(`get response of video : ${ JSON.stringify(response, null, 2)}`);
sendDone();
}).catch((response) => {
// self.error = "Can not get the data";
console.log('Can not add the data in the system...'); console.log('Can not add the data in the system...');
errorOccurred(JSON.stringify(response, null, 2)); errorOccured(JSON.stringify(response, null, 2));
}); });
} }
public checkSimilarString(valueA: string, valueB: string): boolean { public checkSimilarString(valueA:string, valueB:string): boolean {
let valueAL = valueA.toLowerCase(); let valueAL = valueA.toLowerCase();
let valueBL = valueB.toLowerCase(); let valueBL = valueB.toLowerCase();
valueAL = valueAL.replace(/[ \t\n\r-_#~@]/g, ''); valueAL = valueAL.replace(/[ \t\n\r-_#~@]/g, '');
valueBL = valueBL.replace(/[ \t\n\r-_#~@]/g, ''); valueBL = valueBL.replace(/[ \t\n\r-_#~@]/g, '');
if (valueAL === valueBL) { if(valueAL === valueBL) {
return true; return true;
} }
if (valueAL.startsWith(valueBL)) { if(valueAL.startsWith(valueBL)) {
return true; return true;
} }
if (valueBL.startsWith(valueAL)) { if(valueBL.startsWith(valueAL)) {
return true; return true;
} }
return false; return false;
} }
checkConcordence(): void { checkConcordence():void {
if (this.parsedElement === null) { if(this.parsedElement === null) {
return; return;
} }
// ckear checker // ckear checker
for (let iii = 0; iii < this.parsedElement.length; iii++) { for(let iii = 0; iii < this.parsedElement.length; iii++) {
this.parsedElement[iii].nameDetected = false; this.parsedElement[iii].nameDetected = false;
this.parsedElement[iii].episodeDetected = false; this.parsedElement[iii].episodeDetected = false;
} }
if (this.listFileInBdd === null) { if(this.listFileInBdd === null) {
return; return;
} }
for (let iii = 0; iii < this.listFileInBdd.length; iii++) { for(let iii = 0; iii < this.listFileInBdd.length; iii++) {
this.listFileInBdd[iii].nameDetected = false; this.listFileInBdd[iii].nameDetected = false;
this.listFileInBdd[iii].episodeDetected = false; this.listFileInBdd[iii].episodeDetected = false;
} }
for (let iii = 0; iii < this.parsedElement.length; iii++) { for(let iii = 0; iii < this.parsedElement.length; iii++) {
for (let jjj = 0; jjj < this.listFileInBdd.length; jjj++) { for(let jjj = 0; jjj < this.listFileInBdd.length; jjj++) {
if (this.checkSimilarString(this.parsedElement[iii].title, this.listFileInBdd[jjj].name)) { if(this.checkSimilarString(this.parsedElement[iii].title, this.listFileInBdd[jjj].name)) {
this.parsedElement[iii].nameDetected = true; this.parsedElement[iii].nameDetected = true;
this.listFileInBdd[jjj].nameDetected = true; this.listFileInBdd[jjj].nameDetected = true;
} }
if (this.parsedElement[iii].episode === this.listFileInBdd[jjj].episode) { if(this.parsedElement[iii].episode === this.listFileInBdd[jjj].episode) {
this.parsedElement[iii].episodeDetected = true; this.parsedElement[iii].episodeDetected = true;
this.listFileInBdd[jjj].episodeDetected = true; this.listFileInBdd[jjj].episodeDetected = true;
} }
@ -503,13 +497,13 @@ export class UploadScene implements OnInit {
updateListOfVideoToCheck(): void { updateListOfVideoToCheck(): void {
// No series ID set ==> nothing to do. // No series ID set ==> nothing to do.
if (this.seriesId === null) { if(this.seriesId === null) {
this.listFileInBdd = null; this.listFileInBdd = null;
return; return;
} }
let self = this; let self = this;
// no season check only the series files. // no season check only the series files.
if (this.globalSeason === null) { if(this.globalSeason === null) {
self.seriesService.getVideo(self.seriesId) self.seriesService.getVideo(self.seriesId)
.then((response: any[]) => { .then((response: any[]) => {
self.listFileInBdd = response; self.listFileInBdd = response;
@ -524,22 +518,22 @@ export class UploadScene implements OnInit {
return; return;
} }
self.seasonId = null; self.saisonId = null;
// set 1 find the ID of the season: // set 1 find the ID of the season:
this.seriesService.getSeason(this.seriesId) this.seriesService.getSeason(this.seriesId)
.then((response: any[]) => { .then((response: any[]) => {
// console.log("find season: " + response.length); // console.log("find season: " + response.length);
for (let iii = 0; iii < response.length; iii++) { for(let iii = 0; iii < response.length; iii++) {
// console.log(" - " + JSON.stringify(response[iii]) + 'compare with : ' + JSON.stringify(self.globalSeason)); // console.log(" - " + JSON.stringify(response[iii]) + 'compare with : ' + JSON.stringify(self.globalSeason));
if (response[iii].name === `${self.globalSeason}`) { if(response[iii].name === `${self.globalSeason}`) {
self.seasonId = response[iii].id; self.saisonId = response[iii].id;
break; break;
} }
} }
if (self.seasonId === null) { if(self.saisonId === null) {
return; return;
} }
self.seasonService.getVideo(self.seasonId) self.seasonService.getVideo(self.saisonId)
.then((response2: any[]) => { .then((response2: any[]) => {
self.listFileInBdd = response2; self.listFileInBdd = response2;
// console.log("find video: " + response2.length); // console.log("find video: " + response2.length);
@ -555,20 +549,16 @@ export class UploadScene implements OnInit {
}); });
} }
abortUpload(): void {
this.cancelHandle.abort();
}
eventPopUpSeason(event: string): void { eventPopUpSeason(event: string): void {
console.log(`GET event: ${event}`); console.log(`GET event: ${ event}`);
this.popInService.close('popin-new-season'); this.popInService.close('popin-new-season');
} }
eventPopUpSeries(event: string): void { eventPopUpSeries(event: string): void {
console.log(`GET event: ${event}`); console.log(`GET event: ${ event}`);
this.popInService.close('popin-new-series'); this.popInService.close('popin-new-series');
} }
eventPopUpType(event: string): void { eventPopUpType(event: string): void {
console.log(`GET event: ${event}`); console.log(`GET event: ${ event}`);
this.popInService.close('popin-new-type'); this.popInService.close('popin-new-type');
} }
@ -585,7 +575,3 @@ export class UploadScene implements OnInit {
this.popInService.open('popin-create-type'); this.popInService.open('popin-create-type');
} }
} }
function isNullOrUndefined(abort: () => boolean) {
throw new Error('Function not implemented.');
}

View File

@ -2,209 +2,194 @@
<div class="title"> <div class="title">
Edit Media Edit Media
</div> </div>
@if(itemIsRemoved) { <div class="fill-all" *ngIf="itemIsRemoved">
<div class="fill-all"> <div class="message-big">
<div class="message-big"> <br/><br/><br/>
<br/><br/><br/> The media has been removed
The media has been removed <br/><br/><br/>
<br/><br/><br/> </div>
</div>
<div class="fill-all" *ngIf="itemIsNotFound">
<div class="message-big">
<br/><br/><br/>
The media does not exist
<br/><br/><br/>
</div>
</div>
<div class="fill-all" *ngIf="itemIsLoading">
<div class="message-big">
<br/><br/><br/>
Loading ...<br/>
Please wait.
<br/><br/><br/>
</div>
</div>
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="request_raw">
<div class="label">
Title:
</div>
<div class="input">
<input type="text"
placeholder="Name of the Media"
[value]="data.name"
(input)="onName($event.target.value)"
/>
</div> </div>
</div> </div>
} <div class="request_raw2">
@else if(itemIsNotFound) { <div class="label">
<div class="fill-all"> <i class="material-icons">description</i> Description:
<div class="message-big"> </div>
<br/><br/><br/> <div class="input">
The media does not exist <textarea (input)="onDescription($event.target.value)" placeholder="Description of the Media" rows=6>{{data.description}}</textarea>
<br/><br/><br/> <!--<input type="text"
placeholder="Description of the Media"
[value]="data.description"
(input)="onDescription($event.target.value)"/>-->
</div> </div>
</div> </div>
} <div class="request_raw">
@else if(itemIsLoading) { <div class="label">
<div class="fill-all"> <i class="material-icons">date_range</i> Date:
<div class="message-big"> </div>
<br/><br/><br/> <div class="input">
Loading ...<br/> <input type="number"
Please wait. pattern="[0-9]{0-4}"
<br/><br/><br/> placeholder="2112"
[value]="data.time"
(input)="onDate($event.target)"/>
</div> </div>
</div> </div>
} <div class="request_raw">
@else { <div class="label">
<div class="fill-all"> Type:
<div class="request_raw">
<div class="label">
Title:
</div>
<div class="input">
<input type="text"
placeholder="Name of the Media"
[value]="data.name"
(input)="onName($event.target.value)"
/>
</div>
</div> </div>
<div class="request_raw2"> <div class="input">
<div class="label"> <select [ngModel]="data.typeId"
<i class="material-icons">description</i> Description: (ngModelChange)="onChangeType($event)">
</div> <option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option>
<div class="input"> </select>
<textarea (input)="onDescription($event.target.value)" placeholder="Description of the Media" rows=6>{{data.description}}</textarea>
<!--<input type="text"
placeholder="Description of the Media"
[value]="data.description"
(input)="onDescription($event.target.value)"/>-->
</div>
</div> </div>
<div class="request_raw"> <div class="input_add">
<div class="label"> <button class="button color-button-normal color-shadow-black" (click)="newType()" type="submit">
<i class="material-icons">date_range</i> Date: <i class="material-icons">add_circle_outline</i>
</div> </button>
<div class="input">
<input type="number"
pattern="[0-9]{0-4}"
placeholder="2112"
[value]="data.time"
(input)="onDate($event.target)"/>
</div>
</div> </div>
<div class="request_raw">
<div class="label">
Type:
</div>
<div class="input">
<select [ngModel]="data.typeId"
(ngModelChange)="onChangeType($event)">
@for (data of listType; track data.value;) {
<option [ngValue]="data.value">{{data.label}}</option>
}
</select>
</div>
<div class="input_add">
<button class="button color-button-normal color-shadow-black" (click)="newType()" type="submit">
<i class="material-icons">add_circle_outline</i>
</button>
</div>
</div>
<div class="request_raw">
<div class="label">
Series:
</div>
<div class="input">
<select [ngModel]="data.seriesId"
(ngModelChange)="onChangeSeries($event)">
@for (data of listSeries; track data.value;) {
<option [ngValue]="data.value">{{data.label}}</option>
}
</select>
</div>
<div class="input_add">
<button class="button color-button-normal color-shadow-black" (click)="newSeries()" type="submit">
<i class="material-icons">add_circle_outline</i>
</button>
</div>
</div>
<div class="request_raw">
<div class="label">
Season:
</div>
<div class="input">
<select [ngModel]="data.seasonId"
(ngModelChange)="onChangeSeason($event)">
@for (data of listSeason; track data.value;) {
<option [ngValue]="data.value">{{data.label}}</option>
}
</select>
</div>
<div class="input_add">
<button class="button color-button-normal color-shadow-black" (click)="newSeason()" type="submit">
<i class="material-icons">add_circle_outline</i>
</button>
</div>
</div>
<div class="request_raw">
<div class="label">
Episode:
</div>
<div class="input">
<input type="number"
pattern="[0-9]{0-4}"
placeholder="5"
[value]="data.episode"
(input)="onEpisode($event.target)"/>
</div>
</div>
<div class="send_value">
<button class="button fill-x color-button-validate color-shadow-black" [disabled]="!needSend" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button>
</div>
<div class="clear"></div>
</div> </div>
<!-- ------------------------- Cover section --------------------------------- --> <div class="request_raw">
<div class="title"> <div class="label">
Covers Series:
</div>
<div class="fill-all">
<div class="hide-element">
<input type="file"
#fileInput
(change)="onChangeCover($event.target)"
placeholder="Select a cover file"
accept=".png,.jpg,.jpeg,.webp"/>
</div> </div>
<div class="request_raw"> <div class="input">
<div class="input"> <select [ngModel]="data.seriesId"
@for (data of coversDisplay; track data.id;) { (ngModelChange)="onChangeSeries($event)">
<div class="cover"> <option *ngFor="let element of listSeries" [ngValue]="element.value">{{element.label}}</option>
<div class="cover-image"> </select>
<img src="{{data.url}}"/> </div>
</div> <div class="input_add">
<div class="cover-button"> <button class="button color-button-normal color-shadow-black" (click)="newSeries()" type="submit">
<button (click)="removeCover(data.id)"> <i class="material-icons">add_circle_outline</i>
<i class="material-icons button-remove">highlight_off</i> </button>
</button> </div>
</div> </div>
</div> <div class="request_raw">
} <div class="label">
<div class="cover"> Season:
<div class="cover-no-image"> </div>
</div> <div class="input">
<div class="cover-button"> <select [ngModel]="data.seasonId"
<button (click)="fileInput.click()"> (ngModelChange)="onChangeSeason($event)">
<i class="material-icons button-add">add_circle_outline</i> <option *ngFor="let element of listSeason" [ngValue]="element.value">{{element.label}}</option>
</button> </select>
</div> </div>
<div class="input_add">
<button class="button color-button-normal color-shadow-black" (click)="newSeason()" type="submit">
<i class="material-icons">add_circle_outline</i>
</button>
</div>
</div>
<div class="request_raw">
<div class="label">
Episode:
</div>
<div class="input">
<input type="number"
pattern="[0-9]{0-4}"
placeholder="5"
[value]="data.episode"
(input)="onEpisode($event.target)"/>
</div>
</div>
<div class="send_value">
<button class="button fill-x color-button-validate color-shadow-black" [disabled]="!needSend" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button>
</div>
<div class="clear"></div>
</div>
<!-- ------------------------- Cover section --------------------------------- -->
<div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
Covers
</div>
<div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="hide-element">
<input type="file"
#fileInput
(change)="onChangeCover($event.target)"
placeholder="Select a cover file"
accept=".png,.jpg,.jpeg,.webp"/>
</div>
<div class="request_raw">
<div class="input">
<div class="cover" *ngFor="let element of coversDisplay">
<div class="cover-image">
<img src="{{element.url}}"/>
</div>
<div class="cover-button">
<button (click)="removeCover(element.id)">
<i class="material-icons button-remove">highlight_off</i>
</button>
</div>
</div>
<div class="cover">
<div class="cover-no-image">
</div>
<div class="cover-button">
<button (click)="fileInput.click()">
<i class="material-icons button-add">add_circle_outline</i>
</button>
</div> </div>
</div> </div>
</div> </div>
<div class="clear"></div>
</div> </div>
<!-- ------------------------- ADMIN section --------------------------------- --> <div class="clear"></div>
<div class="title"> </div>
Administration <!-- ------------------------- ADMIN section --------------------------------- -->
</div> <div class="title" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<div class="fill-all"> Administration
<div class="request_raw"> </div>
<div class="label"> <div class="fill-all" *ngIf="!itemIsRemoved && !itemIsNotFound && !itemIsLoading">
<i class="material-icons">data_usage</i> ID: <div class="request_raw">
</div> <div class="label">
<div class="input"> <i class="material-icons">data_usage</i> ID:
{{data.dataId}}
</div>
</div> </div>
<div class="clear"></div> <div class="input">
<div class="request_raw"> {{data.dataId}}
<div class="label">
<i class="material-icons">delete_forever</i> Trash:
</div>
<div class="input">
<button class="button color-button-cancel color-shadow-black" (click)="removeItem()" type="submit">
<i class="material-icons">delete</i> Remove Media
</button>
</div>
</div> </div>
<div class="clear"></div>
</div> </div>
} <div class="clear"></div>
<div class="request_raw">
<div class="label">
<i class="material-icons">delete_forever</i> Trash:
</div>
<div class="input">
<button class="button color-button-cancel color-shadow-black" (click)="removeItem()" type="submit">
<i class="material-icons">delete</i> Remove Media
</button>
</div>
</div>
<div class="clear"></div>
</div>
</div> </div>
<create-type ></create-type> <create-type ></create-type>
@ -213,8 +198,7 @@
[mediaUploaded]="upload.mediaSendSize" [mediaUploaded]="upload.mediaSendSize"
[mediaSize]="upload.mediaSize" [mediaSize]="upload.mediaSize"
[result]="upload.result" [result]="upload.result"
[error]="upload.error" [error]="upload.error"></upload-progress>
(abort)="abortUpload()"></upload-progress>
<delete-confirm <delete-confirm
[comment]="confirmDeleteComment" [comment]="confirmDeleteComment"

Some files were not shown because too many files have changed in this diff Show More