[FEAT] upgrade the api generation and search how to manage cover auto-change

This commit is contained in:
Edouard DUPIN 2024-09-15 01:15:33 +02:00
parent 23feaadab3
commit 031f5650e4
32 changed files with 917 additions and 2739 deletions

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?>
<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>
<artifactId>karusic</artifactId>
<version>0.1.0</version>
<properties>
<maven.compiler.version>3.1</maven.compiler.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>

View File

@ -25,8 +25,7 @@ public class WebLauncherLocal extends WebLauncher {
public static void generateObjects() throws Exception {
LOGGER.info("Generate APIs");
final List<Class<?>> listOfResources = List.of(AlbumResource.class, ArtistResource.class, Front.class,
GenderResource.class, HealthCheck.class, PlaylistResource.class, UserResource.class,
final List<Class<?>> listOfResources = List.of(AlbumResource.class, ArtistResource.class, Front.class, GenderResource.class, HealthCheck.class, PlaylistResource.class, UserResource.class,
TrackResource.class, DataResource.class, ProxyResource.class);
final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(listOfResources);

View File

@ -7,6 +7,7 @@ import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson;
@ -61,8 +62,7 @@ public class AlbumResource {
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Update a specific album")
public Album patch(@PathParam("id") final Long id, @AsyncType(Album.class) final String jsonRequest)
throws Exception {
public Album patch(@PathParam("id") final Long id, @AsyncType(Album.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Album.class, id, jsonRequest);
return DataAccess.get(Album.class, id);
}
@ -89,8 +89,7 @@ public class AlbumResource {
@Path("{id}/track/{trackId}")
@RolesAllowed("ADMIN")
@Operation(description = "Remove a Track on a specific album")
public Album removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId)
throws Exception {
public Album removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
AddOnManyToMany.removeLink(Album.class, id, "track", trackId);
return DataAccess.get(Album.class, id);
}
@ -101,11 +100,8 @@ public class AlbumResource {
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Add a cover on a specific album")
@TypeScriptProgress
public Album uploadCover(
@PathParam("id") final Long id,
@FormDataParam("uri") final String uri,
@FormDataParam("file") final InputStream fileInputStream,
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
public Album uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
if (uri != null) {
DataTools.uploadCoverFromUri(Album.class, id, uri);
} else {
@ -118,8 +114,7 @@ public class AlbumResource {
@Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN")
@Operation(description = "Remove a cover on a specific album")
public Album removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId)
throws Exception {
public Album removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
AddOnDataJson.removeLink(Album.class, id, "covers", coverId);
return DataAccess.get(Album.class, id);
}

View File

@ -7,6 +7,7 @@ import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson;
@ -55,8 +56,7 @@ public class ArtistResource {
@Path("{id}")
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
public Artist patch(@PathParam("id") final Long id, @AsyncType(Artist.class) final String jsonRequest)
throws Exception {
public Artist patch(@PathParam("id") final Long id, @AsyncType(Artist.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Artist.class, id, jsonRequest);
return DataAccess.get(Artist.class, id);
}
@ -73,11 +73,8 @@ public class ArtistResource {
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@TypeScriptProgress
public Artist uploadCover(
@PathParam("id") final Long id,
@FormDataParam("uri") final String uri,
@FormDataParam("file") final InputStream fileInputStream,
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
public Artist uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
if (uri != null) {
DataTools.uploadCoverFromUri(Artist.class, id, uri);
} else {
@ -89,8 +86,7 @@ public class ArtistResource {
@DELETE
@Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN")
public Artist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId)
throws Exception {
public Artist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
LOGGER.error("klmlmkmlkmlklmklmk");
AddOnDataJson.removeLink(Artist.class, id, "covers", coverId);
return DataAccess.get(Artist.class, id);

View File

@ -7,6 +7,7 @@ import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson;
@ -55,8 +56,7 @@ public class GenderResource {
@Path("{id}")
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
public Gender patch(@PathParam("id") final Long id, @AsyncType(Gender.class) final String jsonRequest)
throws Exception {
public Gender patch(@PathParam("id") final Long id, @AsyncType(Gender.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Gender.class, id, jsonRequest);
return DataAccess.get(Gender.class, id);
}
@ -73,11 +73,8 @@ public class GenderResource {
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@TypeScriptProgress
public Gender uploadCover(
@PathParam("id") final Long id,
@FormDataParam("uri") final String uri,
@FormDataParam("file") final InputStream fileInputStream,
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
public Gender uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
if (uri != null) {
DataTools.uploadCoverFromUri(Gender.class, id, uri);
} else {
@ -89,8 +86,7 @@ public class GenderResource {
@DELETE
@Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN")
public Gender removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId)
throws Exception {
public Gender removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
AddOnDataJson.removeLink(Gender.class, id, "covers", coverId);
return DataAccess.get(Gender.class, id);
}

View File

@ -15,8 +15,8 @@ import jakarta.ws.rs.core.Response;
@Produces(MediaType.APPLICATION_JSON)
public class HealthCheck {
public record HealthResult(
String value) {};
public record HealthResult(String value) {
};
@GET
@PermitAll

View File

@ -55,8 +55,7 @@ public class PlaylistResource {
@Path("{id}")
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
public Playlist patch(@PathParam("id") final Long id, @AsyncType(Playlist.class) final String jsonRequest)
throws Exception {
public Playlist patch(@PathParam("id") final Long id, @AsyncType(Playlist.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Playlist.class, id, jsonRequest);
return DataAccess.get(Playlist.class, id);
}
@ -72,8 +71,7 @@ public class PlaylistResource {
@Path("{id}/track/{trackId}")
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
public Playlist addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId)
throws Exception {
public Playlist addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
AddOnManyToMany.removeLink(Playlist.class, id, "track", trackId);
return DataAccess.get(Playlist.class, id);
}
@ -81,8 +79,7 @@ public class PlaylistResource {
@DELETE
@Path("{id}/track/{trackId}")
@RolesAllowed("ADMIN")
public Playlist removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId)
throws Exception {
public Playlist removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
AddOnManyToMany.removeLink(Playlist.class, id, "track", trackId);
return DataAccess.get(Playlist.class, id);
}
@ -92,18 +89,15 @@ public class PlaylistResource {
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@AsyncType(Playlist.class)
public void uploadCover(
@PathParam("id") final Long id,
@FormDataParam("file") final InputStream fileInputStream,
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
public void uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
throws Exception {
DataTools.uploadCover(Playlist.class, id, fileInputStream, fileMetaData);
}
@DELETE
@Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN")
public Playlist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId)
throws Exception {
public Playlist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
AddOnDataJson.removeLink(Playlist.class, id, "covers", coverId);
return DataAccess.get(Playlist.class, id);
}

View File

@ -66,8 +66,7 @@ public class TrackResource {
@Path("{id}")
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
public Track patch(@PathParam("id") final Long id, @AsyncType(Track.class) final String jsonRequest)
throws Exception {
public Track patch(@PathParam("id") final Long id, @AsyncType(Track.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Track.class, id, jsonRequest);
return DataAccess.get(Track.class, id);
}
@ -91,8 +90,7 @@ public class TrackResource {
@DELETE
@Path("{id}/artist/{trackId}")
@RolesAllowed("ADMIN")
public Track removeTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId)
throws Exception {
public Track removeTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception {
AddOnManyToMany.removeLink(Track.class, id, "artist", artistId);
return DataAccess.get(Track.class, id);
}
@ -102,10 +100,7 @@ public class TrackResource {
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@TypeScriptProgress
public Track uploadCover(
@PathParam("id") final Long id,
@FormDataParam("uri") final String uri,
@FormDataParam("file") final InputStream fileInputStream,
public Track uploadCover(@PathParam("id") final Long id, @FormDataParam("uri") final String uri, @FormDataParam("file") final InputStream fileInputStream,
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
if (uri != null) {
DataTools.uploadCoverFromUri(Track.class, id, uri);
@ -118,8 +113,7 @@ public class TrackResource {
@DELETE
@Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN")
public Track removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId)
throws Exception {
public Track removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
AddOnDataJson.removeLink(Track.class, id, "covers", coverId);
return DataAccess.get(Track.class, id);
}
@ -131,8 +125,7 @@ public class TrackResource {
// Formatter:off
@AsyncType(Track.class)
@TypeScriptProgress
public Response uploadTrack(
@FormDataParam("fileName") String fileName, //
public Response uploadTrack(@FormDataParam("fileName") String fileName, //
@FormDataParam("gender") String gender, //
@FormDataParam("artist") String artist, //
// @FormDataParam("seriesId") String seriesId, Not used ...
@ -162,14 +155,7 @@ public class TrackResource {
LOGGER.info(" > title: " + title);
LOGGER.info(" > fileInputStream: " + fileInputStream);
LOGGER.info(" > fileMetaData: " + fileMetaData);
/*
if (typeId == null) {
return Response.status(406).
entity("Missong Input 'type'").
type("text/plain").
build();
}
*/
/* if (typeId == null) { return Response.status(406). entity("Missong Input 'type'"). type("text/plain"). build(); } */
final long tmpUID = DataTools.getTmpDataId();
final String sha512 = DataTools.saveTemporaryFile(fileInputStream, tmpUID);
@ -251,12 +237,7 @@ public class TrackResource {
trackElem.artists.add(artistElem.id);
}
trackElem = DataAccess.insert(trackElem);
/*
Old mode of artist insertion (removed due to the slowlest request of getting value
if (artistElem != null) {
DataAccess.addLink(Track.class, trackElem.id, "artist", artistElem.id);
}
*/
/* Old mode of artist insertion (removed due to the slowlest request of getting value if (artistElem != null) { DataAccess.addLink(Track.class, trackElem.id, "artist", artistElem.id); } */
return Response.ok(trackElem).build();
} catch (final Exception ex) {
LOGGER.info("Catch an unexpected error ... {}", ex.getMessage());

View File

@ -18,8 +18,7 @@ public class Initialization extends MigrationSqlStep {
private static final Logger LOGGER = LoggerFactory.getLogger(Initialization.class);
public static final int KARSO_INITIALISATION_ID = 1;
public static final List<Class<?>> CLASSES_BASE = List.of(Album.class, Artist.class, Data.class, Gender.class,
Playlist.class, Track.class, User.class);
public static final List<Class<?>> CLASSES_BASE = List.of(Album.class, Artist.class, Data.class, Gender.class, Playlist.class, Track.class, User.class);
@Override
public String getName() {

View File

@ -40,8 +40,7 @@ public class Migration20240226 extends MigrationSqlStep {
ALTER TABLE `data` ADD `uuid` binary(16) AFTER `id`;
""");
addAction(() -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(),
new OverrideTableName("data"));
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
for (final UUIDConversion elem : datas) {
elem.uuid = UuidUtils.nextUUID();
}
@ -56,12 +55,9 @@ public class Migration20240226 extends MigrationSqlStep {
for (final String tableName : tableToTransform) {
addAction("ALTER TABLE `" + tableName + "` ADD `covers` text NULL;");
addAction(() -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(),
new OverrideTableName("data"));
final List<CoverConversion> medias = DataAccess.gets(CoverConversion.class, new AccessDeletedItems(),
new OverrideTableName(tableName));
final List<LinkTableLongLong> links = DataAccess.gets(LinkTableLongLong.class,
new OverrideTableName(tableName + "_link_cover"));
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
final List<CoverConversion> medias = DataAccess.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName));
final List<LinkTableLongLong> links = DataAccess.gets(LinkTableLongLong.class, new OverrideTableName(tableName + "_link_cover"));
LOGGER.info("Get somes data: {} {} {}", datas.size(), medias.size(), links.size());
for (final CoverConversion media : medias) {
final List<UUID> values = new ArrayList<>();
@ -89,10 +85,8 @@ public class Migration20240226 extends MigrationSqlStep {
ALTER TABLE `track` ADD `dataUUID` binary(16) AFTER dataId;
""");
addAction(() -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(),
new OverrideTableName("data"));
final List<MediaConversion> medias = DataAccess.gets(MediaConversion.class, new AccessDeletedItems(),
new OverrideTableName("track"));
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
final List<MediaConversion> medias = DataAccess.gets(MediaConversion.class, new AccessDeletedItems(), new OverrideTableName("track"));
for (final MediaConversion media : medias) {
for (final UUIDConversion data : datas) {
if (data.id.equals(media.dataId)) {
@ -118,8 +112,7 @@ public class Migration20240226 extends MigrationSqlStep {
""");
// Move the files...
addAction(() -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(),
new OverrideTableName("data"));
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
for (final UUIDConversion data : datas) {
final String origin = DataResource.getFileDataOld(data.id);
final String destination = DataResource.getFileData(data.uuid);

View File

@ -37,8 +37,7 @@ public class Artist extends GenericDataSoftDelete {
@Override
public String toString() {
return "Artist [id=" + this.id + ", name=" + this.name + ", description=" + this.description + ", covers="
+ this.covers + ", firstName=" + this.firstName + ", surname=" + this.surname + ", birth=" + this.birth
+ ", death=" + this.death + "]";
return "Artist [id=" + this.id + ", name=" + this.name + ", description=" + this.description + ", covers=" + this.covers + ", firstName=" + this.firstName + ", surname=" + this.surname
+ ", birth=" + this.birth + ", death=" + this.death + "]";
}
}

View File

@ -50,9 +50,7 @@ public class Track extends GenericDataSoftDelete {
@Override
public String toString() {
return "Track [id=" + this.id + ", deleted=" + this.deleted + ", createdAt=" + this.createdAt + ", updatedAt="
+ this.updatedAt + ", name=" + this.name + ", description=" + this.description + ", covers="
+ this.covers + ", genderId=" + this.genderId + ", albumId=" + this.albumId + ", track=" + this.track
+ ", dataId=" + this.dataId + ", artists=" + this.artists + "]";
return "Track [id=" + this.id + ", deleted=" + this.deleted + ", createdAt=" + this.createdAt + ", updatedAt=" + this.updatedAt + ", name=" + this.name + ", description=" + this.description
+ ", covers=" + this.covers + ", genderId=" + this.genderId + ", albumId=" + this.albumId + ", track=" + this.track + ", dataId=" + this.dataId + ", artists=" + this.artists + "]";
}
}

View File

@ -3,7 +3,6 @@ package org.kar.karusic.util;
public class ConfigVariable {
public static final String BASE_NAME = "ORG_KARUSIC_";
public static String getFrontFolder() {
String out = System.getenv(BASE_NAME + "FRONT_FOLDER");
if (out == null) {

View File

@ -5,8 +5,6 @@ import java.util.Map;
import org.kar.archidata.tools.JWTWrapper;
public class Common {
static String USER_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_user_login", "KarAuth", "karusic",
Map.of("karusic", Map.of("USER", Boolean.TRUE)));
static String ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karusic",
Map.of("karusic", Map.of("USER", Boolean.TRUE, "ADMIN", Boolean.TRUE)));
static String USER_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_user_login", "KarAuth", "karusic", Map.of("karusic", Map.of("USER", Boolean.TRUE)));
static String ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karusic", Map.of("karusic", Map.of("USER", Boolean.TRUE, "ADMIN", Boolean.TRUE)));
}

View File

@ -27,6 +27,7 @@
"*.{ts,tsx,js,jsx,json}": "prettier --write"
},
"dependencies": {
"framer-motion": "11.5.4",
"@chakra-ui/anatomy": "2.2.2",
"@chakra-ui/cli": "2.4.1",
"@chakra-ui/react": "2.8.2",
@ -44,22 +45,22 @@
"dayjs": "1.11.13",
"history": "5.3.0",
"react": "18.3.1",
"react-color-palette": "7.2.2",
"react-color-palette": "7.3.0",
"react-currency-input-field": "3.8.0",
"react-custom-scrollbars": "4.2.1",
"react-day-picker": "9.0.8",
"react-day-picker": "9.0.9",
"react-dom": "18.3.1",
"react-error-boundary": "4.0.13",
"react-focus-lock": "2.13.2",
"react-icons": "5.3.0",
"react-popper": "2.3.0",
"react-router-dom": "6.26.1",
"react-router-dom": "6.26.2",
"react-select": "5.8.0",
"react-simple-keyboard": "3.7.148",
"react-simple-keyboard": "3.8.1",
"react-sticky-el": "2.1.1",
"react-use": "17.5.1",
"react-use-draggable-scroll": "0.4.7",
"react-virtuoso": "4.10.2",
"react-virtuoso": "4.10.4",
"ts-pattern": "5.3.1",
"uuid": "10.0.0",
"zod": "3.23.8",
@ -67,44 +68,44 @@
},
"devDependencies": {
"@chakra-ui/styled-system": "2.9.2",
"@playwright/test": "1.46.1",
"@storybook/addon-actions": "8.2.9",
"@storybook/addon-essentials": "8.2.9",
"@storybook/addon-links": "8.2.9",
"@storybook/addon-mdx-gfm": "8.2.9",
"@storybook/react": "8.2.9",
"@storybook/react-vite": "8.2.9",
"@storybook/theming": "8.2.9",
"@playwright/test": "1.47.1",
"@storybook/addon-actions": "8.3.0",
"@storybook/addon-essentials": "8.3.0",
"@storybook/addon-links": "8.3.0",
"@storybook/addon-mdx-gfm": "8.3.0",
"@storybook/react": "8.3.0",
"@storybook/react-vite": "8.3.0",
"@storybook/theming": "8.3.0",
"@testing-library/jest-dom": "6.5.0",
"@testing-library/react": "16.0.1",
"@testing-library/user-event": "14.5.2",
"@trivago/prettier-plugin-sort-imports": "4.3.0",
"@types/jest": "29.5.12",
"@types/node": "22.5.2",
"@types/jest": "29.5.13",
"@types/node": "22.5.5",
"@types/react": "18.3.5",
"@types/react-dom": "18.3.0",
"@types/react-sticky-el": "1.0.7",
"@typescript-eslint/eslint-plugin": "8.3.0",
"@typescript-eslint/parser": "8.3.0",
"@typescript-eslint/eslint-plugin": "8.5.0",
"@typescript-eslint/parser": "8.5.0",
"@vitejs/plugin-react": "4.3.1",
"eslint": "9.9.1",
"eslint": "9.10.0",
"eslint-plugin-codeceptjs": "1.3.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-react": "7.35.0",
"eslint-plugin-import": "2.30.0",
"eslint-plugin-react": "7.36.1",
"eslint-plugin-react-hooks": "4.6.2",
"eslint-plugin-storybook": "0.8.0",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"knip": "5.29.1",
"lint-staged": "15.2.9",
"npm-check-updates": "^17.1.0",
"knip": "5.30.2",
"lint-staged": "15.2.10",
"npm-check-updates": "^17.1.1",
"prettier": "3.3.3",
"puppeteer": "23.2.1",
"puppeteer": "23.3.0",
"react-is": "18.3.1",
"storybook": "8.2.9",
"storybook": "8.3.0",
"ts-node": "10.9.2",
"typescript": "5.5.4",
"vite": "5.4.2",
"vitest": "2.0.5"
"typescript": "5.6.2",
"vite": "5.4.5",
"vitest": "2.1.1"
}
}

3040
front2/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -230,8 +230,8 @@ export namespace AlbumResource {
id: Long,
},
data: {
file: File,
uri: string,
file?: File,
uri?: string,
},
callbacks?: RESTCallbacks,
}): Promise<Album> {

View File

@ -161,8 +161,8 @@ export namespace ArtistResource {
id: Long,
},
data: {
file: File,
uri: string,
file?: File,
uri?: string,
},
callbacks?: RESTCallbacks,
}): Promise<Artist> {

View File

@ -161,8 +161,8 @@ export namespace GenderResource {
id: Long,
},
data: {
file: File,
uri: string,
file?: File,
uri?: string,
},
callbacks?: RESTCallbacks,
}): Promise<Gender> {

View File

@ -1,6 +1,6 @@
import { ReactElement } from 'react';
import { ReactElement, useEffect, useState } from 'react';
import { Box, BoxProps } from '@chakra-ui/react';
import { Box, BoxProps, Flex } from '@chakra-ui/react';
import { Image } from '@chakra-ui/react';
import { DataUrlAccess } from '@/utils/data-url-access';
@ -17,6 +17,9 @@ export const Covers = ({
size = '100px',
...rest
}: CoversProps) => {
const [currentImageIndex, setCurrentImageIndex] = useState(0);
const [previousImageIndex, setPreviousImageIndex] = useState(0);
const [topOpacity, setTopOpacity] = useState(0.0);
if (!data || data.length < 1) {
if (iconEmpty) {
return iconEmpty;
@ -35,6 +38,48 @@ export const Covers = ({
);
}
}
if (data.length == 1) {
const url = DataUrlAccess.getThumbnailUrl(data[0]);
return <Image loading="lazy" src={url} boxSize={size} {...rest} />;
}
useEffect(() => {
const interval = setInterval(() => {
setPreviousImageIndex(currentImageIndex);
setTopOpacity(0.0);
setTimeout(() => {
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % data.length);
setTopOpacity(1.0);
}, 1500);
}, 3000);
return () => clearInterval(interval);
}, []);
const urlCurrent = DataUrlAccess.getThumbnailUrl(data[currentImageIndex]);
const urlPrevious = DataUrlAccess.getThumbnailUrl(data[previousImageIndex]);
return <Flex position="relative" {...rest} maxWidth={size} width={size} height={size} overflow="hidden" border="1px">
<Image
src={urlPrevious}
loading="lazy"
position="absolute"
top="0"
left="0"
width="100%"
height="100%"
zIndex={1}
boxSize={size}
/>
<Image
src={urlCurrent}
loading="lazy"
position="absolute"
top="0"
left="0"
width="100%"
height="100%"
boxSize={size}
transition="opacity 0.5s ease-in-out"
opacity={topOpacity}
zIndex={2}
border="1px"
/>
</Flex>
};

View File

@ -23,6 +23,7 @@ export const DisplayAlbum = ({ dataAlbum }: DisplayAlbumProps) => {
data={dataAlbum?.covers}
size="100"
height="full"
flex={1}
iconEmpty={<LuDisc3 size="100" height="full" />}
/>
<Flex

View File

@ -91,15 +91,10 @@ export const AlbumEditPopUp = ({}: AlbumEditPopUpProps) => {
if (isNullOrUndefined(albumIdInt)) {
return;
}
// no real need the wrapper must be able to set optional the uri our file ...
const plop = new File([], 'emptyFile.txt', {
type: 'text/plain',
});
store.update(
AlbumResource.uploadCover({
restConfig: session.getRestConfig(),
data: {
file: plop,
uri: uri,
},
params: {
@ -121,7 +116,6 @@ export const AlbumEditPopUp = ({}: AlbumEditPopUpProps) => {
restConfig: session.getRestConfig(),
data: {
file: files[0],
uri: null,
},
params: {
id: albumIdInt,

View File

@ -91,15 +91,10 @@ export const ArtistEditPopUp = ({}: ArtistEditPopUpProps) => {
if (isNullOrUndefined(artistIdInt)) {
return;
}
// no real need the wrapper must be able to set optional the uri our file ...
const plop = new File([], 'emptyFile.txt', {
type: 'text/plain',
});
store.update(
ArtistResource.uploadCover({
restConfig: session.getRestConfig(),
data: {
file: plop,
uri: uri,
},
params: {
@ -120,7 +115,6 @@ export const ArtistEditPopUp = ({}: ArtistEditPopUpProps) => {
restConfig: session.getRestConfig(),
data: {
file: files[0],
uri: null,
},
params: {
id: artistIdInt,

View File

@ -90,15 +90,10 @@ export const GenderEditPopUp = ({}: GenderEditPopUpProps) => {
if (isNullOrUndefined(genderIdInt)) {
return;
}
// no real need the wrapper must be able to set optional the uri our file ...
const plop = new File([], 'emptyFile.txt', {
type: 'text/plain',
});
store.update(
GenderResource.uploadCover({
restConfig: session.getRestConfig(),
data: {
file: plop,
uri: uri,
},
params: {
@ -119,7 +114,6 @@ export const GenderEditPopUp = ({}: GenderEditPopUpProps) => {
restConfig: session.getRestConfig(),
data: {
file: files[0],
uri: null,
},
params: {
id: genderIdInt,