[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 \
|
||||
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
|
||||
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
|
||||
@ -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"?>
|
||||
<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>
|
||||
<groupId>org.kar</groupId>
|
||||
<groupId>org.atriasoft</groupId>
|
||||
<artifactId>karideo</artifactId>
|
||||
<version>0.3.0</version>
|
||||
<properties>
|
||||
@ -10,17 +10,11 @@
|
||||
<maven.compiler.target>23</maven.compiler.target>
|
||||
<maven.dependency.version>3.1.1</maven.dependency.version>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>gitea</id>
|
||||
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>kangaroo-and-rabbit</groupId>
|
||||
<groupId>org.atria-soft</groupId>
|
||||
<artifactId>archidata</artifactId>
|
||||
<version>0.24.0</version>
|
||||
<version>0.28.0</version>
|
||||
</dependency>
|
||||
<!-- Loopback of logger JDK logging API to SLF4J -->
|
||||
<dependency>
|
||||
@ -112,7 +106,7 @@
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<mainClass>org.kar.karideo.WebLauncher</mainClass>
|
||||
<mainClass>org.atriasoft.karideo.WebLauncher</mainClass>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
@ -121,7 +115,7 @@
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<mainClass>org.kar.karideo.WebLauncherLocal</mainClass>
|
||||
<mainClass>org.atriasoft.karideo.WebLauncherLocal</mainClass>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
@ -130,7 +124,7 @@
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<mainClass>org.kar.karideo.GenerateApi</mainClass>
|
||||
<mainClass>org.atriasoft.karideo.GenerateApi</mainClass>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
@ -1,9 +1,9 @@
|
||||
org.kar.karideo.dataTmpFolder=/application/data/tmp
|
||||
org.kar.karideo.dataTmpFolder=/application/data/media
|
||||
org.kar.karideo.rest.oauth=http://192.168.1.156:21080/oauth/api/
|
||||
org.kar.karideo.db.host=1992.156.1.156
|
||||
org.kar.karideo.db.port=20306
|
||||
org.kar.karideo.db.login=root
|
||||
org.kar.karideo.db.port=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh
|
||||
org.kar.karideo.db.name=karideo
|
||||
org.kar.karideo.address=http://0.0.0.0:18080/karideo/api/
|
||||
org.atriasoft.karideo.dataTmpFolder=/application/data/tmp
|
||||
org.atriasoft.karideo.dataTmpFolder=/application/data/media
|
||||
org.atriasoft.karideo.rest.oauth=http://192.168.1.156:21080/oauth/api/
|
||||
org.atriasoft.karideo.db.host=1992.156.1.156
|
||||
org.atriasoft.karideo.db.port=20306
|
||||
org.atriasoft.karideo.db.login=root
|
||||
org.atriasoft.karideo.db.port=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh
|
||||
org.atriasoft.karideo.db.name=karideo
|
||||
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.LoggerFactory;
|
||||
|
@ -1,38 +1,40 @@
|
||||
package org.kar.karideo;
|
||||
package org.atriasoft.karideo;
|
||||
|
||||
import java.net.URI;
|
||||
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.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
|
||||
import org.glassfish.jersey.jackson.JacksonFeature;
|
||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.kar.archidata.UpdateJwtPublicKey;
|
||||
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.glassfish.jersey.server.validation.ValidationFeature;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.bridge.SLF4JBridgeHandler;
|
||||
@ -64,6 +66,7 @@ public class WebLauncher {
|
||||
migrationEngine.add(new Migration20240226());
|
||||
migrationEngine.add(new Migration20240611());
|
||||
migrationEngine.add(new Migration20250214());
|
||||
migrationEngine.add(new Migration20250414());
|
||||
WebLauncher.LOGGER.info("Migrate the DB [START]");
|
||||
migrationEngine.migrateWaitAdmin(new DbConfig());
|
||||
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
|
||||
@ -116,6 +119,8 @@ public class WebLauncher {
|
||||
ContextGenericTools.addJsr310(rc);
|
||||
// add jackson to be discover when we are ins stand-alone server
|
||||
rc.register(JacksonFeature.class);
|
||||
// enable jersey specific validations (@Valid)
|
||||
rc.register(ValidationFeature.class);
|
||||
// enable this to show low level request
|
||||
// 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 org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.karideo.migration.Initialization;
|
||||
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||
import org.atriasoft.karideo.migration.Initialization;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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 org.kar.karideo.util.ConfigVariable;
|
||||
import org.atriasoft.karideo.util.ConfigVariable;
|
||||
|
||||
@Path("/front")
|
||||
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.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.JWTWrapper;
|
||||
import org.atriasoft.archidata.exception.FailException;
|
||||
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||
import org.atriasoft.archidata.tools.JWTWrapper;
|
||||
import org.slf4j.Logger;
|
||||
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.InputStream;
|
||||
import java.sql.SQLException;
|
||||
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.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.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
@ -57,14 +58,15 @@ public class MediaResource {
|
||||
return DataAccess.get(Media.class, id);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@PUT
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(description = "Modify a specific Media", tags = "GLOBAL")
|
||||
public Media patch(@PathParam("id") final Long id, @AsyncType(Media.class) final String jsonRequest) throws Exception {
|
||||
LOGGER.info("update video {} ==> '{}'", id, jsonRequest);
|
||||
DataAccess.updateWithJson(Media.class, id, jsonRequest);
|
||||
public Media patch(@PathParam("id") final Long id, @Valid final Media media) throws Exception {
|
||||
LOGGER.info("update video {} ==> '{}'", id, media);
|
||||
media.id = id;
|
||||
DataAccess.update(media, id);
|
||||
return DataAccess.get(Media.class, id);
|
||||
}
|
||||
|
||||
@ -88,7 +90,7 @@ public class MediaResource {
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
@Operation(description = "Create a new Media", tags = "GLOBAL")
|
||||
@TypeScriptProgress
|
||||
@ApiTypeScriptProgress
|
||||
public Media uploadMedia( //
|
||||
// @AsyncType(Long.class) @FormDataParam("universeId") String universeId, //
|
||||
// @AsyncType(Long.class) @FormDataParam("typeId") String typeId, //
|
||||
@ -174,7 +176,7 @@ public class MediaResource {
|
||||
DataResource.removeTemporaryFile(tmpUID);
|
||||
throw new InputException("seriesId", "seriesId does not exist ...");
|
||||
}
|
||||
if (seriesNode.parentId != typeNode.id) {
|
||||
if (seriesNode.parentId.equals(typeNode.id)) {
|
||||
DataResource.removeTemporaryFile(tmpUID);
|
||||
throw new InputException("seriesId", "seriesId object have not the correct parent...");
|
||||
}
|
||||
@ -233,9 +235,9 @@ public class MediaResource {
|
||||
@Path("{id}/cover")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
@AsyncType(Media.class)
|
||||
@ApiAsyncType(Media.class)
|
||||
@Operation(description = "Upload a new season cover media", tags = "GLOBAL")
|
||||
@TypeScriptProgress
|
||||
@ApiTypeScriptProgress
|
||||
public Media uploadCover( //
|
||||
@PathParam("id") final Long id, //
|
||||
@FormDataParam("file") final InputStream fileInputStream, //
|
||||
@ -253,7 +255,7 @@ public class MediaResource {
|
||||
@Operation(description = "Remove a specific cover of a media", tags = "GLOBAL")
|
||||
public Media removeCover( //
|
||||
@PathParam("id") final Long id, //
|
||||
@PathParam("coverId") final UUID coverId //
|
||||
@PathParam("coverId") final ObjectId coverId //
|
||||
) throws Exception {
|
||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||
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.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.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.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
@ -58,17 +58,18 @@ public class SeasonResource {
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@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);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@PUT
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(description = "Modify a specific season", tags = "GLOBAL")
|
||||
public Season patch(@PathParam("id") final Long id, @AsyncType(Season.class) final String jsonRequest) throws Exception {
|
||||
DataAccess.updateWithJson(Season.class, id, jsonRequest);
|
||||
public Season patch(@PathParam("id") final Long id, @Valid final Season season) throws Exception {
|
||||
season.id = id;
|
||||
DataAccess.update(season, id);
|
||||
return DataAccess.get(Season.class, id);
|
||||
}
|
||||
|
||||
@ -85,7 +86,7 @@ public class SeasonResource {
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@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)
|
||||
throws Exception {
|
||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||
@ -98,7 +99,7 @@ public class SeasonResource {
|
||||
@Path("{id}/cover/{coverId}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@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()) {
|
||||
AddOnDataJson.removeLink(dbIo, Season.class, "id", id, "covers", coverId);
|
||||
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.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.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.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
@ -61,17 +61,18 @@ public class SeriesResource {
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@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);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@PUT
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(description = "Modify a specific Series", tags = "GLOBAL")
|
||||
public Series patch(@PathParam("id") final Long id, @AsyncType(Series.class) final String jsonRequest) throws Exception {
|
||||
DataAccess.updateWithJson(Series.class, id, jsonRequest);
|
||||
public Series patch(@PathParam("id") final Long id, @Valid final Series series) throws Exception {
|
||||
series.id = id;
|
||||
DataAccess.update(series, id);
|
||||
return DataAccess.get(Series.class, id);
|
||||
}
|
||||
|
||||
@ -88,7 +89,7 @@ public class SeriesResource {
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
@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)
|
||||
throws Exception {
|
||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||
@ -101,7 +102,7 @@ public class SeriesResource {
|
||||
@Path("{id}/cover/{coverId}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@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()) {
|
||||
AddOnDataJson.removeLink(dbIo, Series.class, "id", id, "covers", coverId);
|
||||
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.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.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.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
@ -61,17 +61,18 @@ public class TypeResource {
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@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);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@PUT
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(description = "Modify a specific Type", tags = "GLOBAL")
|
||||
public Type patch(@PathParam("id") final Long id, @AsyncType(Type.class) final String jsonRequest) throws Exception {
|
||||
DataAccess.updateWithJson(Type.class, id, jsonRequest);
|
||||
public Type patch(@PathParam("id") final Long id, @Valid final Type type) throws Exception {
|
||||
type.id = id;
|
||||
DataAccess.update(type, id);
|
||||
return DataAccess.get(Type.class, id);
|
||||
}
|
||||
|
||||
@ -88,7 +89,7 @@ public class TypeResource {
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
@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)
|
||||
throws Exception {
|
||||
try (DBAccess dbIo = DBAccess.createInterface()) {
|
||||
@ -101,7 +102,7 @@ public class TypeResource {
|
||||
@Path("{id}/cover/{coverId}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@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()) {
|
||||
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 org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryAnd;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.filter.GenericContext;
|
||||
import org.kar.karideo.model.UserMediaAdvancement;
|
||||
import org.atriasoft.archidata.dataAccess.DataAccess;
|
||||
import org.atriasoft.archidata.dataAccess.QueryAnd;
|
||||
import org.atriasoft.archidata.dataAccess.QueryCondition;
|
||||
import org.atriasoft.archidata.dataAccess.options.Condition;
|
||||
import org.atriasoft.archidata.filter.GenericContext;
|
||||
import org.atriasoft.karideo.model.UserMediaAdvancement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
@ -69,12 +70,12 @@ public class UserMediaAdvancementResource {
|
||||
public record MediaInformationsDelta(int time, float percent, boolean addCount) {
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@PUT
|
||||
@Path("{id}")
|
||||
@RolesAllowed("USER")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@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);
|
||||
if (elem == null) {
|
||||
// insert element
|
@ -1,10 +1,10 @@
|
||||
package org.kar.karideo.api;
|
||||
package org.atriasoft.karideo.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.filter.GenericContext;
|
||||
import org.kar.karideo.model.UserKarideo;
|
||||
import org.atriasoft.archidata.dataAccess.DataAccess;
|
||||
import org.atriasoft.archidata.filter.GenericContext;
|
||||
import org.atriasoft.karideo.model.UserKarideo;
|
||||
import org.slf4j.Logger;
|
||||
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.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.Logger;
|
@ -1,28 +1,29 @@
|
||||
package org.kar.karideo.migration;
|
||||
package org.atriasoft.karideo.migration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.api.DataResource;
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.externalRestApi.AnalyzeApi;
|
||||
import org.kar.archidata.externalRestApi.TsGenerateApi;
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
import org.kar.archidata.model.Data;
|
||||
import org.kar.archidata.model.User;
|
||||
import org.kar.archidata.model.token.JwtToken;
|
||||
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.model.Media;
|
||||
import org.kar.karideo.model.Season;
|
||||
import org.kar.karideo.model.Series;
|
||||
import org.kar.karideo.model.Type;
|
||||
import org.kar.karideo.model.UserMediaAdvancement;
|
||||
import org.atriasoft.archidata.api.DataResource;
|
||||
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||
import org.atriasoft.archidata.externalRestApi.AnalyzeApi;
|
||||
import org.atriasoft.archidata.externalRestApi.TsGenerateApi;
|
||||
import org.atriasoft.archidata.filter.PartRight;
|
||||
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||
import org.atriasoft.archidata.model.Data;
|
||||
import org.atriasoft.archidata.model.User;
|
||||
import org.atriasoft.archidata.model.token.JwtToken;
|
||||
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.model.Media;
|
||||
import org.atriasoft.karideo.model.Season;
|
||||
import org.atriasoft.karideo.model.Series;
|
||||
import org.atriasoft.karideo.model.Type;
|
||||
import org.atriasoft.karideo.model.UserMediaAdvancement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -45,6 +46,7 @@ public class Initialization extends MigrationSqlStep {
|
||||
final AnalyzeApi api = new AnalyzeApi();
|
||||
api.addAllApi(listOfResources);
|
||||
api.addModel(JwtToken.class);
|
||||
api.addModel(PartRight.class);
|
||||
TsGenerateApi.generateApi(api, "../front/src/back-api/");
|
||||
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.kar.karideo.model.UserMediaAdvancement;
|
||||
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||
import org.atriasoft.karideo.model.UserMediaAdvancement;
|
||||
|
||||
public class Migration20230810 extends MigrationSqlStep {
|
||||
|
@ -1,8 +1,8 @@
|
||||
package org.kar.karideo.migration;
|
||||
package org.atriasoft.karideo.migration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
import org.atriasoft.archidata.migration.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 {
|
||||
|
@ -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.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.LoggerFactory;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.kar.karideo.migration;
|
||||
package org.atriasoft.karideo.migration;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
@ -11,15 +11,15 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.kar.archidata.api.DataResource;
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
|
||||
import org.kar.archidata.dataAccess.options.OverrideTableName;
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.karideo.migration.model.CoverConversion;
|
||||
import org.kar.karideo.migration.model.MediaConversion;
|
||||
import org.kar.karideo.migration.model.OIDConversion;
|
||||
import org.atriasoft.archidata.api.DataResource;
|
||||
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||
import org.atriasoft.archidata.dataAccess.options.AccessDeletedItems;
|
||||
import org.atriasoft.archidata.dataAccess.options.OverrideTableName;
|
||||
import org.atriasoft.archidata.migration.MigrationSqlStep;
|
||||
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||
import org.atriasoft.karideo.migration.model.CoverConversion;
|
||||
import org.atriasoft.karideo.migration.model.MediaConversion;
|
||||
import org.atriasoft.karideo.migration.model.OIDConversion;
|
||||
import org.slf4j.Logger;
|
||||
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.UUID;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.atriasoft.archidata.annotation.DataJson;
|
||||
|
||||
import jakarta.persistence.Id;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.kar.karideo.migration.model;
|
||||
package org.atriasoft.karideo.migration.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.kar.karideo.migration.model;
|
||||
package org.atriasoft.karideo.migration.model;
|
||||
|
||||
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.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.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.model.Data;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
import org.hibernate.validator.constraints.UniqueElements;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@ -17,51 +21,58 @@ import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.PositiveOrZero;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@Entity
|
||||
@Table(name = "media")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@ApiGenerationMode(create = true, update = true)
|
||||
public class Media extends GenericDataSoftDelete {
|
||||
@Schema(description = "Name of the media (this represent the title)")
|
||||
@Column(nullable = false, length = 0)
|
||||
@Size(min = 0, max = 256)
|
||||
public String name;
|
||||
@Schema(description = "Description of the media")
|
||||
@Column(length = 0)
|
||||
@Size(min = 0, max = 8192)
|
||||
public String description;
|
||||
@Schema(description = "Foreign Key Id of the data")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class)
|
||||
@Column(nullable = false)
|
||||
@CheckForeignKey(target = Data.class)
|
||||
public ObjectId dataId;
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class)
|
||||
@Column(nullable = false)
|
||||
@Nullable
|
||||
public UUID dataIdOld;
|
||||
@Schema(description = "Type of the media")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
|
||||
@CheckForeignKey(target = Type.class)
|
||||
public Long typeId;
|
||||
@Schema(description = "Series reference of the media")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
|
||||
@CheckForeignKey(target = Series.class)
|
||||
public Long seriesId;
|
||||
@Schema(description = "Season reference of the media")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Season.class)
|
||||
@CheckForeignKey(target = Season.class)
|
||||
public Long seasonId;
|
||||
@Schema(description = "Episode Id")
|
||||
@PositiveOrZero
|
||||
public Integer episode;
|
||||
// ")
|
||||
public Integer date;
|
||||
@Schema(description = "Creation years of the media")
|
||||
public Integer time;
|
||||
public Date datePublication;
|
||||
@Schema(description = "Limitation Age of the media")
|
||||
@PositiveOrZero
|
||||
public Integer ageLimit;
|
||||
@Schema(description = "List of Id of the specific covers")
|
||||
@DataJson(targetEntity = Data.class)
|
||||
@DataJson()
|
||||
@Nullable
|
||||
public List<ObjectId> covers = null;
|
||||
@CollectionNotEmpty
|
||||
@UniqueElements
|
||||
public List<@CheckForeignKey(target = Data.class) ObjectId> covers = null;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Media [name=" + this.name + ", description=" + this.description + ", dataId=" + this.dataId + ", typeId=" + this.typeId + ", seriesId=" + this.seriesId + ", seasonId=" + this.seasonId
|
||||
+ ", episode=" + this.episode + ", date=" + this.date + ", time=" + this.time + ", ageLimit=" + this.ageLimit + ", covers=" + this.covers + "]";
|
||||
+ ", 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 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.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
import org.hibernate.validator.constraints.UniqueElements;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@ -15,23 +20,31 @@ import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@Table(name = "season")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@ApiGenerationMode(create = true, update = true)
|
||||
public class Season extends GenericDataSoftDelete {
|
||||
@Column(nullable = false, length = 0)
|
||||
@Schema(description = "Name of the media (this represent the title)")
|
||||
@Size(min = 0, max = 256)
|
||||
public String name;
|
||||
@Column(length = 0)
|
||||
@Schema(description = "Description of the media")
|
||||
@Size(min = 0, max = 8192)
|
||||
public String description;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "series parent ID")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class)
|
||||
@CheckForeignKey(target = Series.class)
|
||||
public Long parentId;
|
||||
@Schema(description = "List of Id of the specific covers")
|
||||
@DataJson()
|
||||
@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 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.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
import org.hibernate.validator.constraints.UniqueElements;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@ -15,23 +20,31 @@ import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@Table(name = "series")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@ApiGenerationMode(create = true, update = true)
|
||||
public class Series extends GenericDataSoftDelete {
|
||||
@Column(nullable = false, length = 0)
|
||||
@Size(min = 0, max = 256)
|
||||
@Schema(description = "Name of the media (this represent the title)")
|
||||
public String name;
|
||||
@Column(length = 0)
|
||||
@Schema(description = "Description of the media")
|
||||
@Size(min = 0, max = 8192)
|
||||
public String description;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "series parent ID")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)
|
||||
@CheckForeignKey(target = Type.class)
|
||||
public Long parentId;
|
||||
@Schema(description = "List of Id of the specific covers")
|
||||
@DataJson()
|
||||
@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 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.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
import org.hibernate.validator.constraints.UniqueElements;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@ -13,21 +18,28 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@Table(name = "type")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@ApiGenerationMode(create = true, update = true)
|
||||
public class Type extends GenericDataSoftDelete {
|
||||
@Column(nullable = false, length = 0)
|
||||
@Size(min = 0, max = 256)
|
||||
@Schema(description = "Name of the media (this represent the title)")
|
||||
public String name;
|
||||
@Column(length = 0)
|
||||
@Schema(description = "Description of the media")
|
||||
@Size(min = 0, max = 8192)
|
||||
public String description;
|
||||
@Schema(description = "List of Id of the specific covers")
|
||||
@DataJson()
|
||||
@Nullable
|
||||
public List<ObjectId> covers = null;
|
||||
@CollectionNotEmpty
|
||||
@UniqueElements
|
||||
public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null;
|
||||
|
||||
public Type() {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package org.kar.karideo.model;
|
||||
package org.atriasoft.karideo.model;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.User;
|
||||
import org.atriasoft.archidata.annotation.DataIfNotExists;
|
||||
import org.atriasoft.archidata.model.User;
|
||||
|
||||
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.kar.archidata.annotation.DataNotRead;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
import org.atriasoft.archidata.annotation.DataIfNotExists;
|
||||
import org.atriasoft.archidata.annotation.DataNotRead;
|
||||
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;
|
||||
|
||||
@ -12,28 +15,35 @@ import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.PositiveOrZero;
|
||||
|
||||
@Table(name = "userMediaAdvancement")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@ApiGenerationMode(create = true, update = true)
|
||||
public class UserMediaAdvancement extends GenericDataSoftDelete {
|
||||
@DataNotRead
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Foreign Key Id of the user")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = UserKarideo.class)
|
||||
@Nullable
|
||||
@ApiAccessLimitation(updatable = false, creatable = false)
|
||||
public Long userId;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Id of the media")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Media.class)
|
||||
@CheckForeignKey(target = Media.class)
|
||||
public Long mediaId;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Percent of advancement in the media")
|
||||
@PositiveOrZero
|
||||
public Float percent;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Number of second of advancement in the media")
|
||||
@PositiveOrZero
|
||||
public Integer time;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Number of time this media has been read")
|
||||
@PositiveOrZero
|
||||
public Integer count;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.kar.karideo.util;
|
||||
package org.atriasoft.karideo.util;
|
||||
|
||||
public class ConfigVariable {
|
||||
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 org.kar.archidata.tools.JWTWrapper;
|
||||
import org.atriasoft.archidata.filter.PartRight;
|
||||
import org.atriasoft.archidata.tools.JWTWrapper;
|
||||
|
||||
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 ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", Boolean.TRUE, "ADMIN", 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", 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.util.List;
|
||||
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.db.DbConfig;
|
||||
import org.kar.archidata.db.DbIoFactory;
|
||||
import org.kar.archidata.exception.DataAccessException;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
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.kar.karideo.model.UserKarideo;
|
||||
import org.atriasoft.archidata.dataAccess.DBAccess;
|
||||
import org.atriasoft.archidata.db.DbConfig;
|
||||
import org.atriasoft.archidata.db.DbIoFactory;
|
||||
import org.atriasoft.archidata.exception.DataAccessException;
|
||||
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||
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.atriasoft.karideo.model.UserKarideo;
|
||||
import org.slf4j.Logger;
|
||||
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.ExecutionCondition;
|
@ -1,4 +1,4 @@
|
||||
package test.kar.karideo;
|
||||
package test.atriasoft.karideo;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
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.TestMethodOrder;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.RESTApi;
|
||||
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||
import org.atriasoft.archidata.tools.RESTApi;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -1,6 +1,4 @@
|
||||
package test.kar.karideo;
|
||||
|
||||
import java.io.IOException;
|
||||
package test.atriasoft.karideo;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
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.TestMethodOrder;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.kar.archidata.exception.RESTErrorResponseException;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.RESTApi;
|
||||
import org.kar.karideo.api.HealthCheck.HealthResult;
|
||||
import org.atriasoft.archidata.exception.RESTErrorResponseException;
|
||||
import org.atriasoft.archidata.tools.ConfigBaseVariable;
|
||||
import org.atriasoft.archidata.tools.RESTApi;
|
||||
import org.atriasoft.karideo.api.HealthCheck.HealthResult;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -27,29 +25,22 @@ public class TestHealthCheck {
|
||||
|
||||
@BeforeAll
|
||||
public static void configureWebServer() throws Exception {
|
||||
ConfigureDb.configure();
|
||||
LOGGER.info("configure server ...");
|
||||
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)");
|
||||
webInterface.process();
|
||||
LOGGER.info("Start REST (DONE)");
|
||||
api = new RESTApi(ConfigBaseVariable.apiAdress);
|
||||
api.setToken(Common.ADMIN_TOKEN);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopWebServer() throws InterruptedException, IOException {
|
||||
public static void stopWebServer() throws Exception {
|
||||
LOGGER.info("Kill the web server");
|
||||
webInterface.stop();
|
||||
webInterface = null;
|
||||
LOGGER.info("Remove the test db");
|
||||
// DBEntry.closeAllForceMode();
|
||||
ConfigBaseVariable.clearAllValue();
|
||||
ConfigureDb.clear();
|
||||
}
|
||||
|
||||
@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.LoggerFactory;
|
||||
|
@ -2,6 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Karideo</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
|
@ -29,64 +29,66 @@
|
||||
"*.{ts,tsx,js,jsx,json}": "prettier --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-speech-recognition": "4.0.0",
|
||||
"regenerator-runtime": "0.14.1",
|
||||
"@locator/babel-jsx": "0.4.4",
|
||||
"@trivago/prettier-plugin-sort-imports": "5.2.2",
|
||||
"@chakra-ui/cli": "3.8.1",
|
||||
"@chakra-ui/react": "3.8.1",
|
||||
"@chakra-ui/cli": "3.16.0",
|
||||
"@chakra-ui/react": "3.16.0",
|
||||
"@emotion/react": "11.14.0",
|
||||
"allotment": "1.20.3",
|
||||
"css-mediaquery": "0.1.2",
|
||||
"dayjs": "1.11.13",
|
||||
"history": "5.3.0",
|
||||
"next-themes": "^0.4.4",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react-error-boundary": "5.0.0",
|
||||
"react-icons": "5.5.0",
|
||||
"react-router-dom": "7.2.0",
|
||||
"react-select": "5.10.0",
|
||||
"react-router-dom": "7.5.0",
|
||||
"react-select": "5.10.1",
|
||||
"react-use": "17.6.0",
|
||||
"zod": "3.24.2",
|
||||
"zustand": "5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chakra-ui/styled-system": "^2.12.0",
|
||||
"@playwright/test": "1.50.1",
|
||||
"@storybook/addon-actions": "8.5.8",
|
||||
"@storybook/addon-essentials": "8.5.8",
|
||||
"@storybook/addon-links": "8.5.8",
|
||||
"@storybook/addon-mdx-gfm": "8.5.8",
|
||||
"@storybook/react": "8.5.8",
|
||||
"@storybook/react-vite": "8.5.8",
|
||||
"@storybook/theming": "8.5.8",
|
||||
"@playwright/test": "1.51.1",
|
||||
"@storybook/addon-actions": "8.6.12",
|
||||
"@storybook/addon-essentials": "8.6.12",
|
||||
"@storybook/addon-links": "8.6.12",
|
||||
"@storybook/addon-mdx-gfm": "8.6.12",
|
||||
"@storybook/react": "8.6.12",
|
||||
"@storybook/react-vite": "8.6.12",
|
||||
"@storybook/theming": "8.6.12",
|
||||
"@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",
|
||||
"@trivago/prettier-plugin-sort-imports": "5.2.2",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/node": "22.13.5",
|
||||
"@types/react": "19.0.10",
|
||||
"@types/react-dom": "19.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "8.24.1",
|
||||
"@typescript-eslint/parser": "8.24.1",
|
||||
"@types/node": "22.14.1",
|
||||
"@types/react": "19.1.2",
|
||||
"@types/react-dom": "19.1.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.30.1",
|
||||
"@typescript-eslint/parser": "8.30.1",
|
||||
"@vitejs/plugin-react": "4.3.4",
|
||||
"eslint": "9.21.0",
|
||||
"eslint": "9.24.0",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-react": "7.37.4",
|
||||
"eslint-plugin-react-hooks": "5.1.0",
|
||||
"eslint-plugin-storybook": "0.11.3",
|
||||
"eslint-plugin-react": "7.37.5",
|
||||
"eslint-plugin-react-hooks": "5.2.0",
|
||||
"eslint-plugin-storybook": "0.12.0",
|
||||
"jest": "29.7.0",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"knip": "5.44.5",
|
||||
"lint-staged": "15.4.3",
|
||||
"npm-check-updates": "^17.1.15",
|
||||
"prettier": "3.5.2",
|
||||
"puppeteer": "24.2.1",
|
||||
"react-is": "19.0.0",
|
||||
"storybook": "8.5.8",
|
||||
"knip": "5.50.3",
|
||||
"lint-staged": "15.5.1",
|
||||
"npm-check-updates": "^17.1.18",
|
||||
"prettier": "3.5.3",
|
||||
"puppeteer": "24.6.1",
|
||||
"react-is": "19.1.0",
|
||||
"storybook": "8.6.12",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.7.3",
|
||||
"vite": "6.1.1",
|
||||
"vitest": "3.0.6"
|
||||
"typescript": "5.8.3",
|
||||
"vite": "6.2.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,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
headers,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
@ -32,7 +32,9 @@ export namespace DataResource {
|
||||
name: string,
|
||||
oid: ObjectId,
|
||||
},
|
||||
data: string,
|
||||
headers?: {
|
||||
Range?: string,
|
||||
},
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -42,7 +44,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
headers,
|
||||
});
|
||||
};
|
||||
/**
|
||||
@ -52,7 +54,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
headers,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
@ -61,7 +63,9 @@ export namespace DataResource {
|
||||
params: {
|
||||
oid: ObjectId,
|
||||
},
|
||||
data: string,
|
||||
headers?: {
|
||||
Range: string,
|
||||
},
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -71,7 +75,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
headers,
|
||||
});
|
||||
};
|
||||
/**
|
||||
@ -81,7 +85,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
headers,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
@ -90,7 +94,9 @@ export namespace DataResource {
|
||||
params: {
|
||||
oid: ObjectId,
|
||||
},
|
||||
data: string,
|
||||
headers?: {
|
||||
Range: string,
|
||||
},
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -100,7 +106,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
headers,
|
||||
});
|
||||
};
|
||||
/**
|
||||
|
@ -14,7 +14,7 @@ import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Media,
|
||||
MediaWrite,
|
||||
MediaUpdate,
|
||||
UUID,
|
||||
ZodMedia,
|
||||
isMedia,
|
||||
@ -87,12 +87,12 @@ export namespace MediaResource {
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: MediaWrite,
|
||||
data: MediaUpdate,
|
||||
}): Promise<Media> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/media/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
|
@ -14,7 +14,8 @@ import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Season,
|
||||
SeasonWrite,
|
||||
SeasonCreate,
|
||||
SeasonUpdate,
|
||||
UUID,
|
||||
ZodSeason,
|
||||
isSeason,
|
||||
@ -88,12 +89,12 @@ export namespace SeasonResource {
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: SeasonWrite,
|
||||
data: SeasonUpdate,
|
||||
}): Promise<Season> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/season/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
@ -110,7 +111,7 @@ export namespace SeasonResource {
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: SeasonWrite,
|
||||
data: SeasonCreate,
|
||||
}): Promise<Season> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
|
@ -14,7 +14,8 @@ import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Series,
|
||||
SeriesWrite,
|
||||
SeriesCreate,
|
||||
SeriesUpdate,
|
||||
UUID,
|
||||
ZodSeries,
|
||||
isSeries,
|
||||
@ -88,12 +89,12 @@ export namespace SeriesResource {
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: SeriesWrite,
|
||||
data: SeriesUpdate,
|
||||
}): Promise<Series> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/series/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
@ -110,7 +111,7 @@ export namespace SeriesResource {
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: SeriesWrite,
|
||||
data: SeriesCreate,
|
||||
}): Promise<Series> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
|
@ -14,7 +14,8 @@ import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Type,
|
||||
TypeWrite,
|
||||
TypeCreate,
|
||||
TypeUpdate,
|
||||
UUID,
|
||||
ZodType,
|
||||
isType,
|
||||
@ -88,12 +89,12 @@ export namespace TypeResource {
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: TypeWrite,
|
||||
data: TypeUpdate,
|
||||
}): Promise<Type> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/type/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
@ -110,7 +111,7 @@ export namespace TypeResource {
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: TypeWrite,
|
||||
data: TypeCreate,
|
||||
}): Promise<Type> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
MediaInformationsDeltaWrite,
|
||||
MediaInformationsDelta,
|
||||
UserMediaAdvancement,
|
||||
ZodUserMediaAdvancement,
|
||||
isUserMediaAdvancement,
|
||||
@ -85,12 +85,12 @@ export namespace UserMediaAdvancementResource {
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: MediaInformationsDeltaWrite,
|
||||
data: MediaInformationsDelta,
|
||||
}): Promise<UserMediaAdvancement> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/advancement/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
|
@ -3,23 +3,23 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
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({
|
||||
/**
|
||||
* Sha512 of the data
|
||||
*/
|
||||
sha512: zod.string().max(512),
|
||||
sha512: zod.string().max(512).readonly(),
|
||||
/**
|
||||
* Mime -type of the media
|
||||
*/
|
||||
mimeType: zod.string().max(512),
|
||||
mimeType: zod.string().max(512).readonly(),
|
||||
/**
|
||||
* Size in Byte of the data
|
||||
*/
|
||||
size: ZodLong,
|
||||
size: ZodLong.readonly(),
|
||||
/**
|
||||
* Unique ObjectID of the object
|
||||
*/
|
||||
@ -38,30 +38,3 @@ export function isData(data: any): data is Data {
|
||||
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 {ZodGenericData, ZodGenericDataWrite } from "./generic-data";
|
||||
import {ZodGenericData, ZodGenericDataUpdate , ZodGenericDataCreate } from "./generic-data";
|
||||
|
||||
export const ZodGenericDataSoftDelete = ZodGenericData.extend({
|
||||
/**
|
||||
@ -24,16 +24,29 @@ export function isGenericDataSoftDelete(data: any): data is GenericDataSoftDelet
|
||||
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 {
|
||||
ZodGenericDataSoftDeleteWrite.parse(data);
|
||||
ZodGenericDataSoftDeleteUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodGenericTiming, ZodGenericTimingUpdate , ZodGenericTimingCreate } from "./generic-timing";
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodGenericTiming, ZodGenericTimingWrite } from "./generic-timing";
|
||||
|
||||
export const ZodGenericData = ZodGenericTiming.extend({
|
||||
/**
|
||||
@ -25,16 +25,29 @@ export function isGenericData(data: any): data is GenericData {
|
||||
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 {
|
||||
ZodGenericDataWrite.parse(data);
|
||||
ZodGenericDataUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,33 @@ export function isGenericTiming(data: any): data is GenericTiming {
|
||||
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 {
|
||||
ZodGenericTimingWrite.parse(data);
|
||||
ZodGenericTimingUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -19,18 +19,3 @@ export function isHealthResult(data: any): data is HealthResult {
|
||||
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 "./oid-generic-data"
|
||||
export * from "./oid-generic-data-soft-delete"
|
||||
export * from "./part-right"
|
||||
export * from "./rest-error-response"
|
||||
export * from "./rest-input-error"
|
||||
export * from "./season"
|
||||
export * from "./series"
|
||||
export * from "./timestamp"
|
||||
|
@ -21,20 +21,3 @@ export function isJwtHeader(data: any): data is JwtHeader {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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 {ZodJwtHeader, ZodJwtHeaderWrite } from "./jwt-header";
|
||||
import {ZodJwtPayload, ZodJwtPayloadWrite } from "./jwt-payload";
|
||||
import {ZodJwtHeader} from "./jwt-header";
|
||||
import {ZodJwtPayload} from "./jwt-payload";
|
||||
|
||||
export const ZodJwtToken = zod.object({
|
||||
header: ZodJwtHeader,
|
||||
@ -24,21 +24,3 @@ export function isJwtToken(data: any): data is JwtToken {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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 {ZodObjectId} from "./object-id";
|
||||
import {ZodUUID} from "./uuid";
|
||||
import {ZodLong} from "./long";
|
||||
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({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string(),
|
||||
name: zod.string().max(256),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
description: zod.string().max(8192).optional(),
|
||||
/**
|
||||
* Foreign Key Id of the data
|
||||
*/
|
||||
dataId: ZodObjectId,
|
||||
dataIdOld: ZodUUID.optional(),
|
||||
/**
|
||||
* Type of the media
|
||||
*/
|
||||
@ -39,11 +38,10 @@ export const ZodMedia = ZodGenericDataSoftDelete.extend({
|
||||
* Episode Id
|
||||
*/
|
||||
episode: ZodInteger.optional(),
|
||||
date: ZodInteger.optional(),
|
||||
/**
|
||||
* Creation years of the media
|
||||
*/
|
||||
time: ZodInteger.optional(),
|
||||
datePublication: ZodIsoDate.optional(),
|
||||
/**
|
||||
* Limitation Age of the media
|
||||
*/
|
||||
@ -66,20 +64,19 @@ export function isMedia(data: any): data is Media {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodMediaWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
export const ZodMediaUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string().optional(),
|
||||
name: zod.string().max(256),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().nullable().optional(),
|
||||
description: zod.string().max(8192).nullable().optional(),
|
||||
/**
|
||||
* Foreign Key Id of the data
|
||||
*/
|
||||
dataId: ZodObjectId.optional(),
|
||||
dataIdOld: ZodUUID.nullable().optional(),
|
||||
dataId: ZodObjectId,
|
||||
/**
|
||||
* Type of the media
|
||||
*/
|
||||
@ -96,11 +93,10 @@ export const ZodMediaWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
* Episode Id
|
||||
*/
|
||||
episode: ZodInteger.nullable().optional(),
|
||||
date: ZodInteger.nullable().optional(),
|
||||
/**
|
||||
* Creation years of the media
|
||||
*/
|
||||
time: ZodInteger.nullable().optional(),
|
||||
datePublication: ZodIsoDate.nullable().optional(),
|
||||
/**
|
||||
* 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 {
|
||||
ZodMediaWrite.parse(data);
|
||||
ZodMediaUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
import { z as zod } from "zod";
|
||||
|
||||
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({
|
||||
/**
|
||||
@ -29,16 +29,29 @@ export function isOIDGenericDataSoftDelete(data: any): data is OIDGenericDataSof
|
||||
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 {
|
||||
ZodOIDGenericDataSoftDeleteWrite.parse(data);
|
||||
ZodOIDGenericDataSoftDeleteUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodObjectId} from "./object-id";
|
||||
import {ZodGenericTiming, ZodGenericTimingWrite } from "./generic-timing";
|
||||
import {ZodGenericTiming, ZodGenericTimingUpdate , ZodGenericTimingCreate } from "./generic-timing";
|
||||
|
||||
export const ZodOIDGenericData = ZodGenericTiming.extend({
|
||||
/**
|
||||
@ -25,16 +25,29 @@ export function isOIDGenericData(data: any): data is OIDGenericData {
|
||||
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 {
|
||||
ZodOIDGenericDataWrite.parse(data);
|
||||
ZodOIDGenericDataUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,9 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodObjectId} from "./object-id";
|
||||
import {ZodInteger} from "./integer";
|
||||
import {ZodObjectId} from "./object-id";
|
||||
import {ZodRestInputError} from "./rest-input-error";
|
||||
|
||||
export const ZodRestErrorResponse = zod.object({
|
||||
oid: ZodObjectId.optional(),
|
||||
@ -13,6 +14,7 @@ export const ZodRestErrorResponse = zod.object({
|
||||
time: zod.string(),
|
||||
status: ZodInteger,
|
||||
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 {ZodLong} from "./long";
|
||||
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({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string(),
|
||||
name: zod.string().max(256),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
description: zod.string().max(8192).optional(),
|
||||
/**
|
||||
* series parent ID
|
||||
*/
|
||||
@ -38,19 +38,19 @@ export function isSeason(data: any): data is Season {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodSeasonWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
export const ZodSeasonUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string().optional(),
|
||||
name: zod.string().max(256),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().nullable().optional(),
|
||||
description: zod.string().max(8192).nullable().optional(),
|
||||
/**
|
||||
* series parent ID
|
||||
*/
|
||||
parentId: ZodLong.optional(),
|
||||
parentId: ZodLong,
|
||||
/**
|
||||
* 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 {
|
||||
ZodSeasonWrite.parse(data);
|
||||
ZodSeasonUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -3,19 +3,19 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
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({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string(),
|
||||
name: zod.string().max(256),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
description: zod.string().max(8192).optional(),
|
||||
/**
|
||||
* series parent ID
|
||||
*/
|
||||
@ -38,19 +38,19 @@ export function isSeries(data: any): data is Series {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodSeriesWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
export const ZodSeriesUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string().optional(),
|
||||
name: zod.string().max(256),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().nullable().optional(),
|
||||
description: zod.string().max(8192).nullable().optional(),
|
||||
/**
|
||||
* series parent ID
|
||||
*/
|
||||
parentId: ZodLong.optional(),
|
||||
parentId: ZodLong,
|
||||
/**
|
||||
* 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 {
|
||||
ZodSeriesWrite.parse(data);
|
||||
ZodSeriesUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,17 @@
|
||||
import { z as zod } from "zod";
|
||||
|
||||
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({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string(),
|
||||
name: zod.string().max(256),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
description: zod.string().max(8192).optional(),
|
||||
/**
|
||||
* List of Id of the specific covers
|
||||
*/
|
||||
@ -33,15 +33,15 @@ export function isType(data: any): data is Type {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodTypeWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
export const ZodTypeUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
/**
|
||||
* Name of the media (this represent the title)
|
||||
*/
|
||||
name: zod.string().optional(),
|
||||
name: zod.string().max(256),
|
||||
/**
|
||||
* Description of the media
|
||||
*/
|
||||
description: zod.string().nullable().optional(),
|
||||
description: zod.string().max(8192).nullable().optional(),
|
||||
/**
|
||||
* 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 {
|
||||
ZodTypeWrite.parse(data);
|
||||
ZodTypeUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodUser, ZodUserWrite } from "./user";
|
||||
import {ZodUser, ZodUserUpdate , ZodUserCreate } from "./user";
|
||||
|
||||
export const ZodUserKarideo = ZodUser;
|
||||
|
||||
@ -18,16 +18,3 @@ export function isUserKarideo(data: any): data is UserKarideo {
|
||||
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 {ZodLong} from "./long";
|
||||
import {ZodFloat} from "./float";
|
||||
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({
|
||||
/**
|
||||
* Foreign Key Id of the user
|
||||
*/
|
||||
userId: ZodLong.optional(),
|
||||
userId: ZodLong.readonly().optional(),
|
||||
/**
|
||||
* Id of the media
|
||||
*/
|
||||
@ -43,38 +43,65 @@ export function isUserMediaAdvancement(data: any): data is UserMediaAdvancement
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodUserMediaAdvancementWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
/**
|
||||
* Foreign Key Id of the user
|
||||
*/
|
||||
userId: ZodLong.nullable().optional(),
|
||||
export const ZodUserMediaAdvancementUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
/**
|
||||
* Id of the media
|
||||
*/
|
||||
mediaId: ZodLong.optional(),
|
||||
mediaId: ZodLong,
|
||||
/**
|
||||
* Percent of advancement in the media
|
||||
*/
|
||||
percent: ZodFloat.optional(),
|
||||
percent: ZodFloat,
|
||||
/**
|
||||
* Number of second of advancement in the media
|
||||
*/
|
||||
time: ZodInteger.optional(),
|
||||
time: ZodInteger,
|
||||
/**
|
||||
* 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 {
|
||||
ZodUserMediaAdvancementWrite.parse(data);
|
||||
ZodUserMediaAdvancementUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -22,20 +22,3 @@ export function isUserOut(data: any): data is UserOut {
|
||||
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 {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({
|
||||
login: zod.string().min(3).max(128),
|
||||
@ -30,8 +30,8 @@ export function isUser(data: any): data is User {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
login: zod.string().min(3).max(128).optional(),
|
||||
export const ZodUserUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
login: zod.string().min(3).max(128),
|
||||
lastConnection: ZodTimestamp.nullable().optional(),
|
||||
blocked: zod.boolean().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 {
|
||||
ZodUserWrite.parse(data);
|
||||
ZodUserUpdate.parse(data);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -3,30 +3,29 @@
|
||||
* @copyright 2024, Edouard DUPIN, all right reserved
|
||||
* @license MPL-2
|
||||
*/
|
||||
|
||||
import { RestErrorResponse, isRestErrorResponse } from "./model";
|
||||
import { RestErrorResponse, isRestErrorResponse } from './model';
|
||||
|
||||
export enum HTTPRequestModel {
|
||||
ARCHIVE = "ARCHIVE",
|
||||
DELETE = "DELETE",
|
||||
HEAD = "HEAD",
|
||||
GET = "GET",
|
||||
OPTION = "OPTION",
|
||||
PATCH = "PATCH",
|
||||
POST = "POST",
|
||||
PUT = "PUT",
|
||||
RESTORE = "RESTORE",
|
||||
ARCHIVE = 'ARCHIVE',
|
||||
DELETE = 'DELETE',
|
||||
HEAD = 'HEAD',
|
||||
GET = 'GET',
|
||||
OPTION = 'OPTION',
|
||||
PATCH = 'PATCH',
|
||||
POST = 'POST',
|
||||
PUT = 'PUT',
|
||||
RESTORE = 'RESTORE',
|
||||
}
|
||||
export enum HTTPMimeType {
|
||||
ALL = "*/*",
|
||||
CSV = "text/csv",
|
||||
IMAGE = "image/*",
|
||||
IMAGE_JPEG = "image/jpeg",
|
||||
IMAGE_PNG = "image/png",
|
||||
JSON = "application/json",
|
||||
MULTIPART = "multipart/form-data",
|
||||
OCTET_STREAM = "application/octet-stream",
|
||||
TEXT_PLAIN = "text/plain",
|
||||
ALL = '*/*',
|
||||
CSV = 'text/csv',
|
||||
IMAGE = 'image/*',
|
||||
IMAGE_JPEG = 'image/jpeg',
|
||||
IMAGE_PNG = 'image/png',
|
||||
JSON = 'application/json',
|
||||
MULTIPART = 'multipart/form-data',
|
||||
OCTET_STREAM = 'application/octet-stream',
|
||||
TEXT_PLAIN = 'text/plain',
|
||||
}
|
||||
|
||||
export interface RESTConfig {
|
||||
@ -54,6 +53,14 @@ export interface ModelResponseHttp {
|
||||
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 {
|
||||
return data === undefined || data === null;
|
||||
}
|
||||
@ -78,6 +85,7 @@ export interface RESTRequestType {
|
||||
data?: any;
|
||||
params?: object;
|
||||
queries?: object;
|
||||
headers?: any;
|
||||
callbacks?: RESTCallbacks;
|
||||
}
|
||||
|
||||
@ -87,15 +95,15 @@ function replaceAll(input, searchValue, replaceValue) {
|
||||
|
||||
function removeTrailingSlashes(input: string): string {
|
||||
if (isNullOrUndefined(input)) {
|
||||
return "undefined";
|
||||
return 'undefined';
|
||||
}
|
||||
return input.replace(/\/+$/, "");
|
||||
return input.replace(/\/+$/, '');
|
||||
}
|
||||
function removeLeadingSlashes(input: string): string {
|
||||
if (isNullOrUndefined(input)) {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
return input.replace(/^\/+/, "");
|
||||
return input.replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
export function RESTUrl({
|
||||
@ -133,9 +141,9 @@ export function RESTUrl({
|
||||
}
|
||||
}
|
||||
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(
|
||||
@ -159,7 +167,7 @@ export function fetchProgress(
|
||||
return new Promise((resolve, reject) => {
|
||||
// Stream the upload progress
|
||||
if (progressUpload) {
|
||||
xhr.io?.upload.addEventListener("progress", (dataEvent) => {
|
||||
xhr.io?.upload.addEventListener('progress', (dataEvent) => {
|
||||
if (dataEvent.lengthComputable) {
|
||||
progressUpload(dataEvent.loaded, dataEvent.total);
|
||||
}
|
||||
@ -167,7 +175,7 @@ export function fetchProgress(
|
||||
}
|
||||
// Stream the download progress
|
||||
if (progressDownload) {
|
||||
xhr.io?.addEventListener("progress", (dataEvent) => {
|
||||
xhr.io?.addEventListener('progress', (dataEvent) => {
|
||||
if (dataEvent.lengthComputable) {
|
||||
progressDownload(dataEvent.loaded, dataEvent.total);
|
||||
}
|
||||
@ -187,19 +195,19 @@ export function fetchProgress(
|
||||
};
|
||||
}
|
||||
// Check if we have an internal Fail:
|
||||
xhr.io?.addEventListener("error", () => {
|
||||
xhr.io?.addEventListener('error', () => {
|
||||
xhr.io = undefined;
|
||||
reject(new TypeError("Failed to fetch"));
|
||||
reject(new TypeError('Failed to fetch'));
|
||||
});
|
||||
|
||||
// Capture the end of the stream
|
||||
xhr.io?.addEventListener("loadend", () => {
|
||||
xhr.io?.addEventListener('loadend', () => {
|
||||
if (xhr.io?.readyState !== XMLHttpRequest.DONE) {
|
||||
return;
|
||||
}
|
||||
if (xhr.io?.status === 0) {
|
||||
//the stream has been aborted
|
||||
reject(new TypeError("Fetch has been aborted"));
|
||||
reject(new TypeError('Fetch has been aborted'));
|
||||
return;
|
||||
}
|
||||
// Stream is ended, transform in a generic response:
|
||||
@ -209,17 +217,17 @@ export function fetchProgress(
|
||||
});
|
||||
const headersArray = replaceAll(
|
||||
xhr.io.getAllResponseHeaders().trim(),
|
||||
"\r\n",
|
||||
"\n"
|
||||
).split("\n");
|
||||
'\r\n',
|
||||
'\n'
|
||||
).split('\n');
|
||||
headersArray.forEach(function (header) {
|
||||
const firstColonIndex = header.indexOf(":");
|
||||
const firstColonIndex = header.indexOf(':');
|
||||
if (firstColonIndex !== -1) {
|
||||
const key = header.substring(0, firstColonIndex).trim();
|
||||
const value = header.substring(firstColonIndex + 1).trim();
|
||||
response.headers.set(key, value);
|
||||
} else {
|
||||
response.headers.set(header, "");
|
||||
response.headers.set(header, '');
|
||||
}
|
||||
});
|
||||
xhr.io = undefined;
|
||||
@ -241,27 +249,29 @@ export function RESTRequest({
|
||||
data,
|
||||
params,
|
||||
queries,
|
||||
headers = {},
|
||||
callbacks,
|
||||
}: RESTRequestType): Promise<ModelResponseHttp> {
|
||||
// Create the URL PATH:
|
||||
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
||||
let headers: any = {};
|
||||
if (restConfig.token !== undefined && restModel.tokenInUrl !== true) {
|
||||
headers["Authorization"] = `Bearer ${restConfig.token}`;
|
||||
headers['Authorization'] = `Bearer ${restConfig.token}`;
|
||||
}
|
||||
if (restModel.accept !== undefined) {
|
||||
headers["Accept"] = restModel.accept;
|
||||
headers['Accept'] = restModel.accept;
|
||||
}
|
||||
if (restModel.requestType !== HTTPRequestModel.GET &&
|
||||
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
|
||||
restModel.requestType !== HTTPRequestModel.RESTORE
|
||||
if (
|
||||
restModel.requestType !== HTTPRequestModel.GET &&
|
||||
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
|
||||
restModel.requestType !== HTTPRequestModel.RESTORE
|
||||
) {
|
||||
// if Get we have not a content type, the body is empty
|
||||
if (restModel.contentType !== HTTPMimeType.MULTIPART &&
|
||||
restModel.contentType !== undefined
|
||||
) {
|
||||
if (
|
||||
restModel.contentType !== HTTPMimeType.MULTIPART &&
|
||||
restModel.contentType !== undefined
|
||||
) {
|
||||
// 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;
|
||||
@ -302,19 +312,27 @@ export function RESTRequest({
|
||||
}
|
||||
action
|
||||
.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) {
|
||||
const contentType = response.headers.get("Content-Type");
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (
|
||||
!isNullOrUndefined(restModel.accept) &&
|
||||
restModel.accept !== contentType
|
||||
) {
|
||||
reject({
|
||||
name: "Model accept type incompatible",
|
||||
name: 'Model accept type incompatible',
|
||||
time: Date().toString(),
|
||||
status: 901,
|
||||
message: `REST Content type are not compatible: ${restModel.accept} != ${contentType}`,
|
||||
statusMessage: "Fetch error",
|
||||
error: "rest-tools.ts Wrong type in the message return type",
|
||||
statusMessage: 'Fetch error',
|
||||
error: 'rest-tools.ts Wrong type in the message return type',
|
||||
} as RestErrorResponse);
|
||||
} else if (contentType === HTTPMimeType.JSON) {
|
||||
response
|
||||
@ -324,12 +342,12 @@ export function RESTRequest({
|
||||
})
|
||||
.catch((reason: Error) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
name: 'API serialization error',
|
||||
time: Date().toString(),
|
||||
status: 902,
|
||||
message: `REST parse json fail: ${reason}`,
|
||||
statusMessage: "Fetch parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
statusMessage: 'Fetch parse error',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
} else {
|
||||
@ -349,22 +367,22 @@ export function RESTRequest({
|
||||
.text()
|
||||
.then((dataError: string) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
name: 'API serialization error',
|
||||
time: Date().toString(),
|
||||
status: 903,
|
||||
message: `REST parse error json with wrong type fail. ${dataError}`,
|
||||
statusMessage: "Fetch parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
statusMessage: 'Fetch parse error',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
name: 'API serialization error',
|
||||
time: Date().toString(),
|
||||
status: response.status,
|
||||
message: `unmanaged error model: ??? with error: ${reason}`,
|
||||
statusMessage: "Fetch ERROR parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
statusMessage: 'Fetch ERROR parse error',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
}
|
||||
@ -374,22 +392,22 @@ export function RESTRequest({
|
||||
.text()
|
||||
.then((dataError: string) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
name: 'API serialization error',
|
||||
time: Date().toString(),
|
||||
status: response.status,
|
||||
message: `unmanaged error model: ${dataError} with error: ${reason}`,
|
||||
statusMessage: "Fetch ERROR TEXT parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
statusMessage: 'Fetch ERROR TEXT parse error',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
name: 'API serialization error',
|
||||
time: Date().toString(),
|
||||
status: response.status,
|
||||
message: `unmanaged error model: ??? with error: ${reason}`,
|
||||
statusMessage: "Fetch ERROR TEXT FAIL",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
statusMessage: 'Fetch ERROR TEXT FAIL',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
});
|
||||
@ -400,12 +418,12 @@ export function RESTRequest({
|
||||
reject(error);
|
||||
} else {
|
||||
reject({
|
||||
name: "Request fail",
|
||||
name: 'Request fail',
|
||||
time: Date(),
|
||||
status: 999,
|
||||
message: error,
|
||||
statusMessage: "Fetch catch error",
|
||||
error: "rest-tools.ts detect an error in the fetch request",
|
||||
statusMessage: 'Fetch catch error',
|
||||
error: 'rest-tools.ts detect an error in the fetch request',
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -426,12 +444,12 @@ export function RESTRequestJson<TYPE>(
|
||||
resolve(value.data);
|
||||
} else {
|
||||
reject({
|
||||
name: "Model check fail",
|
||||
name: 'Model check fail',
|
||||
time: Date().toString(),
|
||||
status: 950,
|
||||
error: "REST Fail to verify the data",
|
||||
statusMessage: "API cast ERROR",
|
||||
message: "api.ts Check type as fail",
|
||||
error: 'REST Fail to verify the data',
|
||||
statusMessage: 'API cast ERROR',
|
||||
message: 'api.ts Check type as fail',
|
||||
} as RestErrorResponse);
|
||||
}
|
||||
})
|
||||
|
@ -8,7 +8,7 @@ import { DataUrlAccess } from '@/utils/data-url-access';
|
||||
import { Icon } from './Icon';
|
||||
|
||||
export type CoversProps = Omit<BoxProps, 'iconEmpty'> & {
|
||||
data?: ObjectId[];
|
||||
data?: readonly ObjectId[];
|
||||
size?: BoxProps['width'];
|
||||
iconEmpty?: ReactElement;
|
||||
slideshow?: boolean;
|
||||
@ -70,7 +70,9 @@ export const Covers = ({
|
||||
src={url}
|
||||
maxWidth={size}
|
||||
maxHeight={size}
|
||||
boxSize={size}
|
||||
//boxSize={size}
|
||||
width="100%"
|
||||
height="100%"
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
|
@ -1,26 +1,62 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
|
||||
|
||||
import { Box, Button, ConditionalValue, Flex, HStack, IconButton, Span, Text, 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, MdSupervisedUserCircle } from 'react-icons/md';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ConditionalValue,
|
||||
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 { useColorMode, useColorModeValue } from '@/components/ui/color-mode';
|
||||
import { DrawerBody, DrawerContent, DrawerHeader, DrawerRoot } from '@/components/ui/drawer';
|
||||
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '@/components/ui/menu';
|
||||
import {
|
||||
DrawerBody,
|
||||
DrawerContent,
|
||||
DrawerHeader,
|
||||
DrawerRoot,
|
||||
} from '@/components/ui/drawer';
|
||||
import {
|
||||
MenuContent,
|
||||
MenuItem,
|
||||
MenuRoot,
|
||||
MenuTrigger,
|
||||
} from '@/components/ui/menu';
|
||||
import { environment } from '@/environment';
|
||||
import { useServiceContext } from '@/service/ServiceContext';
|
||||
import { useSessionService } from '@/service/session';
|
||||
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';
|
||||
|
||||
@ -37,6 +73,8 @@ export const BUTTON_TOP_BAR_PROPERTY = {
|
||||
export type TopBarProps = {
|
||||
children?: ReactNode;
|
||||
title?: string;
|
||||
titleLink?: string;
|
||||
titleIcon?: ReactNode;
|
||||
};
|
||||
|
||||
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 { colorMode, toggleColorMode } = useColorMode();
|
||||
const { session } = useServiceContext();
|
||||
const { clearToken } = useSessionService();
|
||||
const { clearToken, isConnected } = useSessionService();
|
||||
const backColor = useColorModeValue('back.100', 'back.800');
|
||||
const drawerDisclose = useDisclosure();
|
||||
const onChangeTheme = () => {
|
||||
drawerDisclose.onOpen();
|
||||
const isVisible = useBreakpointValue({ base: false, md: true });
|
||||
const onOpenLeftMenu = () => {
|
||||
if (!isConnected) {
|
||||
onForceReload();
|
||||
} else {
|
||||
drawerDisclose.onOpen();
|
||||
}
|
||||
};
|
||||
const onSignIn = (): void => {
|
||||
clearToken();
|
||||
@ -99,8 +147,13 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
const onKarso = (): void => {
|
||||
requestOpenSite();
|
||||
};
|
||||
const onForceReload = (): void => {
|
||||
// @ts-expect-error
|
||||
window.location.reload(true);
|
||||
};
|
||||
return (
|
||||
<Flex
|
||||
minWidth="320px"
|
||||
position="absolute"
|
||||
top={0}
|
||||
left={0}
|
||||
@ -114,33 +167,32 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
||||
zIndex={200}
|
||||
>
|
||||
{session?.isConnected ?
|
||||
<Button {...BUTTON_TOP_BAR_PROPERTY} onClick={onChangeTheme}>
|
||||
<Button {...BUTTON_TOP_BAR_PROPERTY} onClick={onOpenLeftMenu}>
|
||||
<HStack>
|
||||
<LuAlignJustify />
|
||||
<Text paddingLeft="3px" fontWeight="bold">
|
||||
{environment.applName}
|
||||
</Text>
|
||||
{isVisible && (
|
||||
<Text paddingLeft="3px" fontWeight="bold">
|
||||
{environment.applName}
|
||||
</Text>
|
||||
)}
|
||||
</HStack>
|
||||
</Button>
|
||||
|
||||
:(
|
||||
<HStack {...BUTTON_TOP_BAR_PROPERTY} >
|
||||
<LuAlignJustify />
|
||||
<Span paddingLeft="3px" fontWeight="bold">{environment.applName}</Span>
|
||||
</HStack>)
|
||||
}
|
||||
{title && (
|
||||
<Text
|
||||
<Flex
|
||||
truncate
|
||||
fontSize="20px"
|
||||
fontWeight="bold"
|
||||
textTransform="uppercase"
|
||||
marginRight="auto"
|
||||
userSelect="none"
|
||||
color="brand.500"
|
||||
onClick={titleLink ? () => navigate(titleLink) : undefined}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
<Flex gap="4px">
|
||||
{titleIcon}
|
||||
{title}
|
||||
</Flex>
|
||||
</Flex>
|
||||
)}
|
||||
{children}
|
||||
<Flex right="0">
|
||||
@ -205,6 +257,13 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
<MenuItem value="karso" valueText="Karso" onClick={onKarso}>
|
||||
<LuKeySquare /> Karso (SSO)
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
value="force_reload"
|
||||
valueText="Karso"
|
||||
onClick={onForceReload}
|
||||
>
|
||||
<MdRestartAlt /> force reload
|
||||
</MenuItem>
|
||||
{colorMode === 'light' ? (
|
||||
<MenuItem
|
||||
value="set-dark"
|
||||
@ -226,52 +285,52 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
</MenuRoot>
|
||||
)}
|
||||
</Flex>
|
||||
{session?.isConnected &&
|
||||
<DrawerRoot
|
||||
placement="start"
|
||||
onOpenChange={drawerDisclose.onClose}
|
||||
open={drawerDisclose.open}
|
||||
data-testid="top-bar_drawer-root"
|
||||
>
|
||||
<DrawerContent data-testid="top-bar_drawer-content">
|
||||
<DrawerHeader
|
||||
paddingY="auto"
|
||||
as="button"
|
||||
onClick={drawerDisclose.onClose}
|
||||
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
||||
backgroundColor={backColor}
|
||||
color={useColorModeValue('brand.900', 'brand.50')}
|
||||
textTransform="uppercase"
|
||||
>
|
||||
<HStack {...BUTTON_TOP_BAR_PROPERTY} cursor="pointer">
|
||||
<LuArrowBigLeft />
|
||||
<Span paddingLeft="3px">{environment.applName}</Span>
|
||||
</HStack>
|
||||
</DrawerHeader>
|
||||
<DrawerBody paddingX="0px">
|
||||
<Box marginY="3" />
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/"
|
||||
title="Home"
|
||||
icon={<MdHome />}
|
||||
/>
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/on-air"
|
||||
title="On air"
|
||||
icon={<MdOutlinePlaylistPlay />}
|
||||
/>
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/add"
|
||||
title="Add Media"
|
||||
icon={<MdOutlineUploadFile />}
|
||||
/>
|
||||
</DrawerBody>
|
||||
</DrawerContent>
|
||||
</DrawerRoot>
|
||||
}
|
||||
{session?.isConnected && (
|
||||
<DrawerRoot
|
||||
placement="start"
|
||||
onOpenChange={drawerDisclose.onClose}
|
||||
open={drawerDisclose.open}
|
||||
data-testid="top-bar_drawer-root"
|
||||
>
|
||||
<DrawerContent data-testid="top-bar_drawer-content">
|
||||
<DrawerHeader
|
||||
paddingY="auto"
|
||||
as="button"
|
||||
onClick={drawerDisclose.onClose}
|
||||
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
||||
backgroundColor={backColor}
|
||||
color={useColorModeValue('brand.900', 'brand.50')}
|
||||
textTransform="uppercase"
|
||||
>
|
||||
<HStack {...BUTTON_TOP_BAR_PROPERTY} cursor="pointer">
|
||||
<LuArrowBigLeft />
|
||||
<Span paddingLeft="3px">{environment.applName}</Span>
|
||||
</HStack>
|
||||
</DrawerHeader>
|
||||
<DrawerBody paddingX="0px">
|
||||
<Box marginY="3" />
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/"
|
||||
title="Home"
|
||||
icon={<MdHome />}
|
||||
/>
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/on-air"
|
||||
title="On air"
|
||||
icon={<MdOutlinePlaylistPlay />}
|
||||
/>
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/add"
|
||||
title="Add Media"
|
||||
icon={<MdOutlineUploadFile />}
|
||||
/>
|
||||
</DrawerBody>
|
||||
</DrawerContent>
|
||||
</DrawerRoot>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
@ -1,6 +1,14 @@
|
||||
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 {
|
||||
MdFastForward,
|
||||
MdFastRewind,
|
||||
@ -16,7 +24,7 @@ import {
|
||||
MdRepeat,
|
||||
MdRepeatOne,
|
||||
MdStop,
|
||||
MdTrendingFlat
|
||||
MdTrendingFlat,
|
||||
} from 'react-icons/md';
|
||||
|
||||
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||
@ -70,15 +78,15 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
||||
const [isRunning, setIsRunning] = useState(true);
|
||||
useEffect(() => {
|
||||
if (!isRunning || time <= 0) {
|
||||
console.log(`exit timer`);
|
||||
setIsRunning(false);
|
||||
console.log(`exit timer`);
|
||||
setIsRunning(false);
|
||||
return;
|
||||
}
|
||||
const timer = setInterval(() => {
|
||||
setTime((prevTime) => {
|
||||
console.log(`current time : ${prevTime}`);
|
||||
return prevTime - 1;
|
||||
});
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
@ -97,9 +105,9 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
||||
setIsRunning(true);
|
||||
}
|
||||
};
|
||||
window.addEventListener("mousemove", resetTimerLocal);
|
||||
window.addEventListener('mousemove', resetTimerLocal);
|
||||
return () => {
|
||||
window.removeEventListener("mousemove", resetTimerLocal);
|
||||
window.removeEventListener('mousemove', resetTimerLocal);
|
||||
};
|
||||
}, [playMediaList, setTime, setIsRunning]);
|
||||
|
||||
@ -121,30 +129,33 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
||||
useEffect(() => {
|
||||
setMediaSource(
|
||||
dataMedia && dataMedia?.dataId
|
||||
? DataUrlAccess.getUrl(dataMedia?.dataId)
|
||||
? DataUrlAccess.getUrl(dataMedia?.dataId, 'plop.mkv')
|
||||
: ''
|
||||
);
|
||||
}, [dataMedia, setMediaSource]);
|
||||
console.log(`mediaSource = ${mediaSource}`);
|
||||
const backColor = useColorModeValue('back.100', 'back.800');
|
||||
const configButton = isMobile ? {
|
||||
borderRadius: 'full',
|
||||
backgroundColor: 'transparent',
|
||||
_hover: {
|
||||
bgColor: 'brand.500',
|
||||
},
|
||||
width: '35px',
|
||||
height: '35px',
|
||||
padding: '2px',
|
||||
} : {
|
||||
borderRadius: 'full',
|
||||
backgroundColor: 'transparent',
|
||||
_hover: {
|
||||
bgColor: 'brand.500',
|
||||
},
|
||||
width: '50px',
|
||||
height: '50px',
|
||||
padding: '5px',
|
||||
};
|
||||
const configButton = isMobile
|
||||
? {
|
||||
borderRadius: 'full',
|
||||
backgroundColor: 'transparent',
|
||||
_hover: {
|
||||
bgColor: 'brand.500',
|
||||
},
|
||||
width: '35px',
|
||||
height: '35px',
|
||||
padding: '2px',
|
||||
}
|
||||
: {
|
||||
borderRadius: 'full',
|
||||
backgroundColor: 'transparent',
|
||||
_hover: {
|
||||
bgColor: 'brand.500',
|
||||
},
|
||||
width: '50px',
|
||||
height: '50px',
|
||||
padding: '5px',
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!videoRef || !videoRef.current) {
|
||||
@ -237,6 +248,7 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
||||
* Call when meta-data is updated
|
||||
*/
|
||||
function onChangeMetadata(): void {
|
||||
console.log(`onChangeMetadata: ${videoRef.current?.duration}`);
|
||||
const seconds = videoRef.current?.duration;
|
||||
if (seconds !== undefined) {
|
||||
setDuration(seconds);
|
||||
@ -246,14 +258,16 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
||||
if (!videoRef || !videoRef.current) {
|
||||
return;
|
||||
}
|
||||
//console.log(`onTimeUpdate ${videoRef.current.currentTime}`);
|
||||
console.log(`onTimeUpdate ${videoRef.current.currentTime}`);
|
||||
setTimeProgress(videoRef.current.currentTime);
|
||||
};
|
||||
const onDurationChange = (event) => {};
|
||||
const onChangeStateToPlay = () => {
|
||||
console.log(`onChangeStateToPlay ...`);
|
||||
setIsPlaying(true);
|
||||
};
|
||||
const onChangeStateToPause = () => {
|
||||
console.log(`onChangeStateToPause ...`);
|
||||
setIsPlaying(false);
|
||||
};
|
||||
const marks = () => {
|
||||
@ -292,208 +306,227 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
|
||||
setIsPiP(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Erreur avec Picture-in-Picture:", error);
|
||||
console.error('Erreur avec Picture-in-Picture:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
const [isFullScreen, setIsFullScreen] = useState(false);
|
||||
useEffect(() => {
|
||||
const handleFullScreenChange = () => {
|
||||
console.log(`changeFullScreen: ${!!document.fullscreenElement}`)
|
||||
console.log(`changeFullScreen: ${!!document.fullscreenElement}`);
|
||||
setIsFullScreen(!!document.fullscreenElement);
|
||||
};
|
||||
|
||||
document.addEventListener("fullscreenchange", handleFullScreenChange);
|
||||
document.addEventListener('fullscreenchange', handleFullScreenChange);
|
||||
return () => {
|
||||
document.removeEventListener("fullscreenchange", handleFullScreenChange);
|
||||
document.removeEventListener('fullscreenchange', handleFullScreenChange);
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
{!isNullOrUndefined(MediaOffset) && (
|
||||
<>
|
||||
<Flex
|
||||
position="absolute"
|
||||
//height="500px"
|
||||
minHeight="150px"
|
||||
paddingY="5px"
|
||||
paddingX="10px"
|
||||
marginX="15px"
|
||||
bottom={0}
|
||||
left={0}
|
||||
right={0}
|
||||
zIndex={1000}
|
||||
borderWidth="1px"
|
||||
borderColor="brand.900"
|
||||
bgColor={isFullScreen ? "0x000000" : backColor}
|
||||
borderTopRadius="10px"
|
||||
direction="column"
|
||||
ref={containerRef}
|
||||
<Flex
|
||||
position="absolute"
|
||||
//height="500px"
|
||||
minHeight="150px"
|
||||
paddingY="5px"
|
||||
paddingX="10px"
|
||||
marginX="15px"
|
||||
bottom={0}
|
||||
left={0}
|
||||
right={0}
|
||||
zIndex={1000}
|
||||
borderWidth="1px"
|
||||
borderColor="brand.900"
|
||||
bgColor={isFullScreen ? '0x000000' : backColor}
|
||||
borderTopRadius="10px"
|
||||
direction="column"
|
||||
ref={containerRef}
|
||||
>
|
||||
<chakra.video
|
||||
position={isFullScreen ? "absolute" : "relative"}
|
||||
maxHeight={isFullScreen ? undefined : "30vh"}
|
||||
maxWidth={isFullScreen ? undefined : "100%"}
|
||||
height={isFullScreen ? "100%" : undefined}
|
||||
width={isFullScreen ? "100%": undefined}
|
||||
<Flex
|
||||
position={isFullScreen ? 'absolute' : 'relative'}
|
||||
maxHeight={isFullScreen ? undefined : '30vh'}
|
||||
maxWidth={isFullScreen ? undefined : '100%'}
|
||||
marginX="auto"
|
||||
src={mediaSource}
|
||||
ref={videoRef}
|
||||
//preload={true}
|
||||
onPlay={onChangeStateToPlay}
|
||||
onPause={onChangeStateToPause}
|
||||
onTimeUpdate={onTimeUpdate}
|
||||
onDurationChange={onDurationChange}
|
||||
onLoadedMetadata={onChangeMetadata}
|
||||
autoPlay={true}
|
||||
onEnded={onAudioEnded}
|
||||
>
|
||||
<video
|
||||
height={isFullScreen ? '100%' : undefined}
|
||||
width={isFullScreen ? '100%' : undefined}
|
||||
src={mediaSource}
|
||||
ref={videoRef}
|
||||
onPlay={onChangeStateToPlay}
|
||||
onPause={onChangeStateToPause}
|
||||
onTimeUpdate={onTimeUpdate}
|
||||
onDurationChange={onDurationChange}
|
||||
onLoadedMetadata={onChangeMetadata}
|
||||
autoPlay={true}
|
||||
onEnded={onAudioEnded}
|
||||
/>
|
||||
{(!isFullScreen || (!isMobile || isRunning)) && <><Text
|
||||
alignContent="left"
|
||||
fontSize="20px"
|
||||
fontWeight="bold"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{dataMedia?.name ?? '???'}
|
||||
</Text>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="16px"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{dataSeries && dataSeries.name}
|
||||
{dataSeason && dataSeason?.name}
|
||||
{dataType && ` / ${dataType.name}`}
|
||||
</Text>
|
||||
{isFullScreen && <Spacer/>}
|
||||
<Box width="full" paddingX="15px">
|
||||
<Slider
|
||||
defaultValue={[0]}
|
||||
value={[timeProgress]}
|
||||
min={0}
|
||||
max={duration}
|
||||
step={0.1}
|
||||
onValueChange={(e) => onSeek(e.value)}
|
||||
variant="outline"
|
||||
colorPalette="brand"
|
||||
marks={marks()}
|
||||
//focusCapture={false}
|
||||
>
|
||||
<SliderTrack
|
||||
bg="brand.200"
|
||||
height="10px"
|
||||
borderRadius="full"
|
||||
></SliderTrack>
|
||||
</Slider>
|
||||
</Box>
|
||||
<Flex>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="16px"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{formatTime(timeProgress)}
|
||||
</Text>
|
||||
<Text alignContent="left" fontSize="16px" userSelect="none">
|
||||
{formatTime(duration)}
|
||||
</Text>
|
||||
</Flex>
|
||||
{(!isFullScreen || !isMobile || isRunning) && (
|
||||
<>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="20px"
|
||||
fontWeight="bold"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{dataMedia?.name ?? '???'}
|
||||
</Text>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="16px"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{dataSeries && dataSeries.name}
|
||||
{dataSeason && dataSeason?.name}
|
||||
{dataType && ` / ${dataType.name}`}
|
||||
</Text>
|
||||
{isFullScreen && <Spacer />}
|
||||
<Box width="full" paddingX="15px">
|
||||
<Slider
|
||||
defaultValue={[0]}
|
||||
value={[timeProgress]}
|
||||
min={0}
|
||||
max={duration}
|
||||
step={0.1}
|
||||
onValueChange={(e) => onSeek(e.value)}
|
||||
variant="outline"
|
||||
colorPalette="brand"
|
||||
marks={marks()}
|
||||
//focusCapture={false}
|
||||
>
|
||||
<SliderTrack
|
||||
bg="brand.200"
|
||||
height="10px"
|
||||
borderRadius="full"
|
||||
></SliderTrack>
|
||||
</Slider>
|
||||
</Box>
|
||||
<Flex>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="16px"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{formatTime(timeProgress)}
|
||||
</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 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"
|
||||
onClick={onClick}
|
||||
>
|
||||
<Spacer/>
|
||||
<Spacer />
|
||||
<Text
|
||||
as="span"
|
||||
alignContent="left"
|
||||
@ -57,6 +57,7 @@ export const DisplayMediaFull = ({
|
||||
// TODO: noOfLines={1}
|
||||
color={MediaActive?.id === media.id ? 'green.700' : undefined}
|
||||
>
|
||||
{media.id}
|
||||
{media.name} {media.episode && ` [${media.episode}]`}
|
||||
</Text>
|
||||
{/* {dataSeason && (
|
||||
|
@ -4,7 +4,7 @@ import { Button, Tabs, Text, useDisclosure } from '@chakra-ui/react';
|
||||
import { MdAdminPanelSettings, MdDeleteForever, MdEdit } from 'react-icons/md';
|
||||
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 { FormInput } from '@/components/form/FormInput';
|
||||
import { FormNumber } from '@/components/form/FormNumber';
|
||||
@ -63,19 +63,24 @@ export const MediaEditPopUp = ({}: MediaEditPopUpProps) => {
|
||||
};
|
||||
const initialRef = useRef<HTMLButtonElement>(null);
|
||||
const finalRef = useRef<HTMLButtonElement>(null);
|
||||
const form = useFormidable<MediaWrite>({
|
||||
const form = useFormidable<MediaUpdate>({
|
||||
initialValues: dataMedia,
|
||||
deltaConfig: { omit: ['covers'] },
|
||||
});
|
||||
const onSave = async (dataDelta: MediaWrite) => {
|
||||
const onSave = async (data: MediaUpdate) => {
|
||||
if (isNullOrUndefined(mediaIdInt)) {
|
||||
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(
|
||||
MediaResource.patch({
|
||||
restConfig: session.getRestConfig(),
|
||||
data: dataDelta,
|
||||
data: ZodMediaUpdate.parse({ episode: episodeNumber, ...rest }),
|
||||
params: {
|
||||
id: mediaIdInt,
|
||||
},
|
||||
@ -146,7 +151,7 @@ export const MediaEditPopUp = ({}: MediaEditPopUpProps) => {
|
||||
>
|
||||
{/* <DialogOverlay /> */}
|
||||
<DialogContent>
|
||||
<Formidable.From form={form} onSubmitDelta={onSave}>
|
||||
<Formidable.From form={form} onSubmit={onSave}>
|
||||
<DialogHeader>Edit Media</DialogHeader>
|
||||
{/* <DialogCloseButton ref={finalRef} /> */}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from 'react-icons/md';
|
||||
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 { FormGroupShow } from '@/components/form/FormGroup';
|
||||
import { FormInput } from '@/components/form/FormInput';
|
||||
@ -66,19 +66,19 @@ export const SeasonEditPopUp = ({}: SeasonEditPopUpProps) => {
|
||||
};
|
||||
const initialRef = useRef<HTMLButtonElement>(null);
|
||||
const finalRef = useRef<HTMLButtonElement>(null);
|
||||
const form = useFormidable<SeasonWrite>({
|
||||
const form = useFormidable<SeasonUpdate>({
|
||||
initialValues: dataSeason,
|
||||
deltaConfig: { omit: ['covers'] },
|
||||
});
|
||||
const onSave = async (deltaData: SeasonWrite) => {
|
||||
const onSave = async (data: SeasonUpdate) => {
|
||||
if (isNullOrUndefined(seasonIdInt)) {
|
||||
return;
|
||||
}
|
||||
console.log(`onSave = ${JSON.stringify(deltaData, null, 2)}`);
|
||||
console.log(`onSave = ${JSON.stringify(data, null, 2)}`);
|
||||
store.update(
|
||||
SeasonResource.patch({
|
||||
restConfig: session.getRestConfig(),
|
||||
data: deltaData,
|
||||
data: ZodSeasonUpdate.parse(data),
|
||||
params: {
|
||||
id: seasonIdInt,
|
||||
},
|
||||
@ -150,7 +150,7 @@ export const SeasonEditPopUp = ({}: SeasonEditPopUpProps) => {
|
||||
data-testid="Season-edit-pop-up"
|
||||
>
|
||||
<DialogContent>
|
||||
<Formidable.From form={form} onSubmitDelta={onSave}>
|
||||
<Formidable.From form={form} onSubmit={onSave}>
|
||||
<DialogHeader>Edit Season</DialogHeader>
|
||||
{/* <DialogCloseButton ref={finalRef} /> */}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from 'react-icons/md';
|
||||
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 { FormInput } from '@/components/form/FormInput';
|
||||
import { FormTextarea } from '@/components/form/FormTextarea';
|
||||
@ -62,19 +62,19 @@ export const SeriesEditPopUp = ({}: SeriesEditPopUpProps) => {
|
||||
};
|
||||
const initialRef = useRef<HTMLButtonElement>(null);
|
||||
const finalRef = useRef<HTMLButtonElement>(null);
|
||||
const form = useFormidable<SeriesWrite>({
|
||||
const form = useFormidable<SeriesUpdate>({
|
||||
initialValues: dataSeries,
|
||||
deltaConfig: { omit: ['covers'] },
|
||||
});
|
||||
const onSave = async (dataDelta: SeriesWrite) => {
|
||||
const onSave = async (data: SeriesUpdate) => {
|
||||
if (isNullOrUndefined(seriesIdInt)) {
|
||||
return;
|
||||
}
|
||||
console.log(`onSave = ${JSON.stringify(dataDelta, null, 2)}`);
|
||||
console.log(`onSave = ${JSON.stringify(data, null, 2)}`);
|
||||
store.update(
|
||||
SeriesResource.patch({
|
||||
restConfig: session.getRestConfig(),
|
||||
data: dataDelta,
|
||||
data: ZodSeriesUpdate.parse(data),
|
||||
params: {
|
||||
id: seriesIdInt,
|
||||
},
|
||||
@ -146,7 +146,7 @@ export const SeriesEditPopUp = ({}: SeriesEditPopUpProps) => {
|
||||
>
|
||||
{/* <DialogOverlay /> */}
|
||||
<DialogContent>
|
||||
<Formidable.From form={form} onSubmitDelta={onSave}>
|
||||
<Formidable.From form={form} onSubmit={onSave}>
|
||||
<DialogHeader>Edit Series</DialogHeader>
|
||||
{/* <DialogCloseButton ref={finalRef} /> */}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from 'react-icons/md';
|
||||
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 { FormInput } from '@/components/form/FormInput';
|
||||
import { FormTextarea } from '@/components/form/FormTextarea';
|
||||
@ -65,19 +65,19 @@ export const TypeEditPopUp = ({}: TypeEditPopUpProps) => {
|
||||
};
|
||||
const initialRef = useRef<HTMLButtonElement>(null);
|
||||
const finalRef = useRef<HTMLButtonElement>(null);
|
||||
const form = useFormidable<TypeWrite>({
|
||||
const form = useFormidable<TypeUpdate>({
|
||||
initialValues: dataType,
|
||||
deltaConfig: { omit: ['covers'] },
|
||||
});
|
||||
const onSave = async (dataDelta: TypeWrite) => {
|
||||
const onSave = async (data: TypeUpdate) => {
|
||||
if (isNullOrUndefined(typeIdInt)) {
|
||||
return;
|
||||
}
|
||||
console.log(`onSave = ${JSON.stringify(dataDelta, null, 2)}`);
|
||||
console.log(`onSave = ${JSON.stringify(data, null, 2)}`);
|
||||
store.update(
|
||||
TypeResource.patch({
|
||||
restConfig: session.getRestConfig(),
|
||||
data: dataDelta,
|
||||
data: ZodTypeUpdate.parse(data),
|
||||
params: {
|
||||
id: typeIdInt,
|
||||
},
|
||||
@ -148,7 +148,7 @@ export const TypeEditPopUp = ({}: TypeEditPopUpProps) => {
|
||||
>
|
||||
{/* <DialogOverlay /> */}
|
||||
<DialogContent>
|
||||
<Formidable.From form={form} onSubmitDelta={onSave}>
|
||||
<Formidable.From form={form} onSubmit={onSave}>
|
||||
<DialogHeader>Edit Type</DialogHeader>
|
||||
{/* <DialogCloseButton ref={finalRef} /> */}
|
||||
|
||||
|
@ -60,7 +60,6 @@ export const environment = isDevelopmentEnvironment()
|
||||
? environment_local
|
||||
: environment_back_prod;
|
||||
|
||||
|
||||
/**
|
||||
* get the current REST api URL. Depend on the VITE_API_BASE_URL env variable.
|
||||
* @returns The URL with http(s)://***
|
||||
|
@ -408,7 +408,7 @@ export const AddPage = () => {
|
||||
episode: `${parsedElement[index].episode}`,
|
||||
};
|
||||
console.log(`data= ${JSON.stringify(data, null, 2)}`);
|
||||
console.error('Not_ implemented');
|
||||
console.error('Not_implemented');
|
||||
storeMedia
|
||||
.update(
|
||||
MediaResource.uploadMedia({
|
||||
@ -468,6 +468,18 @@ export const AddPage = () => {
|
||||
);
|
||||
};
|
||||
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(
|
||||
SeriesResource.post({
|
||||
restConfig: session.getRestConfig(),
|
||||
@ -763,7 +775,7 @@ export const MediaDetectionDetail = ({ data }: { data: InspectionType }) => {
|
||||
</Text>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Text>{data.media.date}</Text>
|
||||
<Text>{data.media.datePublication}</Text>
|
||||
</Table.Cell>
|
||||
<Table.Cell></Table.Cell>
|
||||
</Table.Row>
|
||||
|
@ -1,47 +1,58 @@
|
||||
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 { useEffectOnce } from 'react-use';
|
||||
|
||||
import avatar_generic from '@/assets/images/avatar_generic.svg';
|
||||
import { Icon } from '@/components';
|
||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||
import { TopBar } from '@/components/TopBar/TopBar';
|
||||
import { isDevelopmentEnvironment } from '@/environment';
|
||||
import { toaster } from '@/components/ui/toaster';
|
||||
import { useSessionService } from '@/service/session';
|
||||
import { b64_to_utf8 } from '@/utils/sso';
|
||||
|
||||
export const SSOPage = () => {
|
||||
const { data, keepConnected, token } = useParams();
|
||||
console.log(`- data: ${data}`);
|
||||
console.log(`- keepConnected: ${keepConnected}`);
|
||||
console.log(`- token: ${token}`);
|
||||
//const { data, keepConnected, token } = useState<string|undefined>();
|
||||
// console.log(`- data: ${data}`);
|
||||
// console.log(`- keepConnected: ${keepConnected}`);
|
||||
// console.log(`- token: ${token}`);
|
||||
const navigate = useNavigate();
|
||||
const { isConnected, setToken, login, clearToken } = useSessionService();
|
||||
useEffect(() => {
|
||||
if (token) {
|
||||
setToken(token);
|
||||
} else {
|
||||
clearToken();
|
||||
const { isConnected, errorSession, setToken, login } = useSessionService();
|
||||
useEffectOnce(() => {
|
||||
if (token === undefined || token === '') {
|
||||
return;
|
||||
}
|
||||
}, [token, setToken, clearToken]);
|
||||
const delay = isDevelopmentEnvironment() ? 2000 : 2000;
|
||||
try {
|
||||
setToken(token);
|
||||
} catch (e) {
|
||||
toaster.create({
|
||||
title: 'Connection Fail',
|
||||
description: `invalid token data model.`,
|
||||
type: 'error',
|
||||
});
|
||||
navigate('/');
|
||||
}
|
||||
});
|
||||
const delay = 1000;
|
||||
useEffect(() => {
|
||||
if (isConnected) {
|
||||
const destination = data ? b64_to_utf8(data) : '/';
|
||||
console.log(`program redirect to: ${destination} (${delay}ms)`);
|
||||
toaster.create({
|
||||
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(() => {
|
||||
navigate(`/${destination}`);
|
||||
// note: check if the "navigate" is in the dependence of the use effect!!!
|
||||
navigate(`/${destinationFinal}`, { replace: true });
|
||||
}, delay);
|
||||
}
|
||||
}, [isConnected]);
|
||||
/*
|
||||
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)}`);
|
||||
*/
|
||||
}, [isConnected, login, navigate]);
|
||||
return (
|
||||
<>
|
||||
<TopBar />
|
||||
@ -53,20 +64,52 @@ export const SSOPage = () => {
|
||||
<Center w="full">
|
||||
<Image src={avatar_generic} boxSize="150px" borderRadius="full" />
|
||||
</Center>
|
||||
{!isConnected && (
|
||||
<Text>
|
||||
<b>ERROR: </b> connection fail !
|
||||
</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> {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 && (
|
||||
<>
|
||||
<Text>
|
||||
<b>Connected: </b> Redirect soon!
|
||||
</Text>
|
||||
<Text>
|
||||
<b>Welcome back: </b> {login}
|
||||
</Text>
|
||||
</>
|
||||
<Flex direction="column">
|
||||
<Flex color="green.500" fontSize="25px" gap={2} marginX="auto">
|
||||
<MdFactCheck />
|
||||
<Text marginY="auto">
|
||||
<b>Connected: </b> Redirect soon!
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex fontSize="25px" gap={2} marginX="auto">
|
||||
<Text marginY="auto">
|
||||
<b>Welcome back: </b> {login}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
)}
|
||||
</PageLayoutInfoCenter>
|
||||
</>
|
||||
|
@ -22,7 +22,7 @@ export const useAdvancementServiceWrapped = (
|
||||
{
|
||||
restApiName: 'Advancement',
|
||||
primaryKey: 'id',
|
||||
available: session.token !== undefined,
|
||||
available: false, //session.token !== undefined,
|
||||
getsCall: () => {
|
||||
return UserMediaAdvancementResource.gets({
|
||||
restConfig: session.getRestConfig(),
|
||||
@ -47,40 +47,43 @@ export type updateTimeProps = {
|
||||
time: number;
|
||||
total: number;
|
||||
addCount: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export const useAdvancementUpdateTime = (id: number,
|
||||
config: Omit<useQueryCallProps<UserMediaAdvancement, updateTimeProps>, 'queryFunction'>
|
||||
= {}) => {
|
||||
export const useAdvancementUpdateTime = (
|
||||
id: number,
|
||||
config: Omit<
|
||||
useQueryCallProps<UserMediaAdvancement, updateTimeProps>,
|
||||
'queryFunction'
|
||||
> = {}
|
||||
) => {
|
||||
const { store } = useAdvancementService();
|
||||
|
||||
const { onSuccess, ...restConfig } = config;
|
||||
const { getRestConfig } = useSessionService();
|
||||
const { call, ...rest } = useQueryCall<
|
||||
UserMediaAdvancement,
|
||||
updateTimeProps
|
||||
>({
|
||||
queryFunction: (inputData) => {
|
||||
const data = {
|
||||
time: inputData.time,
|
||||
percent: inputData.time / inputData.total,
|
||||
addCount: inputData.addCount
|
||||
};
|
||||
return UserMediaAdvancementResource.patch({
|
||||
restConfig: getRestConfig(),
|
||||
params: {
|
||||
id
|
||||
},
|
||||
data
|
||||
});
|
||||
},
|
||||
onSuccess: (response) => {
|
||||
if (onSuccess) {
|
||||
onSuccess(response);
|
||||
}
|
||||
store.updateRaw(response);
|
||||
},
|
||||
...restConfig,
|
||||
});
|
||||
const { call, ...rest } = useQueryCall<UserMediaAdvancement, updateTimeProps>(
|
||||
{
|
||||
queryFunction: (inputData) => {
|
||||
const data = {
|
||||
time: inputData.time,
|
||||
percent: inputData.time / inputData.total,
|
||||
addCount: inputData.addCount,
|
||||
};
|
||||
return UserMediaAdvancementResource.patch({
|
||||
restConfig: getRestConfig(),
|
||||
params: {
|
||||
id,
|
||||
},
|
||||
data,
|
||||
});
|
||||
},
|
||||
onSuccess: (response) => {
|
||||
if (onSuccess) {
|
||||
onSuccess(response);
|
||||
}
|
||||
store.updateRaw(response);
|
||||
},
|
||||
...restConfig,
|
||||
}
|
||||
);
|
||||
return { updateTime: call, ...rest };
|
||||
};
|
||||
|
@ -24,7 +24,7 @@ export const useMediaServiceWrapped = (
|
||||
{
|
||||
restApiName: 'Media',
|
||||
primaryKey: 'id',
|
||||
available: session.token !== undefined,
|
||||
available: session.isConnected,
|
||||
getsCall: () => {
|
||||
return MediaResource.gets({
|
||||
restConfig: session.getRestConfig(),
|
||||
|
@ -25,7 +25,7 @@ export const useSeasonServiceWrapped = (
|
||||
{
|
||||
restApiName: 'Season',
|
||||
primaryKey: 'id',
|
||||
available: session.token !== undefined,
|
||||
available: session.isConnected,
|
||||
getsCall: () => {
|
||||
return SeasonResource.gets({
|
||||
restConfig: session.getRestConfig(),
|
||||
|
@ -26,7 +26,7 @@ export const useSeriesServiceWrapped = (
|
||||
{
|
||||
restApiName: 'Series',
|
||||
primaryKey: 'id',
|
||||
available: session.token !== undefined,
|
||||
available: session.isConnected,
|
||||
getsCall: () => {
|
||||
return SeriesResource.gets({
|
||||
restConfig: session.getRestConfig(),
|
||||
|
@ -25,7 +25,7 @@ export const useTypeServiceWrapped = (
|
||||
{
|
||||
restApiName: 'Type',
|
||||
primaryKey: 'id',
|
||||
available: session.token !== undefined,
|
||||
available: session.isConnected,
|
||||
getsCall: () => {
|
||||
return TypeResource.gets({
|
||||
restConfig: session.getRestConfig(),
|
||||
|
@ -1,21 +1,33 @@
|
||||
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 { toaster } from '@/components/ui/toaster';
|
||||
import { environment, getApiUrl } from '@/environment';
|
||||
import { useServiceContext } from '@/service/ServiceContext';
|
||||
import { isBrowser } from '@/utils/layout';
|
||||
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({
|
||||
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 = {
|
||||
admin:
|
||||
'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 = {
|
||||
token?: string;
|
||||
isConnected: boolean;
|
||||
errorSession?: SessionErrorType;
|
||||
setToken: (token: string) => void;
|
||||
clearToken: () => void;
|
||||
login?: string;
|
||||
@ -51,102 +97,165 @@ export const useSessionService = (): 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
|
||||
);
|
||||
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...');
|
||||
setConfig(undefined);
|
||||
if (token === undefined) {
|
||||
console.log(` ==> No User`);
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
} else {
|
||||
const dataParsedToken = parseToken(token)?.payload;
|
||||
console.log(`Get right: ${JSON.stringify(dataParsedToken, null, 2)}`);
|
||||
setConfig(dataParsedToken);
|
||||
console.log(' ==> Login ... (try to keep right)');
|
||||
if (isBrowser) {
|
||||
localStorage.setItem(TOKEN_KEY, token);
|
||||
const updateRight = useEffect(() => {
|
||||
//console.log('Detect a new token...');
|
||||
if (isBrowser) {
|
||||
//console.log('update internal property');
|
||||
if (tokenStorage === undefined) {
|
||||
//console.log(` ==> No User`);
|
||||
setToken(undefined);
|
||||
setTokenStr('');
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
} else {
|
||||
//console.log(' ==> Login ... (try to keep right)');
|
||||
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(
|
||||
(token: string) => {
|
||||
setToken(token);
|
||||
updateRight();
|
||||
(token?: string) => {
|
||||
if (token ? token.startsWith('__') : false) {
|
||||
token = undefined;
|
||||
}
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
setTokenStorage(token);
|
||||
setTokenStr('');
|
||||
setToken(undefined);
|
||||
setErrorSession(undefined);
|
||||
},
|
||||
[updateRight, setToken]
|
||||
);
|
||||
const clearToken = useCallback(() => {
|
||||
console.log('Clear Token');
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
setTokenLocal(undefined);
|
||||
setToken(undefined);
|
||||
updateRight();
|
||||
}, [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(() => {
|
||||
updateRight();
|
||||
}, [updateRight]);
|
||||
setErrorApiGlobalCallback((response: Response) => {
|
||||
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 {
|
||||
token,
|
||||
token: tokenStr,
|
||||
isConnected: token !== undefined,
|
||||
errorSession,
|
||||
setToken: setTokenLocal,
|
||||
clearToken,
|
||||
login: config?.login,
|
||||
login: token?.payload?.login,
|
||||
hasReadRight,
|
||||
hasWriteRight,
|
||||
getRestConfig,
|
||||
getRestConfig: getRestConfigLocal,
|
||||
};
|
||||
};
|
||||
|
||||
export const useHasRight = (group: RightGroup) => {
|
||||
export const useHasRight = (part: RightGroup) => {
|
||||
const { token, hasReadRight, hasWriteRight } = useSessionService();
|
||||
const isReadable = useMemo(() => {
|
||||
console.log(`get is read for: ${group} ==> ${hasReadRight(group)}`);
|
||||
return hasReadRight(group);
|
||||
}, [token, hasReadRight, group]);
|
||||
//console.log(`get is read for: ${part} ==> ${hasReadRight(part)}`);
|
||||
return hasReadRight(part);
|
||||
}, [token, hasReadRight, part]);
|
||||
const isWritable = useMemo(() => {
|
||||
return hasWriteRight(group);
|
||||
}, [token, hasWriteRight, group]);
|
||||
return hasWriteRight(part);
|
||||
}, [token, hasWriteRight, part]);
|
||||
return { isReadable, isWritable };
|
||||
};
|
||||
|
@ -9,12 +9,20 @@ import { colors } from './colors';
|
||||
|
||||
const baseTheme: SystemConfig = {
|
||||
globalCss: {
|
||||
':root': {
|
||||
// permit to "firefox" not reload the page when scroll on top
|
||||
overscrollBehavior: 'contain',
|
||||
},
|
||||
body: {
|
||||
// permit to "chromium" not reload the page when scroll on top
|
||||
overscrollBehavior: 'contain',
|
||||
// Prevents text selection
|
||||
userSelect: 'none',
|
||||
// Other ...
|
||||
overflowY: 'none',
|
||||
bg: { _light: 'back.50', _dark: 'back.700' },
|
||||
color: { _light: 'text.900', _dark: 'text.50' },
|
||||
fontFamily: 'Roboto, Helvetica, Arial, "sans-serif"',
|
||||
userSelect: 'none' /* Prevents text selection */,
|
||||
},
|
||||
svg: {
|
||||
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(
|
||||
`Request sign-in: '${environment.ssoSignIn}' + '${hashLocalData(name)}'`
|
||||
);
|
||||
window.location.href = environment.ssoSignIn + hashLocalData(name) + "/";
|
||||
window.location.href = environment.ssoSignIn + hashLocalData(name) + '/';
|
||||
}
|
||||
/**
|
||||
* Request SSO Disconnect
|
||||
*/
|
||||
export function requestSignOut(name?: string): void {
|
||||
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
|
||||
window.location.href = url;
|
||||
}
|
||||
@ -124,7 +124,7 @@ export function requestSignOut(name?: string): void {
|
||||
*/
|
||||
export function requestSignUp(name?: string): void {
|
||||
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
|
||||
window.location.href = url;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user