[FEAT] update to the new archidata 0.28.0, and update namespace kar-> atriasoft
This commit is contained in:
parent
77acd2060b
commit
3d7ee42ca8
@ -98,4 +98,4 @@ EXPOSE 80
|
|||||||
HEALTHCHECK --start-period=10s --start-interval=2s --interval=30s --timeout=5s --retries=10 \
|
HEALTHCHECK --start-period=10s --start-interval=2s --interval=30s --timeout=5s --retries=10 \
|
||||||
CMD wget --no-verbose --tries=1 --spider http://localhost:80/api/health_check || exit 1
|
CMD wget --no-verbose --tries=1 --spider http://localhost:80/api/health_check || exit 1
|
||||||
|
|
||||||
CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karideo.WebLauncher"]
|
CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.atriasoft.karideo.WebLauncher"]
|
||||||
|
@ -11,7 +11,7 @@ mvn package
|
|||||||
// download all dependency in out/maven/dependency
|
// download all dependency in out/maven/dependency
|
||||||
mvn dependency:copy-dependencies
|
mvn dependency:copy-dependencies
|
||||||
|
|
||||||
java -cp out/maven/kar-karideo-0.1.0.jar org.kar.karideo.WebLauncher
|
java -cp out/maven/kar-karideo-0.1.0.jar org.atriasoft.karideo.WebLauncher
|
||||||
|
|
||||||
|
|
||||||
// create a single package jar
|
// create a single package jar
|
||||||
@ -19,7 +19,7 @@ mvn clean compile assembly:single
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
java -cp out/maven/karideo-0.1.0-jar-with-dependencies.jar org.kar.karideo.WebLauncher
|
java -cp out/maven/karideo-0.1.0-jar-with-dependencies.jar org.atriasoft.karideo.WebLauncher
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
18
back/pom.xml
18
back/pom.xml
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.kar</groupId>
|
<groupId>org.atriasoft</groupId>
|
||||||
<artifactId>karideo</artifactId>
|
<artifactId>karideo</artifactId>
|
||||||
<version>0.3.0</version>
|
<version>0.3.0</version>
|
||||||
<properties>
|
<properties>
|
||||||
@ -10,17 +10,11 @@
|
|||||||
<maven.compiler.target>23</maven.compiler.target>
|
<maven.compiler.target>23</maven.compiler.target>
|
||||||
<maven.dependency.version>3.1.1</maven.dependency.version>
|
<maven.dependency.version>3.1.1</maven.dependency.version>
|
||||||
</properties>
|
</properties>
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>gitea</id>
|
|
||||||
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>kangaroo-and-rabbit</groupId>
|
<groupId>org.atria-soft</groupId>
|
||||||
<artifactId>archidata</artifactId>
|
<artifactId>archidata</artifactId>
|
||||||
<version>0.24.0</version>
|
<version>0.28.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Loopback of logger JDK logging API to SLF4J -->
|
<!-- Loopback of logger JDK logging API to SLF4J -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -112,7 +106,7 @@
|
|||||||
<goal>java</goal>
|
<goal>java</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>org.kar.karideo.WebLauncher</mainClass>
|
<mainClass>org.atriasoft.karideo.WebLauncher</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@ -121,7 +115,7 @@
|
|||||||
<goal>java</goal>
|
<goal>java</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>org.kar.karideo.WebLauncherLocal</mainClass>
|
<mainClass>org.atriasoft.karideo.WebLauncherLocal</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@ -130,7 +124,7 @@
|
|||||||
<goal>java</goal>
|
<goal>java</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>org.kar.karideo.GenerateApi</mainClass>
|
<mainClass>org.atriasoft.karideo.GenerateApi</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
org.kar.karideo.dataTmpFolder=/application/data/tmp
|
org.atriasoft.karideo.dataTmpFolder=/application/data/tmp
|
||||||
org.kar.karideo.dataTmpFolder=/application/data/media
|
org.atriasoft.karideo.dataTmpFolder=/application/data/media
|
||||||
org.kar.karideo.rest.oauth=http://192.168.1.156:21080/oauth/api/
|
org.atriasoft.karideo.rest.oauth=http://192.168.1.156:21080/oauth/api/
|
||||||
org.kar.karideo.db.host=1992.156.1.156
|
org.atriasoft.karideo.db.host=1992.156.1.156
|
||||||
org.kar.karideo.db.port=20306
|
org.atriasoft.karideo.db.port=20306
|
||||||
org.kar.karideo.db.login=root
|
org.atriasoft.karideo.db.login=root
|
||||||
org.kar.karideo.db.port=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh
|
org.atriasoft.karideo.db.port=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh
|
||||||
org.kar.karideo.db.name=karideo
|
org.atriasoft.karideo.db.name=karideo
|
||||||
org.kar.karideo.address=http://0.0.0.0:18080/karideo/api/
|
org.atriasoft.karideo.address=http://0.0.0.0:18080/karideo/api/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.kar.karideo;
|
package org.atriasoft.karideo;
|
||||||
|
|
||||||
import org.kar.karideo.migration.Initialization;
|
import org.atriasoft.karideo.migration.Initialization;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -1,38 +1,40 @@
|
|||||||
package org.kar.karideo;
|
package org.atriasoft.karideo;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.logging.LogManager;
|
import java.util.logging.LogManager;
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.UpdateJwtPublicKey;
|
||||||
|
import org.atriasoft.archidata.api.DataResource;
|
||||||
|
import org.atriasoft.archidata.catcher.GenericCatcher;
|
||||||
|
import org.atriasoft.archidata.db.DbConfig;
|
||||||
|
import org.atriasoft.archidata.filter.CORSFilter;
|
||||||
|
import org.atriasoft.archidata.filter.OptionFilter;
|
||||||
|
import org.atriasoft.archidata.migration.MigrationEngine;
|
||||||
|
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||||
|
import org.atriasoft.archidata.tools.ContextGenericTools;
|
||||||
|
import org.atriasoft.karideo.api.Front;
|
||||||
|
import org.atriasoft.karideo.api.HealthCheck;
|
||||||
|
import org.atriasoft.karideo.api.MediaResource;
|
||||||
|
import org.atriasoft.karideo.api.SeasonResource;
|
||||||
|
import org.atriasoft.karideo.api.SeriesResource;
|
||||||
|
import org.atriasoft.karideo.api.TypeResource;
|
||||||
|
import org.atriasoft.karideo.api.UserMediaAdvancementResource;
|
||||||
|
import org.atriasoft.karideo.api.UserResource;
|
||||||
|
import org.atriasoft.karideo.filter.KarideoAuthenticationFilter;
|
||||||
|
import org.atriasoft.karideo.migration.Initialization;
|
||||||
|
import org.atriasoft.karideo.migration.Migration20230810;
|
||||||
|
import org.atriasoft.karideo.migration.Migration20231015;
|
||||||
|
import org.atriasoft.karideo.migration.Migration20231126;
|
||||||
|
import org.atriasoft.karideo.migration.Migration20240226;
|
||||||
|
import org.atriasoft.karideo.migration.Migration20240611;
|
||||||
|
import org.atriasoft.karideo.migration.Migration20250214;
|
||||||
|
import org.atriasoft.karideo.migration.Migration20250414;
|
||||||
import org.glassfish.grizzly.http.server.HttpServer;
|
import org.glassfish.grizzly.http.server.HttpServer;
|
||||||
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
|
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
|
||||||
import org.glassfish.jersey.jackson.JacksonFeature;
|
import org.glassfish.jersey.jackson.JacksonFeature;
|
||||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||||
import org.glassfish.jersey.server.ResourceConfig;
|
import org.glassfish.jersey.server.ResourceConfig;
|
||||||
import org.kar.archidata.UpdateJwtPublicKey;
|
import org.glassfish.jersey.server.validation.ValidationFeature;
|
||||||
import org.kar.archidata.api.DataResource;
|
|
||||||
import org.kar.archidata.catcher.GenericCatcher;
|
|
||||||
import org.kar.archidata.db.DbConfig;
|
|
||||||
import org.kar.archidata.filter.CORSFilter;
|
|
||||||
import org.kar.archidata.filter.OptionFilter;
|
|
||||||
import org.kar.archidata.migration.MigrationEngine;
|
|
||||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
|
||||||
import org.kar.archidata.tools.ContextGenericTools;
|
|
||||||
import org.kar.karideo.api.Front;
|
|
||||||
import org.kar.karideo.api.HealthCheck;
|
|
||||||
import org.kar.karideo.api.MediaResource;
|
|
||||||
import org.kar.karideo.api.SeasonResource;
|
|
||||||
import org.kar.karideo.api.SeriesResource;
|
|
||||||
import org.kar.karideo.api.TypeResource;
|
|
||||||
import org.kar.karideo.api.UserMediaAdvancementResource;
|
|
||||||
import org.kar.karideo.api.UserResource;
|
|
||||||
import org.kar.karideo.filter.KarideoAuthenticationFilter;
|
|
||||||
import org.kar.karideo.migration.Initialization;
|
|
||||||
import org.kar.karideo.migration.Migration20230810;
|
|
||||||
import org.kar.karideo.migration.Migration20231015;
|
|
||||||
import org.kar.karideo.migration.Migration20231126;
|
|
||||||
import org.kar.karideo.migration.Migration20240226;
|
|
||||||
import org.kar.karideo.migration.Migration20240611;
|
|
||||||
import org.kar.karideo.migration.Migration20250214;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.slf4j.bridge.SLF4JBridgeHandler;
|
import org.slf4j.bridge.SLF4JBridgeHandler;
|
||||||
@ -64,6 +66,7 @@ public class WebLauncher {
|
|||||||
migrationEngine.add(new Migration20240226());
|
migrationEngine.add(new Migration20240226());
|
||||||
migrationEngine.add(new Migration20240611());
|
migrationEngine.add(new Migration20240611());
|
||||||
migrationEngine.add(new Migration20250214());
|
migrationEngine.add(new Migration20250214());
|
||||||
|
migrationEngine.add(new Migration20250414());
|
||||||
WebLauncher.LOGGER.info("Migrate the DB [START]");
|
WebLauncher.LOGGER.info("Migrate the DB [START]");
|
||||||
migrationEngine.migrateWaitAdmin(new DbConfig());
|
migrationEngine.migrateWaitAdmin(new DbConfig());
|
||||||
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
|
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
|
||||||
@ -116,6 +119,8 @@ public class WebLauncher {
|
|||||||
ContextGenericTools.addJsr310(rc);
|
ContextGenericTools.addJsr310(rc);
|
||||||
// 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 jersey specific validations (@Valid)
|
||||||
|
rc.register(ValidationFeature.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());
|
||||||
|
|
@ -1,10 +1,10 @@
|
|||||||
|
|
||||||
package org.kar.karideo;
|
package org.atriasoft.karideo;
|
||||||
|
|
||||||
import java.util.logging.LogManager;
|
import java.util.logging.LogManager;
|
||||||
|
|
||||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||||
import org.kar.karideo.migration.Initialization;
|
import org.atriasoft.karideo.migration.Initialization;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.slf4j.bridge.SLF4JBridgeHandler;
|
import org.slf4j.bridge.SLF4JBridgeHandler;
|
@ -1,10 +1,10 @@
|
|||||||
package org.kar.karideo.api;
|
package org.atriasoft.karideo.api;
|
||||||
|
|
||||||
import org.kar.archidata.api.FrontGeneric;
|
import org.atriasoft.archidata.api.FrontGeneric;
|
||||||
|
|
||||||
import jakarta.ws.rs.Path;
|
import jakarta.ws.rs.Path;
|
||||||
|
|
||||||
import org.kar.karideo.util.ConfigVariable;
|
import org.atriasoft.karideo.util.ConfigVariable;
|
||||||
|
|
||||||
@Path("/front")
|
@Path("/front")
|
||||||
public class Front extends FrontGeneric {
|
public class Front extends FrontGeneric {
|
@ -1,8 +1,8 @@
|
|||||||
package org.kar.karideo.api;
|
package org.atriasoft.karideo.api;
|
||||||
|
|
||||||
import org.kar.archidata.exception.FailException;
|
import org.atriasoft.archidata.exception.FailException;
|
||||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||||
import org.kar.archidata.tools.JWTWrapper;
|
import org.atriasoft.archidata.tools.JWTWrapper;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -1,37 +1,38 @@
|
|||||||
package org.kar.karideo.api;
|
package org.atriasoft.karideo.api;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.atriasoft.archidata.annotation.apiGenerator.ApiAsyncType;
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress;
|
||||||
|
import org.atriasoft.archidata.api.DataResource;
|
||||||
|
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||||
|
import org.atriasoft.archidata.dataAccess.DataAccess;
|
||||||
|
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson;
|
||||||
|
import org.atriasoft.archidata.exception.FailException;
|
||||||
|
import org.atriasoft.archidata.exception.InputException;
|
||||||
|
import org.atriasoft.archidata.model.Data;
|
||||||
|
import org.atriasoft.archidata.tools.DataTools;
|
||||||
|
import org.atriasoft.karideo.model.Media;
|
||||||
|
import org.atriasoft.karideo.model.Season;
|
||||||
|
import org.atriasoft.karideo.model.Series;
|
||||||
|
import org.atriasoft.karideo.model.Type;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
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.dataAccess.DBAccess;
|
|
||||||
import org.kar.archidata.dataAccess.DataAccess;
|
|
||||||
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
|
|
||||||
import org.kar.archidata.exception.FailException;
|
|
||||||
import org.kar.archidata.exception.InputException;
|
|
||||||
import org.kar.archidata.model.Data;
|
|
||||||
import org.kar.archidata.tools.DataTools;
|
|
||||||
import org.kar.karideo.model.Media;
|
|
||||||
import org.kar.karideo.model.Season;
|
|
||||||
import org.kar.karideo.model.Series;
|
|
||||||
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 io.swagger.v3.oas.annotations.Operation;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.ws.rs.Consumes;
|
import jakarta.ws.rs.Consumes;
|
||||||
import jakarta.ws.rs.DELETE;
|
import jakarta.ws.rs.DELETE;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.PATCH;
|
|
||||||
import jakarta.ws.rs.POST;
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.PUT;
|
||||||
import jakarta.ws.rs.Path;
|
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;
|
||||||
@ -57,14 +58,15 @@ public class MediaResource {
|
|||||||
return DataAccess.get(Media.class, id);
|
return DataAccess.get(Media.class, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PATCH
|
@PUT
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(description = "Modify a specific Media", tags = "GLOBAL")
|
@Operation(description = "Modify a specific Media", tags = "GLOBAL")
|
||||||
public Media patch(@PathParam("id") final Long id, @AsyncType(Media.class) final String jsonRequest) throws Exception {
|
public Media patch(@PathParam("id") final Long id, @Valid final Media media) throws Exception {
|
||||||
LOGGER.info("update video {} ==> '{}'", id, jsonRequest);
|
LOGGER.info("update video {} ==> '{}'", id, media);
|
||||||
DataAccess.updateWithJson(Media.class, id, jsonRequest);
|
media.id = id;
|
||||||
|
DataAccess.update(media, id);
|
||||||
return DataAccess.get(Media.class, id);
|
return DataAccess.get(Media.class, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +90,7 @@ public class MediaResource {
|
|||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||||
@Operation(description = "Create a new Media", tags = "GLOBAL")
|
@Operation(description = "Create a new Media", tags = "GLOBAL")
|
||||||
@TypeScriptProgress
|
@ApiTypeScriptProgress
|
||||||
public Media uploadMedia( //
|
public Media uploadMedia( //
|
||||||
// @AsyncType(Long.class) @FormDataParam("universeId") String universeId, //
|
// @AsyncType(Long.class) @FormDataParam("universeId") String universeId, //
|
||||||
// @AsyncType(Long.class) @FormDataParam("typeId") String typeId, //
|
// @AsyncType(Long.class) @FormDataParam("typeId") String typeId, //
|
||||||
@ -174,7 +176,7 @@ public class MediaResource {
|
|||||||
DataResource.removeTemporaryFile(tmpUID);
|
DataResource.removeTemporaryFile(tmpUID);
|
||||||
throw new InputException("seriesId", "seriesId does not exist ...");
|
throw new InputException("seriesId", "seriesId does not exist ...");
|
||||||
}
|
}
|
||||||
if (seriesNode.parentId != typeNode.id) {
|
if (seriesNode.parentId.equals(typeNode.id)) {
|
||||||
DataResource.removeTemporaryFile(tmpUID);
|
DataResource.removeTemporaryFile(tmpUID);
|
||||||
throw new InputException("seriesId", "seriesId object have not the correct parent...");
|
throw new InputException("seriesId", "seriesId object have not the correct parent...");
|
||||||
}
|
}
|
||||||
@ -233,9 +235,9 @@ public class MediaResource {
|
|||||||
@Path("{id}/cover")
|
@Path("{id}/cover")
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||||
@AsyncType(Media.class)
|
@ApiAsyncType(Media.class)
|
||||||
@Operation(description = "Upload a new season cover media", tags = "GLOBAL")
|
@Operation(description = "Upload a new season cover media", tags = "GLOBAL")
|
||||||
@TypeScriptProgress
|
@ApiTypeScriptProgress
|
||||||
public Media uploadCover( //
|
public Media uploadCover( //
|
||||||
@PathParam("id") final Long id, //
|
@PathParam("id") final Long id, //
|
||||||
@FormDataParam("file") final InputStream fileInputStream, //
|
@FormDataParam("file") final InputStream fileInputStream, //
|
||||||
@ -253,7 +255,7 @@ public class MediaResource {
|
|||||||
@Operation(description = "Remove a specific cover of a media", tags = "GLOBAL")
|
@Operation(description = "Remove a specific cover of a media", tags = "GLOBAL")
|
||||||
public Media removeCover( //
|
public Media removeCover( //
|
||||||
@PathParam("id") final Long id, //
|
@PathParam("id") final Long id, //
|
||||||
@PathParam("coverId") final UUID coverId //
|
@PathParam("coverId") final ObjectId coverId //
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||||
AddOnDataJson.removeLink(dbIo, Media.class, "id", id, "covers", coverId);
|
AddOnDataJson.removeLink(dbIo, Media.class, "id", id, "covers", coverId);
|
@ -1,31 +1,31 @@
|
|||||||
package org.kar.karideo.api;
|
package org.atriasoft.karideo.api;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress;
|
||||||
|
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||||
|
import org.atriasoft.archidata.dataAccess.DataAccess;
|
||||||
|
import org.atriasoft.archidata.dataAccess.QueryAnd;
|
||||||
|
import org.atriasoft.archidata.dataAccess.QueryCondition;
|
||||||
|
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson;
|
||||||
|
import org.atriasoft.archidata.dataAccess.options.Condition;
|
||||||
|
import org.atriasoft.archidata.tools.DataTools;
|
||||||
|
import org.atriasoft.karideo.model.Season;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
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.DBAccess;
|
|
||||||
import org.kar.archidata.dataAccess.DataAccess;
|
|
||||||
import org.kar.archidata.dataAccess.QueryAnd;
|
|
||||||
import org.kar.archidata.dataAccess.QueryCondition;
|
|
||||||
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
|
|
||||||
import org.kar.archidata.dataAccess.options.Condition;
|
|
||||||
import org.kar.archidata.tools.DataTools;
|
|
||||||
import org.kar.karideo.model.Season;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.ws.rs.Consumes;
|
import jakarta.ws.rs.Consumes;
|
||||||
import jakarta.ws.rs.DELETE;
|
import jakarta.ws.rs.DELETE;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.PATCH;
|
|
||||||
import jakarta.ws.rs.POST;
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.PUT;
|
||||||
import jakarta.ws.rs.Path;
|
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;
|
||||||
@ -58,17 +58,18 @@ public class SeasonResource {
|
|||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(description = "Create a new season", tags = "GLOBAL")
|
@Operation(description = "Create a new season", tags = "GLOBAL")
|
||||||
public Season post(final Season jsonRequest) throws Exception {
|
public Season post(@Valid final Season jsonRequest) throws Exception {
|
||||||
return DataAccess.insert(jsonRequest);
|
return DataAccess.insert(jsonRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PATCH
|
@PUT
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(description = "Modify a specific season", tags = "GLOBAL")
|
@Operation(description = "Modify a specific season", tags = "GLOBAL")
|
||||||
public Season patch(@PathParam("id") final Long id, @AsyncType(Season.class) final String jsonRequest) throws Exception {
|
public Season patch(@PathParam("id") final Long id, @Valid final Season season) throws Exception {
|
||||||
DataAccess.updateWithJson(Season.class, id, jsonRequest);
|
season.id = id;
|
||||||
|
DataAccess.update(season, id);
|
||||||
return DataAccess.get(Season.class, id);
|
return DataAccess.get(Season.class, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ public class SeasonResource {
|
|||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Operation(description = "Upload a new season cover season", tags = "GLOBAL")
|
@Operation(description = "Upload a new season cover season", tags = "GLOBAL")
|
||||||
@TypeScriptProgress
|
@ApiTypeScriptProgress
|
||||||
public Season uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
|
public Season uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||||
@ -98,7 +99,7 @@ public class SeasonResource {
|
|||||||
@Path("{id}/cover/{coverId}")
|
@Path("{id}/cover/{coverId}")
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Operation(description = "Remove a specific cover of a season", tags = "GLOBAL")
|
@Operation(description = "Remove a specific cover of a season", tags = "GLOBAL")
|
||||||
public Season removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
|
public Season removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception {
|
||||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||||
AddOnDataJson.removeLink(dbIo, Season.class, "id", id, "covers", coverId);
|
AddOnDataJson.removeLink(dbIo, Season.class, "id", id, "covers", coverId);
|
||||||
return dbIo.get(Season.class, id);
|
return dbIo.get(Season.class, id);
|
@ -1,31 +1,31 @@
|
|||||||
package org.kar.karideo.api;
|
package org.atriasoft.karideo.api;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress;
|
||||||
|
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||||
|
import org.atriasoft.archidata.dataAccess.DataAccess;
|
||||||
|
import org.atriasoft.archidata.dataAccess.QueryAnd;
|
||||||
|
import org.atriasoft.archidata.dataAccess.QueryCondition;
|
||||||
|
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson;
|
||||||
|
import org.atriasoft.archidata.dataAccess.options.Condition;
|
||||||
|
import org.atriasoft.archidata.tools.DataTools;
|
||||||
|
import org.atriasoft.karideo.model.Series;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
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.DBAccess;
|
|
||||||
import org.kar.archidata.dataAccess.DataAccess;
|
|
||||||
import org.kar.archidata.dataAccess.QueryAnd;
|
|
||||||
import org.kar.archidata.dataAccess.QueryCondition;
|
|
||||||
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
|
|
||||||
import org.kar.archidata.dataAccess.options.Condition;
|
|
||||||
import org.kar.archidata.tools.DataTools;
|
|
||||||
import org.kar.karideo.model.Series;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.ws.rs.Consumes;
|
import jakarta.ws.rs.Consumes;
|
||||||
import jakarta.ws.rs.DELETE;
|
import jakarta.ws.rs.DELETE;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.PATCH;
|
|
||||||
import jakarta.ws.rs.POST;
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.PUT;
|
||||||
import jakarta.ws.rs.Path;
|
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;
|
||||||
@ -61,17 +61,18 @@ public class SeriesResource {
|
|||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(description = "Create a new Series", tags = "GLOBAL")
|
@Operation(description = "Create a new Series", tags = "GLOBAL")
|
||||||
public Series post(final Series jsonRequest) throws Exception {
|
public Series post(@Valid final Series jsonRequest) throws Exception {
|
||||||
return DataAccess.insert(jsonRequest);
|
return DataAccess.insert(jsonRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PATCH
|
@PUT
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(description = "Modify a specific Series", tags = "GLOBAL")
|
@Operation(description = "Modify a specific Series", tags = "GLOBAL")
|
||||||
public Series patch(@PathParam("id") final Long id, @AsyncType(Series.class) final String jsonRequest) throws Exception {
|
public Series patch(@PathParam("id") final Long id, @Valid final Series series) throws Exception {
|
||||||
DataAccess.updateWithJson(Series.class, id, jsonRequest);
|
series.id = id;
|
||||||
|
DataAccess.update(series, id);
|
||||||
return DataAccess.get(Series.class, id);
|
return DataAccess.get(Series.class, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,7 @@ public class SeriesResource {
|
|||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||||
@Operation(description = "Upload a new season cover Series", tags = "GLOBAL")
|
@Operation(description = "Upload a new season cover Series", tags = "GLOBAL")
|
||||||
@TypeScriptProgress
|
@ApiTypeScriptProgress
|
||||||
public Series uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
|
public Series uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||||
@ -101,7 +102,7 @@ public class SeriesResource {
|
|||||||
@Path("{id}/cover/{coverId}")
|
@Path("{id}/cover/{coverId}")
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Operation(description = "Remove a specific Series of a season", tags = "GLOBAL")
|
@Operation(description = "Remove a specific Series of a season", tags = "GLOBAL")
|
||||||
public Series removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
|
public Series removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception {
|
||||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||||
AddOnDataJson.removeLink(dbIo, Series.class, "id", id, "covers", coverId);
|
AddOnDataJson.removeLink(dbIo, Series.class, "id", id, "covers", coverId);
|
||||||
return dbIo.get(Series.class, id);
|
return dbIo.get(Series.class, id);
|
@ -1,30 +1,30 @@
|
|||||||
package org.kar.karideo.api;
|
package org.atriasoft.karideo.api;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress;
|
||||||
|
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||||
|
import org.atriasoft.archidata.dataAccess.DataAccess;
|
||||||
|
import org.atriasoft.archidata.dataAccess.QueryCondition;
|
||||||
|
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson;
|
||||||
|
import org.atriasoft.archidata.dataAccess.options.Condition;
|
||||||
|
import org.atriasoft.archidata.tools.DataTools;
|
||||||
|
import org.atriasoft.karideo.model.Type;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
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.DBAccess;
|
|
||||||
import org.kar.archidata.dataAccess.DataAccess;
|
|
||||||
import org.kar.archidata.dataAccess.QueryCondition;
|
|
||||||
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
|
|
||||||
import org.kar.archidata.dataAccess.options.Condition;
|
|
||||||
import org.kar.archidata.tools.DataTools;
|
|
||||||
import org.kar.karideo.model.Type;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.ws.rs.Consumes;
|
import jakarta.ws.rs.Consumes;
|
||||||
import jakarta.ws.rs.DELETE;
|
import jakarta.ws.rs.DELETE;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.PATCH;
|
|
||||||
import jakarta.ws.rs.POST;
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.PUT;
|
||||||
import jakarta.ws.rs.Path;
|
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;
|
||||||
@ -61,17 +61,18 @@ public class TypeResource {
|
|||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(description = "Create a new Type", tags = "GLOBAL")
|
@Operation(description = "Create a new Type", tags = "GLOBAL")
|
||||||
public Type post(final Type jsonRequest) throws Exception {
|
public Type post(@Valid final Type jsonRequest) throws Exception {
|
||||||
return DataAccess.insert(jsonRequest);
|
return DataAccess.insert(jsonRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PATCH
|
@PUT
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(description = "Modify a specific Type", tags = "GLOBAL")
|
@Operation(description = "Modify a specific Type", tags = "GLOBAL")
|
||||||
public Type patch(@PathParam("id") final Long id, @AsyncType(Type.class) final String jsonRequest) throws Exception {
|
public Type patch(@PathParam("id") final Long id, @Valid final Type type) throws Exception {
|
||||||
DataAccess.updateWithJson(Type.class, id, jsonRequest);
|
type.id = id;
|
||||||
|
DataAccess.update(type, id);
|
||||||
return DataAccess.get(Type.class, id);
|
return DataAccess.get(Type.class, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,7 @@ public class TypeResource {
|
|||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||||
@Operation(description = "Upload a new season cover Type", tags = "GLOBAL")
|
@Operation(description = "Upload a new season cover Type", tags = "GLOBAL")
|
||||||
@TypeScriptProgress
|
@ApiTypeScriptProgress
|
||||||
public Type uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
|
public Type uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||||
@ -101,7 +102,7 @@ public class TypeResource {
|
|||||||
@Path("{id}/cover/{coverId}")
|
@Path("{id}/cover/{coverId}")
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
@Operation(description = "Remove a specific cover of a type", tags = "GLOBAL")
|
@Operation(description = "Remove a specific cover of a type", tags = "GLOBAL")
|
||||||
public Type removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
|
public Type removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception {
|
||||||
|
|
||||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||||
AddOnDataJson.removeLink(dbIo, Type.class, "id", id, "covers", coverId);
|
AddOnDataJson.removeLink(dbIo, Type.class, "id", id, "covers", coverId);
|
@ -1,22 +1,23 @@
|
|||||||
package org.kar.karideo.api;
|
package org.atriasoft.karideo.api;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.kar.archidata.dataAccess.DataAccess;
|
import org.atriasoft.archidata.dataAccess.DataAccess;
|
||||||
import org.kar.archidata.dataAccess.QueryAnd;
|
import org.atriasoft.archidata.dataAccess.QueryAnd;
|
||||||
import org.kar.archidata.dataAccess.QueryCondition;
|
import org.atriasoft.archidata.dataAccess.QueryCondition;
|
||||||
import org.kar.archidata.dataAccess.options.Condition;
|
import org.atriasoft.archidata.dataAccess.options.Condition;
|
||||||
import org.kar.archidata.filter.GenericContext;
|
import org.atriasoft.archidata.filter.GenericContext;
|
||||||
import org.kar.karideo.model.UserMediaAdvancement;
|
import org.atriasoft.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 io.swagger.v3.oas.annotations.Operation;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.ws.rs.Consumes;
|
import jakarta.ws.rs.Consumes;
|
||||||
import jakarta.ws.rs.DELETE;
|
import jakarta.ws.rs.DELETE;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.PATCH;
|
import jakarta.ws.rs.PUT;
|
||||||
import jakarta.ws.rs.Path;
|
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;
|
||||||
@ -69,12 +70,12 @@ public class UserMediaAdvancementResource {
|
|||||||
public record MediaInformationsDelta(int time, float percent, boolean addCount) {
|
public record MediaInformationsDelta(int time, float percent, boolean addCount) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PATCH
|
@PUT
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@RolesAllowed("USER")
|
@RolesAllowed("USER")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(description = "Modify a user advancement", tags = "GLOBAL")
|
@Operation(description = "Modify a user advancement", tags = "GLOBAL")
|
||||||
public UserMediaAdvancement patch(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformationsDelta data) throws Exception {
|
public UserMediaAdvancement patch(@Context final SecurityContext sc, @PathParam("id") final Long id, @Valid final MediaInformationsDelta data) throws Exception {
|
||||||
final UserMediaAdvancement elem = get(sc, id);
|
final UserMediaAdvancement elem = get(sc, id);
|
||||||
if (elem == null) {
|
if (elem == null) {
|
||||||
// insert element
|
// insert element
|
@ -1,10 +1,10 @@
|
|||||||
package org.kar.karideo.api;
|
package org.atriasoft.karideo.api;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.kar.archidata.dataAccess.DataAccess;
|
import org.atriasoft.archidata.dataAccess.DataAccess;
|
||||||
import org.kar.archidata.filter.GenericContext;
|
import org.atriasoft.archidata.filter.GenericContext;
|
||||||
import org.kar.karideo.model.UserKarideo;
|
import org.atriasoft.karideo.model.UserKarideo;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
package org.kar.karideo.filter;
|
package org.atriasoft.karideo.filter;
|
||||||
|
|
||||||
import org.kar.archidata.filter.AuthenticationFilter;
|
import org.atriasoft.archidata.filter.AuthenticationFilter;
|
||||||
|
|
||||||
import jakarta.ws.rs.Priorities;
|
import jakarta.ws.rs.Priorities;
|
||||||
import jakarta.ws.rs.ext.Provider;
|
import jakarta.ws.rs.ext.Provider;
|
@ -1,4 +1,4 @@
|
|||||||
package org.kar.karideo.internal;
|
package org.atriasoft.karideo.internal;
|
||||||
|
|
||||||
//import io.scenarium.logger.LogLevel;
|
//import io.scenarium.logger.LogLevel;
|
||||||
//import io.scenarium.logger.Logger;
|
//import io.scenarium.logger.Logger;
|
@ -1,28 +1,29 @@
|
|||||||
package org.kar.karideo.migration;
|
package org.atriasoft.karideo.migration;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.kar.archidata.api.DataResource;
|
import org.atriasoft.archidata.api.DataResource;
|
||||||
import org.kar.archidata.dataAccess.DBAccess;
|
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||||
import org.kar.archidata.externalRestApi.AnalyzeApi;
|
import org.atriasoft.archidata.externalRestApi.AnalyzeApi;
|
||||||
import org.kar.archidata.externalRestApi.TsGenerateApi;
|
import org.atriasoft.archidata.externalRestApi.TsGenerateApi;
|
||||||
import org.kar.archidata.migration.MigrationSqlStep;
|
import org.atriasoft.archidata.filter.PartRight;
|
||||||
import org.kar.archidata.model.Data;
|
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||||
import org.kar.archidata.model.User;
|
import org.atriasoft.archidata.model.Data;
|
||||||
import org.kar.archidata.model.token.JwtToken;
|
import org.atriasoft.archidata.model.User;
|
||||||
import org.kar.karideo.api.Front;
|
import org.atriasoft.archidata.model.token.JwtToken;
|
||||||
import org.kar.karideo.api.HealthCheck;
|
import org.atriasoft.karideo.api.Front;
|
||||||
import org.kar.karideo.api.MediaResource;
|
import org.atriasoft.karideo.api.HealthCheck;
|
||||||
import org.kar.karideo.api.SeasonResource;
|
import org.atriasoft.karideo.api.MediaResource;
|
||||||
import org.kar.karideo.api.SeriesResource;
|
import org.atriasoft.karideo.api.SeasonResource;
|
||||||
import org.kar.karideo.api.TypeResource;
|
import org.atriasoft.karideo.api.SeriesResource;
|
||||||
import org.kar.karideo.api.UserMediaAdvancementResource;
|
import org.atriasoft.karideo.api.TypeResource;
|
||||||
import org.kar.karideo.api.UserResource;
|
import org.atriasoft.karideo.api.UserMediaAdvancementResource;
|
||||||
import org.kar.karideo.model.Media;
|
import org.atriasoft.karideo.api.UserResource;
|
||||||
import org.kar.karideo.model.Season;
|
import org.atriasoft.karideo.model.Media;
|
||||||
import org.kar.karideo.model.Series;
|
import org.atriasoft.karideo.model.Season;
|
||||||
import org.kar.karideo.model.Type;
|
import org.atriasoft.karideo.model.Series;
|
||||||
import org.kar.karideo.model.UserMediaAdvancement;
|
import org.atriasoft.karideo.model.Type;
|
||||||
|
import org.atriasoft.karideo.model.UserMediaAdvancement;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ public class Initialization extends MigrationSqlStep {
|
|||||||
final AnalyzeApi api = new AnalyzeApi();
|
final AnalyzeApi api = new AnalyzeApi();
|
||||||
api.addAllApi(listOfResources);
|
api.addAllApi(listOfResources);
|
||||||
api.addModel(JwtToken.class);
|
api.addModel(JwtToken.class);
|
||||||
|
api.addModel(PartRight.class);
|
||||||
TsGenerateApi.generateApi(api, "../front/src/back-api/");
|
TsGenerateApi.generateApi(api, "../front/src/back-api/");
|
||||||
LOGGER.info("Generate APIs (DONE)");
|
LOGGER.info("Generate APIs (DONE)");
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package org.kar.karideo.migration;
|
package org.atriasoft.karideo.migration;
|
||||||
|
|
||||||
import org.kar.archidata.migration.MigrationSqlStep;
|
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||||
import org.kar.karideo.model.UserMediaAdvancement;
|
import org.atriasoft.karideo.model.UserMediaAdvancement;
|
||||||
|
|
||||||
public class Migration20230810 extends MigrationSqlStep {
|
public class Migration20230810 extends MigrationSqlStep {
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
package org.kar.karideo.migration;
|
package org.atriasoft.karideo.migration;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.kar.archidata.migration.MigrationSqlStep;
|
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||||
|
|
||||||
public class Migration20231015 extends MigrationSqlStep {
|
public class Migration20231015 extends MigrationSqlStep {
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
package org.kar.karideo.migration;
|
package org.atriasoft.karideo.migration;
|
||||||
|
|
||||||
import org.kar.archidata.migration.MigrationSqlStep;
|
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||||
|
|
||||||
public class Migration20231126 extends MigrationSqlStep {
|
public class Migration20231126 extends MigrationSqlStep {
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
package org.kar.karideo.migration;
|
package org.atriasoft.karideo.migration;
|
||||||
|
|
||||||
import org.kar.archidata.migration.MigrationSqlStep;
|
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
package org.kar.karideo.migration;
|
package org.atriasoft.karideo.migration;
|
||||||
|
|
||||||
import org.kar.archidata.migration.MigrationSqlStep;
|
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.kar.karideo.migration;
|
package org.atriasoft.karideo.migration;
|
||||||
|
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -11,15 +11,15 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.kar.archidata.api.DataResource;
|
import org.atriasoft.archidata.api.DataResource;
|
||||||
import org.kar.archidata.dataAccess.DBAccess;
|
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||||
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
|
import org.atriasoft.archidata.dataAccess.options.AccessDeletedItems;
|
||||||
import org.kar.archidata.dataAccess.options.OverrideTableName;
|
import org.atriasoft.archidata.dataAccess.options.OverrideTableName;
|
||||||
import org.kar.archidata.migration.MigrationSqlStep;
|
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||||
import org.kar.karideo.migration.model.CoverConversion;
|
import org.atriasoft.karideo.migration.model.CoverConversion;
|
||||||
import org.kar.karideo.migration.model.MediaConversion;
|
import org.atriasoft.karideo.migration.model.MediaConversion;
|
||||||
import org.kar.karideo.migration.model.OIDConversion;
|
import org.atriasoft.karideo.migration.model.OIDConversion;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -0,0 +1,24 @@
|
|||||||
|
package org.atriasoft.karideo.migration;
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Migration20250414 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-2025-04-14: update to archidata 0.28.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateStep() throws Exception {
|
||||||
|
addAction("""
|
||||||
|
ALTER TABLE `media` ADD `datePublication` timestamp(3) NULL;
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
package org.kar.karideo.migration.model;
|
package org.atriasoft.karideo.migration.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.kar.archidata.annotation.DataJson;
|
import org.atriasoft.archidata.annotation.DataJson;
|
||||||
|
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.kar.karideo.migration.model;
|
package org.atriasoft.karideo.migration.model;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.kar.karideo.migration.model;
|
package org.atriasoft.karideo.migration.model;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -1,12 +1,16 @@
|
|||||||
package org.kar.karideo.model;
|
package org.atriasoft.karideo.model;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.annotation.DataJson;
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CheckForeignKey;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty;
|
||||||
|
import org.atriasoft.archidata.model.Data;
|
||||||
|
import org.atriasoft.archidata.model.GenericDataSoftDelete;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.kar.archidata.annotation.DataJson;
|
import org.hibernate.validator.constraints.UniqueElements;
|
||||||
import org.kar.archidata.model.Data;
|
|
||||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@ -17,51 +21,58 @@ import jakarta.persistence.Entity;
|
|||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.PositiveOrZero;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "media")
|
@Table(name = "media")
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@ApiGenerationMode(create = true, update = true)
|
||||||
public class Media extends GenericDataSoftDelete {
|
public class Media extends GenericDataSoftDelete {
|
||||||
@Schema(description = "Name of the media (this represent the title)")
|
@Schema(description = "Name of the media (this represent the title)")
|
||||||
@Column(nullable = false, length = 0)
|
@Column(nullable = false, length = 0)
|
||||||
|
@Size(min = 0, max = 256)
|
||||||
public String name;
|
public String name;
|
||||||
@Schema(description = "Description of the media")
|
@Schema(description = "Description of the media")
|
||||||
@Column(length = 0)
|
@Column(length = 0)
|
||||||
|
@Size(min = 0, max = 8192)
|
||||||
public String description;
|
public String description;
|
||||||
@Schema(description = "Foreign Key Id of the data")
|
@Schema(description = "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)
|
||||||
|
@CheckForeignKey(target = Data.class)
|
||||||
public ObjectId dataId;
|
public ObjectId dataId;
|
||||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class)
|
|
||||||
@Column(nullable = false)
|
|
||||||
@Nullable
|
|
||||||
public UUID dataIdOld;
|
|
||||||
@Schema(description = "Type of the media")
|
@Schema(description = "Type of the media")
|
||||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
|
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
|
||||||
|
@CheckForeignKey(target = Type.class)
|
||||||
public Long typeId;
|
public Long typeId;
|
||||||
@Schema(description = "Series reference of the media")
|
@Schema(description = "Series reference of the media")
|
||||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
|
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
|
||||||
|
@CheckForeignKey(target = Series.class)
|
||||||
public Long seriesId;
|
public Long seriesId;
|
||||||
@Schema(description = "Season reference of the media")
|
@Schema(description = "Season reference of the media")
|
||||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Season.class)
|
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Season.class)
|
||||||
|
@CheckForeignKey(target = Season.class)
|
||||||
public Long seasonId;
|
public Long seasonId;
|
||||||
@Schema(description = "Episode Id")
|
@Schema(description = "Episode Id")
|
||||||
|
@PositiveOrZero
|
||||||
public Integer episode;
|
public Integer episode;
|
||||||
// ")
|
|
||||||
public Integer date;
|
|
||||||
@Schema(description = "Creation years of the media")
|
@Schema(description = "Creation years of the media")
|
||||||
public Integer time;
|
public Date datePublication;
|
||||||
@Schema(description = "Limitation Age of the media")
|
@Schema(description = "Limitation Age of the media")
|
||||||
|
@PositiveOrZero
|
||||||
public Integer ageLimit;
|
public Integer ageLimit;
|
||||||
@Schema(description = "List of Id of the specific covers")
|
@Schema(description = "List of Id of the specific covers")
|
||||||
@DataJson(targetEntity = Data.class)
|
@DataJson()
|
||||||
@Nullable
|
@Nullable
|
||||||
public List<ObjectId> covers = null;
|
@CollectionNotEmpty
|
||||||
|
@UniqueElements
|
||||||
|
public List<@CheckForeignKey(target = Data.class) ObjectId> covers = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Media [name=" + this.name + ", description=" + this.description + ", dataId=" + this.dataId + ", typeId=" + this.typeId + ", seriesId=" + this.seriesId + ", seasonId=" + this.seasonId
|
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 + "]";
|
+ ", episode=" + this.episode + ", date=" + this.datePublication + ", ageLimit=" + this.ageLimit + ", covers=" + this.covers + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,11 +1,16 @@
|
|||||||
package org.kar.karideo.model;
|
package org.atriasoft.karideo.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.annotation.DataIfNotExists;
|
||||||
|
import org.atriasoft.archidata.annotation.DataJson;
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CheckForeignKey;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty;
|
||||||
|
import org.atriasoft.archidata.model.Data;
|
||||||
|
import org.atriasoft.archidata.model.GenericDataSoftDelete;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.kar.archidata.annotation.DataIfNotExists;
|
import org.hibernate.validator.constraints.UniqueElements;
|
||||||
import org.kar.archidata.annotation.DataJson;
|
|
||||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@ -15,23 +20,31 @@ import jakarta.persistence.Column;
|
|||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
|
||||||
@Table(name = "season")
|
@Table(name = "season")
|
||||||
@DataIfNotExists
|
@DataIfNotExists
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@ApiGenerationMode(create = true, update = true)
|
||||||
public class Season extends GenericDataSoftDelete {
|
public class Season extends GenericDataSoftDelete {
|
||||||
@Column(nullable = false, length = 0)
|
@Column(nullable = false, length = 0)
|
||||||
@Schema(description = "Name of the media (this represent the title)")
|
@Schema(description = "Name of the media (this represent the title)")
|
||||||
|
@Size(min = 0, max = 256)
|
||||||
public String name;
|
public String name;
|
||||||
@Column(length = 0)
|
@Column(length = 0)
|
||||||
@Schema(description = "Description of the media")
|
@Schema(description = "Description of the media")
|
||||||
|
@Size(min = 0, max = 8192)
|
||||||
public String description;
|
public String description;
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@Schema(description = "series parent ID")
|
@Schema(description = "series parent ID")
|
||||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
|
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
|
||||||
|
@CheckForeignKey(target = Series.class)
|
||||||
public Long parentId;
|
public Long parentId;
|
||||||
@Schema(description = "List of Id of the specific covers")
|
@Schema(description = "List of Id of the specific covers")
|
||||||
@DataJson()
|
@DataJson()
|
||||||
@Nullable
|
@Nullable
|
||||||
public List<ObjectId> covers = null;
|
@CollectionNotEmpty
|
||||||
|
@UniqueElements
|
||||||
|
public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null;
|
||||||
}
|
}
|
@ -1,11 +1,16 @@
|
|||||||
package org.kar.karideo.model;
|
package org.atriasoft.karideo.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.annotation.DataIfNotExists;
|
||||||
|
import org.atriasoft.archidata.annotation.DataJson;
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CheckForeignKey;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty;
|
||||||
|
import org.atriasoft.archidata.model.Data;
|
||||||
|
import org.atriasoft.archidata.model.GenericDataSoftDelete;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.kar.archidata.annotation.DataIfNotExists;
|
import org.hibernate.validator.constraints.UniqueElements;
|
||||||
import org.kar.archidata.annotation.DataJson;
|
|
||||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@ -15,23 +20,31 @@ import jakarta.persistence.Column;
|
|||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
|
||||||
@Table(name = "series")
|
@Table(name = "series")
|
||||||
@DataIfNotExists
|
@DataIfNotExists
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@ApiGenerationMode(create = true, update = true)
|
||||||
public class Series extends GenericDataSoftDelete {
|
public class Series extends GenericDataSoftDelete {
|
||||||
@Column(nullable = false, length = 0)
|
@Column(nullable = false, length = 0)
|
||||||
|
@Size(min = 0, max = 256)
|
||||||
@Schema(description = "Name of the media (this represent the title)")
|
@Schema(description = "Name of the media (this represent the title)")
|
||||||
public String name;
|
public String name;
|
||||||
@Column(length = 0)
|
@Column(length = 0)
|
||||||
@Schema(description = "Description of the media")
|
@Schema(description = "Description of the media")
|
||||||
|
@Size(min = 0, max = 8192)
|
||||||
public String description;
|
public String description;
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@Schema(description = "series parent ID")
|
@Schema(description = "series parent ID")
|
||||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
|
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
|
||||||
|
@CheckForeignKey(target = Type.class)
|
||||||
public Long parentId;
|
public Long parentId;
|
||||||
@Schema(description = "List of Id of the specific covers")
|
@Schema(description = "List of Id of the specific covers")
|
||||||
@DataJson()
|
@DataJson()
|
||||||
@Nullable
|
@Nullable
|
||||||
public List<ObjectId> covers = null;
|
@CollectionNotEmpty
|
||||||
|
@UniqueElements
|
||||||
|
public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null;
|
||||||
}
|
}
|
@ -1,11 +1,16 @@
|
|||||||
package org.kar.karideo.model;
|
package org.atriasoft.karideo.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.atriasoft.archidata.annotation.DataIfNotExists;
|
||||||
|
import org.atriasoft.archidata.annotation.DataJson;
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CheckForeignKey;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty;
|
||||||
|
import org.atriasoft.archidata.model.Data;
|
||||||
|
import org.atriasoft.archidata.model.GenericDataSoftDelete;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.kar.archidata.annotation.DataIfNotExists;
|
import org.hibernate.validator.constraints.UniqueElements;
|
||||||
import org.kar.archidata.annotation.DataJson;
|
|
||||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@ -13,21 +18,28 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import jakarta.annotation.Nullable;
|
import jakarta.annotation.Nullable;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
|
||||||
@Table(name = "type")
|
@Table(name = "type")
|
||||||
@DataIfNotExists
|
@DataIfNotExists
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@ApiGenerationMode(create = true, update = true)
|
||||||
public class Type extends GenericDataSoftDelete {
|
public class Type extends GenericDataSoftDelete {
|
||||||
@Column(nullable = false, length = 0)
|
@Column(nullable = false, length = 0)
|
||||||
|
@Size(min = 0, max = 256)
|
||||||
@Schema(description = "Name of the media (this represent the title)")
|
@Schema(description = "Name of the media (this represent the title)")
|
||||||
public String name;
|
public String name;
|
||||||
@Column(length = 0)
|
@Column(length = 0)
|
||||||
@Schema(description = "Description of the media")
|
@Schema(description = "Description of the media")
|
||||||
|
@Size(min = 0, max = 8192)
|
||||||
public String description;
|
public String description;
|
||||||
@Schema(description = "List of Id of the specific covers")
|
@Schema(description = "List of Id of the specific covers")
|
||||||
@DataJson()
|
@DataJson()
|
||||||
@Nullable
|
@Nullable
|
||||||
public List<ObjectId> covers = null;
|
@CollectionNotEmpty
|
||||||
|
@UniqueElements
|
||||||
|
public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null;
|
||||||
|
|
||||||
public Type() {}
|
public Type() {}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
package org.kar.karideo.model;
|
package org.atriasoft.karideo.model;
|
||||||
|
|
||||||
import org.kar.archidata.annotation.DataIfNotExists;
|
import org.atriasoft.archidata.annotation.DataIfNotExists;
|
||||||
import org.kar.archidata.model.User;
|
import org.atriasoft.archidata.model.User;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
@ -1,8 +1,11 @@
|
|||||||
package org.kar.karideo.model;
|
package org.atriasoft.karideo.model;
|
||||||
|
|
||||||
import org.kar.archidata.annotation.DataIfNotExists;
|
import org.atriasoft.archidata.annotation.DataIfNotExists;
|
||||||
import org.kar.archidata.annotation.DataNotRead;
|
import org.atriasoft.archidata.annotation.DataNotRead;
|
||||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiAccessLimitation;
|
||||||
|
import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode;
|
||||||
|
import org.atriasoft.archidata.annotation.checker.CheckForeignKey;
|
||||||
|
import org.atriasoft.archidata.model.GenericDataSoftDelete;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@ -12,28 +15,35 @@ import jakarta.persistence.Column;
|
|||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.PositiveOrZero;
|
||||||
|
|
||||||
@Table(name = "userMediaAdvancement")
|
@Table(name = "userMediaAdvancement")
|
||||||
@DataIfNotExists
|
@DataIfNotExists
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@ApiGenerationMode(create = true, update = true)
|
||||||
public class UserMediaAdvancement extends GenericDataSoftDelete {
|
public class UserMediaAdvancement extends GenericDataSoftDelete {
|
||||||
@DataNotRead
|
@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)
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ApiAccessLimitation(updatable = false, creatable = false)
|
||||||
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)
|
||||||
|
@CheckForeignKey(target = 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 advancement in the media")
|
||||||
|
@PositiveOrZero
|
||||||
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 advancement in the media")
|
||||||
|
@PositiveOrZero
|
||||||
public Integer time;
|
public Integer 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")
|
||||||
|
@PositiveOrZero
|
||||||
public Integer count;
|
public Integer count;
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.kar.karideo.util;
|
package org.atriasoft.karideo.util;
|
||||||
|
|
||||||
public class ConfigVariable {
|
public class ConfigVariable {
|
||||||
public static final String BASE_NAME = "ORG_KARIDEO_";
|
public static final String BASE_NAME = "ORG_KARIDEO_";
|
@ -1,20 +0,0 @@
|
|||||||
package org.kar.karideo;
|
|
||||||
|
|
||||||
public class CacheFilter {
|
|
||||||
@Override
|
|
||||||
public List<ResourceFilter> create(AbstractMethod am) {
|
|
||||||
if (am.isAnnotationPresent(CacheMaxAge.class)) {
|
|
||||||
CacheMaxAge maxAge = am.getAnnotation(CacheMaxAge.class);
|
|
||||||
return newCacheFilter("max-age: " + maxAge.unit().toSeconds(maxAge.time()));
|
|
||||||
} else if (am.isAnnotationPresent(NoCache.class)) {
|
|
||||||
return newCacheFilter("no-cache");
|
|
||||||
} else {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ResourceFilter> newCacheFilter(String content) {
|
|
||||||
return Collections
|
|
||||||
.<ResourceFilter> singletonList(new CacheResponseFilter(content));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,11 @@
|
|||||||
package test.kar.karideo;
|
package test.atriasoft.karideo;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.kar.archidata.tools.JWTWrapper;
|
import org.atriasoft.archidata.filter.PartRight;
|
||||||
|
import org.atriasoft.archidata.tools.JWTWrapper;
|
||||||
|
|
||||||
public class Common {
|
public class Common {
|
||||||
static String USER_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_user_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", Boolean.TRUE)));
|
static String USER_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_user_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", PartRight.READ)));
|
||||||
static String ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", Boolean.TRUE, "ADMIN", Boolean.TRUE)));
|
static String ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", PartRight.READ_WRITE, "ADMIN", PartRight.READ_WRITE)));
|
||||||
}
|
}
|
@ -1,18 +1,18 @@
|
|||||||
package test.kar.karideo;
|
package test.atriasoft.karideo;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.kar.archidata.dataAccess.DBAccess;
|
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||||
import org.kar.archidata.db.DbConfig;
|
import org.atriasoft.archidata.db.DbConfig;
|
||||||
import org.kar.archidata.db.DbIoFactory;
|
import org.atriasoft.archidata.db.DbIoFactory;
|
||||||
import org.kar.archidata.exception.DataAccessException;
|
import org.atriasoft.archidata.exception.DataAccessException;
|
||||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||||
import org.kar.karideo.model.Media;
|
import org.atriasoft.karideo.model.Media;
|
||||||
import org.kar.karideo.model.Season;
|
import org.atriasoft.karideo.model.Season;
|
||||||
import org.kar.karideo.model.Series;
|
import org.atriasoft.karideo.model.Series;
|
||||||
import org.kar.karideo.model.Type;
|
import org.atriasoft.karideo.model.Type;
|
||||||
import org.kar.karideo.model.UserKarideo;
|
import org.atriasoft.karideo.model.UserKarideo;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package test.kar.karideo;
|
package test.atriasoft.karideo;
|
||||||
|
|
||||||
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
|
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
|
||||||
import org.junit.jupiter.api.extension.ExecutionCondition;
|
import org.junit.jupiter.api.extension.ExecutionCondition;
|
@ -1,4 +1,4 @@
|
|||||||
package test.kar.karideo;
|
package test.atriasoft.karideo;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
@ -6,8 +6,8 @@ import org.junit.jupiter.api.MethodOrderer;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||||
import org.kar.archidata.tools.RESTApi;
|
import org.atriasoft.archidata.tools.RESTApi;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -1,6 +1,4 @@
|
|||||||
package test.kar.karideo;
|
package test.atriasoft.karideo;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
@ -10,10 +8,10 @@ import org.junit.jupiter.api.Order;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.kar.archidata.exception.RESTErrorResponseException;
|
import org.atriasoft.archidata.exception.RESTErrorResponseException;
|
||||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||||
import org.kar.archidata.tools.RESTApi;
|
import org.atriasoft.archidata.tools.RESTApi;
|
||||||
import org.kar.karideo.api.HealthCheck.HealthResult;
|
import org.atriasoft.karideo.api.HealthCheck.HealthResult;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -27,29 +25,22 @@ public class TestHealthCheck {
|
|||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void configureWebServer() throws Exception {
|
public static void configureWebServer() throws Exception {
|
||||||
|
ConfigureDb.configure();
|
||||||
LOGGER.info("configure server ...");
|
LOGGER.info("configure server ...");
|
||||||
webInterface = new WebLauncherTest();
|
webInterface = new WebLauncherTest();
|
||||||
LOGGER.info("Create DB");
|
|
||||||
try {
|
|
||||||
webInterface.migrateDB();
|
|
||||||
} catch (final Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
LOGGER.error("Detect an error: {}", ex.getMessage());
|
|
||||||
}
|
|
||||||
LOGGER.info("Start REST (BEGIN)");
|
LOGGER.info("Start REST (BEGIN)");
|
||||||
webInterface.process();
|
webInterface.process();
|
||||||
LOGGER.info("Start REST (DONE)");
|
LOGGER.info("Start REST (DONE)");
|
||||||
api = new RESTApi(ConfigBaseVariable.apiAdress);
|
api = new RESTApi(ConfigBaseVariable.apiAdress);
|
||||||
|
api.setToken(Common.ADMIN_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
public static void stopWebServer() throws InterruptedException, IOException {
|
public static void stopWebServer() throws Exception {
|
||||||
LOGGER.info("Kill the web server");
|
LOGGER.info("Kill the web server");
|
||||||
webInterface.stop();
|
webInterface.stop();
|
||||||
webInterface = null;
|
webInterface = null;
|
||||||
LOGGER.info("Remove the test db");
|
ConfigureDb.clear();
|
||||||
// DBEntry.closeAllForceMode();
|
|
||||||
ConfigBaseVariable.clearAllValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Order(1)
|
@Order(1)
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
package test.kar.karideo;
|
package test.atriasoft.karideo;
|
||||||
|
|
||||||
import org.kar.karideo.WebLauncher;
|
import org.atriasoft.karideo.WebLauncher;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -2,6 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Karideo</title>
|
<title>Karideo</title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
@ -29,64 +29,66 @@
|
|||||||
"*.{ts,tsx,js,jsx,json}": "prettier --write"
|
"*.{ts,tsx,js,jsx,json}": "prettier --write"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"react-speech-recognition": "4.0.0",
|
||||||
|
"regenerator-runtime": "0.14.1",
|
||||||
"@locator/babel-jsx": "0.4.4",
|
"@locator/babel-jsx": "0.4.4",
|
||||||
"@trivago/prettier-plugin-sort-imports": "5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "5.2.2",
|
||||||
"@chakra-ui/cli": "3.8.1",
|
"@chakra-ui/cli": "3.16.0",
|
||||||
"@chakra-ui/react": "3.8.1",
|
"@chakra-ui/react": "3.16.0",
|
||||||
"@emotion/react": "11.14.0",
|
"@emotion/react": "11.14.0",
|
||||||
"allotment": "1.20.3",
|
"allotment": "1.20.3",
|
||||||
"css-mediaquery": "0.1.2",
|
"css-mediaquery": "0.1.2",
|
||||||
"dayjs": "1.11.13",
|
"dayjs": "1.11.13",
|
||||||
"history": "5.3.0",
|
"history": "5.3.0",
|
||||||
"next-themes": "^0.4.4",
|
"next-themes": "^0.4.6",
|
||||||
"react": "19.0.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.1.0",
|
||||||
"react-error-boundary": "5.0.0",
|
"react-error-boundary": "5.0.0",
|
||||||
"react-icons": "5.5.0",
|
"react-icons": "5.5.0",
|
||||||
"react-router-dom": "7.2.0",
|
"react-router-dom": "7.5.0",
|
||||||
"react-select": "5.10.0",
|
"react-select": "5.10.1",
|
||||||
"react-use": "17.6.0",
|
"react-use": "17.6.0",
|
||||||
"zod": "3.24.2",
|
"zod": "3.24.2",
|
||||||
"zustand": "5.0.3"
|
"zustand": "5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@chakra-ui/styled-system": "^2.12.0",
|
"@chakra-ui/styled-system": "^2.12.0",
|
||||||
"@playwright/test": "1.50.1",
|
"@playwright/test": "1.51.1",
|
||||||
"@storybook/addon-actions": "8.5.8",
|
"@storybook/addon-actions": "8.6.12",
|
||||||
"@storybook/addon-essentials": "8.5.8",
|
"@storybook/addon-essentials": "8.6.12",
|
||||||
"@storybook/addon-links": "8.5.8",
|
"@storybook/addon-links": "8.6.12",
|
||||||
"@storybook/addon-mdx-gfm": "8.5.8",
|
"@storybook/addon-mdx-gfm": "8.6.12",
|
||||||
"@storybook/react": "8.5.8",
|
"@storybook/react": "8.6.12",
|
||||||
"@storybook/react-vite": "8.5.8",
|
"@storybook/react-vite": "8.6.12",
|
||||||
"@storybook/theming": "8.5.8",
|
"@storybook/theming": "8.6.12",
|
||||||
"@testing-library/jest-dom": "6.6.3",
|
"@testing-library/jest-dom": "6.6.3",
|
||||||
"@testing-library/react": "16.2.0",
|
"@testing-library/react": "16.3.0",
|
||||||
"@testing-library/user-event": "14.6.1",
|
"@testing-library/user-event": "14.6.1",
|
||||||
"@trivago/prettier-plugin-sort-imports": "5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "5.2.2",
|
||||||
"@types/jest": "29.5.14",
|
"@types/jest": "29.5.14",
|
||||||
"@types/node": "22.13.5",
|
"@types/node": "22.14.1",
|
||||||
"@types/react": "19.0.10",
|
"@types/react": "19.1.2",
|
||||||
"@types/react-dom": "19.0.4",
|
"@types/react-dom": "19.1.2",
|
||||||
"@typescript-eslint/eslint-plugin": "8.24.1",
|
"@typescript-eslint/eslint-plugin": "8.30.1",
|
||||||
"@typescript-eslint/parser": "8.24.1",
|
"@typescript-eslint/parser": "8.30.1",
|
||||||
"@vitejs/plugin-react": "4.3.4",
|
"@vitejs/plugin-react": "4.3.4",
|
||||||
"eslint": "9.21.0",
|
"eslint": "9.24.0",
|
||||||
"eslint-plugin-import": "2.31.0",
|
"eslint-plugin-import": "2.31.0",
|
||||||
"eslint-plugin-react": "7.37.4",
|
"eslint-plugin-react": "7.37.5",
|
||||||
"eslint-plugin-react-hooks": "5.1.0",
|
"eslint-plugin-react-hooks": "5.2.0",
|
||||||
"eslint-plugin-storybook": "0.11.3",
|
"eslint-plugin-storybook": "0.12.0",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jest-environment-jsdom": "29.7.0",
|
"jest-environment-jsdom": "29.7.0",
|
||||||
"knip": "5.44.5",
|
"knip": "5.50.3",
|
||||||
"lint-staged": "15.4.3",
|
"lint-staged": "15.5.1",
|
||||||
"npm-check-updates": "^17.1.15",
|
"npm-check-updates": "^17.1.18",
|
||||||
"prettier": "3.5.2",
|
"prettier": "3.5.3",
|
||||||
"puppeteer": "24.2.1",
|
"puppeteer": "24.6.1",
|
||||||
"react-is": "19.0.0",
|
"react-is": "19.1.0",
|
||||||
"storybook": "8.5.8",
|
"storybook": "8.6.12",
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.2",
|
||||||
"typescript": "5.7.3",
|
"typescript": "5.8.3",
|
||||||
"vite": "6.1.1",
|
"vite": "6.2.6",
|
||||||
"vitest": "3.0.6"
|
"vitest": "3.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3104
front/pnpm-lock.yaml
generated
3104
front/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
BIN
front/public/icons/icon-192x192.png
Normal file
BIN
front/public/icons/icon-192x192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
front/public/icons/icon-512x512.png
Normal file
BIN
front/public/icons/icon-512x512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
21
front/public/manifest.json
Normal file
21
front/public/manifest.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "Karusic",
|
||||||
|
"short_name": "Karusic",
|
||||||
|
"description": "(K)angaroo (A)nd (R)abbit m(usic) is a music streaming",
|
||||||
|
"start_url": "/karusic/",
|
||||||
|
"display": "standalone",
|
||||||
|
"background_color": "#000000",
|
||||||
|
"theme_color": "#FFFFFF",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/karusic/icons/icon-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/karusic/icons/icon-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -22,7 +22,7 @@ export namespace DataResource {
|
|||||||
restConfig,
|
restConfig,
|
||||||
queries,
|
queries,
|
||||||
params,
|
params,
|
||||||
data,
|
headers,
|
||||||
}: {
|
}: {
|
||||||
restConfig: RESTConfig,
|
restConfig: RESTConfig,
|
||||||
queries: {
|
queries: {
|
||||||
@ -32,7 +32,9 @@ export namespace DataResource {
|
|||||||
name: string,
|
name: string,
|
||||||
oid: ObjectId,
|
oid: ObjectId,
|
||||||
},
|
},
|
||||||
data: string,
|
headers?: {
|
||||||
|
Range?: string,
|
||||||
|
},
|
||||||
}): Promise<object> {
|
}): Promise<object> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
@ -42,7 +44,7 @@ export namespace DataResource {
|
|||||||
restConfig,
|
restConfig,
|
||||||
params,
|
params,
|
||||||
queries,
|
queries,
|
||||||
data,
|
headers,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@ -52,7 +54,7 @@ export namespace DataResource {
|
|||||||
restConfig,
|
restConfig,
|
||||||
queries,
|
queries,
|
||||||
params,
|
params,
|
||||||
data,
|
headers,
|
||||||
}: {
|
}: {
|
||||||
restConfig: RESTConfig,
|
restConfig: RESTConfig,
|
||||||
queries: {
|
queries: {
|
||||||
@ -61,7 +63,9 @@ export namespace DataResource {
|
|||||||
params: {
|
params: {
|
||||||
oid: ObjectId,
|
oid: ObjectId,
|
||||||
},
|
},
|
||||||
data: string,
|
headers?: {
|
||||||
|
Range: string,
|
||||||
|
},
|
||||||
}): Promise<object> {
|
}): Promise<object> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
@ -71,7 +75,7 @@ export namespace DataResource {
|
|||||||
restConfig,
|
restConfig,
|
||||||
params,
|
params,
|
||||||
queries,
|
queries,
|
||||||
data,
|
headers,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@ -81,7 +85,7 @@ export namespace DataResource {
|
|||||||
restConfig,
|
restConfig,
|
||||||
queries,
|
queries,
|
||||||
params,
|
params,
|
||||||
data,
|
headers,
|
||||||
}: {
|
}: {
|
||||||
restConfig: RESTConfig,
|
restConfig: RESTConfig,
|
||||||
queries: {
|
queries: {
|
||||||
@ -90,7 +94,9 @@ export namespace DataResource {
|
|||||||
params: {
|
params: {
|
||||||
oid: ObjectId,
|
oid: ObjectId,
|
||||||
},
|
},
|
||||||
data: string,
|
headers?: {
|
||||||
|
Range: string,
|
||||||
|
},
|
||||||
}): Promise<object> {
|
}): Promise<object> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
@ -100,7 +106,7 @@ export namespace DataResource {
|
|||||||
restConfig,
|
restConfig,
|
||||||
params,
|
params,
|
||||||
queries,
|
queries,
|
||||||
data,
|
headers,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -14,7 +14,7 @@ import { z as zod } from "zod"
|
|||||||
import {
|
import {
|
||||||
Long,
|
Long,
|
||||||
Media,
|
Media,
|
||||||
MediaWrite,
|
MediaUpdate,
|
||||||
UUID,
|
UUID,
|
||||||
ZodMedia,
|
ZodMedia,
|
||||||
isMedia,
|
isMedia,
|
||||||
@ -87,12 +87,12 @@ export namespace MediaResource {
|
|||||||
params: {
|
params: {
|
||||||
id: Long,
|
id: Long,
|
||||||
},
|
},
|
||||||
data: MediaWrite,
|
data: MediaUpdate,
|
||||||
}): Promise<Media> {
|
}): Promise<Media> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
endPoint: "/media/{id}",
|
endPoint: "/media/{id}",
|
||||||
requestType: HTTPRequestModel.PATCH,
|
requestType: HTTPRequestModel.PUT,
|
||||||
contentType: HTTPMimeType.JSON,
|
contentType: HTTPMimeType.JSON,
|
||||||
accept: HTTPMimeType.JSON,
|
accept: HTTPMimeType.JSON,
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,8 @@ import { z as zod } from "zod"
|
|||||||
import {
|
import {
|
||||||
Long,
|
Long,
|
||||||
Season,
|
Season,
|
||||||
SeasonWrite,
|
SeasonCreate,
|
||||||
|
SeasonUpdate,
|
||||||
UUID,
|
UUID,
|
||||||
ZodSeason,
|
ZodSeason,
|
||||||
isSeason,
|
isSeason,
|
||||||
@ -88,12 +89,12 @@ export namespace SeasonResource {
|
|||||||
params: {
|
params: {
|
||||||
id: Long,
|
id: Long,
|
||||||
},
|
},
|
||||||
data: SeasonWrite,
|
data: SeasonUpdate,
|
||||||
}): Promise<Season> {
|
}): Promise<Season> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
endPoint: "/season/{id}",
|
endPoint: "/season/{id}",
|
||||||
requestType: HTTPRequestModel.PATCH,
|
requestType: HTTPRequestModel.PUT,
|
||||||
contentType: HTTPMimeType.JSON,
|
contentType: HTTPMimeType.JSON,
|
||||||
accept: HTTPMimeType.JSON,
|
accept: HTTPMimeType.JSON,
|
||||||
},
|
},
|
||||||
@ -110,7 +111,7 @@ export namespace SeasonResource {
|
|||||||
data,
|
data,
|
||||||
}: {
|
}: {
|
||||||
restConfig: RESTConfig,
|
restConfig: RESTConfig,
|
||||||
data: SeasonWrite,
|
data: SeasonCreate,
|
||||||
}): Promise<Season> {
|
}): Promise<Season> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
|
@ -14,7 +14,8 @@ import { z as zod } from "zod"
|
|||||||
import {
|
import {
|
||||||
Long,
|
Long,
|
||||||
Series,
|
Series,
|
||||||
SeriesWrite,
|
SeriesCreate,
|
||||||
|
SeriesUpdate,
|
||||||
UUID,
|
UUID,
|
||||||
ZodSeries,
|
ZodSeries,
|
||||||
isSeries,
|
isSeries,
|
||||||
@ -88,12 +89,12 @@ export namespace SeriesResource {
|
|||||||
params: {
|
params: {
|
||||||
id: Long,
|
id: Long,
|
||||||
},
|
},
|
||||||
data: SeriesWrite,
|
data: SeriesUpdate,
|
||||||
}): Promise<Series> {
|
}): Promise<Series> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
endPoint: "/series/{id}",
|
endPoint: "/series/{id}",
|
||||||
requestType: HTTPRequestModel.PATCH,
|
requestType: HTTPRequestModel.PUT,
|
||||||
contentType: HTTPMimeType.JSON,
|
contentType: HTTPMimeType.JSON,
|
||||||
accept: HTTPMimeType.JSON,
|
accept: HTTPMimeType.JSON,
|
||||||
},
|
},
|
||||||
@ -110,7 +111,7 @@ export namespace SeriesResource {
|
|||||||
data,
|
data,
|
||||||
}: {
|
}: {
|
||||||
restConfig: RESTConfig,
|
restConfig: RESTConfig,
|
||||||
data: SeriesWrite,
|
data: SeriesCreate,
|
||||||
}): Promise<Series> {
|
}): Promise<Series> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
|
@ -14,7 +14,8 @@ import { z as zod } from "zod"
|
|||||||
import {
|
import {
|
||||||
Long,
|
Long,
|
||||||
Type,
|
Type,
|
||||||
TypeWrite,
|
TypeCreate,
|
||||||
|
TypeUpdate,
|
||||||
UUID,
|
UUID,
|
||||||
ZodType,
|
ZodType,
|
||||||
isType,
|
isType,
|
||||||
@ -88,12 +89,12 @@ export namespace TypeResource {
|
|||||||
params: {
|
params: {
|
||||||
id: Long,
|
id: Long,
|
||||||
},
|
},
|
||||||
data: TypeWrite,
|
data: TypeUpdate,
|
||||||
}): Promise<Type> {
|
}): Promise<Type> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
endPoint: "/type/{id}",
|
endPoint: "/type/{id}",
|
||||||
requestType: HTTPRequestModel.PATCH,
|
requestType: HTTPRequestModel.PUT,
|
||||||
contentType: HTTPMimeType.JSON,
|
contentType: HTTPMimeType.JSON,
|
||||||
accept: HTTPMimeType.JSON,
|
accept: HTTPMimeType.JSON,
|
||||||
},
|
},
|
||||||
@ -110,7 +111,7 @@ export namespace TypeResource {
|
|||||||
data,
|
data,
|
||||||
}: {
|
}: {
|
||||||
restConfig: RESTConfig,
|
restConfig: RESTConfig,
|
||||||
data: TypeWrite,
|
data: TypeCreate,
|
||||||
}): Promise<Type> {
|
}): Promise<Type> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
import { z as zod } from "zod"
|
import { z as zod } from "zod"
|
||||||
import {
|
import {
|
||||||
Long,
|
Long,
|
||||||
MediaInformationsDeltaWrite,
|
MediaInformationsDelta,
|
||||||
UserMediaAdvancement,
|
UserMediaAdvancement,
|
||||||
ZodUserMediaAdvancement,
|
ZodUserMediaAdvancement,
|
||||||
isUserMediaAdvancement,
|
isUserMediaAdvancement,
|
||||||
@ -85,12 +85,12 @@ export namespace UserMediaAdvancementResource {
|
|||||||
params: {
|
params: {
|
||||||
id: Long,
|
id: Long,
|
||||||
},
|
},
|
||||||
data: MediaInformationsDeltaWrite,
|
data: MediaInformationsDelta,
|
||||||
}): Promise<UserMediaAdvancement> {
|
}): Promise<UserMediaAdvancement> {
|
||||||
return RESTRequestJson({
|
return RESTRequestJson({
|
||||||
restModel: {
|
restModel: {
|
||||||
endPoint: "/advancement/{id}",
|
endPoint: "/advancement/{id}",
|
||||||
requestType: HTTPRequestModel.PATCH,
|
requestType: HTTPRequestModel.PUT,
|
||||||
contentType: HTTPMimeType.JSON,
|
contentType: HTTPMimeType.JSON,
|
||||||
accept: HTTPMimeType.JSON,
|
accept: HTTPMimeType.JSON,
|
||||||
},
|
},
|
||||||
|
@ -3,23 +3,23 @@
|
|||||||
*/
|
*/
|
||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodLong} from "./long";
|
|
||||||
import {ZodObjectId} from "./object-id";
|
import {ZodObjectId} from "./object-id";
|
||||||
import {ZodOIDGenericDataSoftDelete, ZodOIDGenericDataSoftDeleteWrite } from "./oid-generic-data-soft-delete";
|
import {ZodLong} from "./long";
|
||||||
|
import {ZodOIDGenericDataSoftDelete, ZodOIDGenericDataSoftDeleteUpdate , ZodOIDGenericDataSoftDeleteCreate } from "./oid-generic-data-soft-delete";
|
||||||
|
|
||||||
export const ZodData = ZodOIDGenericDataSoftDelete.extend({
|
export const ZodData = ZodOIDGenericDataSoftDelete.extend({
|
||||||
/**
|
/**
|
||||||
* Sha512 of the data
|
* Sha512 of the data
|
||||||
*/
|
*/
|
||||||
sha512: zod.string().max(512),
|
sha512: zod.string().max(512).readonly(),
|
||||||
/**
|
/**
|
||||||
* Mime -type of the media
|
* Mime -type of the media
|
||||||
*/
|
*/
|
||||||
mimeType: zod.string().max(512),
|
mimeType: zod.string().max(512).readonly(),
|
||||||
/**
|
/**
|
||||||
* Size in Byte of the data
|
* Size in Byte of the data
|
||||||
*/
|
*/
|
||||||
size: ZodLong,
|
size: ZodLong.readonly(),
|
||||||
/**
|
/**
|
||||||
* Unique ObjectID of the object
|
* Unique ObjectID of the object
|
||||||
*/
|
*/
|
||||||
@ -38,30 +38,3 @@ export function isData(data: any): data is Data {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodDataWrite = ZodOIDGenericDataSoftDeleteWrite.extend({
|
|
||||||
/**
|
|
||||||
* Sha512 of the data
|
|
||||||
*/
|
|
||||||
sha512: zod.string().max(512).optional(),
|
|
||||||
/**
|
|
||||||
* Mime -type of the media
|
|
||||||
*/
|
|
||||||
mimeType: zod.string().max(512).optional(),
|
|
||||||
/**
|
|
||||||
* Size in Byte of the data
|
|
||||||
*/
|
|
||||||
size: ZodLong.optional(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type DataWrite = zod.infer<typeof ZodDataWrite>;
|
|
||||||
|
|
||||||
export function isDataWrite(data: any): data is DataWrite {
|
|
||||||
try {
|
|
||||||
ZodDataWrite.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodDataWrite' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodGenericData, ZodGenericDataWrite } from "./generic-data";
|
import {ZodGenericData, ZodGenericDataUpdate , ZodGenericDataCreate } from "./generic-data";
|
||||||
|
|
||||||
export const ZodGenericDataSoftDelete = ZodGenericData.extend({
|
export const ZodGenericDataSoftDelete = ZodGenericData.extend({
|
||||||
/**
|
/**
|
||||||
@ -24,16 +24,29 @@ export function isGenericDataSoftDelete(data: any): data is GenericDataSoftDelet
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodGenericDataSoftDeleteWrite = ZodGenericDataWrite;
|
export const ZodGenericDataSoftDeleteUpdate = ZodGenericDataUpdate;
|
||||||
|
|
||||||
export type GenericDataSoftDeleteWrite = zod.infer<typeof ZodGenericDataSoftDeleteWrite>;
|
export type GenericDataSoftDeleteUpdate = zod.infer<typeof ZodGenericDataSoftDeleteUpdate>;
|
||||||
|
|
||||||
export function isGenericDataSoftDeleteWrite(data: any): data is GenericDataSoftDeleteWrite {
|
export function isGenericDataSoftDeleteUpdate(data: any): data is GenericDataSoftDeleteUpdate {
|
||||||
try {
|
try {
|
||||||
ZodGenericDataSoftDeleteWrite.parse(data);
|
ZodGenericDataSoftDeleteUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodGenericDataSoftDeleteCreate = ZodGenericDataCreate;
|
||||||
|
|
||||||
|
export type GenericDataSoftDeleteCreate = zod.infer<typeof ZodGenericDataSoftDeleteCreate>;
|
||||||
|
|
||||||
|
export function isGenericDataSoftDeleteCreate(data: any): data is GenericDataSoftDeleteCreate {
|
||||||
|
try {
|
||||||
|
ZodGenericDataSoftDeleteCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
|
import {ZodGenericTiming, ZodGenericTimingUpdate , ZodGenericTimingCreate } from "./generic-timing";
|
||||||
import {ZodLong} from "./long";
|
import {ZodLong} from "./long";
|
||||||
import {ZodGenericTiming, ZodGenericTimingWrite } from "./generic-timing";
|
|
||||||
|
|
||||||
export const ZodGenericData = ZodGenericTiming.extend({
|
export const ZodGenericData = ZodGenericTiming.extend({
|
||||||
/**
|
/**
|
||||||
@ -25,16 +25,29 @@ export function isGenericData(data: any): data is GenericData {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodGenericDataWrite = ZodGenericTimingWrite;
|
export const ZodGenericDataUpdate = ZodGenericTimingUpdate;
|
||||||
|
|
||||||
export type GenericDataWrite = zod.infer<typeof ZodGenericDataWrite>;
|
export type GenericDataUpdate = zod.infer<typeof ZodGenericDataUpdate>;
|
||||||
|
|
||||||
export function isGenericDataWrite(data: any): data is GenericDataWrite {
|
export function isGenericDataUpdate(data: any): data is GenericDataUpdate {
|
||||||
try {
|
try {
|
||||||
ZodGenericDataWrite.parse(data);
|
ZodGenericDataUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodGenericDataWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodGenericDataUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodGenericDataCreate = ZodGenericTimingCreate;
|
||||||
|
|
||||||
|
export type GenericDataCreate = zod.infer<typeof ZodGenericDataCreate>;
|
||||||
|
|
||||||
|
export function isGenericDataCreate(data: any): data is GenericDataCreate {
|
||||||
|
try {
|
||||||
|
ZodGenericDataCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodGenericDataCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,18 +28,33 @@ export function isGenericTiming(data: any): data is GenericTiming {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodGenericTimingWrite = zod.object({
|
export const ZodGenericTimingUpdate = zod.object({
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GenericTimingWrite = zod.infer<typeof ZodGenericTimingWrite>;
|
export type GenericTimingUpdate = zod.infer<typeof ZodGenericTimingUpdate>;
|
||||||
|
|
||||||
export function isGenericTimingWrite(data: any): data is GenericTimingWrite {
|
export function isGenericTimingUpdate(data: any): data is GenericTimingUpdate {
|
||||||
try {
|
try {
|
||||||
ZodGenericTimingWrite.parse(data);
|
ZodGenericTimingUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodGenericTimingWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodGenericTimingUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodGenericTimingCreate = zod.object({
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export type GenericTimingCreate = zod.infer<typeof ZodGenericTimingCreate>;
|
||||||
|
|
||||||
|
export function isGenericTimingCreate(data: any): data is GenericTimingCreate {
|
||||||
|
try {
|
||||||
|
ZodGenericTimingCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodGenericTimingCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,18 +19,3 @@ export function isHealthResult(data: any): data is HealthResult {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodHealthResultWrite = zod.object({
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -18,7 +18,9 @@ export * from "./media-informations-delta"
|
|||||||
export * from "./object-id"
|
export * from "./object-id"
|
||||||
export * from "./oid-generic-data"
|
export * from "./oid-generic-data"
|
||||||
export * from "./oid-generic-data-soft-delete"
|
export * from "./oid-generic-data-soft-delete"
|
||||||
|
export * from "./part-right"
|
||||||
export * from "./rest-error-response"
|
export * from "./rest-error-response"
|
||||||
|
export * from "./rest-input-error"
|
||||||
export * from "./season"
|
export * from "./season"
|
||||||
export * from "./series"
|
export * from "./series"
|
||||||
export * from "./timestamp"
|
export * from "./timestamp"
|
||||||
|
@ -21,20 +21,3 @@ export function isJwtHeader(data: any): data is JwtHeader {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodJwtHeaderWrite = zod.object({
|
|
||||||
typ: zod.string().max(128).optional(),
|
|
||||||
alg: zod.string().max(128).optional(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type JwtHeaderWrite = zod.infer<typeof ZodJwtHeaderWrite>;
|
|
||||||
|
|
||||||
export function isJwtHeaderWrite(data: any): data is JwtHeaderWrite {
|
|
||||||
try {
|
|
||||||
ZodJwtHeaderWrite.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodJwtHeaderWrite' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -27,25 +27,3 @@ export function isJwtPayload(data: any): data is JwtPayload {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodJwtPayloadWrite = zod.object({
|
|
||||||
sub: zod.string().optional(),
|
|
||||||
application: zod.string().optional(),
|
|
||||||
iss: zod.string().optional(),
|
|
||||||
right: zod.record(zod.string(), zod.record(zod.string(), ZodLong)).optional(),
|
|
||||||
login: zod.string().optional(),
|
|
||||||
exp: ZodLong.optional(),
|
|
||||||
iat: ZodLong.optional(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type JwtPayloadWrite = zod.infer<typeof ZodJwtPayloadWrite>;
|
|
||||||
|
|
||||||
export function isJwtPayloadWrite(data: any): data is JwtPayloadWrite {
|
|
||||||
try {
|
|
||||||
ZodJwtPayloadWrite.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodJwtPayloadWrite' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodJwtHeader, ZodJwtHeaderWrite } from "./jwt-header";
|
import {ZodJwtHeader} from "./jwt-header";
|
||||||
import {ZodJwtPayload, ZodJwtPayloadWrite } from "./jwt-payload";
|
import {ZodJwtPayload} from "./jwt-payload";
|
||||||
|
|
||||||
export const ZodJwtToken = zod.object({
|
export const ZodJwtToken = zod.object({
|
||||||
header: ZodJwtHeader,
|
header: ZodJwtHeader,
|
||||||
@ -24,21 +24,3 @@ export function isJwtToken(data: any): data is JwtToken {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodJwtTokenWrite = zod.object({
|
|
||||||
header: ZodJwtHeader.optional(),
|
|
||||||
payload: ZodJwtPayload.optional(),
|
|
||||||
signature: zod.string().optional(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type JwtTokenWrite = zod.infer<typeof ZodJwtTokenWrite>;
|
|
||||||
|
|
||||||
export function isJwtTokenWrite(data: any): data is JwtTokenWrite {
|
|
||||||
try {
|
|
||||||
ZodJwtTokenWrite.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodJwtTokenWrite' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -19,18 +19,3 @@ export function isMediaInformationsDelta(data: any): data is MediaInformationsDe
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodMediaInformationsDeltaWrite = zod.object({
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,25 +4,24 @@
|
|||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodObjectId} from "./object-id";
|
import {ZodObjectId} from "./object-id";
|
||||||
import {ZodUUID} from "./uuid";
|
|
||||||
import {ZodLong} from "./long";
|
import {ZodLong} from "./long";
|
||||||
import {ZodInteger} from "./integer";
|
import {ZodInteger} from "./integer";
|
||||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
import {ZodIsoDate} from "./iso-date";
|
||||||
|
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||||
|
|
||||||
export const ZodMedia = ZodGenericDataSoftDelete.extend({
|
export const ZodMedia = ZodGenericDataSoftDelete.extend({
|
||||||
/**
|
/**
|
||||||
* Name of the media (this represent the title)
|
* Name of the media (this represent the title)
|
||||||
*/
|
*/
|
||||||
name: zod.string(),
|
name: zod.string().max(256),
|
||||||
/**
|
/**
|
||||||
* Description of the media
|
* Description of the media
|
||||||
*/
|
*/
|
||||||
description: zod.string().optional(),
|
description: zod.string().max(8192).optional(),
|
||||||
/**
|
/**
|
||||||
* Foreign Key Id of the data
|
* Foreign Key Id of the data
|
||||||
*/
|
*/
|
||||||
dataId: ZodObjectId,
|
dataId: ZodObjectId,
|
||||||
dataIdOld: ZodUUID.optional(),
|
|
||||||
/**
|
/**
|
||||||
* Type of the media
|
* Type of the media
|
||||||
*/
|
*/
|
||||||
@ -39,11 +38,10 @@ export const ZodMedia = ZodGenericDataSoftDelete.extend({
|
|||||||
* Episode Id
|
* Episode Id
|
||||||
*/
|
*/
|
||||||
episode: ZodInteger.optional(),
|
episode: ZodInteger.optional(),
|
||||||
date: ZodInteger.optional(),
|
|
||||||
/**
|
/**
|
||||||
* Creation years of the media
|
* Creation years of the media
|
||||||
*/
|
*/
|
||||||
time: ZodInteger.optional(),
|
datePublication: ZodIsoDate.optional(),
|
||||||
/**
|
/**
|
||||||
* Limitation Age of the media
|
* Limitation Age of the media
|
||||||
*/
|
*/
|
||||||
@ -66,20 +64,19 @@ export function isMedia(data: any): data is Media {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodMediaWrite = ZodGenericDataSoftDeleteWrite.extend({
|
export const ZodMediaUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||||
/**
|
/**
|
||||||
* Name of the media (this represent the title)
|
* Name of the media (this represent the title)
|
||||||
*/
|
*/
|
||||||
name: zod.string().optional(),
|
name: zod.string().max(256),
|
||||||
/**
|
/**
|
||||||
* Description of the media
|
* Description of the media
|
||||||
*/
|
*/
|
||||||
description: zod.string().nullable().optional(),
|
description: zod.string().max(8192).nullable().optional(),
|
||||||
/**
|
/**
|
||||||
* Foreign Key Id of the data
|
* Foreign Key Id of the data
|
||||||
*/
|
*/
|
||||||
dataId: ZodObjectId.optional(),
|
dataId: ZodObjectId,
|
||||||
dataIdOld: ZodUUID.nullable().optional(),
|
|
||||||
/**
|
/**
|
||||||
* Type of the media
|
* Type of the media
|
||||||
*/
|
*/
|
||||||
@ -96,11 +93,10 @@ export const ZodMediaWrite = ZodGenericDataSoftDeleteWrite.extend({
|
|||||||
* Episode Id
|
* Episode Id
|
||||||
*/
|
*/
|
||||||
episode: ZodInteger.nullable().optional(),
|
episode: ZodInteger.nullable().optional(),
|
||||||
date: ZodInteger.nullable().optional(),
|
|
||||||
/**
|
/**
|
||||||
* Creation years of the media
|
* Creation years of the media
|
||||||
*/
|
*/
|
||||||
time: ZodInteger.nullable().optional(),
|
datePublication: ZodIsoDate.nullable().optional(),
|
||||||
/**
|
/**
|
||||||
* Limitation Age of the media
|
* Limitation Age of the media
|
||||||
*/
|
*/
|
||||||
@ -112,14 +108,69 @@ export const ZodMediaWrite = ZodGenericDataSoftDeleteWrite.extend({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type MediaWrite = zod.infer<typeof ZodMediaWrite>;
|
export type MediaUpdate = zod.infer<typeof ZodMediaUpdate>;
|
||||||
|
|
||||||
export function isMediaWrite(data: any): data is MediaWrite {
|
export function isMediaUpdate(data: any): data is MediaUpdate {
|
||||||
try {
|
try {
|
||||||
ZodMediaWrite.parse(data);
|
ZodMediaUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodMediaWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodMediaUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodMediaCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||||
|
/**
|
||||||
|
* Name of the media (this represent the title)
|
||||||
|
*/
|
||||||
|
name: zod.string().max(256),
|
||||||
|
/**
|
||||||
|
* Description of the media
|
||||||
|
*/
|
||||||
|
description: zod.string().max(8192).nullable().optional(),
|
||||||
|
/**
|
||||||
|
* Foreign Key Id of the data
|
||||||
|
*/
|
||||||
|
dataId: ZodObjectId,
|
||||||
|
/**
|
||||||
|
* Type of the media
|
||||||
|
*/
|
||||||
|
typeId: ZodLong.nullable().optional(),
|
||||||
|
/**
|
||||||
|
* Series reference of the media
|
||||||
|
*/
|
||||||
|
seriesId: ZodLong.nullable().optional(),
|
||||||
|
/**
|
||||||
|
* Season reference of the media
|
||||||
|
*/
|
||||||
|
seasonId: ZodLong.nullable().optional(),
|
||||||
|
/**
|
||||||
|
* Episode Id
|
||||||
|
*/
|
||||||
|
episode: ZodInteger.nullable().optional(),
|
||||||
|
/**
|
||||||
|
* Creation years of the media
|
||||||
|
*/
|
||||||
|
datePublication: ZodIsoDate.nullable().optional(),
|
||||||
|
/**
|
||||||
|
* Limitation Age of the media
|
||||||
|
*/
|
||||||
|
ageLimit: ZodInteger.nullable().optional(),
|
||||||
|
/**
|
||||||
|
* List of Id of the specific covers
|
||||||
|
*/
|
||||||
|
covers: zod.array(ZodObjectId).nullable().optional(),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export type MediaCreate = zod.infer<typeof ZodMediaCreate>;
|
||||||
|
|
||||||
|
export function isMediaCreate(data: any): data is MediaCreate {
|
||||||
|
try {
|
||||||
|
ZodMediaCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodMediaCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodObjectId} from "./object-id";
|
import {ZodObjectId} from "./object-id";
|
||||||
import {ZodOIDGenericData, ZodOIDGenericDataWrite } from "./oid-generic-data";
|
import {ZodOIDGenericData, ZodOIDGenericDataUpdate , ZodOIDGenericDataCreate } from "./oid-generic-data";
|
||||||
|
|
||||||
export const ZodOIDGenericDataSoftDelete = ZodOIDGenericData.extend({
|
export const ZodOIDGenericDataSoftDelete = ZodOIDGenericData.extend({
|
||||||
/**
|
/**
|
||||||
@ -29,16 +29,29 @@ export function isOIDGenericDataSoftDelete(data: any): data is OIDGenericDataSof
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodOIDGenericDataSoftDeleteWrite = ZodOIDGenericDataWrite;
|
export const ZodOIDGenericDataSoftDeleteUpdate = ZodOIDGenericDataUpdate;
|
||||||
|
|
||||||
export type OIDGenericDataSoftDeleteWrite = zod.infer<typeof ZodOIDGenericDataSoftDeleteWrite>;
|
export type OIDGenericDataSoftDeleteUpdate = zod.infer<typeof ZodOIDGenericDataSoftDeleteUpdate>;
|
||||||
|
|
||||||
export function isOIDGenericDataSoftDeleteWrite(data: any): data is OIDGenericDataSoftDeleteWrite {
|
export function isOIDGenericDataSoftDeleteUpdate(data: any): data is OIDGenericDataSoftDeleteUpdate {
|
||||||
try {
|
try {
|
||||||
ZodOIDGenericDataSoftDeleteWrite.parse(data);
|
ZodOIDGenericDataSoftDeleteUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodOIDGenericDataSoftDeleteWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodOIDGenericDataSoftDeleteUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodOIDGenericDataSoftDeleteCreate = ZodOIDGenericDataCreate;
|
||||||
|
|
||||||
|
export type OIDGenericDataSoftDeleteCreate = zod.infer<typeof ZodOIDGenericDataSoftDeleteCreate>;
|
||||||
|
|
||||||
|
export function isOIDGenericDataSoftDeleteCreate(data: any): data is OIDGenericDataSoftDeleteCreate {
|
||||||
|
try {
|
||||||
|
ZodOIDGenericDataSoftDeleteCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodOIDGenericDataSoftDeleteCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodObjectId} from "./object-id";
|
import {ZodObjectId} from "./object-id";
|
||||||
import {ZodGenericTiming, ZodGenericTimingWrite } from "./generic-timing";
|
import {ZodGenericTiming, ZodGenericTimingUpdate , ZodGenericTimingCreate } from "./generic-timing";
|
||||||
|
|
||||||
export const ZodOIDGenericData = ZodGenericTiming.extend({
|
export const ZodOIDGenericData = ZodGenericTiming.extend({
|
||||||
/**
|
/**
|
||||||
@ -25,16 +25,29 @@ export function isOIDGenericData(data: any): data is OIDGenericData {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodOIDGenericDataWrite = ZodGenericTimingWrite;
|
export const ZodOIDGenericDataUpdate = ZodGenericTimingUpdate;
|
||||||
|
|
||||||
export type OIDGenericDataWrite = zod.infer<typeof ZodOIDGenericDataWrite>;
|
export type OIDGenericDataUpdate = zod.infer<typeof ZodOIDGenericDataUpdate>;
|
||||||
|
|
||||||
export function isOIDGenericDataWrite(data: any): data is OIDGenericDataWrite {
|
export function isOIDGenericDataUpdate(data: any): data is OIDGenericDataUpdate {
|
||||||
try {
|
try {
|
||||||
ZodOIDGenericDataWrite.parse(data);
|
ZodOIDGenericDataUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodOIDGenericDataWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodOIDGenericDataUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodOIDGenericDataCreate = ZodGenericTimingCreate;
|
||||||
|
|
||||||
|
export type OIDGenericDataCreate = zod.infer<typeof ZodOIDGenericDataCreate>;
|
||||||
|
|
||||||
|
export function isOIDGenericDataCreate(data: any): data is OIDGenericDataCreate {
|
||||||
|
try {
|
||||||
|
ZodOIDGenericDataCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodOIDGenericDataCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
*/
|
*/
|
||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodObjectId} from "./object-id";
|
|
||||||
import {ZodInteger} from "./integer";
|
import {ZodInteger} from "./integer";
|
||||||
|
import {ZodObjectId} from "./object-id";
|
||||||
|
import {ZodRestInputError} from "./rest-input-error";
|
||||||
|
|
||||||
export const ZodRestErrorResponse = zod.object({
|
export const ZodRestErrorResponse = zod.object({
|
||||||
oid: ZodObjectId.optional(),
|
oid: ZodObjectId.optional(),
|
||||||
@ -13,6 +14,7 @@ export const ZodRestErrorResponse = zod.object({
|
|||||||
time: zod.string(),
|
time: zod.string(),
|
||||||
status: ZodInteger,
|
status: ZodInteger,
|
||||||
statusMessage: zod.string(),
|
statusMessage: zod.string(),
|
||||||
|
inputError: zod.array(ZodRestInputError).optional(),
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
24
front/src/back-api/model/rest-input-error.ts
Normal file
24
front/src/back-api/model/rest-input-error.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Interface of the server (auto-generated code)
|
||||||
|
*/
|
||||||
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
|
|
||||||
|
export const ZodRestInputError = zod.object({
|
||||||
|
argument: zod.string().optional(),
|
||||||
|
path: zod.string().optional(),
|
||||||
|
message: zod.string(),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export type RestInputError = zod.infer<typeof ZodRestInputError>;
|
||||||
|
|
||||||
|
export function isRestInputError(data: any): data is RestInputError {
|
||||||
|
try {
|
||||||
|
ZodRestInputError.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodRestInputError' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -3,19 +3,19 @@
|
|||||||
*/
|
*/
|
||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodLong} from "./long";
|
|
||||||
import {ZodObjectId} from "./object-id";
|
import {ZodObjectId} from "./object-id";
|
||||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
import {ZodLong} from "./long";
|
||||||
|
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||||
|
|
||||||
export const ZodSeason = ZodGenericDataSoftDelete.extend({
|
export const ZodSeason = ZodGenericDataSoftDelete.extend({
|
||||||
/**
|
/**
|
||||||
* Name of the media (this represent the title)
|
* Name of the media (this represent the title)
|
||||||
*/
|
*/
|
||||||
name: zod.string(),
|
name: zod.string().max(256),
|
||||||
/**
|
/**
|
||||||
* Description of the media
|
* Description of the media
|
||||||
*/
|
*/
|
||||||
description: zod.string().optional(),
|
description: zod.string().max(8192).optional(),
|
||||||
/**
|
/**
|
||||||
* series parent ID
|
* series parent ID
|
||||||
*/
|
*/
|
||||||
@ -38,19 +38,19 @@ export function isSeason(data: any): data is Season {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodSeasonWrite = ZodGenericDataSoftDeleteWrite.extend({
|
export const ZodSeasonUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||||
/**
|
/**
|
||||||
* Name of the media (this represent the title)
|
* Name of the media (this represent the title)
|
||||||
*/
|
*/
|
||||||
name: zod.string().optional(),
|
name: zod.string().max(256),
|
||||||
/**
|
/**
|
||||||
* Description of the media
|
* Description of the media
|
||||||
*/
|
*/
|
||||||
description: zod.string().nullable().optional(),
|
description: zod.string().max(8192).nullable().optional(),
|
||||||
/**
|
/**
|
||||||
* series parent ID
|
* series parent ID
|
||||||
*/
|
*/
|
||||||
parentId: ZodLong.optional(),
|
parentId: ZodLong,
|
||||||
/**
|
/**
|
||||||
* List of Id of the specific covers
|
* List of Id of the specific covers
|
||||||
*/
|
*/
|
||||||
@ -58,14 +58,45 @@ export const ZodSeasonWrite = ZodGenericDataSoftDeleteWrite.extend({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SeasonWrite = zod.infer<typeof ZodSeasonWrite>;
|
export type SeasonUpdate = zod.infer<typeof ZodSeasonUpdate>;
|
||||||
|
|
||||||
export function isSeasonWrite(data: any): data is SeasonWrite {
|
export function isSeasonUpdate(data: any): data is SeasonUpdate {
|
||||||
try {
|
try {
|
||||||
ZodSeasonWrite.parse(data);
|
ZodSeasonUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodSeasonWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodSeasonUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodSeasonCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||||
|
/**
|
||||||
|
* Name of the media (this represent the title)
|
||||||
|
*/
|
||||||
|
name: zod.string().max(256),
|
||||||
|
/**
|
||||||
|
* Description of the media
|
||||||
|
*/
|
||||||
|
description: zod.string().max(8192).nullable().optional(),
|
||||||
|
/**
|
||||||
|
* series parent ID
|
||||||
|
*/
|
||||||
|
parentId: ZodLong,
|
||||||
|
/**
|
||||||
|
* List of Id of the specific covers
|
||||||
|
*/
|
||||||
|
covers: zod.array(ZodObjectId).nullable().optional(),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export type SeasonCreate = zod.infer<typeof ZodSeasonCreate>;
|
||||||
|
|
||||||
|
export function isSeasonCreate(data: any): data is SeasonCreate {
|
||||||
|
try {
|
||||||
|
ZodSeasonCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodSeasonCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,19 @@
|
|||||||
*/
|
*/
|
||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodLong} from "./long";
|
|
||||||
import {ZodObjectId} from "./object-id";
|
import {ZodObjectId} from "./object-id";
|
||||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
import {ZodLong} from "./long";
|
||||||
|
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||||
|
|
||||||
export const ZodSeries = ZodGenericDataSoftDelete.extend({
|
export const ZodSeries = ZodGenericDataSoftDelete.extend({
|
||||||
/**
|
/**
|
||||||
* Name of the media (this represent the title)
|
* Name of the media (this represent the title)
|
||||||
*/
|
*/
|
||||||
name: zod.string(),
|
name: zod.string().max(256),
|
||||||
/**
|
/**
|
||||||
* Description of the media
|
* Description of the media
|
||||||
*/
|
*/
|
||||||
description: zod.string().optional(),
|
description: zod.string().max(8192).optional(),
|
||||||
/**
|
/**
|
||||||
* series parent ID
|
* series parent ID
|
||||||
*/
|
*/
|
||||||
@ -38,19 +38,19 @@ export function isSeries(data: any): data is Series {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodSeriesWrite = ZodGenericDataSoftDeleteWrite.extend({
|
export const ZodSeriesUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||||
/**
|
/**
|
||||||
* Name of the media (this represent the title)
|
* Name of the media (this represent the title)
|
||||||
*/
|
*/
|
||||||
name: zod.string().optional(),
|
name: zod.string().max(256),
|
||||||
/**
|
/**
|
||||||
* Description of the media
|
* Description of the media
|
||||||
*/
|
*/
|
||||||
description: zod.string().nullable().optional(),
|
description: zod.string().max(8192).nullable().optional(),
|
||||||
/**
|
/**
|
||||||
* series parent ID
|
* series parent ID
|
||||||
*/
|
*/
|
||||||
parentId: ZodLong.optional(),
|
parentId: ZodLong,
|
||||||
/**
|
/**
|
||||||
* List of Id of the specific covers
|
* List of Id of the specific covers
|
||||||
*/
|
*/
|
||||||
@ -58,14 +58,45 @@ export const ZodSeriesWrite = ZodGenericDataSoftDeleteWrite.extend({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SeriesWrite = zod.infer<typeof ZodSeriesWrite>;
|
export type SeriesUpdate = zod.infer<typeof ZodSeriesUpdate>;
|
||||||
|
|
||||||
export function isSeriesWrite(data: any): data is SeriesWrite {
|
export function isSeriesUpdate(data: any): data is SeriesUpdate {
|
||||||
try {
|
try {
|
||||||
ZodSeriesWrite.parse(data);
|
ZodSeriesUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodSeriesWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodSeriesUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodSeriesCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||||
|
/**
|
||||||
|
* Name of the media (this represent the title)
|
||||||
|
*/
|
||||||
|
name: zod.string().max(256),
|
||||||
|
/**
|
||||||
|
* Description of the media
|
||||||
|
*/
|
||||||
|
description: zod.string().max(8192).nullable().optional(),
|
||||||
|
/**
|
||||||
|
* series parent ID
|
||||||
|
*/
|
||||||
|
parentId: ZodLong,
|
||||||
|
/**
|
||||||
|
* List of Id of the specific covers
|
||||||
|
*/
|
||||||
|
covers: zod.array(ZodObjectId).nullable().optional(),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export type SeriesCreate = zod.infer<typeof ZodSeriesCreate>;
|
||||||
|
|
||||||
|
export function isSeriesCreate(data: any): data is SeriesCreate {
|
||||||
|
try {
|
||||||
|
ZodSeriesCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodSeriesCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,17 @@
|
|||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodObjectId} from "./object-id";
|
import {ZodObjectId} from "./object-id";
|
||||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||||
|
|
||||||
export const ZodType = ZodGenericDataSoftDelete.extend({
|
export const ZodType = ZodGenericDataSoftDelete.extend({
|
||||||
/**
|
/**
|
||||||
* Name of the media (this represent the title)
|
* Name of the media (this represent the title)
|
||||||
*/
|
*/
|
||||||
name: zod.string(),
|
name: zod.string().max(256),
|
||||||
/**
|
/**
|
||||||
* Description of the media
|
* Description of the media
|
||||||
*/
|
*/
|
||||||
description: zod.string().optional(),
|
description: zod.string().max(8192).optional(),
|
||||||
/**
|
/**
|
||||||
* List of Id of the specific covers
|
* List of Id of the specific covers
|
||||||
*/
|
*/
|
||||||
@ -33,15 +33,15 @@ export function isType(data: any): data is Type {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodTypeWrite = ZodGenericDataSoftDeleteWrite.extend({
|
export const ZodTypeUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||||
/**
|
/**
|
||||||
* Name of the media (this represent the title)
|
* Name of the media (this represent the title)
|
||||||
*/
|
*/
|
||||||
name: zod.string().optional(),
|
name: zod.string().max(256),
|
||||||
/**
|
/**
|
||||||
* Description of the media
|
* Description of the media
|
||||||
*/
|
*/
|
||||||
description: zod.string().nullable().optional(),
|
description: zod.string().max(8192).nullable().optional(),
|
||||||
/**
|
/**
|
||||||
* List of Id of the specific covers
|
* List of Id of the specific covers
|
||||||
*/
|
*/
|
||||||
@ -49,14 +49,41 @@ export const ZodTypeWrite = ZodGenericDataSoftDeleteWrite.extend({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TypeWrite = zod.infer<typeof ZodTypeWrite>;
|
export type TypeUpdate = zod.infer<typeof ZodTypeUpdate>;
|
||||||
|
|
||||||
export function isTypeWrite(data: any): data is TypeWrite {
|
export function isTypeUpdate(data: any): data is TypeUpdate {
|
||||||
try {
|
try {
|
||||||
ZodTypeWrite.parse(data);
|
ZodTypeUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodTypeWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodTypeUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodTypeCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||||
|
/**
|
||||||
|
* Name of the media (this represent the title)
|
||||||
|
*/
|
||||||
|
name: zod.string().max(256),
|
||||||
|
/**
|
||||||
|
* Description of the media
|
||||||
|
*/
|
||||||
|
description: zod.string().max(8192).nullable().optional(),
|
||||||
|
/**
|
||||||
|
* List of Id of the specific covers
|
||||||
|
*/
|
||||||
|
covers: zod.array(ZodObjectId).nullable().optional(),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TypeCreate = zod.infer<typeof ZodTypeCreate>;
|
||||||
|
|
||||||
|
export function isTypeCreate(data: any): data is TypeCreate {
|
||||||
|
try {
|
||||||
|
ZodTypeCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodTypeCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodUser, ZodUserWrite } from "./user";
|
import {ZodUser, ZodUserUpdate , ZodUserCreate } from "./user";
|
||||||
|
|
||||||
export const ZodUserKarideo = ZodUser;
|
export const ZodUserKarideo = ZodUser;
|
||||||
|
|
||||||
@ -18,16 +18,3 @@ export function isUserKarideo(data: any): data is UserKarideo {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodUserKarideoWrite = ZodUserWrite;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,15 +4,15 @@
|
|||||||
import { z as zod } from "zod";
|
import { z as zod } from "zod";
|
||||||
|
|
||||||
import {ZodLong} from "./long";
|
import {ZodLong} from "./long";
|
||||||
import {ZodFloat} from "./float";
|
|
||||||
import {ZodInteger} from "./integer";
|
import {ZodInteger} from "./integer";
|
||||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
import {ZodFloat} from "./float";
|
||||||
|
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||||
|
|
||||||
export const ZodUserMediaAdvancement = ZodGenericDataSoftDelete.extend({
|
export const ZodUserMediaAdvancement = ZodGenericDataSoftDelete.extend({
|
||||||
/**
|
/**
|
||||||
* Foreign Key Id of the user
|
* Foreign Key Id of the user
|
||||||
*/
|
*/
|
||||||
userId: ZodLong.optional(),
|
userId: ZodLong.readonly().optional(),
|
||||||
/**
|
/**
|
||||||
* Id of the media
|
* Id of the media
|
||||||
*/
|
*/
|
||||||
@ -43,38 +43,65 @@ export function isUserMediaAdvancement(data: any): data is UserMediaAdvancement
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodUserMediaAdvancementWrite = ZodGenericDataSoftDeleteWrite.extend({
|
export const ZodUserMediaAdvancementUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||||
/**
|
|
||||||
* Foreign Key Id of the user
|
|
||||||
*/
|
|
||||||
userId: ZodLong.nullable().optional(),
|
|
||||||
/**
|
/**
|
||||||
* Id of the media
|
* Id of the media
|
||||||
*/
|
*/
|
||||||
mediaId: ZodLong.optional(),
|
mediaId: ZodLong,
|
||||||
/**
|
/**
|
||||||
* Percent of advancement in the media
|
* Percent of advancement in the media
|
||||||
*/
|
*/
|
||||||
percent: ZodFloat.optional(),
|
percent: ZodFloat,
|
||||||
/**
|
/**
|
||||||
* Number of second of advancement in the media
|
* Number of second of advancement in the media
|
||||||
*/
|
*/
|
||||||
time: ZodInteger.optional(),
|
time: ZodInteger,
|
||||||
/**
|
/**
|
||||||
* Number of time this media has been read
|
* Number of time this media has been read
|
||||||
*/
|
*/
|
||||||
count: ZodInteger.optional(),
|
count: ZodInteger,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type UserMediaAdvancementWrite = zod.infer<typeof ZodUserMediaAdvancementWrite>;
|
export type UserMediaAdvancementUpdate = zod.infer<typeof ZodUserMediaAdvancementUpdate>;
|
||||||
|
|
||||||
export function isUserMediaAdvancementWrite(data: any): data is UserMediaAdvancementWrite {
|
export function isUserMediaAdvancementUpdate(data: any): data is UserMediaAdvancementUpdate {
|
||||||
try {
|
try {
|
||||||
ZodUserMediaAdvancementWrite.parse(data);
|
ZodUserMediaAdvancementUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodUserMediaAdvancementWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodUserMediaAdvancementUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodUserMediaAdvancementCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||||
|
/**
|
||||||
|
* 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 UserMediaAdvancementCreate = zod.infer<typeof ZodUserMediaAdvancementCreate>;
|
||||||
|
|
||||||
|
export function isUserMediaAdvancementCreate(data: any): data is UserMediaAdvancementCreate {
|
||||||
|
try {
|
||||||
|
ZodUserMediaAdvancementCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodUserMediaAdvancementCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,20 +22,3 @@ export function isUserOut(data: any): data is UserOut {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodUserOutWrite = zod.object({
|
|
||||||
id: ZodLong,
|
|
||||||
login: zod.string().nullable().optional(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -5,7 +5,7 @@ import { z as zod } from "zod";
|
|||||||
|
|
||||||
import {ZodTimestamp} from "./timestamp";
|
import {ZodTimestamp} from "./timestamp";
|
||||||
import {ZodUUID} from "./uuid";
|
import {ZodUUID} from "./uuid";
|
||||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||||
|
|
||||||
export const ZodUser = ZodGenericDataSoftDelete.extend({
|
export const ZodUser = ZodGenericDataSoftDelete.extend({
|
||||||
login: zod.string().min(3).max(128),
|
login: zod.string().min(3).max(128),
|
||||||
@ -30,8 +30,8 @@ export function isUser(data: any): data is User {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({
|
export const ZodUserUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||||
login: zod.string().min(3).max(128).optional(),
|
login: zod.string().min(3).max(128),
|
||||||
lastConnection: ZodTimestamp.nullable().optional(),
|
lastConnection: ZodTimestamp.nullable().optional(),
|
||||||
blocked: zod.boolean().nullable().optional(),
|
blocked: zod.boolean().nullable().optional(),
|
||||||
blockedReason: zod.string().max(512).nullable().optional(),
|
blockedReason: zod.string().max(512).nullable().optional(),
|
||||||
@ -42,14 +42,37 @@ export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type UserWrite = zod.infer<typeof ZodUserWrite>;
|
export type UserUpdate = zod.infer<typeof ZodUserUpdate>;
|
||||||
|
|
||||||
export function isUserWrite(data: any): data is UserWrite {
|
export function isUserUpdate(data: any): data is UserUpdate {
|
||||||
try {
|
try {
|
||||||
ZodUserWrite.parse(data);
|
ZodUserUpdate.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(`Fail to parse data type='ZodUserWrite' error=${e}`);
|
console.log(`Fail to parse data type='ZodUserUpdate' error=${e}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const ZodUserCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||||
|
login: zod.string().min(3).max(128),
|
||||||
|
lastConnection: ZodTimestamp.nullable().optional(),
|
||||||
|
blocked: zod.boolean().nullable().optional(),
|
||||||
|
blockedReason: zod.string().max(512).nullable().optional(),
|
||||||
|
/**
|
||||||
|
* List of Id of the specific covers
|
||||||
|
*/
|
||||||
|
covers: zod.array(ZodUUID).nullable().optional(),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export type UserCreate = zod.infer<typeof ZodUserCreate>;
|
||||||
|
|
||||||
|
export function isUserCreate(data: any): data is UserCreate {
|
||||||
|
try {
|
||||||
|
ZodUserCreate.parse(data);
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(`Fail to parse data type='ZodUserCreate' error=${e}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,30 +3,29 @@
|
|||||||
* @copyright 2024, Edouard DUPIN, all right reserved
|
* @copyright 2024, Edouard DUPIN, all right reserved
|
||||||
* @license MPL-2
|
* @license MPL-2
|
||||||
*/
|
*/
|
||||||
|
import { RestErrorResponse, isRestErrorResponse } from './model';
|
||||||
import { RestErrorResponse, isRestErrorResponse } from "./model";
|
|
||||||
|
|
||||||
export enum HTTPRequestModel {
|
export enum HTTPRequestModel {
|
||||||
ARCHIVE = "ARCHIVE",
|
ARCHIVE = 'ARCHIVE',
|
||||||
DELETE = "DELETE",
|
DELETE = 'DELETE',
|
||||||
HEAD = "HEAD",
|
HEAD = 'HEAD',
|
||||||
GET = "GET",
|
GET = 'GET',
|
||||||
OPTION = "OPTION",
|
OPTION = 'OPTION',
|
||||||
PATCH = "PATCH",
|
PATCH = 'PATCH',
|
||||||
POST = "POST",
|
POST = 'POST',
|
||||||
PUT = "PUT",
|
PUT = 'PUT',
|
||||||
RESTORE = "RESTORE",
|
RESTORE = 'RESTORE',
|
||||||
}
|
}
|
||||||
export enum HTTPMimeType {
|
export enum HTTPMimeType {
|
||||||
ALL = "*/*",
|
ALL = '*/*',
|
||||||
CSV = "text/csv",
|
CSV = 'text/csv',
|
||||||
IMAGE = "image/*",
|
IMAGE = 'image/*',
|
||||||
IMAGE_JPEG = "image/jpeg",
|
IMAGE_JPEG = 'image/jpeg',
|
||||||
IMAGE_PNG = "image/png",
|
IMAGE_PNG = 'image/png',
|
||||||
JSON = "application/json",
|
JSON = 'application/json',
|
||||||
MULTIPART = "multipart/form-data",
|
MULTIPART = 'multipart/form-data',
|
||||||
OCTET_STREAM = "application/octet-stream",
|
OCTET_STREAM = 'application/octet-stream',
|
||||||
TEXT_PLAIN = "text/plain",
|
TEXT_PLAIN = 'text/plain',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RESTConfig {
|
export interface RESTConfig {
|
||||||
@ -54,6 +53,14 @@ export interface ModelResponseHttp {
|
|||||||
data: any;
|
data: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ErrorRestApiCallback = (response: Response) => void;
|
||||||
|
|
||||||
|
let errorApiGlobalCallback: ErrorRestApiCallback | undefined = undefined;
|
||||||
|
|
||||||
|
export const setErrorApiGlobalCallback = (callback: ErrorRestApiCallback) => {
|
||||||
|
errorApiGlobalCallback = callback;
|
||||||
|
};
|
||||||
|
|
||||||
function isNullOrUndefined(data: any): data is undefined | null {
|
function isNullOrUndefined(data: any): data is undefined | null {
|
||||||
return data === undefined || data === null;
|
return data === undefined || data === null;
|
||||||
}
|
}
|
||||||
@ -78,6 +85,7 @@ export interface RESTRequestType {
|
|||||||
data?: any;
|
data?: any;
|
||||||
params?: object;
|
params?: object;
|
||||||
queries?: object;
|
queries?: object;
|
||||||
|
headers?: any;
|
||||||
callbacks?: RESTCallbacks;
|
callbacks?: RESTCallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,15 +95,15 @@ function replaceAll(input, searchValue, replaceValue) {
|
|||||||
|
|
||||||
function removeTrailingSlashes(input: string): string {
|
function removeTrailingSlashes(input: string): string {
|
||||||
if (isNullOrUndefined(input)) {
|
if (isNullOrUndefined(input)) {
|
||||||
return "undefined";
|
return 'undefined';
|
||||||
}
|
}
|
||||||
return input.replace(/\/+$/, "");
|
return input.replace(/\/+$/, '');
|
||||||
}
|
}
|
||||||
function removeLeadingSlashes(input: string): string {
|
function removeLeadingSlashes(input: string): string {
|
||||||
if (isNullOrUndefined(input)) {
|
if (isNullOrUndefined(input)) {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
return input.replace(/^\/+/, "");
|
return input.replace(/^\/+/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RESTUrl({
|
export function RESTUrl({
|
||||||
@ -133,9 +141,9 @@ export function RESTUrl({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (restConfig.token !== undefined && restModel.tokenInUrl === true) {
|
if (restConfig.token !== undefined && restModel.tokenInUrl === true) {
|
||||||
searchParams.append("Authorization", `Bearer ${restConfig.token}`);
|
searchParams.append('Authorization', `Bearer ${restConfig.token}`);
|
||||||
}
|
}
|
||||||
return generateUrl + "?" + searchParams.toString();
|
return generateUrl + '?' + searchParams.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchProgress(
|
export function fetchProgress(
|
||||||
@ -159,7 +167,7 @@ export function fetchProgress(
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// Stream the upload progress
|
// Stream the upload progress
|
||||||
if (progressUpload) {
|
if (progressUpload) {
|
||||||
xhr.io?.upload.addEventListener("progress", (dataEvent) => {
|
xhr.io?.upload.addEventListener('progress', (dataEvent) => {
|
||||||
if (dataEvent.lengthComputable) {
|
if (dataEvent.lengthComputable) {
|
||||||
progressUpload(dataEvent.loaded, dataEvent.total);
|
progressUpload(dataEvent.loaded, dataEvent.total);
|
||||||
}
|
}
|
||||||
@ -167,7 +175,7 @@ export function fetchProgress(
|
|||||||
}
|
}
|
||||||
// Stream the download progress
|
// Stream the download progress
|
||||||
if (progressDownload) {
|
if (progressDownload) {
|
||||||
xhr.io?.addEventListener("progress", (dataEvent) => {
|
xhr.io?.addEventListener('progress', (dataEvent) => {
|
||||||
if (dataEvent.lengthComputable) {
|
if (dataEvent.lengthComputable) {
|
||||||
progressDownload(dataEvent.loaded, dataEvent.total);
|
progressDownload(dataEvent.loaded, dataEvent.total);
|
||||||
}
|
}
|
||||||
@ -187,19 +195,19 @@ export function fetchProgress(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Check if we have an internal Fail:
|
// Check if we have an internal Fail:
|
||||||
xhr.io?.addEventListener("error", () => {
|
xhr.io?.addEventListener('error', () => {
|
||||||
xhr.io = undefined;
|
xhr.io = undefined;
|
||||||
reject(new TypeError("Failed to fetch"));
|
reject(new TypeError('Failed to fetch'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Capture the end of the stream
|
// Capture the end of the stream
|
||||||
xhr.io?.addEventListener("loadend", () => {
|
xhr.io?.addEventListener('loadend', () => {
|
||||||
if (xhr.io?.readyState !== XMLHttpRequest.DONE) {
|
if (xhr.io?.readyState !== XMLHttpRequest.DONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (xhr.io?.status === 0) {
|
if (xhr.io?.status === 0) {
|
||||||
//the stream has been aborted
|
//the stream has been aborted
|
||||||
reject(new TypeError("Fetch has been aborted"));
|
reject(new TypeError('Fetch has been aborted'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Stream is ended, transform in a generic response:
|
// Stream is ended, transform in a generic response:
|
||||||
@ -209,17 +217,17 @@ export function fetchProgress(
|
|||||||
});
|
});
|
||||||
const headersArray = replaceAll(
|
const headersArray = replaceAll(
|
||||||
xhr.io.getAllResponseHeaders().trim(),
|
xhr.io.getAllResponseHeaders().trim(),
|
||||||
"\r\n",
|
'\r\n',
|
||||||
"\n"
|
'\n'
|
||||||
).split("\n");
|
).split('\n');
|
||||||
headersArray.forEach(function (header) {
|
headersArray.forEach(function (header) {
|
||||||
const firstColonIndex = header.indexOf(":");
|
const firstColonIndex = header.indexOf(':');
|
||||||
if (firstColonIndex !== -1) {
|
if (firstColonIndex !== -1) {
|
||||||
const key = header.substring(0, firstColonIndex).trim();
|
const key = header.substring(0, firstColonIndex).trim();
|
||||||
const value = header.substring(firstColonIndex + 1).trim();
|
const value = header.substring(firstColonIndex + 1).trim();
|
||||||
response.headers.set(key, value);
|
response.headers.set(key, value);
|
||||||
} else {
|
} else {
|
||||||
response.headers.set(header, "");
|
response.headers.set(header, '');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
xhr.io = undefined;
|
xhr.io = undefined;
|
||||||
@ -241,27 +249,29 @@ export function RESTRequest({
|
|||||||
data,
|
data,
|
||||||
params,
|
params,
|
||||||
queries,
|
queries,
|
||||||
|
headers = {},
|
||||||
callbacks,
|
callbacks,
|
||||||
}: RESTRequestType): Promise<ModelResponseHttp> {
|
}: RESTRequestType): Promise<ModelResponseHttp> {
|
||||||
// Create the URL PATH:
|
// Create the URL PATH:
|
||||||
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
||||||
let headers: any = {};
|
|
||||||
if (restConfig.token !== undefined && restModel.tokenInUrl !== true) {
|
if (restConfig.token !== undefined && restModel.tokenInUrl !== true) {
|
||||||
headers["Authorization"] = `Bearer ${restConfig.token}`;
|
headers['Authorization'] = `Bearer ${restConfig.token}`;
|
||||||
}
|
}
|
||||||
if (restModel.accept !== undefined) {
|
if (restModel.accept !== undefined) {
|
||||||
headers["Accept"] = restModel.accept;
|
headers['Accept'] = restModel.accept;
|
||||||
}
|
}
|
||||||
if (restModel.requestType !== HTTPRequestModel.GET &&
|
if (
|
||||||
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
|
restModel.requestType !== HTTPRequestModel.GET &&
|
||||||
restModel.requestType !== HTTPRequestModel.RESTORE
|
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
|
||||||
|
restModel.requestType !== HTTPRequestModel.RESTORE
|
||||||
) {
|
) {
|
||||||
// if Get we have not a content type, the body is empty
|
// if Get we have not a content type, the body is empty
|
||||||
if (restModel.contentType !== HTTPMimeType.MULTIPART &&
|
if (
|
||||||
restModel.contentType !== undefined
|
restModel.contentType !== HTTPMimeType.MULTIPART &&
|
||||||
) {
|
restModel.contentType !== undefined
|
||||||
|
) {
|
||||||
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
|
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
|
||||||
headers["Content-Type"] = restModel.contentType;
|
headers['Content-Type'] = restModel.contentType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let body = data;
|
let body = data;
|
||||||
@ -302,19 +312,27 @@ export function RESTRequest({
|
|||||||
}
|
}
|
||||||
action
|
action
|
||||||
.then((response: Response) => {
|
.then((response: Response) => {
|
||||||
|
if (
|
||||||
|
errorApiGlobalCallback &&
|
||||||
|
400 <= response.status &&
|
||||||
|
response.status <= 499
|
||||||
|
) {
|
||||||
|
// Detect an error and trigger the generic error callback:
|
||||||
|
errorApiGlobalCallback(response);
|
||||||
|
}
|
||||||
if (response.status >= 200 && response.status <= 299) {
|
if (response.status >= 200 && response.status <= 299) {
|
||||||
const contentType = response.headers.get("Content-Type");
|
const contentType = response.headers.get('Content-Type');
|
||||||
if (
|
if (
|
||||||
!isNullOrUndefined(restModel.accept) &&
|
!isNullOrUndefined(restModel.accept) &&
|
||||||
restModel.accept !== contentType
|
restModel.accept !== contentType
|
||||||
) {
|
) {
|
||||||
reject({
|
reject({
|
||||||
name: "Model accept type incompatible",
|
name: 'Model accept type incompatible',
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 901,
|
status: 901,
|
||||||
message: `REST Content type are not compatible: ${restModel.accept} != ${contentType}`,
|
message: `REST Content type are not compatible: ${restModel.accept} != ${contentType}`,
|
||||||
statusMessage: "Fetch error",
|
statusMessage: 'Fetch error',
|
||||||
error: "rest-tools.ts Wrong type in the message return type",
|
error: 'rest-tools.ts Wrong type in the message return type',
|
||||||
} as RestErrorResponse);
|
} as RestErrorResponse);
|
||||||
} else if (contentType === HTTPMimeType.JSON) {
|
} else if (contentType === HTTPMimeType.JSON) {
|
||||||
response
|
response
|
||||||
@ -324,12 +342,12 @@ export function RESTRequest({
|
|||||||
})
|
})
|
||||||
.catch((reason: Error) => {
|
.catch((reason: Error) => {
|
||||||
reject({
|
reject({
|
||||||
name: "API serialization error",
|
name: 'API serialization error',
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 902,
|
status: 902,
|
||||||
message: `REST parse json fail: ${reason}`,
|
message: `REST parse json fail: ${reason}`,
|
||||||
statusMessage: "Fetch parse error",
|
statusMessage: 'Fetch parse error',
|
||||||
error: "rest-tools.ts Wrong message model to parse",
|
error: 'rest-tools.ts Wrong message model to parse',
|
||||||
} as RestErrorResponse);
|
} as RestErrorResponse);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -349,22 +367,22 @@ export function RESTRequest({
|
|||||||
.text()
|
.text()
|
||||||
.then((dataError: string) => {
|
.then((dataError: string) => {
|
||||||
reject({
|
reject({
|
||||||
name: "API serialization error",
|
name: 'API serialization error',
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 903,
|
status: 903,
|
||||||
message: `REST parse error json with wrong type fail. ${dataError}`,
|
message: `REST parse error json with wrong type fail. ${dataError}`,
|
||||||
statusMessage: "Fetch parse error",
|
statusMessage: 'Fetch parse error',
|
||||||
error: "rest-tools.ts Wrong message model to parse",
|
error: 'rest-tools.ts Wrong message model to parse',
|
||||||
} as RestErrorResponse);
|
} as RestErrorResponse);
|
||||||
})
|
})
|
||||||
.catch((reason: any) => {
|
.catch((reason: any) => {
|
||||||
reject({
|
reject({
|
||||||
name: "API serialization error",
|
name: 'API serialization error',
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: response.status,
|
status: response.status,
|
||||||
message: `unmanaged error model: ??? with error: ${reason}`,
|
message: `unmanaged error model: ??? with error: ${reason}`,
|
||||||
statusMessage: "Fetch ERROR parse error",
|
statusMessage: 'Fetch ERROR parse error',
|
||||||
error: "rest-tools.ts Wrong message model to parse",
|
error: 'rest-tools.ts Wrong message model to parse',
|
||||||
} as RestErrorResponse);
|
} as RestErrorResponse);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -374,22 +392,22 @@ export function RESTRequest({
|
|||||||
.text()
|
.text()
|
||||||
.then((dataError: string) => {
|
.then((dataError: string) => {
|
||||||
reject({
|
reject({
|
||||||
name: "API serialization error",
|
name: 'API serialization error',
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: response.status,
|
status: response.status,
|
||||||
message: `unmanaged error model: ${dataError} with error: ${reason}`,
|
message: `unmanaged error model: ${dataError} with error: ${reason}`,
|
||||||
statusMessage: "Fetch ERROR TEXT parse error",
|
statusMessage: 'Fetch ERROR TEXT parse error',
|
||||||
error: "rest-tools.ts Wrong message model to parse",
|
error: 'rest-tools.ts Wrong message model to parse',
|
||||||
} as RestErrorResponse);
|
} as RestErrorResponse);
|
||||||
})
|
})
|
||||||
.catch((reason: any) => {
|
.catch((reason: any) => {
|
||||||
reject({
|
reject({
|
||||||
name: "API serialization error",
|
name: 'API serialization error',
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: response.status,
|
status: response.status,
|
||||||
message: `unmanaged error model: ??? with error: ${reason}`,
|
message: `unmanaged error model: ??? with error: ${reason}`,
|
||||||
statusMessage: "Fetch ERROR TEXT FAIL",
|
statusMessage: 'Fetch ERROR TEXT FAIL',
|
||||||
error: "rest-tools.ts Wrong message model to parse",
|
error: 'rest-tools.ts Wrong message model to parse',
|
||||||
} as RestErrorResponse);
|
} as RestErrorResponse);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -400,12 +418,12 @@ export function RESTRequest({
|
|||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
reject({
|
reject({
|
||||||
name: "Request fail",
|
name: 'Request fail',
|
||||||
time: Date(),
|
time: Date(),
|
||||||
status: 999,
|
status: 999,
|
||||||
message: error,
|
message: error,
|
||||||
statusMessage: "Fetch catch error",
|
statusMessage: 'Fetch catch error',
|
||||||
error: "rest-tools.ts detect an error in the fetch request",
|
error: 'rest-tools.ts detect an error in the fetch request',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -426,12 +444,12 @@ export function RESTRequestJson<TYPE>(
|
|||||||
resolve(value.data);
|
resolve(value.data);
|
||||||
} else {
|
} else {
|
||||||
reject({
|
reject({
|
||||||
name: "Model check fail",
|
name: 'Model check fail',
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 950,
|
status: 950,
|
||||||
error: "REST Fail to verify the data",
|
error: 'REST Fail to verify the data',
|
||||||
statusMessage: "API cast ERROR",
|
statusMessage: 'API cast ERROR',
|
||||||
message: "api.ts Check type as fail",
|
message: 'api.ts Check type as fail',
|
||||||
} as RestErrorResponse);
|
} as RestErrorResponse);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -8,7 +8,7 @@ import { DataUrlAccess } from '@/utils/data-url-access';
|
|||||||
import { Icon } from './Icon';
|
import { Icon } from './Icon';
|
||||||
|
|
||||||
export type CoversProps = Omit<BoxProps, 'iconEmpty'> & {
|
export type CoversProps = Omit<BoxProps, 'iconEmpty'> & {
|
||||||
data?: ObjectId[];
|
data?: readonly ObjectId[];
|
||||||
size?: BoxProps['width'];
|
size?: BoxProps['width'];
|
||||||
iconEmpty?: ReactElement;
|
iconEmpty?: ReactElement;
|
||||||
slideshow?: boolean;
|
slideshow?: boolean;
|
||||||
@ -70,7 +70,9 @@ export const Covers = ({
|
|||||||
src={url}
|
src={url}
|
||||||
maxWidth={size}
|
maxWidth={size}
|
||||||
maxHeight={size}
|
maxHeight={size}
|
||||||
boxSize={size}
|
//boxSize={size}
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1,26 +1,62 @@
|
|||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
import { Box, Button, ConditionalValue, Flex, HStack, IconButton, Span, Text, useDisclosure } from '@chakra-ui/react';
|
Button,
|
||||||
import { LuAlignJustify, LuArrowBigLeft, LuCircleUserRound, LuKeySquare, LuLogIn, LuLogOut, LuMoon, LuSettings, LuSun } from 'react-icons/lu';
|
ConditionalValue,
|
||||||
import { MdHelp, MdHome, MdMore, MdOutlinePlaylistPlay, MdOutlineUploadFile, MdSupervisedUserCircle } from 'react-icons/md';
|
Flex,
|
||||||
|
HStack,
|
||||||
|
IconButton,
|
||||||
|
Span,
|
||||||
|
Text,
|
||||||
|
useBreakpointValue,
|
||||||
|
useDisclosure,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import {
|
||||||
|
LuAlignJustify,
|
||||||
|
LuArrowBigLeft,
|
||||||
|
LuCircleUserRound,
|
||||||
|
LuKeySquare,
|
||||||
|
LuLogIn,
|
||||||
|
LuLogOut,
|
||||||
|
LuMoon,
|
||||||
|
LuSettings,
|
||||||
|
LuSun,
|
||||||
|
} from 'react-icons/lu';
|
||||||
|
import {
|
||||||
|
MdHelp,
|
||||||
|
MdHome,
|
||||||
|
MdMore,
|
||||||
|
MdOutlinePlaylistPlay,
|
||||||
|
MdOutlineUploadFile,
|
||||||
|
MdRestartAlt,
|
||||||
|
MdSupervisedUserCircle,
|
||||||
|
} from 'react-icons/md';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { useColorMode, useColorModeValue } from '@/components/ui/color-mode';
|
import { useColorMode, useColorModeValue } from '@/components/ui/color-mode';
|
||||||
import { DrawerBody, DrawerContent, DrawerHeader, DrawerRoot } from '@/components/ui/drawer';
|
import {
|
||||||
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '@/components/ui/menu';
|
DrawerBody,
|
||||||
|
DrawerContent,
|
||||||
|
DrawerHeader,
|
||||||
|
DrawerRoot,
|
||||||
|
} from '@/components/ui/drawer';
|
||||||
|
import {
|
||||||
|
MenuContent,
|
||||||
|
MenuItem,
|
||||||
|
MenuRoot,
|
||||||
|
MenuTrigger,
|
||||||
|
} from '@/components/ui/menu';
|
||||||
import { environment } from '@/environment';
|
import { environment } from '@/environment';
|
||||||
import { useServiceContext } from '@/service/ServiceContext';
|
import { useServiceContext } from '@/service/ServiceContext';
|
||||||
import { useSessionService } from '@/service/session';
|
import { useSessionService } from '@/service/session';
|
||||||
import { colors } from '@/theme/colors';
|
import { colors } from '@/theme/colors';
|
||||||
import { requestOpenSite, requestSignIn, requestSignOut, requestSignUp } from '@/utils/sso';
|
import {
|
||||||
|
requestOpenSite,
|
||||||
|
requestSignIn,
|
||||||
|
requestSignOut,
|
||||||
|
requestSignUp,
|
||||||
|
} from '@/utils/sso';
|
||||||
|
|
||||||
export const TOP_BAR_HEIGHT = '50px';
|
export const TOP_BAR_HEIGHT = '50px';
|
||||||
|
|
||||||
@ -37,6 +73,8 @@ export const BUTTON_TOP_BAR_PROPERTY = {
|
|||||||
export type TopBarProps = {
|
export type TopBarProps = {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
titleLink?: string;
|
||||||
|
titleIcon?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ButtonMenuLeft = ({
|
const ButtonMenuLeft = ({
|
||||||
@ -74,15 +112,25 @@ const ButtonMenuLeft = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export const TopBar = ({ title, children }: TopBarProps) => {
|
export const TopBar = ({
|
||||||
|
title,
|
||||||
|
titleLink,
|
||||||
|
titleIcon,
|
||||||
|
children,
|
||||||
|
}: TopBarProps) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { colorMode, toggleColorMode } = useColorMode();
|
const { colorMode, toggleColorMode } = useColorMode();
|
||||||
const { session } = useServiceContext();
|
const { session } = useServiceContext();
|
||||||
const { clearToken } = useSessionService();
|
const { clearToken, isConnected } = useSessionService();
|
||||||
const backColor = useColorModeValue('back.100', 'back.800');
|
const backColor = useColorModeValue('back.100', 'back.800');
|
||||||
const drawerDisclose = useDisclosure();
|
const drawerDisclose = useDisclosure();
|
||||||
const onChangeTheme = () => {
|
const isVisible = useBreakpointValue({ base: false, md: true });
|
||||||
drawerDisclose.onOpen();
|
const onOpenLeftMenu = () => {
|
||||||
|
if (!isConnected) {
|
||||||
|
onForceReload();
|
||||||
|
} else {
|
||||||
|
drawerDisclose.onOpen();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const onSignIn = (): void => {
|
const onSignIn = (): void => {
|
||||||
clearToken();
|
clearToken();
|
||||||
@ -99,8 +147,13 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
|||||||
const onKarso = (): void => {
|
const onKarso = (): void => {
|
||||||
requestOpenSite();
|
requestOpenSite();
|
||||||
};
|
};
|
||||||
|
const onForceReload = (): void => {
|
||||||
|
// @ts-expect-error
|
||||||
|
window.location.reload(true);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
minWidth="320px"
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top={0}
|
top={0}
|
||||||
left={0}
|
left={0}
|
||||||
@ -114,33 +167,32 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
|||||||
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
||||||
zIndex={200}
|
zIndex={200}
|
||||||
>
|
>
|
||||||
{session?.isConnected ?
|
<Button {...BUTTON_TOP_BAR_PROPERTY} onClick={onOpenLeftMenu}>
|
||||||
<Button {...BUTTON_TOP_BAR_PROPERTY} onClick={onChangeTheme}>
|
|
||||||
<HStack>
|
<HStack>
|
||||||
<LuAlignJustify />
|
<LuAlignJustify />
|
||||||
<Text paddingLeft="3px" fontWeight="bold">
|
{isVisible && (
|
||||||
{environment.applName}
|
<Text paddingLeft="3px" fontWeight="bold">
|
||||||
</Text>
|
{environment.applName}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</HStack>
|
</HStack>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
:(
|
|
||||||
<HStack {...BUTTON_TOP_BAR_PROPERTY} >
|
|
||||||
<LuAlignJustify />
|
|
||||||
<Span paddingLeft="3px" fontWeight="bold">{environment.applName}</Span>
|
|
||||||
</HStack>)
|
|
||||||
}
|
|
||||||
{title && (
|
{title && (
|
||||||
<Text
|
<Flex
|
||||||
|
truncate
|
||||||
fontSize="20px"
|
fontSize="20px"
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
textTransform="uppercase"
|
textTransform="uppercase"
|
||||||
marginRight="auto"
|
marginRight="auto"
|
||||||
userSelect="none"
|
userSelect="none"
|
||||||
color="brand.500"
|
color="brand.500"
|
||||||
|
onClick={titleLink ? () => navigate(titleLink) : undefined}
|
||||||
>
|
>
|
||||||
{title}
|
<Flex gap="4px">
|
||||||
</Text>
|
{titleIcon}
|
||||||
|
{title}
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
)}
|
)}
|
||||||
{children}
|
{children}
|
||||||
<Flex right="0">
|
<Flex right="0">
|
||||||
@ -205,6 +257,13 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
|||||||
<MenuItem value="karso" valueText="Karso" onClick={onKarso}>
|
<MenuItem value="karso" valueText="Karso" onClick={onKarso}>
|
||||||
<LuKeySquare /> Karso (SSO)
|
<LuKeySquare /> Karso (SSO)
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
value="force_reload"
|
||||||
|
valueText="Karso"
|
||||||
|
onClick={onForceReload}
|
||||||
|
>
|
||||||
|
<MdRestartAlt /> force reload
|
||||||
|
</MenuItem>
|
||||||
{colorMode === 'light' ? (
|
{colorMode === 'light' ? (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
value="set-dark"
|
value="set-dark"
|
||||||
@ -226,52 +285,52 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
|||||||
</MenuRoot>
|
</MenuRoot>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
{session?.isConnected &&
|
{session?.isConnected && (
|
||||||
<DrawerRoot
|
<DrawerRoot
|
||||||
placement="start"
|
placement="start"
|
||||||
onOpenChange={drawerDisclose.onClose}
|
onOpenChange={drawerDisclose.onClose}
|
||||||
open={drawerDisclose.open}
|
open={drawerDisclose.open}
|
||||||
data-testid="top-bar_drawer-root"
|
data-testid="top-bar_drawer-root"
|
||||||
>
|
>
|
||||||
<DrawerContent data-testid="top-bar_drawer-content">
|
<DrawerContent data-testid="top-bar_drawer-content">
|
||||||
<DrawerHeader
|
<DrawerHeader
|
||||||
paddingY="auto"
|
paddingY="auto"
|
||||||
as="button"
|
as="button"
|
||||||
onClick={drawerDisclose.onClose}
|
onClick={drawerDisclose.onClose}
|
||||||
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
||||||
backgroundColor={backColor}
|
backgroundColor={backColor}
|
||||||
color={useColorModeValue('brand.900', 'brand.50')}
|
color={useColorModeValue('brand.900', 'brand.50')}
|
||||||
textTransform="uppercase"
|
textTransform="uppercase"
|
||||||
>
|
>
|
||||||
<HStack {...BUTTON_TOP_BAR_PROPERTY} cursor="pointer">
|
<HStack {...BUTTON_TOP_BAR_PROPERTY} cursor="pointer">
|
||||||
<LuArrowBigLeft />
|
<LuArrowBigLeft />
|
||||||
<Span paddingLeft="3px">{environment.applName}</Span>
|
<Span paddingLeft="3px">{environment.applName}</Span>
|
||||||
</HStack>
|
</HStack>
|
||||||
</DrawerHeader>
|
</DrawerHeader>
|
||||||
<DrawerBody paddingX="0px">
|
<DrawerBody paddingX="0px">
|
||||||
<Box marginY="3" />
|
<Box marginY="3" />
|
||||||
<ButtonMenuLeft
|
<ButtonMenuLeft
|
||||||
onClickEnd={drawerDisclose.onClose}
|
onClickEnd={drawerDisclose.onClose}
|
||||||
dest="/"
|
dest="/"
|
||||||
title="Home"
|
title="Home"
|
||||||
icon={<MdHome />}
|
icon={<MdHome />}
|
||||||
/>
|
/>
|
||||||
<ButtonMenuLeft
|
<ButtonMenuLeft
|
||||||
onClickEnd={drawerDisclose.onClose}
|
onClickEnd={drawerDisclose.onClose}
|
||||||
dest="/on-air"
|
dest="/on-air"
|
||||||
title="On air"
|
title="On air"
|
||||||
icon={<MdOutlinePlaylistPlay />}
|
icon={<MdOutlinePlaylistPlay />}
|
||||||
/>
|
/>
|
||||||
<ButtonMenuLeft
|
<ButtonMenuLeft
|
||||||
onClickEnd={drawerDisclose.onClose}
|
onClickEnd={drawerDisclose.onClose}
|
||||||
dest="/add"
|
dest="/add"
|
||||||
title="Add Media"
|
title="Add Media"
|
||||||
icon={<MdOutlineUploadFile />}
|
icon={<MdOutlineUploadFile />}
|
||||||
/>
|
/>
|
||||||
</DrawerBody>
|
</DrawerBody>
|
||||||
</DrawerContent>
|
</DrawerContent>
|
||||||
</DrawerRoot>
|
</DrawerRoot>
|
||||||
}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
import { Box, chakra, Flex, IconButton, SliderTrack, Spacer, Text, useBreakpointValue } from '@chakra-ui/react';
|
import {
|
||||||
|
Box,
|
||||||
|
Flex,
|
||||||
|
IconButton,
|
||||||
|
SliderTrack,
|
||||||
|
Spacer,
|
||||||
|
Text,
|
||||||
|
useBreakpointValue,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
import {
|
import {
|
||||||
MdFastForward,
|
MdFastForward,
|
||||||
MdFastRewind,
|
MdFastRewind,
|
||||||
@ -16,7 +24,7 @@ import {
|
|||||||
MdRepeat,
|
MdRepeat,
|
||||||
MdRepeatOne,
|
MdRepeatOne,
|
||||||
MdStop,
|
MdStop,
|
||||||
MdTrendingFlat
|
MdTrendingFlat,
|
||||||
} from 'react-icons/md';
|
} from 'react-icons/md';
|
||||||
|
|
||||||
import { useColorModeValue } from '@/components/ui/color-mode';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
@ -70,15 +78,15 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
|||||||
const [isRunning, setIsRunning] = useState(true);
|
const [isRunning, setIsRunning] = useState(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isRunning || time <= 0) {
|
if (!isRunning || time <= 0) {
|
||||||
console.log(`exit timer`);
|
console.log(`exit timer`);
|
||||||
setIsRunning(false);
|
setIsRunning(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => {
|
||||||
setTime((prevTime) => {
|
setTime((prevTime) => {
|
||||||
console.log(`current time : ${prevTime}`);
|
console.log(`current time : ${prevTime}`);
|
||||||
return prevTime - 1;
|
return prevTime - 1;
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
return () => clearInterval(timer);
|
return () => clearInterval(timer);
|
||||||
@ -97,9 +105,9 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
|||||||
setIsRunning(true);
|
setIsRunning(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener("mousemove", resetTimerLocal);
|
window.addEventListener('mousemove', resetTimerLocal);
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("mousemove", resetTimerLocal);
|
window.removeEventListener('mousemove', resetTimerLocal);
|
||||||
};
|
};
|
||||||
}, [playMediaList, setTime, setIsRunning]);
|
}, [playMediaList, setTime, setIsRunning]);
|
||||||
|
|
||||||
@ -121,30 +129,33 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMediaSource(
|
setMediaSource(
|
||||||
dataMedia && dataMedia?.dataId
|
dataMedia && dataMedia?.dataId
|
||||||
? DataUrlAccess.getUrl(dataMedia?.dataId)
|
? DataUrlAccess.getUrl(dataMedia?.dataId, 'plop.mkv')
|
||||||
: ''
|
: ''
|
||||||
);
|
);
|
||||||
}, [dataMedia, setMediaSource]);
|
}, [dataMedia, setMediaSource]);
|
||||||
|
console.log(`mediaSource = ${mediaSource}`);
|
||||||
const backColor = useColorModeValue('back.100', 'back.800');
|
const backColor = useColorModeValue('back.100', 'back.800');
|
||||||
const configButton = isMobile ? {
|
const configButton = isMobile
|
||||||
borderRadius: 'full',
|
? {
|
||||||
backgroundColor: 'transparent',
|
borderRadius: 'full',
|
||||||
_hover: {
|
backgroundColor: 'transparent',
|
||||||
bgColor: 'brand.500',
|
_hover: {
|
||||||
},
|
bgColor: 'brand.500',
|
||||||
width: '35px',
|
},
|
||||||
height: '35px',
|
width: '35px',
|
||||||
padding: '2px',
|
height: '35px',
|
||||||
} : {
|
padding: '2px',
|
||||||
borderRadius: 'full',
|
}
|
||||||
backgroundColor: 'transparent',
|
: {
|
||||||
_hover: {
|
borderRadius: 'full',
|
||||||
bgColor: 'brand.500',
|
backgroundColor: 'transparent',
|
||||||
},
|
_hover: {
|
||||||
width: '50px',
|
bgColor: 'brand.500',
|
||||||
height: '50px',
|
},
|
||||||
padding: '5px',
|
width: '50px',
|
||||||
};
|
height: '50px',
|
||||||
|
padding: '5px',
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!videoRef || !videoRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
@ -237,6 +248,7 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
|||||||
* Call when meta-data is updated
|
* Call when meta-data is updated
|
||||||
*/
|
*/
|
||||||
function onChangeMetadata(): void {
|
function onChangeMetadata(): void {
|
||||||
|
console.log(`onChangeMetadata: ${videoRef.current?.duration}`);
|
||||||
const seconds = videoRef.current?.duration;
|
const seconds = videoRef.current?.duration;
|
||||||
if (seconds !== undefined) {
|
if (seconds !== undefined) {
|
||||||
setDuration(seconds);
|
setDuration(seconds);
|
||||||
@ -246,14 +258,16 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
|||||||
if (!videoRef || !videoRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//console.log(`onTimeUpdate ${videoRef.current.currentTime}`);
|
console.log(`onTimeUpdate ${videoRef.current.currentTime}`);
|
||||||
setTimeProgress(videoRef.current.currentTime);
|
setTimeProgress(videoRef.current.currentTime);
|
||||||
};
|
};
|
||||||
const onDurationChange = (event) => {};
|
const onDurationChange = (event) => {};
|
||||||
const onChangeStateToPlay = () => {
|
const onChangeStateToPlay = () => {
|
||||||
|
console.log(`onChangeStateToPlay ...`);
|
||||||
setIsPlaying(true);
|
setIsPlaying(true);
|
||||||
};
|
};
|
||||||
const onChangeStateToPause = () => {
|
const onChangeStateToPause = () => {
|
||||||
|
console.log(`onChangeStateToPause ...`);
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
};
|
};
|
||||||
const marks = () => {
|
const marks = () => {
|
||||||
@ -292,208 +306,227 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
|||||||
setIsPiP(false);
|
setIsPiP(false);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur avec Picture-in-Picture:", error);
|
console.error('Erreur avec Picture-in-Picture:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const [isFullScreen, setIsFullScreen] = useState(false);
|
const [isFullScreen, setIsFullScreen] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleFullScreenChange = () => {
|
const handleFullScreenChange = () => {
|
||||||
console.log(`changeFullScreen: ${!!document.fullscreenElement}`)
|
console.log(`changeFullScreen: ${!!document.fullscreenElement}`);
|
||||||
setIsFullScreen(!!document.fullscreenElement);
|
setIsFullScreen(!!document.fullscreenElement);
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("fullscreenchange", handleFullScreenChange);
|
document.addEventListener('fullscreenchange', handleFullScreenChange);
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener("fullscreenchange", handleFullScreenChange);
|
document.removeEventListener('fullscreenchange', handleFullScreenChange);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isNullOrUndefined(MediaOffset) && (
|
{!isNullOrUndefined(MediaOffset) && (
|
||||||
<>
|
<>
|
||||||
<Flex
|
<Flex
|
||||||
position="absolute"
|
position="absolute"
|
||||||
//height="500px"
|
//height="500px"
|
||||||
minHeight="150px"
|
minHeight="150px"
|
||||||
paddingY="5px"
|
paddingY="5px"
|
||||||
paddingX="10px"
|
paddingX="10px"
|
||||||
marginX="15px"
|
marginX="15px"
|
||||||
bottom={0}
|
bottom={0}
|
||||||
left={0}
|
left={0}
|
||||||
right={0}
|
right={0}
|
||||||
zIndex={1000}
|
zIndex={1000}
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
bgColor={isFullScreen ? "0x000000" : backColor}
|
bgColor={isFullScreen ? '0x000000' : backColor}
|
||||||
borderTopRadius="10px"
|
borderTopRadius="10px"
|
||||||
direction="column"
|
direction="column"
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
>
|
>
|
||||||
<chakra.video
|
<Flex
|
||||||
position={isFullScreen ? "absolute" : "relative"}
|
position={isFullScreen ? 'absolute' : 'relative'}
|
||||||
maxHeight={isFullScreen ? undefined : "30vh"}
|
maxHeight={isFullScreen ? undefined : '30vh'}
|
||||||
maxWidth={isFullScreen ? undefined : "100%"}
|
maxWidth={isFullScreen ? undefined : '100%'}
|
||||||
height={isFullScreen ? "100%" : undefined}
|
|
||||||
width={isFullScreen ? "100%": undefined}
|
|
||||||
marginX="auto"
|
marginX="auto"
|
||||||
src={mediaSource}
|
>
|
||||||
ref={videoRef}
|
<video
|
||||||
//preload={true}
|
height={isFullScreen ? '100%' : undefined}
|
||||||
onPlay={onChangeStateToPlay}
|
width={isFullScreen ? '100%' : undefined}
|
||||||
onPause={onChangeStateToPause}
|
src={mediaSource}
|
||||||
onTimeUpdate={onTimeUpdate}
|
ref={videoRef}
|
||||||
onDurationChange={onDurationChange}
|
onPlay={onChangeStateToPlay}
|
||||||
onLoadedMetadata={onChangeMetadata}
|
onPause={onChangeStateToPause}
|
||||||
autoPlay={true}
|
onTimeUpdate={onTimeUpdate}
|
||||||
onEnded={onAudioEnded}
|
onDurationChange={onDurationChange}
|
||||||
|
onLoadedMetadata={onChangeMetadata}
|
||||||
|
autoPlay={true}
|
||||||
|
onEnded={onAudioEnded}
|
||||||
/>
|
/>
|
||||||
{(!isFullScreen || (!isMobile || isRunning)) && <><Text
|
</Flex>
|
||||||
alignContent="left"
|
{(!isFullScreen || !isMobile || isRunning) && (
|
||||||
fontSize="20px"
|
<>
|
||||||
fontWeight="bold"
|
<Text
|
||||||
userSelect="none"
|
alignContent="left"
|
||||||
marginRight="auto"
|
fontSize="20px"
|
||||||
overflow="hidden"
|
fontWeight="bold"
|
||||||
// noOfLines={1}
|
userSelect="none"
|
||||||
>
|
marginRight="auto"
|
||||||
{dataMedia?.name ?? '???'}
|
overflow="hidden"
|
||||||
</Text>
|
// noOfLines={1}
|
||||||
<Text
|
>
|
||||||
alignContent="left"
|
{dataMedia?.name ?? '???'}
|
||||||
fontSize="16px"
|
</Text>
|
||||||
userSelect="none"
|
<Text
|
||||||
marginRight="auto"
|
alignContent="left"
|
||||||
overflow="hidden"
|
fontSize="16px"
|
||||||
// noOfLines={1}
|
userSelect="none"
|
||||||
>
|
marginRight="auto"
|
||||||
{dataSeries && dataSeries.name}
|
overflow="hidden"
|
||||||
{dataSeason && dataSeason?.name}
|
// noOfLines={1}
|
||||||
{dataType && ` / ${dataType.name}`}
|
>
|
||||||
</Text>
|
{dataSeries && dataSeries.name}
|
||||||
{isFullScreen && <Spacer/>}
|
{dataSeason && dataSeason?.name}
|
||||||
<Box width="full" paddingX="15px">
|
{dataType && ` / ${dataType.name}`}
|
||||||
<Slider
|
</Text>
|
||||||
defaultValue={[0]}
|
{isFullScreen && <Spacer />}
|
||||||
value={[timeProgress]}
|
<Box width="full" paddingX="15px">
|
||||||
min={0}
|
<Slider
|
||||||
max={duration}
|
defaultValue={[0]}
|
||||||
step={0.1}
|
value={[timeProgress]}
|
||||||
onValueChange={(e) => onSeek(e.value)}
|
min={0}
|
||||||
variant="outline"
|
max={duration}
|
||||||
colorPalette="brand"
|
step={0.1}
|
||||||
marks={marks()}
|
onValueChange={(e) => onSeek(e.value)}
|
||||||
//focusCapture={false}
|
variant="outline"
|
||||||
>
|
colorPalette="brand"
|
||||||
<SliderTrack
|
marks={marks()}
|
||||||
bg="brand.200"
|
//focusCapture={false}
|
||||||
height="10px"
|
>
|
||||||
borderRadius="full"
|
<SliderTrack
|
||||||
></SliderTrack>
|
bg="brand.200"
|
||||||
</Slider>
|
height="10px"
|
||||||
</Box>
|
borderRadius="full"
|
||||||
<Flex>
|
></SliderTrack>
|
||||||
<Text
|
</Slider>
|
||||||
alignContent="left"
|
</Box>
|
||||||
fontSize="16px"
|
<Flex>
|
||||||
userSelect="none"
|
<Text
|
||||||
marginRight="auto"
|
alignContent="left"
|
||||||
overflow="hidden"
|
fontSize="16px"
|
||||||
// noOfLines={1}
|
userSelect="none"
|
||||||
>
|
marginRight="auto"
|
||||||
{formatTime(timeProgress)}
|
overflow="hidden"
|
||||||
</Text>
|
// noOfLines={1}
|
||||||
<Text alignContent="left" fontSize="16px" userSelect="none">
|
>
|
||||||
{formatTime(duration)}
|
{formatTime(timeProgress)}
|
||||||
</Text>
|
</Text>
|
||||||
|
<Text alignContent="left" fontSize="16px" userSelect="none">
|
||||||
|
{formatTime(duration)}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex gap="5px">
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'Play'}
|
||||||
|
onClick={onPlay}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
{isPlaying ? (
|
||||||
|
<MdPause style={{ width: '100%', height: '100%' }} />
|
||||||
|
) : (
|
||||||
|
<MdPlayArrow style={{ width: '100%', height: '100%' }} />
|
||||||
|
)}
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'Stop'}
|
||||||
|
onClick={onStop}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
<MdStop style={{ width: '100%', height: '100%' }} />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'Previous Media'}
|
||||||
|
onClick={onNavigatePrevious}
|
||||||
|
marginLeft="auto"
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
<MdNavigateBefore
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
/>{' '}
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'jump 15sec in past'}
|
||||||
|
onClick={onFastRewind}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
<MdFastRewind style={{ width: '100%', height: '100%' }} />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'jump 15sec in future'}
|
||||||
|
onClick={onFastForward}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
<MdFastForward style={{ width: '100%', height: '100%' }} />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'Next Media'}
|
||||||
|
marginRight="auto"
|
||||||
|
onClick={onNavigateNext}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
<MdNavigateNext style={{ width: '100%', height: '100%' }} />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'continue to the end'}
|
||||||
|
onClick={onTypePlay}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
{playModeIcon[playingMode]}
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'Fullscreen'}
|
||||||
|
onClick={onFullScreen}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
{!!document.fullscreenElement ? (
|
||||||
|
<MdFullscreenExit
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<MdFullscreen style={{ width: '100%', height: '100%' }} />
|
||||||
|
)}
|
||||||
|
</IconButton>
|
||||||
|
{isPiPSupported && !isMobile && (
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'Fullscreen'}
|
||||||
|
onClick={onPictureInPicture}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
{isPiP ? (
|
||||||
|
<MdOutlinePictureInPictureAlt
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<MdPictureInPictureAlt
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex gap="5px">
|
</>
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'Play'}
|
|
||||||
onClick={onPlay}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
{isPlaying ? (
|
|
||||||
<MdPause style={{ width: '100%', height: '100%' }} />
|
|
||||||
) : (
|
|
||||||
<MdPlayArrow style={{ width: '100%', height: '100%' }} />
|
|
||||||
)}
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'Stop'}
|
|
||||||
onClick={onStop}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
<MdStop style={{ width: '100%', height: '100%' }} />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'Previous Media'}
|
|
||||||
onClick={onNavigatePrevious}
|
|
||||||
marginLeft="auto"
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
<MdNavigateBefore style={{ width: '100%', height: '100%' }} />{' '}
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'jump 15sec in past'}
|
|
||||||
onClick={onFastRewind}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
<MdFastRewind style={{ width: '100%', height: '100%' }} />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'jump 15sec in future'}
|
|
||||||
onClick={onFastForward}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
<MdFastForward style={{ width: '100%', height: '100%' }} />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'Next Media'}
|
|
||||||
marginRight="auto"
|
|
||||||
onClick={onNavigateNext}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
<MdNavigateNext style={{ width: '100%', height: '100%' }} />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'continue to the end'}
|
|
||||||
onClick={onTypePlay}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
{playModeIcon[playingMode]}
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'Fullscreen'}
|
|
||||||
onClick={onFullScreen}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
{!!document.fullscreenElement ?
|
|
||||||
<MdFullscreenExit style={{ width: '100%', height: '100%' }} />:
|
|
||||||
<MdFullscreen style={{ width: '100%', height: '100%' }} />}
|
|
||||||
</IconButton>
|
|
||||||
{isPiPSupported && !isMobile &&
|
|
||||||
<IconButton
|
|
||||||
{...configButton}
|
|
||||||
aria-label={'Fullscreen'}
|
|
||||||
onClick={onPictureInPicture}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
{isPiP ? <MdOutlinePictureInPictureAlt style={{ width: '100%', height: '100%' }} /> : <MdPictureInPictureAlt style={{ width: '100%', height: '100%' }} /> }
|
|
||||||
</IconButton>
|
|
||||||
}
|
|
||||||
</Flex>
|
|
||||||
</>}
|
|
||||||
</Flex>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -45,7 +45,7 @@ export const DisplayMediaFull = ({
|
|||||||
overflowX="hidden"
|
overflowX="hidden"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<Spacer/>
|
<Spacer />
|
||||||
<Text
|
<Text
|
||||||
as="span"
|
as="span"
|
||||||
alignContent="left"
|
alignContent="left"
|
||||||
@ -57,6 +57,7 @@ export const DisplayMediaFull = ({
|
|||||||
// TODO: noOfLines={1}
|
// TODO: noOfLines={1}
|
||||||
color={MediaActive?.id === media.id ? 'green.700' : undefined}
|
color={MediaActive?.id === media.id ? 'green.700' : undefined}
|
||||||
>
|
>
|
||||||
|
{media.id}
|
||||||
{media.name} {media.episode && ` [${media.episode}]`}
|
{media.name} {media.episode && ` [${media.episode}]`}
|
||||||
</Text>
|
</Text>
|
||||||
{/* {dataSeason && (
|
{/* {dataSeason && (
|
||||||
|
@ -4,7 +4,7 @@ import { Button, Tabs, Text, useDisclosure } from '@chakra-ui/react';
|
|||||||
import { MdAdminPanelSettings, MdDeleteForever, MdEdit } from 'react-icons/md';
|
import { MdAdminPanelSettings, MdDeleteForever, MdEdit } from 'react-icons/md';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { MediaResource, MediaWrite } from '@/back-api';
|
import { MediaResource, MediaUpdate, ZodMediaUpdate } from '@/back-api';
|
||||||
import { FormGroupShow } from '@/components/form/FormGroup';
|
import { FormGroupShow } from '@/components/form/FormGroup';
|
||||||
import { FormInput } from '@/components/form/FormInput';
|
import { FormInput } from '@/components/form/FormInput';
|
||||||
import { FormNumber } from '@/components/form/FormNumber';
|
import { FormNumber } from '@/components/form/FormNumber';
|
||||||
@ -63,19 +63,24 @@ export const MediaEditPopUp = ({}: MediaEditPopUpProps) => {
|
|||||||
};
|
};
|
||||||
const initialRef = useRef<HTMLButtonElement>(null);
|
const initialRef = useRef<HTMLButtonElement>(null);
|
||||||
const finalRef = useRef<HTMLButtonElement>(null);
|
const finalRef = useRef<HTMLButtonElement>(null);
|
||||||
const form = useFormidable<MediaWrite>({
|
const form = useFormidable<MediaUpdate>({
|
||||||
initialValues: dataMedia,
|
initialValues: dataMedia,
|
||||||
deltaConfig: { omit: ['covers'] },
|
deltaConfig: { omit: ['covers'] },
|
||||||
});
|
});
|
||||||
const onSave = async (dataDelta: MediaWrite) => {
|
const onSave = async (data: MediaUpdate) => {
|
||||||
if (isNullOrUndefined(mediaIdInt)) {
|
if (isNullOrUndefined(mediaIdInt)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`onSave = ${JSON.stringify(dataDelta, null, 2)}`);
|
console.log(`onSave = ${JSON.stringify(data, null, 2)}`);
|
||||||
|
const { episode, ...rest } = data;
|
||||||
|
let episodeNumber: undefined | number = undefined;
|
||||||
|
if (episode !== undefined && episode !== null) {
|
||||||
|
episodeNumber = parseInt(`${episode}`, 10);
|
||||||
|
}
|
||||||
store.update(
|
store.update(
|
||||||
MediaResource.patch({
|
MediaResource.patch({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
data: dataDelta,
|
data: ZodMediaUpdate.parse({ episode: episodeNumber, ...rest }),
|
||||||
params: {
|
params: {
|
||||||
id: mediaIdInt,
|
id: mediaIdInt,
|
||||||
},
|
},
|
||||||
@ -146,7 +151,7 @@ export const MediaEditPopUp = ({}: MediaEditPopUpProps) => {
|
|||||||
>
|
>
|
||||||
{/* <DialogOverlay /> */}
|
{/* <DialogOverlay /> */}
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Formidable.From form={form} onSubmitDelta={onSave}>
|
<Formidable.From form={form} onSubmit={onSave}>
|
||||||
<DialogHeader>Edit Media</DialogHeader>
|
<DialogHeader>Edit Media</DialogHeader>
|
||||||
{/* <DialogCloseButton ref={finalRef} /> */}
|
{/* <DialogCloseButton ref={finalRef} /> */}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from 'react-icons/md';
|
} from 'react-icons/md';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { SeasonResource, SeasonWrite } from '@/back-api';
|
import { SeasonResource, SeasonUpdate, ZodSeasonUpdate } from '@/back-api';
|
||||||
import { FormCovers } from '@/components/form/FormCovers';
|
import { FormCovers } from '@/components/form/FormCovers';
|
||||||
import { FormGroupShow } from '@/components/form/FormGroup';
|
import { FormGroupShow } from '@/components/form/FormGroup';
|
||||||
import { FormInput } from '@/components/form/FormInput';
|
import { FormInput } from '@/components/form/FormInput';
|
||||||
@ -66,19 +66,19 @@ export const SeasonEditPopUp = ({}: SeasonEditPopUpProps) => {
|
|||||||
};
|
};
|
||||||
const initialRef = useRef<HTMLButtonElement>(null);
|
const initialRef = useRef<HTMLButtonElement>(null);
|
||||||
const finalRef = useRef<HTMLButtonElement>(null);
|
const finalRef = useRef<HTMLButtonElement>(null);
|
||||||
const form = useFormidable<SeasonWrite>({
|
const form = useFormidable<SeasonUpdate>({
|
||||||
initialValues: dataSeason,
|
initialValues: dataSeason,
|
||||||
deltaConfig: { omit: ['covers'] },
|
deltaConfig: { omit: ['covers'] },
|
||||||
});
|
});
|
||||||
const onSave = async (deltaData: SeasonWrite) => {
|
const onSave = async (data: SeasonUpdate) => {
|
||||||
if (isNullOrUndefined(seasonIdInt)) {
|
if (isNullOrUndefined(seasonIdInt)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`onSave = ${JSON.stringify(deltaData, null, 2)}`);
|
console.log(`onSave = ${JSON.stringify(data, null, 2)}`);
|
||||||
store.update(
|
store.update(
|
||||||
SeasonResource.patch({
|
SeasonResource.patch({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
data: deltaData,
|
data: ZodSeasonUpdate.parse(data),
|
||||||
params: {
|
params: {
|
||||||
id: seasonIdInt,
|
id: seasonIdInt,
|
||||||
},
|
},
|
||||||
@ -150,7 +150,7 @@ export const SeasonEditPopUp = ({}: SeasonEditPopUpProps) => {
|
|||||||
data-testid="Season-edit-pop-up"
|
data-testid="Season-edit-pop-up"
|
||||||
>
|
>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Formidable.From form={form} onSubmitDelta={onSave}>
|
<Formidable.From form={form} onSubmit={onSave}>
|
||||||
<DialogHeader>Edit Season</DialogHeader>
|
<DialogHeader>Edit Season</DialogHeader>
|
||||||
{/* <DialogCloseButton ref={finalRef} /> */}
|
{/* <DialogCloseButton ref={finalRef} /> */}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from 'react-icons/md';
|
} from 'react-icons/md';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { SeriesResource, SeriesWrite } from '@/back-api';
|
import { SeriesResource, SeriesUpdate, ZodSeriesUpdate } from '@/back-api';
|
||||||
import { FormCovers } from '@/components/form/FormCovers';
|
import { FormCovers } from '@/components/form/FormCovers';
|
||||||
import { FormInput } from '@/components/form/FormInput';
|
import { FormInput } from '@/components/form/FormInput';
|
||||||
import { FormTextarea } from '@/components/form/FormTextarea';
|
import { FormTextarea } from '@/components/form/FormTextarea';
|
||||||
@ -62,19 +62,19 @@ export const SeriesEditPopUp = ({}: SeriesEditPopUpProps) => {
|
|||||||
};
|
};
|
||||||
const initialRef = useRef<HTMLButtonElement>(null);
|
const initialRef = useRef<HTMLButtonElement>(null);
|
||||||
const finalRef = useRef<HTMLButtonElement>(null);
|
const finalRef = useRef<HTMLButtonElement>(null);
|
||||||
const form = useFormidable<SeriesWrite>({
|
const form = useFormidable<SeriesUpdate>({
|
||||||
initialValues: dataSeries,
|
initialValues: dataSeries,
|
||||||
deltaConfig: { omit: ['covers'] },
|
deltaConfig: { omit: ['covers'] },
|
||||||
});
|
});
|
||||||
const onSave = async (dataDelta: SeriesWrite) => {
|
const onSave = async (data: SeriesUpdate) => {
|
||||||
if (isNullOrUndefined(seriesIdInt)) {
|
if (isNullOrUndefined(seriesIdInt)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`onSave = ${JSON.stringify(dataDelta, null, 2)}`);
|
console.log(`onSave = ${JSON.stringify(data, null, 2)}`);
|
||||||
store.update(
|
store.update(
|
||||||
SeriesResource.patch({
|
SeriesResource.patch({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
data: dataDelta,
|
data: ZodSeriesUpdate.parse(data),
|
||||||
params: {
|
params: {
|
||||||
id: seriesIdInt,
|
id: seriesIdInt,
|
||||||
},
|
},
|
||||||
@ -146,7 +146,7 @@ export const SeriesEditPopUp = ({}: SeriesEditPopUpProps) => {
|
|||||||
>
|
>
|
||||||
{/* <DialogOverlay /> */}
|
{/* <DialogOverlay /> */}
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Formidable.From form={form} onSubmitDelta={onSave}>
|
<Formidable.From form={form} onSubmit={onSave}>
|
||||||
<DialogHeader>Edit Series</DialogHeader>
|
<DialogHeader>Edit Series</DialogHeader>
|
||||||
{/* <DialogCloseButton ref={finalRef} /> */}
|
{/* <DialogCloseButton ref={finalRef} /> */}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from 'react-icons/md';
|
} from 'react-icons/md';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { TypeResource, TypeWrite } from '@/back-api';
|
import { TypeResource, TypeUpdate, ZodTypeUpdate } from '@/back-api';
|
||||||
import { FormCovers } from '@/components/form/FormCovers';
|
import { FormCovers } from '@/components/form/FormCovers';
|
||||||
import { FormInput } from '@/components/form/FormInput';
|
import { FormInput } from '@/components/form/FormInput';
|
||||||
import { FormTextarea } from '@/components/form/FormTextarea';
|
import { FormTextarea } from '@/components/form/FormTextarea';
|
||||||
@ -65,19 +65,19 @@ export const TypeEditPopUp = ({}: TypeEditPopUpProps) => {
|
|||||||
};
|
};
|
||||||
const initialRef = useRef<HTMLButtonElement>(null);
|
const initialRef = useRef<HTMLButtonElement>(null);
|
||||||
const finalRef = useRef<HTMLButtonElement>(null);
|
const finalRef = useRef<HTMLButtonElement>(null);
|
||||||
const form = useFormidable<TypeWrite>({
|
const form = useFormidable<TypeUpdate>({
|
||||||
initialValues: dataType,
|
initialValues: dataType,
|
||||||
deltaConfig: { omit: ['covers'] },
|
deltaConfig: { omit: ['covers'] },
|
||||||
});
|
});
|
||||||
const onSave = async (dataDelta: TypeWrite) => {
|
const onSave = async (data: TypeUpdate) => {
|
||||||
if (isNullOrUndefined(typeIdInt)) {
|
if (isNullOrUndefined(typeIdInt)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`onSave = ${JSON.stringify(dataDelta, null, 2)}`);
|
console.log(`onSave = ${JSON.stringify(data, null, 2)}`);
|
||||||
store.update(
|
store.update(
|
||||||
TypeResource.patch({
|
TypeResource.patch({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
data: dataDelta,
|
data: ZodTypeUpdate.parse(data),
|
||||||
params: {
|
params: {
|
||||||
id: typeIdInt,
|
id: typeIdInt,
|
||||||
},
|
},
|
||||||
@ -148,7 +148,7 @@ export const TypeEditPopUp = ({}: TypeEditPopUpProps) => {
|
|||||||
>
|
>
|
||||||
{/* <DialogOverlay /> */}
|
{/* <DialogOverlay /> */}
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Formidable.From form={form} onSubmitDelta={onSave}>
|
<Formidable.From form={form} onSubmit={onSave}>
|
||||||
<DialogHeader>Edit Type</DialogHeader>
|
<DialogHeader>Edit Type</DialogHeader>
|
||||||
{/* <DialogCloseButton ref={finalRef} /> */}
|
{/* <DialogCloseButton ref={finalRef} /> */}
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ export const environment = isDevelopmentEnvironment()
|
|||||||
? environment_local
|
? environment_local
|
||||||
: environment_back_prod;
|
: environment_back_prod;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the current REST api URL. Depend on the VITE_API_BASE_URL env variable.
|
* get the current REST api URL. Depend on the VITE_API_BASE_URL env variable.
|
||||||
* @returns The URL with http(s)://***
|
* @returns The URL with http(s)://***
|
||||||
|
@ -408,7 +408,7 @@ export const AddPage = () => {
|
|||||||
episode: `${parsedElement[index].episode}`,
|
episode: `${parsedElement[index].episode}`,
|
||||||
};
|
};
|
||||||
console.log(`data= ${JSON.stringify(data, null, 2)}`);
|
console.log(`data= ${JSON.stringify(data, null, 2)}`);
|
||||||
console.error('Not_ implemented');
|
console.error('Not_implemented');
|
||||||
storeMedia
|
storeMedia
|
||||||
.update(
|
.update(
|
||||||
MediaResource.uploadMedia({
|
MediaResource.uploadMedia({
|
||||||
@ -468,6 +468,18 @@ export const AddPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
const addNewSeries = (data: string): Promise<Series> => {
|
const addNewSeries = (data: string): Promise<Series> => {
|
||||||
|
if (form.values['typeId'] === undefined) {
|
||||||
|
return new Promise((_resolve, reject) => {
|
||||||
|
reject({
|
||||||
|
name: 'form value is empty [typeId] ...',
|
||||||
|
time: Date().toString(),
|
||||||
|
status: 950,
|
||||||
|
error: 'REST Fail to verify the data',
|
||||||
|
statusMessage: 'catch ERROR',
|
||||||
|
message: 'form value is empty [typeId] ...',
|
||||||
|
} as RestErrorResponse);
|
||||||
|
});
|
||||||
|
}
|
||||||
return storeSeries.update(
|
return storeSeries.update(
|
||||||
SeriesResource.post({
|
SeriesResource.post({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
@ -763,7 +775,7 @@ export const MediaDetectionDetail = ({ data }: { data: InspectionType }) => {
|
|||||||
</Text>
|
</Text>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
<Text>{data.media.date}</Text>
|
<Text>{data.media.datePublication}</Text>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell></Table.Cell>
|
<Table.Cell></Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
|
@ -1,47 +1,58 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { Center, Heading, Image, Text } from '@chakra-ui/react';
|
import { Center, Flex, Heading, Image, Text } from '@chakra-ui/react';
|
||||||
|
import { MdFactCheck, MdWarning } from 'react-icons/md';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
import { useEffectOnce } from 'react-use';
|
||||||
|
|
||||||
import avatar_generic from '@/assets/images/avatar_generic.svg';
|
import avatar_generic from '@/assets/images/avatar_generic.svg';
|
||||||
|
import { Icon } from '@/components';
|
||||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||||
import { TopBar } from '@/components/TopBar/TopBar';
|
import { TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { isDevelopmentEnvironment } from '@/environment';
|
import { toaster } from '@/components/ui/toaster';
|
||||||
import { useSessionService } from '@/service/session';
|
import { useSessionService } from '@/service/session';
|
||||||
import { b64_to_utf8 } from '@/utils/sso';
|
import { b64_to_utf8 } from '@/utils/sso';
|
||||||
|
|
||||||
export const SSOPage = () => {
|
export const SSOPage = () => {
|
||||||
const { data, keepConnected, token } = useParams();
|
const { data, keepConnected, token } = useParams();
|
||||||
console.log(`- data: ${data}`);
|
//const { data, keepConnected, token } = useState<string|undefined>();
|
||||||
console.log(`- keepConnected: ${keepConnected}`);
|
// console.log(`- data: ${data}`);
|
||||||
console.log(`- token: ${token}`);
|
// console.log(`- keepConnected: ${keepConnected}`);
|
||||||
|
// console.log(`- token: ${token}`);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { isConnected, setToken, login, clearToken } = useSessionService();
|
const { isConnected, errorSession, setToken, login } = useSessionService();
|
||||||
useEffect(() => {
|
useEffectOnce(() => {
|
||||||
if (token) {
|
if (token === undefined || token === '') {
|
||||||
setToken(token);
|
return;
|
||||||
} else {
|
|
||||||
clearToken();
|
|
||||||
}
|
}
|
||||||
}, [token, setToken, clearToken]);
|
try {
|
||||||
const delay = isDevelopmentEnvironment() ? 2000 : 2000;
|
setToken(token);
|
||||||
|
} catch (e) {
|
||||||
|
toaster.create({
|
||||||
|
title: 'Connection Fail',
|
||||||
|
description: `invalid token data model.`,
|
||||||
|
type: 'error',
|
||||||
|
});
|
||||||
|
navigate('/');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const delay = 1000;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isConnected) {
|
if (isConnected) {
|
||||||
const destination = data ? b64_to_utf8(data) : '/';
|
toaster.create({
|
||||||
console.log(`program redirect to: ${destination} (${delay}ms)`);
|
title: 'Connection Succeed',
|
||||||
|
description: `Welcome back: ${login}.`,
|
||||||
|
type: 'success',
|
||||||
|
});
|
||||||
|
const destination = data ? b64_to_utf8(data) : '/home';
|
||||||
|
const destinationFinal = destination === '' ? '/home' : destination;
|
||||||
|
console.log(`program redirect to: '${destinationFinal}' (${delay}ms)`);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
navigate(`/${destination}`);
|
// note: check if the "navigate" is in the dependence of the use effect!!!
|
||||||
|
navigate(`/${destinationFinal}`, { replace: true });
|
||||||
}, delay);
|
}, delay);
|
||||||
}
|
}
|
||||||
}, [isConnected]);
|
}, [isConnected, login, navigate]);
|
||||||
/*
|
|
||||||
const [searchParams] = useSearchParams();
|
|
||||||
console.log(`data: ${searchParams.get('data')}`);
|
|
||||||
console.log(`keepConnected: ${searchParams.get('keepConnected')}`);
|
|
||||||
console.log(`token: ${searchParams.get('token')}`);
|
|
||||||
const dataFromParam = useGetCreateActionParams();
|
|
||||||
console.log(`data group: ${JSON.stringify(dataFromParam, null, 2)}`);
|
|
||||||
*/
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TopBar />
|
<TopBar />
|
||||||
@ -53,20 +64,52 @@ export const SSOPage = () => {
|
|||||||
<Center w="full">
|
<Center w="full">
|
||||||
<Image src={avatar_generic} boxSize="150px" borderRadius="full" />
|
<Image src={avatar_generic} boxSize="150px" borderRadius="full" />
|
||||||
</Center>
|
</Center>
|
||||||
{!isConnected && (
|
{!isConnected && errorSession !== undefined && (
|
||||||
<Text>
|
<>
|
||||||
<b>ERROR: </b> connection fail !
|
<Flex color="red.500" fontSize="25px" gap={2} marginX="auto">
|
||||||
</Text>
|
<Icon sizeIcon="55px">
|
||||||
|
<MdWarning />
|
||||||
|
</Icon>
|
||||||
|
<Text marginY="auto">
|
||||||
|
<b>ERROR: </b> {errorSession.message}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
{errorSession.description && (
|
||||||
|
<Text
|
||||||
|
whiteSpace="pre-line"
|
||||||
|
fontSize="25px"
|
||||||
|
gap={2}
|
||||||
|
marginX="auto"
|
||||||
|
>
|
||||||
|
{errorSession.description}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!isConnected && errorSession === undefined && (
|
||||||
|
<Flex color="red.500" fontSize="25px" gap={2} marginX="auto">
|
||||||
|
<Icon sizeIcon="55px">
|
||||||
|
<MdWarning />
|
||||||
|
</Icon>
|
||||||
|
<Text marginY="auto">
|
||||||
|
<b>ERROR: </b> Not connected !
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
)}
|
)}
|
||||||
{isConnected && (
|
{isConnected && (
|
||||||
<>
|
<Flex direction="column">
|
||||||
<Text>
|
<Flex color="green.500" fontSize="25px" gap={2} marginX="auto">
|
||||||
<b>Connected: </b> Redirect soon!
|
<MdFactCheck />
|
||||||
</Text>
|
<Text marginY="auto">
|
||||||
<Text>
|
<b>Connected: </b> Redirect soon!
|
||||||
<b>Welcome back: </b> {login}
|
</Text>
|
||||||
</Text>
|
</Flex>
|
||||||
</>
|
<Flex fontSize="25px" gap={2} marginX="auto">
|
||||||
|
<Text marginY="auto">
|
||||||
|
<b>Welcome back: </b> {login}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</PageLayoutInfoCenter>
|
</PageLayoutInfoCenter>
|
||||||
</>
|
</>
|
||||||
|
@ -22,7 +22,7 @@ export const useAdvancementServiceWrapped = (
|
|||||||
{
|
{
|
||||||
restApiName: 'Advancement',
|
restApiName: 'Advancement',
|
||||||
primaryKey: 'id',
|
primaryKey: 'id',
|
||||||
available: session.token !== undefined,
|
available: false, //session.token !== undefined,
|
||||||
getsCall: () => {
|
getsCall: () => {
|
||||||
return UserMediaAdvancementResource.gets({
|
return UserMediaAdvancementResource.gets({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
@ -47,40 +47,43 @@ export type updateTimeProps = {
|
|||||||
time: number;
|
time: number;
|
||||||
total: number;
|
total: number;
|
||||||
addCount: boolean;
|
addCount: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useAdvancementUpdateTime = (id: number,
|
export const useAdvancementUpdateTime = (
|
||||||
config: Omit<useQueryCallProps<UserMediaAdvancement, updateTimeProps>, 'queryFunction'>
|
id: number,
|
||||||
= {}) => {
|
config: Omit<
|
||||||
|
useQueryCallProps<UserMediaAdvancement, updateTimeProps>,
|
||||||
|
'queryFunction'
|
||||||
|
> = {}
|
||||||
|
) => {
|
||||||
const { store } = useAdvancementService();
|
const { store } = useAdvancementService();
|
||||||
|
|
||||||
const { onSuccess, ...restConfig } = config;
|
const { onSuccess, ...restConfig } = config;
|
||||||
const { getRestConfig } = useSessionService();
|
const { getRestConfig } = useSessionService();
|
||||||
const { call, ...rest } = useQueryCall<
|
const { call, ...rest } = useQueryCall<UserMediaAdvancement, updateTimeProps>(
|
||||||
UserMediaAdvancement,
|
{
|
||||||
updateTimeProps
|
queryFunction: (inputData) => {
|
||||||
>({
|
const data = {
|
||||||
queryFunction: (inputData) => {
|
time: inputData.time,
|
||||||
const data = {
|
percent: inputData.time / inputData.total,
|
||||||
time: inputData.time,
|
addCount: inputData.addCount,
|
||||||
percent: inputData.time / inputData.total,
|
};
|
||||||
addCount: inputData.addCount
|
return UserMediaAdvancementResource.patch({
|
||||||
};
|
restConfig: getRestConfig(),
|
||||||
return UserMediaAdvancementResource.patch({
|
params: {
|
||||||
restConfig: getRestConfig(),
|
id,
|
||||||
params: {
|
},
|
||||||
id
|
data,
|
||||||
},
|
});
|
||||||
data
|
},
|
||||||
});
|
onSuccess: (response) => {
|
||||||
},
|
if (onSuccess) {
|
||||||
onSuccess: (response) => {
|
onSuccess(response);
|
||||||
if (onSuccess) {
|
}
|
||||||
onSuccess(response);
|
store.updateRaw(response);
|
||||||
}
|
},
|
||||||
store.updateRaw(response);
|
...restConfig,
|
||||||
},
|
}
|
||||||
...restConfig,
|
);
|
||||||
});
|
|
||||||
return { updateTime: call, ...rest };
|
return { updateTime: call, ...rest };
|
||||||
};
|
};
|
||||||
|
@ -24,7 +24,7 @@ export const useMediaServiceWrapped = (
|
|||||||
{
|
{
|
||||||
restApiName: 'Media',
|
restApiName: 'Media',
|
||||||
primaryKey: 'id',
|
primaryKey: 'id',
|
||||||
available: session.token !== undefined,
|
available: session.isConnected,
|
||||||
getsCall: () => {
|
getsCall: () => {
|
||||||
return MediaResource.gets({
|
return MediaResource.gets({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
|
@ -25,7 +25,7 @@ export const useSeasonServiceWrapped = (
|
|||||||
{
|
{
|
||||||
restApiName: 'Season',
|
restApiName: 'Season',
|
||||||
primaryKey: 'id',
|
primaryKey: 'id',
|
||||||
available: session.token !== undefined,
|
available: session.isConnected,
|
||||||
getsCall: () => {
|
getsCall: () => {
|
||||||
return SeasonResource.gets({
|
return SeasonResource.gets({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
|
@ -26,7 +26,7 @@ export const useSeriesServiceWrapped = (
|
|||||||
{
|
{
|
||||||
restApiName: 'Series',
|
restApiName: 'Series',
|
||||||
primaryKey: 'id',
|
primaryKey: 'id',
|
||||||
available: session.token !== undefined,
|
available: session.isConnected,
|
||||||
getsCall: () => {
|
getsCall: () => {
|
||||||
return SeriesResource.gets({
|
return SeriesResource.gets({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
|
@ -25,7 +25,7 @@ export const useTypeServiceWrapped = (
|
|||||||
{
|
{
|
||||||
restApiName: 'Type',
|
restApiName: 'Type',
|
||||||
primaryKey: 'id',
|
primaryKey: 'id',
|
||||||
available: session.token !== undefined,
|
available: session.isConnected,
|
||||||
getsCall: () => {
|
getsCall: () => {
|
||||||
return TypeResource.gets({
|
return TypeResource.gets({
|
||||||
restConfig: session.getRestConfig(),
|
restConfig: session.getRestConfig(),
|
||||||
|
@ -1,21 +1,33 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { JwtPayload, RESTConfig } from '@/back-api';
|
import { createListCollection } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
JwtToken,
|
||||||
|
RESTConfig,
|
||||||
|
RestErrorResponse,
|
||||||
|
UserResource,
|
||||||
|
setErrorApiGlobalCallback,
|
||||||
|
} from '@/back-api';
|
||||||
import { PartRight } from '@/back-api/model/part-right';
|
import { PartRight } from '@/back-api/model/part-right';
|
||||||
|
import { toaster } from '@/components/ui/toaster';
|
||||||
import { environment, getApiUrl } from '@/environment';
|
import { environment, getApiUrl } from '@/environment';
|
||||||
import { useServiceContext } from '@/service/ServiceContext';
|
import { useServiceContext } from '@/service/ServiceContext';
|
||||||
import { isBrowser } from '@/utils/layout';
|
import { isBrowser } from '@/utils/layout';
|
||||||
import { parseToken } from '@/utils/sso';
|
import { parseToken } from '@/utils/sso';
|
||||||
import { createListCollection } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
const TOKEN_KEY = 'karideo-token-key-storage';
|
const TOKEN_KEY = 'karusic-token-key-storage';
|
||||||
|
|
||||||
export const USERS_COLLECTION = createListCollection({
|
export const USERS_COLLECTION = createListCollection({
|
||||||
items: [
|
items: [
|
||||||
{ label: "admin", value: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYXBwbGljYXRpb24iOiJrYXJ1c2ljIiwiaXNzIjoiS2FyQXV0aCIsInJpZ2h0Ijp7ImthcnVzaWMiOnsiQURNSU4iOnRydWUsIlVTRVIiOnRydWV9fSwibG9naW4iOiJIZWVyb1l1aSIsImV4cCI6MTcyNDIwNjc5NCwiaWF0IjoxNzI0MTY2ODM0fQ.TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E" },
|
{
|
||||||
{ label: "NO_USER", value: "svelte" },
|
label: 'admin',
|
||||||
|
value:
|
||||||
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYXBwbGljYXRpb24iOiJrYXJ1c2ljIiwiaXNzIjoiS2FyQXV0aCIsInJpZ2h0Ijp7ImthcnVzaWMiOnsiQURNSU4iOnRydWUsIlVTRVIiOnRydWV9fSwibG9naW4iOiJIZWVyb1l1aSIsImV4cCI6MTcyNDIwNjc5NCwiaWF0IjoxNzI0MTY2ODM0fQ.TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E',
|
||||||
|
},
|
||||||
|
{ label: 'NO_USER', value: 'svelte' },
|
||||||
],
|
],
|
||||||
})
|
});
|
||||||
export const USERS = {
|
export const USERS = {
|
||||||
admin:
|
admin:
|
||||||
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYXBwbGljYXRpb24iOiJrYXJ1c2ljIiwiaXNzIjoiS2FyQXV0aCIsInJpZ2h0Ijp7ImthcnVzaWMiOnsiQURNSU4iOnRydWUsIlVTRVIiOnRydWV9fSwibG9naW4iOiJIZWVyb1l1aSIsImV4cCI6MTcyNDIwNjc5NCwiaWF0IjoxNzI0MTY2ODM0fQ.TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E',
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYXBwbGljYXRpb24iOiJrYXJ1c2ljIiwiaXNzIjoiS2FyQXV0aCIsInJpZ2h0Ijp7ImthcnVzaWMiOnsiQURNSU4iOnRydWUsIlVTRVIiOnRydWV9fSwibG9naW4iOiJIZWVyb1l1aSIsImV4cCI6MTcyNDIwNjc5NCwiaWF0IjoxNzI0MTY2ODM0fQ.TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E',
|
||||||
@ -34,9 +46,43 @@ export function getRestConfig(): RESTConfig {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getDeltaPrint = (date: Date): string => {
|
||||||
|
const now = new Date();
|
||||||
|
let deltaSeconds = Math.floor((date.getTime() - now.getTime()) / 1000);
|
||||||
|
const isPast = deltaSeconds < 0;
|
||||||
|
|
||||||
|
deltaSeconds = Math.abs(deltaSeconds);
|
||||||
|
|
||||||
|
const days = Math.floor(deltaSeconds / 86400);
|
||||||
|
deltaSeconds %= 86400;
|
||||||
|
|
||||||
|
const hours = Math.floor(deltaSeconds / 3600);
|
||||||
|
deltaSeconds %= 3600;
|
||||||
|
|
||||||
|
const minutes = Math.floor(deltaSeconds / 60);
|
||||||
|
const seconds = deltaSeconds % 60;
|
||||||
|
|
||||||
|
const result = [days > 0 ? `${days}j` : '', `${hours}h${minutes}:${seconds}s`]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
return `${result}${isPast ? ' ago' : ''}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isInThePast = (date: Date): boolean => {
|
||||||
|
const now = new Date();
|
||||||
|
return date.getTime() < now.getTime();
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SessionErrorType = {
|
||||||
|
message: string;
|
||||||
|
description?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type SessionServiceProps = {
|
export type SessionServiceProps = {
|
||||||
token?: string;
|
token?: string;
|
||||||
isConnected: boolean;
|
isConnected: boolean;
|
||||||
|
errorSession?: SessionErrorType;
|
||||||
setToken: (token: string) => void;
|
setToken: (token: string) => void;
|
||||||
clearToken: () => void;
|
clearToken: () => void;
|
||||||
login?: string;
|
login?: string;
|
||||||
@ -51,102 +97,165 @@ export const useSessionService = (): SessionServiceProps => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useSessionServiceWrapped = (): SessionServiceProps => {
|
export const useSessionServiceWrapped = (): SessionServiceProps => {
|
||||||
const [token, setToken] = useState<string | undefined>(
|
// Load the token from the system (init)
|
||||||
|
const [tokenStorage, setTokenStorage] = useState<string | undefined>(
|
||||||
isBrowser ? (localStorage.getItem(TOKEN_KEY) ?? undefined) : undefined
|
isBrowser ? (localStorage.getItem(TOKEN_KEY) ?? undefined) : undefined
|
||||||
);
|
);
|
||||||
const [config, setConfig] = useState<JwtPayload | undefined>(undefined);
|
// Token that is ready to use
|
||||||
|
const [tokenStr, setTokenStr] = useState<string>('');
|
||||||
|
const [errorSession, setErrorSession] = useState<
|
||||||
|
SessionErrorType | undefined
|
||||||
|
>(undefined);
|
||||||
|
const [token, setToken] = useState<JwtToken | undefined>(undefined);
|
||||||
|
|
||||||
const updateRight = useCallback(() => {
|
const getRestConfigLocal = useCallback((): RESTConfig => {
|
||||||
|
return {
|
||||||
|
server: getApiUrl(),
|
||||||
|
token: tokenStr,
|
||||||
|
};
|
||||||
|
}, [tokenStr]);
|
||||||
|
|
||||||
console.log('Detect a new token...');
|
const updateRight = useEffect(() => {
|
||||||
setConfig(undefined);
|
//console.log('Detect a new token...');
|
||||||
if (token === undefined) {
|
if (isBrowser) {
|
||||||
console.log(` ==> No User`);
|
//console.log('update internal property');
|
||||||
localStorage.removeItem(TOKEN_KEY);
|
if (tokenStorage === undefined) {
|
||||||
} else {
|
//console.log(` ==> No User`);
|
||||||
const dataParsedToken = parseToken(token)?.payload;
|
setToken(undefined);
|
||||||
console.log(`Get right: ${JSON.stringify(dataParsedToken, null, 2)}`);
|
setTokenStr('');
|
||||||
setConfig(dataParsedToken);
|
localStorage.removeItem(TOKEN_KEY);
|
||||||
console.log(' ==> Login ... (try to keep right)');
|
} else {
|
||||||
if (isBrowser) {
|
//console.log(' ==> Login ... (try to keep right)');
|
||||||
localStorage.setItem(TOKEN_KEY, token);
|
let tokenParsed: JwtToken | undefined = undefined;
|
||||||
|
try {
|
||||||
|
tokenParsed = parseToken(tokenStorage);
|
||||||
|
} catch (e) {
|
||||||
|
setErrorSession({
|
||||||
|
message: 'Fail to parse the token',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//console.log(`get new token: ${JSON.stringify(tokenParsed, null, 2)}`);
|
||||||
|
const exp = new Date(tokenParsed.payload.exp * 1000);
|
||||||
|
if (isInThePast(exp)) {
|
||||||
|
//console.log(`token expired at: exp: ${exp.toISOString()}: delta=${getDeltaPrint(exp)}`);
|
||||||
|
const iat = new Date(tokenParsed.payload.iat * 1000);
|
||||||
|
//console.log(`iat: ${iat.toISOString()}: delta=${getDeltaPrint(iat)}`);
|
||||||
|
setErrorSession({
|
||||||
|
message: 'The inserted token has expired',
|
||||||
|
description: `It expired at ${exp.toISOString()}\nSince: ${getDeltaPrint(exp)}`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Validate token on the server:
|
||||||
|
UserResource.getMe({
|
||||||
|
restConfig: {
|
||||||
|
server: getApiUrl(),
|
||||||
|
token: tokenStorage,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((_response) => {
|
||||||
|
// if the login work well, then the token does not fail with authentication
|
||||||
|
//console.log('Authentication finished: ...');
|
||||||
|
setTokenStr(tokenStorage);
|
||||||
|
setToken(tokenParsed);
|
||||||
|
localStorage.setItem(TOKEN_KEY, tokenStorage);
|
||||||
|
})
|
||||||
|
.catch((error: RestErrorResponse) => {
|
||||||
|
setErrorSession({
|
||||||
|
message: 'The server reject the token.',
|
||||||
|
description: `name: ${error.name}\nmessage: "${error.message}"`,
|
||||||
|
});
|
||||||
|
setTokenStr('');
|
||||||
|
setToken(undefined);
|
||||||
|
localStorage.removeItem(TOKEN_KEY);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [localStorage, parseToken, token]);
|
}, [
|
||||||
|
localStorage,
|
||||||
|
parseToken,
|
||||||
|
setErrorSession,
|
||||||
|
setToken,
|
||||||
|
setTokenStr,
|
||||||
|
tokenStorage,
|
||||||
|
]);
|
||||||
|
|
||||||
const setTokenLocal = useCallback(
|
const setTokenLocal = useCallback(
|
||||||
(token: string) => {
|
(token?: string) => {
|
||||||
setToken(token);
|
if (token ? token.startsWith('__') : false) {
|
||||||
updateRight();
|
token = undefined;
|
||||||
|
}
|
||||||
|
localStorage.removeItem(TOKEN_KEY);
|
||||||
|
setTokenStorage(token);
|
||||||
|
setTokenStr('');
|
||||||
|
setToken(undefined);
|
||||||
|
setErrorSession(undefined);
|
||||||
},
|
},
|
||||||
[updateRight, setToken]
|
[updateRight, setToken]
|
||||||
);
|
);
|
||||||
const clearToken = useCallback(() => {
|
const clearToken = useCallback(() => {
|
||||||
console.log('Clear Token');
|
localStorage.removeItem(TOKEN_KEY);
|
||||||
|
setTokenLocal(undefined);
|
||||||
setToken(undefined);
|
setToken(undefined);
|
||||||
updateRight();
|
|
||||||
}, [updateRight, setToken]);
|
}, [updateRight, setToken]);
|
||||||
const hasReadRight = useCallback(
|
|
||||||
(group: RightGroup) => {
|
|
||||||
if (token === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const right = config?.right[environment.applName];
|
|
||||||
if (right === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return [PartRight.READ, PartRight.READ_WRITE].includes(
|
|
||||||
right?.[group] ?? 0
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[config]
|
|
||||||
);
|
|
||||||
const hasWriteRight = useCallback(
|
|
||||||
(group: RightGroup) => {
|
|
||||||
if (token === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const right = config?.right[environment.applName];
|
|
||||||
if (right === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return [PartRight.READ, PartRight.READ_WRITE].includes(
|
|
||||||
right?.[group] ?? 0
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[config]
|
|
||||||
);
|
|
||||||
|
|
||||||
const getRestConfig = useCallback((): RESTConfig => {
|
|
||||||
return {
|
|
||||||
server: getApiUrl(),
|
|
||||||
token: token ?? '',
|
|
||||||
};
|
|
||||||
}, [token]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateRight();
|
setErrorApiGlobalCallback((response: Response) => {
|
||||||
}, [updateRight]);
|
if (response.status == 401) {
|
||||||
|
toaster.create({
|
||||||
|
title: 'API request rejected',
|
||||||
|
description: `API Authentication rejected by server.`,
|
||||||
|
type: 'error',
|
||||||
|
});
|
||||||
|
clearToken();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [clearToken]);
|
||||||
|
|
||||||
|
const hasReadRight = useCallback(
|
||||||
|
(part: RightGroup) => {
|
||||||
|
//console.log(`right = ${JSON.stringify(token?.payload?.right?.[environment.applName], null, 2)}`);
|
||||||
|
const right = token?.payload?.right?.[environment.applName];
|
||||||
|
if (right === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return [PartRight.READ, PartRight.READ_WRITE].includes(right[part]);
|
||||||
|
},
|
||||||
|
[token]
|
||||||
|
);
|
||||||
|
const hasWriteRight = useCallback(
|
||||||
|
(part: RightGroup) => {
|
||||||
|
const right = token?.payload?.right?.[environment.applName];
|
||||||
|
if (right === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return [PartRight.READ, PartRight.READ_WRITE].includes(right[part]);
|
||||||
|
},
|
||||||
|
[token]
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token,
|
token: tokenStr,
|
||||||
isConnected: token !== undefined,
|
isConnected: token !== undefined,
|
||||||
|
errorSession,
|
||||||
setToken: setTokenLocal,
|
setToken: setTokenLocal,
|
||||||
clearToken,
|
clearToken,
|
||||||
login: config?.login,
|
login: token?.payload?.login,
|
||||||
hasReadRight,
|
hasReadRight,
|
||||||
hasWriteRight,
|
hasWriteRight,
|
||||||
getRestConfig,
|
getRestConfig: getRestConfigLocal,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useHasRight = (group: RightGroup) => {
|
export const useHasRight = (part: RightGroup) => {
|
||||||
const { token, hasReadRight, hasWriteRight } = useSessionService();
|
const { token, hasReadRight, hasWriteRight } = useSessionService();
|
||||||
const isReadable = useMemo(() => {
|
const isReadable = useMemo(() => {
|
||||||
console.log(`get is read for: ${group} ==> ${hasReadRight(group)}`);
|
//console.log(`get is read for: ${part} ==> ${hasReadRight(part)}`);
|
||||||
return hasReadRight(group);
|
return hasReadRight(part);
|
||||||
}, [token, hasReadRight, group]);
|
}, [token, hasReadRight, part]);
|
||||||
const isWritable = useMemo(() => {
|
const isWritable = useMemo(() => {
|
||||||
return hasWriteRight(group);
|
return hasWriteRight(part);
|
||||||
}, [token, hasWriteRight, group]);
|
}, [token, hasWriteRight, part]);
|
||||||
return { isReadable, isWritable };
|
return { isReadable, isWritable };
|
||||||
};
|
};
|
||||||
|
@ -9,12 +9,20 @@ import { colors } from './colors';
|
|||||||
|
|
||||||
const baseTheme: SystemConfig = {
|
const baseTheme: SystemConfig = {
|
||||||
globalCss: {
|
globalCss: {
|
||||||
|
':root': {
|
||||||
|
// permit to "firefox" not reload the page when scroll on top
|
||||||
|
overscrollBehavior: 'contain',
|
||||||
|
},
|
||||||
body: {
|
body: {
|
||||||
|
// permit to "chromium" not reload the page when scroll on top
|
||||||
|
overscrollBehavior: 'contain',
|
||||||
|
// Prevents text selection
|
||||||
|
userSelect: 'none',
|
||||||
|
// Other ...
|
||||||
overflowY: 'none',
|
overflowY: 'none',
|
||||||
bg: { _light: 'back.50', _dark: 'back.700' },
|
bg: { _light: 'back.50', _dark: 'back.700' },
|
||||||
color: { _light: 'text.900', _dark: 'text.50' },
|
color: { _light: 'text.900', _dark: 'text.50' },
|
||||||
fontFamily: 'Roboto, Helvetica, Arial, "sans-serif"',
|
fontFamily: 'Roboto, Helvetica, Arial, "sans-serif"',
|
||||||
userSelect: 'none' /* Prevents text selection */,
|
|
||||||
},
|
},
|
||||||
svg: {
|
svg: {
|
||||||
width: '32px',
|
width: '32px',
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import { RESTConfig } from '@/back-api';
|
|
||||||
import { getApiUrl } from '@/environment';
|
|
||||||
import { getUserToken } from '@/service/session';
|
|
||||||
|
|
||||||
export function getRestConfig(): RESTConfig {
|
|
||||||
return {
|
|
||||||
server: getApiUrl(),
|
|
||||||
token: getUserToken() ?? '',
|
|
||||||
};
|
|
||||||
}
|
|
@ -108,14 +108,14 @@ export function requestSignIn(name?: string): void {
|
|||||||
console.log(
|
console.log(
|
||||||
`Request sign-in: '${environment.ssoSignIn}' + '${hashLocalData(name)}'`
|
`Request sign-in: '${environment.ssoSignIn}' + '${hashLocalData(name)}'`
|
||||||
);
|
);
|
||||||
window.location.href = environment.ssoSignIn + hashLocalData(name) + "/";
|
window.location.href = environment.ssoSignIn + hashLocalData(name) + '/';
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Request SSO Disconnect
|
* Request SSO Disconnect
|
||||||
*/
|
*/
|
||||||
export function requestSignOut(name?: string): void {
|
export function requestSignOut(name?: string): void {
|
||||||
const url = environment.ssoSignOut + hashLocalData(name);
|
const url = environment.ssoSignOut + hashLocalData(name);
|
||||||
console.log(`Request just to the SSO: ${url}`)
|
console.log(`Request just to the SSO: ${url}`);
|
||||||
// unlog from the SSO
|
// unlog from the SSO
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ export function requestSignOut(name?: string): void {
|
|||||||
*/
|
*/
|
||||||
export function requestSignUp(name?: string): void {
|
export function requestSignUp(name?: string): void {
|
||||||
const url = environment.ssoSignUp + hashLocalData(name);
|
const url = environment.ssoSignUp + hashLocalData(name);
|
||||||
console.log(`Request just to the SSO: ${url}`)
|
console.log(`Request just to the SSO: ${url}`);
|
||||||
// unlog from the SSO
|
// unlog from the SSO
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user