Compare commits
	
		
			43 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8f1934e323 | |||
| 1631d1cab9 | |||
| b71ea1bcd8 | |||
| db1e387ac8 | |||
| 762a1aeced | |||
| 670b5537bb | |||
| 16e7197939 | |||
| 98d213b01e | |||
| 0260b4d408 | |||
| f03a18c34c | |||
| 6107b95dcd | |||
| e9af64405b | |||
| 725cd54d92 | |||
| 08eb0f878a | |||
| 619e9aa4b8 | |||
| 6181022814 | |||
| 3f96b870a0 | |||
| 5eba6d32b6 | |||
| a24484b5f9 | |||
| 77f8527fc4 | |||
| 75cca15898 | |||
| f0b2a859db | |||
| a6fe889d4c | |||
| ad7ff2c340 | |||
| 1271885124 | |||
| dde514a1a0 | |||
| dc7131843d | |||
| 091390e025 | |||
| 3377f80fbc | |||
| 4cf71f35b6 | |||
| faaf3b280b | |||
| 0687369164 | |||
| 147264eb7f | |||
| ec93c31acb | |||
| 873f0acff5 | |||
| 244f8a988e | |||
| d49e1d06fe | |||
| 53c3cfefe3 | |||
| 90fb1ed411 | |||
| 30bc82edb3 | |||
| 1d4c547d89 | |||
| 21d53b77f2 | |||
| 3b27edfa3b | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -53,6 +53,8 @@ testem.log | |||||||
| # System Files | # System Files | ||||||
| .DS_Store | .DS_Store | ||||||
| Thumbs.db | Thumbs.db | ||||||
|  | /env_dev/data | ||||||
|  | /env_dev/dataMongo | ||||||
|  |  | ||||||
| backPY/env | backPY/env | ||||||
|  |  | ||||||
| @@ -62,3 +64,4 @@ __pycache__ | |||||||
|  |  | ||||||
| .design/ | .design/ | ||||||
| .vscode/ | .vscode/ | ||||||
|  | front/storybook-static | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ version_file="../version.txt" | |||||||
| # update new release dependency | # update new release dependency | ||||||
| cd back | cd back | ||||||
| # update the Maven version number | # update the Maven version number | ||||||
| mvn versions:set -DnewVersion=$(sed 's/DEV/SNAPSHOT/g' $version_file) | mvn versions:set -DnewVersion=$(sed 's/dev/SNAPSHOT/g' $version_file) | ||||||
| if grep -q "DEV" "$version_file"; then | if grep -q "DEV" "$version_file"; then | ||||||
|     # update all versions release of dependency |     # update all versions release of dependency | ||||||
|     mvn versions:use-latest-releases  |     mvn versions:use-latest-releases  | ||||||
| @@ -19,11 +19,14 @@ cd - | |||||||
|  |  | ||||||
|  |  | ||||||
| cd front | cd front | ||||||
| if grep -q "DEV" "$version_file"; then | if grep -q "dev" "$version_file"; then | ||||||
|     # update all dependency |     # update all dependency | ||||||
|     pnpm install |     pnpm install | ||||||
|     pnpm run update_packages |     pnpm run update_packages | ||||||
| else | else | ||||||
|     # in case of release ==> can not do it automatically ... |     # in case of release ==> can not do it automatically ... | ||||||
|  |     echo not implemented | ||||||
| fi | fi | ||||||
|  |  | ||||||
| cd - | cd - | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -3,23 +3,31 @@ | |||||||
| ## buyilding-end install applications: | ## buyilding-end install applications: | ||||||
| ## | ## | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| FROM archlinux:base-devel AS builder | FROM archlinux:base-devel AS common | ||||||
| # update system | # update system | ||||||
| RUN pacman -Syu --noconfirm && pacman-db-upgrade \ | RUN pacman -Syu --noconfirm && pacman-db-upgrade \ | ||||||
|     && pacman -S --noconfirm jdk-openjdk maven npm pnpm \ |     && pacman -S --noconfirm jdk-openjdk \ | ||||||
|  |     && pacman -Scc --noconfirm | ||||||
|  |  | ||||||
|  | WORKDIR /tmp | ||||||
|  |  | ||||||
|  | FROM common AS builder | ||||||
|  | # update system | ||||||
|  | RUN pacman -Syu --noconfirm && pacman-db-upgrade \ | ||||||
|  |     && pacman -S --noconfirm maven npm pnpm \ | ||||||
|     && pacman -Scc --noconfirm |     && pacman -Scc --noconfirm | ||||||
|  |  | ||||||
| ENV PATH /tmp/node_modules/.bin:$PATH | ENV PATH /tmp/node_modules/.bin:$PATH | ||||||
| WORKDIR /tmp |  | ||||||
|  |  | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| ## | ## | ||||||
| ## Build back: | ## Build back: | ||||||
| ## | ## | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| FROM builder AS buildBack | FROM builder AS build_back | ||||||
| COPY back/pom.xml /tmp | COPY back/pom.xml ./ | ||||||
| COPY back/src /tmp/src/ | COPY back/Formatter.xml ./ | ||||||
|  | COPY back/src ./src/ | ||||||
| RUN mvn clean compile assembly:single | RUN mvn clean compile assembly:single | ||||||
|  |  | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| @@ -27,27 +35,44 @@ RUN mvn clean compile assembly:single | |||||||
| ## Build front: | ## Build front: | ||||||
| ## | ## | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| FROM builder AS buildFront | FROM builder AS dependency_front | ||||||
|  |  | ||||||
| RUN echo "@kangaroo-and-rabbit:registry=https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/npm/" > /root/.npmrc | RUN echo "@kangaroo-and-rabbit:registry=https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/npm/" > /root/.npmrc | ||||||
|  |  | ||||||
| ADD front/package.json \ | ADD front/package.json \ | ||||||
|     front/karma.conf.js \ |     front/pnpm-lock.yaml \ | ||||||
|     front/protractor.conf.js \ |     ./ | ||||||
|     /tmp/ | ADD front/src/theme ./src/theme | ||||||
|  |  | ||||||
| # install and cache app dependencies | # install and cache app dependencies | ||||||
| RUN pnpm install | RUN pnpm install --prod=false | ||||||
|  |  | ||||||
| ADD front/e2e \ | ############################################################### | ||||||
|  | ## Install sources | ||||||
|  | ############################################################### | ||||||
|  | FROM dependency_front AS load_sources_front | ||||||
|  |  | ||||||
|  | # JUST to get the vertion of the application and his sha... | ||||||
|  | COPY front/build.js \ | ||||||
|  |   front/version.txt \ | ||||||
|   front/tsconfig.json \ |   front/tsconfig.json \ | ||||||
|     front/tslint.json \ |   front/tsconfig.node.json \ | ||||||
|     front/angular.json \ |   front/vite.config.mts \ | ||||||
|     /tmp/ |   front/index.html \ | ||||||
| ADD front/src /tmp/src |   ./ | ||||||
|  | COPY front/public ./public | ||||||
|  | COPY front/src ./src | ||||||
|  |  | ||||||
| # generate build | #We are not in prod mode ==> we need to overwrite the production env. | ||||||
| RUN ng build --output-path=dist --configuration=production --base-href=/karusic/ --deploy-url=/karusic/  | ARG env=front/.env.production | ||||||
|  | COPY ${env} .env | ||||||
|  |  | ||||||
|  | ############################################################### | ||||||
|  | ## Build the sources | ||||||
|  | ############################################################### | ||||||
|  | FROM load_sources_front AS build_front | ||||||
|  | # build in bundle mode all the application | ||||||
|  | RUN pnpm static:build | ||||||
|  |  | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| ## | ## | ||||||
| @@ -55,9 +80,10 @@ RUN ng build --output-path=dist --configuration=production --base-href=/karusic/ | |||||||
| ## | ## | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
|  |  | ||||||
| FROM bellsoft/liberica-openjdk-alpine:latest | #FROM bellsoft/liberica-openjdk-alpine:latest | ||||||
| # add wget to manage the health check... | ## add wget to manage the health check... | ||||||
| RUN apk add --no-cache wget | #RUN apk add --no-cache wget | ||||||
|  | FROM common | ||||||
|  |  | ||||||
| #FROM archlinux:base | #FROM archlinux:base | ||||||
| #RUN pacman -Syu --noconfirm && pacman-db-upgrade | #RUN pacman -Syu --noconfirm && pacman-db-upgrade | ||||||
| @@ -68,10 +94,10 @@ RUN apk add --no-cache wget | |||||||
| ## clean all the caches Need only on the release environment | ## clean all the caches Need only on the release environment | ||||||
| #RUN pacman -Scc --noconfirm | #RUN pacman -Scc --noconfirm | ||||||
|  |  | ||||||
| ENV LANG=C.UTF-8 | ENV LANG C.UTF-8 | ||||||
|  |  | ||||||
| COPY --from=buildBack /tmp/out/maven/*.jar /application/application.jar | COPY --from=build_back /tmp/out/maven/*.jar /application/application.jar | ||||||
| COPY --from=buildFront /tmp/dist /application/front/ | COPY --from=build_front /tmp/dist /application/front/ | ||||||
|  |  | ||||||
| WORKDIR /application/ | WORKDIR /application/ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,4 +0,0 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										67
									
								
								back/pom.xml
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								back/pom.xml
									
									
									
									
									
								
							| @@ -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"> | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
| 	<modelVersion>4.0.0</modelVersion> | 	<modelVersion>4.0.0</modelVersion> | ||||||
| 	<groupId>org.kar</groupId> | 	<groupId>org.kar</groupId> | ||||||
| 	<artifactId>karusic</artifactId> | 	<artifactId>karusic</artifactId> | ||||||
|   <version>0.1.0</version> | 	<version>1.0.2</version> | ||||||
| 	<properties> | 	<properties> | ||||||
|  |  | ||||||
| 		<maven.compiler.version>3.1</maven.compiler.version> | 		<maven.compiler.version>3.1</maven.compiler.version> | ||||||
| 		<maven.compiler.source>21</maven.compiler.source> | 		<maven.compiler.source>21</maven.compiler.source> | ||||||
| 		<maven.compiler.target>21</maven.compiler.target> | 		<maven.compiler.target>21</maven.compiler.target> | ||||||
| @@ -20,17 +20,29 @@ | |||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>kangaroo-and-rabbit</groupId> | 			<groupId>kangaroo-and-rabbit</groupId> | ||||||
| 			<artifactId>archidata</artifactId> | 			<artifactId>archidata</artifactId> | ||||||
| 			<version>0.7.1</version> | 			<version>0.20.2</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- Loopback of logger JDK logging API to SLF4J --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.slf4j</groupId> | 			<groupId>org.slf4j</groupId> | ||||||
| 			<artifactId>slf4j-simple</artifactId> | 			<artifactId>jul-to-slf4j</artifactId> | ||||||
| 			<version>2.0.9</version> | 			<version>2.0.9</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- generic logger of SLF4J to console (in color) --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>ch.qos.logback</groupId> | ||||||
|  | 			<artifactId>logback-classic</artifactId> | ||||||
|  | 			<version>1.4.11</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>xerces</groupId> | ||||||
|  | 			<artifactId>xercesImpl</artifactId> | ||||||
|  | 			<version>2.12.2</version> | ||||||
|  | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>com.fasterxml.jackson.datatype</groupId> | 			<groupId>com.fasterxml.jackson.datatype</groupId> | ||||||
| 			<artifactId>jackson-datatype-jsr310</artifactId> | 			<artifactId>jackson-datatype-jsr310</artifactId> | ||||||
| 			<version>2.16.1</version> | 			<version>2.18.0-rc1</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<!-- | 		<!-- | ||||||
| 		************************************************************  | 		************************************************************  | ||||||
| @@ -40,15 +52,25 @@ | |||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.junit.jupiter</groupId> | 			<groupId>org.junit.jupiter</groupId> | ||||||
| 			<artifactId>junit-jupiter-api</artifactId> | 			<artifactId>junit-jupiter-api</artifactId> | ||||||
| 			<version>5.10.1</version> | 			<version>5.11.0</version> | ||||||
| 			<scope>test</scope> | 			<scope>test</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.junit.jupiter</groupId> | 			<groupId>org.junit.jupiter</groupId> | ||||||
| 			<artifactId>junit-jupiter-engine</artifactId> | 			<artifactId>junit-jupiter-engine</artifactId> | ||||||
| 			<version>5.10.1</version> | 			<version>5.11.0</version> | ||||||
| 			<scope>test</scope> | 			<scope>test</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>net.revelc.code.formatter</groupId> | ||||||
|  | 			<artifactId>formatter-maven-plugin</artifactId> | ||||||
|  | 			<version>2.24.1</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 			<artifactId>maven-checkstyle-plugin</artifactId> | ||||||
|  | 			<version>3.5.0</version> | ||||||
|  | 		</dependency> | ||||||
| 	</dependencies> | 	</dependencies> | ||||||
| 	<build> | 	<build> | ||||||
| 		<sourceDirectory>src</sourceDirectory> | 		<sourceDirectory>src</sourceDirectory> | ||||||
| @@ -186,23 +208,10 @@ | |||||||
| 				</configuration> | 				</configuration> | ||||||
| 			</plugin> | 			</plugin> | ||||||
| 			<!-- Check the style of the code --> | 			<!-- Check the style of the code --> | ||||||
| 			<!-- |  | ||||||
| 			<plugin> |  | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> |  | ||||||
| 				<artifactId>maven-checkstyle-plugin</artifactId> |  | ||||||
| 				<version>3.1.0</version> |  | ||||||
| 				<configuration> |  | ||||||
| 					<configLocation>CheckStyle.xml</configLocation> |  | ||||||
| 					<consoleOutput>true</consoleOutput> |  | ||||||
| 					<failOnViolation>true</failOnViolation> |  | ||||||
| 					<failsOnError>true</failsOnError> |  | ||||||
| 					<includeTestSourceDirectory>true</includeTestSourceDirectory> |  | ||||||
| 				</configuration> |  | ||||||
| 			</plugin> |  | ||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>net.revelc.code.formatter</groupId> | 				<groupId>net.revelc.code.formatter</groupId> | ||||||
| 				<artifactId>formatter-maven-plugin</artifactId> | 				<artifactId>formatter-maven-plugin</artifactId> | ||||||
| 				<version>2.12.2</version> | 				<version>2.23.0</version> | ||||||
| 				<configuration> | 				<configuration> | ||||||
| 					<encoding>UTF-8</encoding> | 					<encoding>UTF-8</encoding> | ||||||
| 					<lineEnding>LF</lineEnding> | 					<lineEnding>LF</lineEnding> | ||||||
| @@ -226,7 +235,23 @@ | |||||||
| 					</execution> | 					</execution> | ||||||
| 				</executions> | 				</executions> | ||||||
| 			</plugin> | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>com.github.spotbugs</groupId> | ||||||
|  | 				<artifactId>spotbugs-maven-plugin</artifactId> | ||||||
|  | 				<version>4.8.5.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<includeFilterFile>spotbugs-security-include.xml</includeFilterFile> | ||||||
|  | 					<excludeFilterFile>spotbugs-security-exclude.xml</excludeFilterFile> | ||||||
|  | 					<!--<plugins> | ||||||
|  | 						<plugin> | ||||||
|  | 							<groupId>com.h3xstream.findsecbugs</groupId> | ||||||
|  | 							<artifactId>findsecbugs-plugin</artifactId> | ||||||
|  | 							<version>1.12.0</version> | ||||||
|  | 						</plugin> | ||||||
|  | 					</plugins> | ||||||
| 					--> | 					--> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
| 		</plugins> | 		</plugins> | ||||||
| 	</build> | 	</build> | ||||||
| 	<!-- Generate Java-docs As Part Of Project Reports --> | 	<!-- Generate Java-docs As Part Of Project Reports --> | ||||||
|   | |||||||
							
								
								
									
										258
									
								
								back/pom.xml.versionsBackup
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								back/pom.xml.versionsBackup
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,258 @@ | |||||||
|  | <?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> | ||||||
|  | 		<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> | ||||||
|  | 			<artifactId>archidata</artifactId> | ||||||
|  | 			<version>0.14.3-SNAPSHOT</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.slf4j</groupId> | ||||||
|  | 			<artifactId>slf4j-simple</artifactId> | ||||||
|  | 			<version>2.1.0-alpha1</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.fasterxml.jackson.datatype</groupId> | ||||||
|  | 			<artifactId>jackson-datatype-jsr310</artifactId> | ||||||
|  | 			<version>2.18.0-rc1</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<!-- | ||||||
|  | 		************************************************************  | ||||||
|  | 		** TEST dependency                                        ** | ||||||
|  | 		************************************************************ | ||||||
|  | 		--> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.junit.jupiter</groupId> | ||||||
|  | 			<artifactId>junit-jupiter-api</artifactId> | ||||||
|  | 			<version>5.11.0</version> | ||||||
|  | 			<scope>test</scope> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.junit.jupiter</groupId> | ||||||
|  | 			<artifactId>junit-jupiter-engine</artifactId> | ||||||
|  | 			<version>5.11.0</version> | ||||||
|  | 			<scope>test</scope> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>net.revelc.code.formatter</groupId> | ||||||
|  | 			<artifactId>formatter-maven-plugin</artifactId> | ||||||
|  | 			<version>2.24.1</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 			<artifactId>maven-checkstyle-plugin</artifactId> | ||||||
|  | 			<version>3.5.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 	</dependencies> | ||||||
|  | 	<build> | ||||||
|  | 		<sourceDirectory>src</sourceDirectory> | ||||||
|  | 		<testSourceDirectory>test/src</testSourceDirectory> | ||||||
|  | 		<directory>${project.basedir}/out/maven/</directory> | ||||||
|  | 		<resources> | ||||||
|  | 			<resource> | ||||||
|  | 				<directory>src/resources</directory> | ||||||
|  | 			</resource> | ||||||
|  | 		</resources> | ||||||
|  | 		<testResources> | ||||||
|  | 			<testResource> | ||||||
|  | 				<directory>${basedir}/test/resources</directory> | ||||||
|  | 			</testResource> | ||||||
|  | 		</testResources> | ||||||
|  | 		<plugins> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-compiler-plugin</artifactId> | ||||||
|  | 				<version>${maven.compiler.version}</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<source>${maven.compiler.source}</source> | ||||||
|  | 					<target>${maven.compiler.target}</target> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.codehaus.mojo</groupId> | ||||||
|  | 				<artifactId>exec-maven-plugin</artifactId> | ||||||
|  | 				<version>1.4.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<mainClass>org.kar.karusic.WebLauncher</mainClass> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<!-- Create the source bundle --> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-source-plugin</artifactId> | ||||||
|  | 				<version>3.2.1</version> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>attach-sources</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>jar</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 			</plugin> | ||||||
|  | 			<!-- junit results --> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-surefire-plugin</artifactId> | ||||||
|  | 				<version>3.0.0-M5</version> | ||||||
|  | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<artifactId>maven-assembly-plugin</artifactId> | ||||||
|  | 				<configuration> | ||||||
|  | 					<archive> | ||||||
|  | 						<manifest> | ||||||
|  | 							<mainClass>fully.qualified.MainClass</mainClass> | ||||||
|  | 						</manifest> | ||||||
|  | 					</archive> | ||||||
|  | 					<descriptorRefs> | ||||||
|  | 						<descriptorRef>jar-with-dependencies</descriptorRef> | ||||||
|  | 					</descriptorRefs> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<!-- Create coverage --> | ||||||
|  | 			<!-- | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.jacoco</groupId> | ||||||
|  | 				<artifactId>jacoco-maven-plugin</artifactId> | ||||||
|  | 				<version>0.8.10</version> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>prepare-agent</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>prepare-agent</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>report</id> | ||||||
|  | 						<phase>test</phase> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>report</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>jacoco-check</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>check</goal> | ||||||
|  | 						</goals> | ||||||
|  | 						<configuration> | ||||||
|  | 							<rules> | ||||||
|  | 								<rule> | ||||||
|  | 									<element>PACKAGE</element> | ||||||
|  | 									<limits> | ||||||
|  | 										<limit> | ||||||
|  | 											<counter>LINE</counter> | ||||||
|  | 											<value>COVEREDRATIO</value> | ||||||
|  | 											<minimum>0.50</minimum> | ||||||
|  | 										</limit> | ||||||
|  | 									</limits> | ||||||
|  | 								</rule> | ||||||
|  | 							</rules> | ||||||
|  | 						</configuration> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 			</plugin> | ||||||
|  | 			--> | ||||||
|  | 			<!-- Java-doc generation for stand-alone site --> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-javadoc-plugin</artifactId> | ||||||
|  | 				<version>3.2.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<show>private</show> | ||||||
|  | 					<nohelp>true</nohelp> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.codehaus.mojo</groupId> | ||||||
|  | 				<artifactId>exec-maven-plugin</artifactId> | ||||||
|  | 				<version>3.1.0</version> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>exec-application</id> | ||||||
|  | 						<phase>package</phase> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>java</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 				<configuration> | ||||||
|  | 					<mainClass>org.kar.karusic.WebLauncher</mainClass> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<!-- Check the style of the code --> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>net.revelc.code.formatter</groupId> | ||||||
|  | 				<artifactId>formatter-maven-plugin</artifactId> | ||||||
|  | 				<version>2.23.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<encoding>UTF-8</encoding> | ||||||
|  | 					<lineEnding>LF</lineEnding> | ||||||
|  | 					<configFile>Formatter.xml</configFile> | ||||||
|  | 					<directories> | ||||||
|  | 						<directory>src/</directory> | ||||||
|  | 						<directory>test/src</directory> | ||||||
|  | 					</directories> | ||||||
|  | 					<includes> | ||||||
|  | 						<include>**/*.java</include> | ||||||
|  | 					</includes> | ||||||
|  | 					<excludes> | ||||||
|  | 						<exclude>module-info.java</exclude> | ||||||
|  | 					</excludes> | ||||||
|  | 				</configuration> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>validate</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>com.github.spotbugs</groupId> | ||||||
|  | 				<artifactId>spotbugs-maven-plugin</artifactId> | ||||||
|  | 				<version>4.8.5.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<includeFilterFile>spotbugs-security-include.xml</includeFilterFile> | ||||||
|  | 					<excludeFilterFile>spotbugs-security-exclude.xml</excludeFilterFile> | ||||||
|  | 					<!--<plugins> | ||||||
|  | 						<plugin> | ||||||
|  | 							<groupId>com.h3xstream.findsecbugs</groupId> | ||||||
|  | 							<artifactId>findsecbugs-plugin</artifactId> | ||||||
|  | 							<version>1.12.0</version> | ||||||
|  | 						</plugin> | ||||||
|  | 					</plugins> | ||||||
|  | 					--> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 		</plugins> | ||||||
|  | 	</build> | ||||||
|  | 	<!-- Generate Java-docs As Part Of Project Reports --> | ||||||
|  | 	<reporting> | ||||||
|  | 		<plugins> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-javadoc-plugin</artifactId> | ||||||
|  | 				<version>3.2.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<show>public</show> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 		</plugins> | ||||||
|  | 	</reporting> | ||||||
|  | </project> | ||||||
							
								
								
									
										27
									
								
								back/src/org/kar/karusic/CodecBson/UUIDCodec.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								back/src/org/kar/karusic/CodecBson/UUIDCodec.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | package org.kar.karusic.CodecBson; | ||||||
|  |  | ||||||
|  | import java.util.UUID; | ||||||
|  |  | ||||||
|  | import org.bson.BsonReader; | ||||||
|  | import org.bson.BsonWriter; | ||||||
|  | import org.bson.codecs.Codec; | ||||||
|  | import org.bson.codecs.DecoderContext; | ||||||
|  | import org.bson.codecs.EncoderContext; | ||||||
|  |  | ||||||
|  | public class UUIDCodec implements Codec<UUID> { | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public UUID decode(final BsonReader reader, final DecoderContext decoderContext) { | ||||||
|  | 		return UUID.fromString(reader.readString()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void encode(final BsonWriter writer, final UUID value, final EncoderContext encoderContext) { | ||||||
|  | 		writer.writeString(value.toString()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public Class<UUID> getEncoderClass() { | ||||||
|  | 		return UUID.class; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -1,24 +1,29 @@ | |||||||
| package org.kar.karusic; | package org.kar.karusic; | ||||||
|  |  | ||||||
| import java.net.URI; | import java.net.URI; | ||||||
|  | import java.util.Iterator; | ||||||
|  | import java.util.logging.LogManager; | ||||||
|  |  | ||||||
|  | import javax.imageio.ImageIO; | ||||||
|  | import javax.imageio.ImageReader; | ||||||
|  | import javax.imageio.ImageWriter; | ||||||
|  |  | ||||||
| import org.glassfish.grizzly.http.server.HttpServer; | import org.glassfish.grizzly.http.server.HttpServer; | ||||||
| import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; | import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; | ||||||
| import org.glassfish.jersey.jackson.JacksonFeature; | import org.glassfish.jersey.jackson.JacksonFeature; | ||||||
| import org.glassfish.jersey.media.multipart.MultiPartFeature; | import org.glassfish.jersey.media.multipart.MultiPartFeature; | ||||||
| import org.glassfish.jersey.server.ResourceConfig; | import org.glassfish.jersey.server.ResourceConfig; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.UpdateJwtPublicKey; | import org.kar.archidata.UpdateJwtPublicKey; | ||||||
| import org.kar.archidata.api.DataResource; | import org.kar.archidata.api.DataResource; | ||||||
| import org.kar.archidata.catcher.ExceptionCatcher; | import org.kar.archidata.api.ProxyResource; | ||||||
| import org.kar.archidata.catcher.FailExceptionCatcher; | import org.kar.archidata.catcher.GenericCatcher; | ||||||
| import org.kar.archidata.catcher.InputExceptionCatcher; | import org.kar.archidata.db.DbConfig; | ||||||
| import org.kar.archidata.catcher.JacksonCatcher; | import org.kar.archidata.exception.DataAccessException; | ||||||
| import org.kar.archidata.catcher.SystemExceptionCatcher; |  | ||||||
| import org.kar.archidata.filter.CORSFilter; | import org.kar.archidata.filter.CORSFilter; | ||||||
| import org.kar.archidata.filter.OptionFilter; | import org.kar.archidata.filter.OptionFilter; | ||||||
| import org.kar.archidata.migration.MigrationEngine; | import org.kar.archidata.migration.MigrationEngine; | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.kar.archidata.tools.ContextGenericTools; | ||||||
| import org.kar.karusic.api.AlbumResource; | import org.kar.karusic.api.AlbumResource; | ||||||
| import org.kar.karusic.api.ArtistResource; | import org.kar.karusic.api.ArtistResource; | ||||||
| import org.kar.karusic.api.Front; | import org.kar.karusic.api.Front; | ||||||
| @@ -32,8 +37,11 @@ import org.kar.karusic.migration.Initialization; | |||||||
| import org.kar.karusic.migration.Migration20231126; | import org.kar.karusic.migration.Migration20231126; | ||||||
| import org.kar.karusic.migration.Migration20240225; | import org.kar.karusic.migration.Migration20240225; | ||||||
| import org.kar.karusic.migration.Migration20240226; | import org.kar.karusic.migration.Migration20240226; | ||||||
|  | import org.kar.karusic.migration.Migration20240907; | ||||||
|  | import org.kar.karusic.migration.Migration20250104; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  | import org.slf4j.bridge.SLF4JBridgeHandler; | ||||||
|  |  | ||||||
| import jakarta.ws.rs.core.UriBuilder; | import jakarta.ws.rs.core.UriBuilder; | ||||||
|  |  | ||||||
| @@ -59,12 +67,18 @@ public class WebLauncher { | |||||||
| 		migrationEngine.add(new Migration20231126()); | 		migrationEngine.add(new Migration20231126()); | ||||||
| 		migrationEngine.add(new Migration20240225()); | 		migrationEngine.add(new Migration20240225()); | ||||||
| 		migrationEngine.add(new Migration20240226()); | 		migrationEngine.add(new Migration20240226()); | ||||||
|  | 		migrationEngine.add(new Migration20240907()); | ||||||
|  | 		migrationEngine.add(new Migration20250104()); | ||||||
| 		WebLauncher.LOGGER.info("Migrate the DB [START]"); | 		WebLauncher.LOGGER.info("Migrate the DB [START]"); | ||||||
| 		migrationEngine.migrateWaitAdmin(GlobalConfiguration.dbConfig); | 		migrationEngine.migrateWaitAdmin(new DbConfig()); | ||||||
| 		WebLauncher.LOGGER.info("Migrate the DB [STOP]"); | 		WebLauncher.LOGGER.info("Migrate the DB [STOP]"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static void main(final String[] args) throws Exception { | 	public static void main(final String[] args) throws Exception { | ||||||
|  | 		// Loop-back of logger JDK logging API to SLF4J | ||||||
|  | 		LogManager.getLogManager().reset(); | ||||||
|  | 		SLF4JBridgeHandler.install(); | ||||||
|  |  | ||||||
| 		WebLauncher.LOGGER.info("[START] application wake UP"); | 		WebLauncher.LOGGER.info("[START] application wake UP"); | ||||||
| 		final WebLauncher launcher = new WebLauncher(); | 		final WebLauncher launcher = new WebLauncher(); | ||||||
| 		launcher.migrateDB(); | 		launcher.migrateDB(); | ||||||
| @@ -77,7 +91,34 @@ public class WebLauncher { | |||||||
| 		WebLauncher.LOGGER.info("STOP the REST server:"); | 		WebLauncher.LOGGER.info("STOP the REST server:"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public void process() throws InterruptedException { | 	public void plop(final String aaa) { | ||||||
|  | 		// List available Image Readers | ||||||
|  | 		WebLauncher.LOGGER.trace("Available Image Readers:"); | ||||||
|  | 		final Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(aaa); | ||||||
|  | 		while (readers.hasNext()) { | ||||||
|  | 			final ImageReader reader = readers.next(); | ||||||
|  | 			WebLauncher.LOGGER.trace("Reader: " + reader.getOriginatingProvider().getDescription(null)); | ||||||
|  | 			WebLauncher.LOGGER.trace("Reader CN: " + reader.getOriginatingProvider().getPluginClassName()); | ||||||
|  | 			// ImageIO.deregisterServiceProvider(reader.getOriginatingProvider()); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// List available Image Writers | ||||||
|  | 		WebLauncher.LOGGER.trace("\nAvailable Image Writers:"); | ||||||
|  | 		final Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(aaa); | ||||||
|  | 		while (writers.hasNext()) { | ||||||
|  | 			final ImageWriter writer = writers.next(); | ||||||
|  | 			WebLauncher.LOGGER.trace("Writer: " + writer.getOriginatingProvider().getDescription(null)); | ||||||
|  | 			WebLauncher.LOGGER.trace("Writer CN: " + writer.getOriginatingProvider().getPluginClassName()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void process() throws InterruptedException, DataAccessException { | ||||||
|  |  | ||||||
|  | 		ImageIO.scanForPlugins(); | ||||||
|  | 		plop("jpeg"); | ||||||
|  | 		plop("png"); | ||||||
|  | 		plop("webmp"); | ||||||
|  | 		plop("webp"); | ||||||
| 		// =================================================================== | 		// =================================================================== | ||||||
| 		// Configure resources | 		// Configure resources | ||||||
| 		// =================================================================== | 		// =================================================================== | ||||||
| @@ -92,11 +133,7 @@ public class WebLauncher { | |||||||
| 		// global authentication system | 		// global authentication system | ||||||
| 		rc.register(KarusicAuthenticationFilter.class); | 		rc.register(KarusicAuthenticationFilter.class); | ||||||
| 		// register exception catcher | 		// register exception catcher | ||||||
| 		rc.register(JacksonCatcher.class); | 		GenericCatcher.addAll(rc); | ||||||
| 		rc.register(InputExceptionCatcher.class); |  | ||||||
| 		rc.register(SystemExceptionCatcher.class); |  | ||||||
| 		rc.register(FailExceptionCatcher.class); |  | ||||||
| 		rc.register(ExceptionCatcher.class); |  | ||||||
| 		// add default resource: | 		// add default resource: | ||||||
| 		rc.register(UserResource.class); | 		rc.register(UserResource.class); | ||||||
| 		rc.register(AlbumResource.class); | 		rc.register(AlbumResource.class); | ||||||
| @@ -105,22 +142,25 @@ public class WebLauncher { | |||||||
| 		rc.register(PlaylistResource.class); | 		rc.register(PlaylistResource.class); | ||||||
| 		rc.register(TrackResource.class); | 		rc.register(TrackResource.class); | ||||||
| 		rc.register(DataResource.class); | 		rc.register(DataResource.class); | ||||||
|  | 		rc.register(ProxyResource.class); | ||||||
|  |  | ||||||
| 		rc.register(HealthCheck.class); | 		rc.register(HealthCheck.class); | ||||||
| 		rc.register(Front.class); | 		rc.register(Front.class); | ||||||
|  |  | ||||||
|  | 		ContextGenericTools.addJsr310(rc); | ||||||
|  |  | ||||||
| 		// add jackson to be discover when we are ins standalone server | 		// add jackson to be discover when we are ins standalone server | ||||||
| 		rc.register(JacksonFeature.class); | 		rc.register(JacksonFeature.class); | ||||||
| 		// enable this to show low level request | 		// enable this to show low level request | ||||||
| 		//rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName()); | 		// rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName()); | ||||||
|  |  | ||||||
| 		//System.out.println("Connect on the BDD:"); | 		// System.out.println("Connect on the BDD:"); | ||||||
| 		//System.out.println("    getDBHost: '" + ConfigVariable.getDBHost() + "'"); | 		// System.out.println(" getDBHost: '" + ConfigVariable.getDBHost() + "'"); | ||||||
| 		//System.out.println("    getDBPort: '" + ConfigVariable.getDBPort() + "'"); | 		// System.out.println(" getDBPort: '" + ConfigVariable.getDBPort() + "'"); | ||||||
| 		//System.out.println("    getDBLogin: '" + ConfigVariable.getDBLogin() + "'"); | 		// System.out.println(" getDBLogin: '" + ConfigVariable.getDBLogin() + "'"); | ||||||
| 		//System.out.println("    getDBPassword: '" + ConfigVariable.getDBPassword() + "'"); | 		// System.out.println(" getDBPassword: '" + ConfigVariable.getDBPassword() + "'"); | ||||||
| 		//System.out.println("    getDBName: '" + ConfigVariable.getDBName() + "'"); | 		// System.out.println(" getDBName: '" + ConfigVariable.getDBName() + "'"); | ||||||
| 		System.out.println(" ==> " + GlobalConfiguration.dbConfig); | 		System.out.println(" ==> " + new DbConfig()); | ||||||
| 		System.out.println("OAuth service " + getBaseURI()); | 		System.out.println("OAuth service " + getBaseURI()); | ||||||
| 		this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); | 		this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); | ||||||
| 		final HttpServer serverLink = this.server; | 		final HttpServer serverLink = this.server; | ||||||
|   | |||||||
| @@ -1,9 +1,13 @@ | |||||||
| package org.kar.karusic; | package org.kar.karusic; | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.logging.LogManager; | ||||||
|  |  | ||||||
| import org.kar.archidata.api.DataResource; | import org.kar.archidata.api.DataResource; | ||||||
| import org.kar.archidata.dataAccess.DataFactoryTsApi; | import org.kar.archidata.api.ProxyResource; | ||||||
|  | import org.kar.archidata.exception.DataAccessException; | ||||||
|  | import org.kar.archidata.externalRestApi.AnalyzeApi; | ||||||
|  | import org.kar.archidata.externalRestApi.TsGenerateApi; | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
| import org.kar.karusic.api.AlbumResource; | import org.kar.karusic.api.AlbumResource; | ||||||
| import org.kar.karusic.api.ArtistResource; | import org.kar.karusic.api.ArtistResource; | ||||||
| @@ -13,27 +17,31 @@ import org.kar.karusic.api.HealthCheck; | |||||||
| import org.kar.karusic.api.PlaylistResource; | import org.kar.karusic.api.PlaylistResource; | ||||||
| import org.kar.karusic.api.TrackResource; | import org.kar.karusic.api.TrackResource; | ||||||
| import org.kar.karusic.api.UserResource; | import org.kar.karusic.api.UserResource; | ||||||
| import org.kar.karusic.migration.Initialization; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  | import org.slf4j.bridge.SLF4JBridgeHandler; | ||||||
|  |  | ||||||
| public class WebLauncherLocal extends WebLauncher { | public class WebLauncherLocal extends WebLauncher { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncherLocal.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncherLocal.class); | ||||||
|  |  | ||||||
| 	private WebLauncherLocal() {} | 	private WebLauncherLocal() {} | ||||||
|  |  | ||||||
|  | 	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, | ||||||
|  | 				TrackResource.class, DataResource.class, ProxyResource.class); | ||||||
|  | 		final AnalyzeApi api = new AnalyzeApi(); | ||||||
|  | 		api.addAllApi(listOfResources); | ||||||
|  | 		TsGenerateApi.generateApi(api, "../front/src/back-api/"); | ||||||
|  | 		LOGGER.info("Generate APIs (DONE)"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public static void main(final String[] args) throws Exception { | 	public static void main(final String[] args) throws Exception { | ||||||
| 		DataFactoryTsApi.generatePackage(List.of( | 		// Loop-back of logger JDK logging API to SLF4J | ||||||
| 				AlbumResource.class, | 		LogManager.getLogManager().reset(); | ||||||
| 				ArtistResource.class, | 		SLF4JBridgeHandler.install(); | ||||||
| 				Front.class, | 		// Generate the APIs in type-script | ||||||
| 				GenderResource.class, | 		generateObjects(); | ||||||
| 				HealthCheck.class, |  | ||||||
| 				PlaylistResource.class, |  | ||||||
| 				UserResource.class, |  | ||||||
| 				TrackResource.class, |  | ||||||
| 				DataResource.class), |  | ||||||
| 				Initialization.CLASSES_BASE, "../front/src/app/back-api/"); |  | ||||||
| 		final WebLauncherLocal launcher = new WebLauncherLocal(); | 		final WebLauncherLocal launcher = new WebLauncherLocal(); | ||||||
| 		launcher.process(); | 		launcher.process(); | ||||||
| 		launcher.LOGGER.info("end-configure the server & wait finish process:"); | 		launcher.LOGGER.info("end-configure the server & wait finish process:"); | ||||||
| @@ -42,12 +50,13 @@ public class WebLauncherLocal extends WebLauncher { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void process() throws InterruptedException { | 	public void process() throws InterruptedException, DataAccessException { | ||||||
| 		if (true) { | 		if (true) { | ||||||
| 			// for local test: | 			// for local test: | ||||||
| 			ConfigBaseVariable.apiAdress = "http://0.0.0.0:19080/karusic/api/"; | 			ConfigBaseVariable.apiAdress = "http://0.0.0.0:19080/karusic/api/"; | ||||||
| 			//ConfigBaseVariable.ssoAdress = "https://atria-soft.org/karso/api/"; | 			// ConfigBaseVariable.ssoAdress = "https://atria-soft.org/karso/api/"; | ||||||
| 			ConfigBaseVariable.dbPort = "3906"; | 			ConfigBaseVariable.dbPort = "3906"; | ||||||
|  | 			ConfigBaseVariable.testMode = "true"; | ||||||
| 		} | 		} | ||||||
| 		try { | 		try { | ||||||
| 			super.migrateDB(); | 			super.migrateDB(); | ||||||
|   | |||||||
| @@ -7,12 +7,15 @@ import java.util.UUID; | |||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | import org.glassfish.jersey.media.multipart.FormDataParam; | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
|  | import org.kar.archidata.annotation.FormDataOptional; | ||||||
| import org.kar.archidata.annotation.TypeScriptProgress; | import org.kar.archidata.annotation.TypeScriptProgress; | ||||||
|  | import org.kar.archidata.dataAccess.DBAccess; | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnDataJson; | import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; | import org.kar.archidata.dataAccess.options.CheckFunction; | ||||||
| import org.kar.archidata.tools.DataTools; | import org.kar.archidata.tools.DataTools; | ||||||
| import org.kar.karusic.model.Album; | import org.kar.karusic.model.Album; | ||||||
|  | import org.kar.karusic.model.Album.AlbumChecker; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -27,19 +30,20 @@ import jakarta.ws.rs.Path; | |||||||
| import jakarta.ws.rs.PathParam; | import jakarta.ws.rs.PathParam; | ||||||
| import jakarta.ws.rs.Produces; | import jakarta.ws.rs.Produces; | ||||||
| import jakarta.ws.rs.core.MediaType; | import jakarta.ws.rs.core.MediaType; | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
|  |  | ||||||
| @Path("/album") | @Path("/album") | ||||||
| @Produces({ MediaType.APPLICATION_JSON }) | @Produces({ MediaType.APPLICATION_JSON }) | ||||||
| public class AlbumResource { | public class AlbumResource { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(AlbumResource.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(AlbumResource.class); | ||||||
|  | 	static final AlbumChecker CHECKER = new AlbumChecker(); | ||||||
|  |  | ||||||
| 	@GET | 	@GET | ||||||
| 	@Path("{id}") | 	@Path("{id}") | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	@Operation(description = "Get a specific Album with his ID") | 	@Operation(description = "Get a specific Album with his ID") | ||||||
| 	public static Album get(@PathParam("id") final Long id) throws Exception { | 	public Album get(@PathParam("id") final Long id) throws Exception { | ||||||
| 		return DataAccess.get(Album.class, id); | 		return DataAccess.get(Album.class, id); | ||||||
|  | 		// return this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)).first(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@GET | 	@GET | ||||||
| @@ -47,14 +51,22 @@ public class AlbumResource { | |||||||
| 	@Operation(description = "Get all the available Albums") | 	@Operation(description = "Get all the available Albums") | ||||||
| 	public List<Album> gets() throws Exception { | 	public List<Album> gets() throws Exception { | ||||||
| 		return DataAccess.gets(Album.class); | 		return DataAccess.gets(Album.class); | ||||||
|  | 		// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class); | ||||||
|  | 		// return query.stream().toList(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@POST | 	@POST | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
| 	@Operation(description = "Add an album (when all the data already exist)") | 	@Operation(description = "Add an album (when all the data already exist)") | ||||||
| 	public Album post(@AsyncType(Album.class) final String jsonRequest) throws Exception { | 	public Album post(final Album data) throws Exception { | ||||||
| 		return DataAccess.insertWithJson(Album.class, jsonRequest); | 		// TODO: how to manage the checker ??? | ||||||
|  | 		// final Album ret = this.morphiaService.getDatastore().save(data); | ||||||
|  | 		// return ret; | ||||||
|  | 		/* final MongoCollection<Track> trackCollection = db.getCollection("TTRACLK", Track.class); final InsertOneResult res = trackCollection.insertOne(plop); LOGGER.warn("plpop {}", res); final | ||||||
|  | 		 * ObjectId ploppppp = res.getInsertedId().asObjectId().getValue(); LOGGER.warn("plpop 2522  {}", res.getInsertedId().asObjectId().getValue()); final Track ret = | ||||||
|  | 		 * trackCollection.find(Filters.eq("_id", res.getInsertedId().asObjectId().getValue())) .first(); System.out.println("Grade found:\t" + ret); */ | ||||||
|  | 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@PATCH | 	@PATCH | ||||||
| @@ -63,47 +75,61 @@ public class AlbumResource { | |||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
| 	@Operation(description = "Update a specific album") | 	@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); | 		// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)); | ||||||
|  | 		// final UpdateOperations<Album> ops = this.morphiaService.getDatastore().createUpdateOperations(Album.class) | ||||||
|  | 		// .set("name", master.getName()); | ||||||
|  | 		// this.morphiaService.getDatastore().update(query, ops); | ||||||
|  | 		// return Response.ok(master).build(); | ||||||
|  |  | ||||||
|  | 		DataAccess.updateWithJson(Album.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||||
| 		return DataAccess.get(Album.class, id); | 		return DataAccess.get(Album.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// @PUT | ||||||
|  | 	// @Path("{id}") | ||||||
|  | 	// @RolesAllowed("ADMIN") | ||||||
|  | 	// @Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	// @Operation(description = "Update a specific album") | ||||||
|  | 	// public Album put(@PathParam("id") final Long id, final Album album) | ||||||
|  | 	// throws Exception { | ||||||
|  | 	// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)); | ||||||
|  | 	// final UpdateOperations<Album> ops = this.morphiaService.getDatastore().createUpdateOperations(Album.class) | ||||||
|  | 	// .set("name", album.getName()); | ||||||
|  | 	// this.morphiaService.getDatastore().update(query, ops); | ||||||
|  | 	// return Response.ok(album).build(); | ||||||
|  | 	// } | ||||||
|  |  | ||||||
| 	@DELETE | 	@DELETE | ||||||
| 	@Path("{id}") | 	@Path("{id}") | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Operation(description = "Remove a specific album") | 	@Operation(description = "Remove a specific album") | ||||||
| 	public void remove(@PathParam("id") final Long id) throws Exception { | 	public void remove(@PathParam("id") final Long id) throws Exception { | ||||||
| 		DataAccess.delete(Album.class, id); | 		DataAccess.delete(Album.class, id); | ||||||
|  | 		// this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)).delete(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@POST | 	/* @POST | ||||||
| 	@Path("{id}/track/{trackId}") | 	 * @Path("{id}/track/{trackId}") | ||||||
| 	@RolesAllowed("ADMIN") | 	 * @RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	 * @Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	@Operation(description = "Add a Track on a specific album") | 	 * @Operation(description = "Add a Track on a specific album") public Album addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { | ||||||
| 	public Album addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { | 	 * AddOnManyToMany.removeLink(this.dam, Album.class, id, "track", trackId); return this.dam.get(Album.class, id); } */ | ||||||
| 		AddOnManyToMany.removeLink(Album.class, id, "track", trackId); |  | ||||||
| 		return DataAccess.get(Album.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@DELETE |  | ||||||
| 	@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 { |  | ||||||
| 		AddOnManyToMany.removeLink(Album.class, id, "track", trackId); |  | ||||||
| 		return DataAccess.get(Album.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@POST | 	@POST | ||||||
| 	@Path("{id}/cover") | 	@Path("{id}/cover") | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	@Operation(description = "Add a cover on a specific album") | 	@Operation(description = "Add a cover on a specific album") | ||||||
| 	@AsyncType(Album.class) |  | ||||||
| 	@TypeScriptProgress | 	@TypeScriptProgress | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, | 	public Album uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) { | 			@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { | ||||||
| 		return DataTools.uploadCover(Album.class, id, fileName, fileInputStream, fileMetaData); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			if (uri != null) { | ||||||
|  | 				DataTools.uploadCoverFromUri(db, Album.class, id, uri); | ||||||
|  | 			} else { | ||||||
|  | 				DataTools.uploadCover(db, Album.class, id, fileInputStream, fileMetaData); | ||||||
|  | 			} | ||||||
|  | 			return db.get(Album.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@DELETE | 	@DELETE | ||||||
| @@ -111,7 +137,9 @@ public class AlbumResource { | |||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Operation(description = "Remove a cover on a specific album") | 	@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); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
| 		return DataAccess.get(Album.class, id); | 			AddOnDataJson.removeLink(db, Album.class, "id", id, "covers", coverId); | ||||||
|  | 			return db.get(Album.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,16 +2,20 @@ package org.kar.karusic.api; | |||||||
|  |  | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | import org.glassfish.jersey.media.multipart.FormDataParam; | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
|  | import org.kar.archidata.annotation.FormDataOptional; | ||||||
| import org.kar.archidata.annotation.TypeScriptProgress; | import org.kar.archidata.annotation.TypeScriptProgress; | ||||||
|  | import org.kar.archidata.dataAccess.DBAccess; | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnDataJson; | import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckFunction; | ||||||
| import org.kar.archidata.tools.DataTools; | import org.kar.archidata.tools.DataTools; | ||||||
| import org.kar.karusic.model.Artist; | import org.kar.karusic.model.Artist; | ||||||
|  | import org.kar.karusic.model.Artist.ArtistChecker; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -25,17 +29,17 @@ import jakarta.ws.rs.Path; | |||||||
| import jakarta.ws.rs.PathParam; | import jakarta.ws.rs.PathParam; | ||||||
| import jakarta.ws.rs.Produces; | import jakarta.ws.rs.Produces; | ||||||
| import jakarta.ws.rs.core.MediaType; | import jakarta.ws.rs.core.MediaType; | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
|  |  | ||||||
| @Path("/artist") | @Path("/artist") | ||||||
| @Produces({ MediaType.APPLICATION_JSON }) | @Produces({ MediaType.APPLICATION_JSON }) | ||||||
| public class ArtistResource { | public class ArtistResource { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(ArtistResource.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(ArtistResource.class); | ||||||
|  | 	static final ArtistChecker CHECKER = new ArtistChecker(); | ||||||
|  |  | ||||||
| 	@GET | 	@GET | ||||||
| 	@Path("{id}") | 	@Path("{id}") | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	public static Artist get(@PathParam("id") final Long id) throws Exception { | 	public Artist get(@PathParam("id") final Long id) throws Exception { | ||||||
| 		return DataAccess.get(Artist.class, id); | 		return DataAccess.get(Artist.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -48,8 +52,8 @@ public class ArtistResource { | |||||||
| 	@POST | 	@POST | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
| 	public Artist post(@AsyncType(Artist.class) final String jsonRequest) throws Exception { | 	public Artist post(final Artist data) throws Exception { | ||||||
| 		return DataAccess.insertWithJson(Artist.class, jsonRequest); | 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@PATCH | 	@PATCH | ||||||
| @@ -57,7 +61,7 @@ public class ArtistResource { | |||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@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); | 		DataAccess.updateWithJson(Artist.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||||
| 		return DataAccess.get(Artist.class, id); | 		return DataAccess.get(Artist.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -72,19 +76,26 @@ public class ArtistResource { | |||||||
| 	@Path("{id}/cover") | 	@Path("{id}/cover") | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	@AsyncType(Artist.class) |  | ||||||
| 	@TypeScriptProgress | 	@TypeScriptProgress | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, | 	public Artist uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) { | 			@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { | ||||||
| 		return DataTools.uploadCover(Artist.class, id, fileName, fileInputStream, fileMetaData); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			if (uri != null) { | ||||||
|  | 				DataTools.uploadCoverFromUri(db, Artist.class, id, uri); | ||||||
|  | 			} else { | ||||||
|  | 				DataTools.uploadCover(db, Artist.class, id, fileInputStream, fileMetaData); | ||||||
|  | 			} | ||||||
|  | 			return db.get(Artist.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@DELETE | 	@DELETE | ||||||
| 	@Path("{id}/cover/{coverId}") | 	@Path("{id}/cover/{coverId}") | ||||||
| 	@RolesAllowed("ADMIN") | 	@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 ObjectId coverId) throws Exception { | ||||||
| 		LOGGER.error("klmlmkmlkmlklmklmk"); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
| 		AddOnDataJson.removeLink(Artist.class, id, "covers", coverId); | 			AddOnDataJson.removeLink(db, Artist.class, "id", id, "covers", coverId); | ||||||
| 		return DataAccess.get(Artist.class, id); | 			return db.get(Artist.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,16 +2,20 @@ package org.kar.karusic.api; | |||||||
|  |  | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | import org.glassfish.jersey.media.multipart.FormDataParam; | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
|  | import org.kar.archidata.annotation.FormDataOptional; | ||||||
| import org.kar.archidata.annotation.TypeScriptProgress; | import org.kar.archidata.annotation.TypeScriptProgress; | ||||||
|  | import org.kar.archidata.dataAccess.DBAccess; | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnDataJson; | import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckFunction; | ||||||
| import org.kar.archidata.tools.DataTools; | import org.kar.archidata.tools.DataTools; | ||||||
| import org.kar.karusic.model.Gender; | import org.kar.karusic.model.Gender; | ||||||
|  | import org.kar.karusic.model.Gender.GenderChecker; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -25,17 +29,17 @@ import jakarta.ws.rs.Path; | |||||||
| import jakarta.ws.rs.PathParam; | import jakarta.ws.rs.PathParam; | ||||||
| import jakarta.ws.rs.Produces; | import jakarta.ws.rs.Produces; | ||||||
| import jakarta.ws.rs.core.MediaType; | import jakarta.ws.rs.core.MediaType; | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
|  |  | ||||||
| @Path("/gender") | @Path("/gender") | ||||||
| @Produces({ MediaType.APPLICATION_JSON }) | @Produces({ MediaType.APPLICATION_JSON }) | ||||||
| public class GenderResource { | public class GenderResource { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(GenderResource.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(GenderResource.class); | ||||||
|  | 	static final GenderChecker CHECKER = new GenderChecker(); | ||||||
|  |  | ||||||
| 	@GET | 	@GET | ||||||
| 	@Path("{id}") | 	@Path("{id}") | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	public static Gender get(@PathParam("id") final Long id) throws Exception { | 	public Gender get(@PathParam("id") final Long id) throws Exception { | ||||||
| 		return DataAccess.get(Gender.class, id); | 		return DataAccess.get(Gender.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -48,8 +52,8 @@ public class GenderResource { | |||||||
| 	@POST | 	@POST | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
| 	public Gender post(@AsyncType(Gender.class) final String jsonRequest) throws Exception { | 	public Gender post(final Gender data) throws Exception { | ||||||
| 		return DataAccess.insertWithJson(Gender.class, jsonRequest); | 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@PATCH | 	@PATCH | ||||||
| @@ -57,7 +61,7 @@ public class GenderResource { | |||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@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); | 		DataAccess.updateWithJson(Gender.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||||
| 		return DataAccess.get(Gender.class, id); | 		return DataAccess.get(Gender.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -72,18 +76,26 @@ public class GenderResource { | |||||||
| 	@Path("{id}/cover") | 	@Path("{id}/cover") | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	@AsyncType(Gender.class) |  | ||||||
| 	@TypeScriptProgress | 	@TypeScriptProgress | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, | 	public Gender uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) { | 			@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { | ||||||
| 		return DataTools.uploadCover(Gender.class, id, fileName, fileInputStream, fileMetaData); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			if (uri != null) { | ||||||
|  | 				DataTools.uploadCoverFromUri(db, Gender.class, id, uri); | ||||||
|  | 			} else { | ||||||
|  | 				DataTools.uploadCover(db, Gender.class, id, fileInputStream, fileMetaData); | ||||||
|  | 			} | ||||||
|  | 			return db.get(Gender.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@DELETE | 	@DELETE | ||||||
| 	@Path("{id}/cover/{coverId}") | 	@Path("{id}/cover/{coverId}") | ||||||
| 	@RolesAllowed("ADMIN") | 	@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 ObjectId coverId) throws Exception { | ||||||
| 		AddOnDataJson.removeLink(Gender.class, id, "covers", coverId); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
| 		return DataAccess.get(Gender.class, id); | 			AddOnDataJson.removeLink(db, Gender.class, "id", id, "covers", coverId); | ||||||
|  | 			return db.get(Gender.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ import jakarta.ws.rs.core.Response; | |||||||
| @Produces(MediaType.APPLICATION_JSON) | @Produces(MediaType.APPLICATION_JSON) | ||||||
| public class HealthCheck { | public class HealthCheck { | ||||||
|  |  | ||||||
| 	public record HealthResult( | 	public record HealthResult(String value) { | ||||||
| 			String value) {}; | 	}; | ||||||
|  |  | ||||||
| 	@GET | 	@GET | ||||||
| 	@PermitAll | 	@PermitAll | ||||||
|   | |||||||
| @@ -2,16 +2,18 @@ package org.kar.karusic.api; | |||||||
|  |  | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | import org.glassfish.jersey.media.multipart.FormDataParam; | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
|  | import org.kar.archidata.dataAccess.DBAccess; | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnDataJson; | import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; | import org.kar.archidata.dataAccess.options.CheckFunction; | ||||||
| import org.kar.archidata.tools.DataTools; | import org.kar.archidata.tools.DataTools; | ||||||
| import org.kar.karusic.model.Playlist; | import org.kar.karusic.model.Playlist; | ||||||
|  | import org.kar.karusic.model.Track.TrackChecker; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -25,17 +27,17 @@ import jakarta.ws.rs.Path; | |||||||
| import jakarta.ws.rs.PathParam; | import jakarta.ws.rs.PathParam; | ||||||
| import jakarta.ws.rs.Produces; | import jakarta.ws.rs.Produces; | ||||||
| import jakarta.ws.rs.core.MediaType; | import jakarta.ws.rs.core.MediaType; | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
|  |  | ||||||
| @Path("/playlist") | @Path("/playlist") | ||||||
| @Produces({ MediaType.APPLICATION_JSON }) | @Produces({ MediaType.APPLICATION_JSON }) | ||||||
| public class PlaylistResource { | public class PlaylistResource { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(PlaylistResource.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(PlaylistResource.class); | ||||||
|  | 	static final TrackChecker CHECKER = new TrackChecker(); | ||||||
|  |  | ||||||
| 	@GET | 	@GET | ||||||
| 	@Path("{id}") | 	@Path("{id}") | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	public static Playlist get(@PathParam("id") final Long id) throws Exception { | 	public Playlist get(@PathParam("id") final Long id) throws Exception { | ||||||
| 		return DataAccess.get(Playlist.class, id); | 		return DataAccess.get(Playlist.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -48,8 +50,8 @@ public class PlaylistResource { | |||||||
| 	@POST | 	@POST | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
| 	public Playlist post(@AsyncType(Playlist.class) final String jsonRequest) throws Exception { | 	public Playlist post(final Playlist data) throws Exception { | ||||||
| 		return DataAccess.insertWithJson(Playlist.class, jsonRequest); | 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@PATCH | 	@PATCH | ||||||
| @@ -57,7 +59,7 @@ public class PlaylistResource { | |||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@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); | 		DataAccess.updateWithJson(Playlist.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||||
| 		return DataAccess.get(Playlist.class, id); | 		return DataAccess.get(Playlist.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -73,16 +75,20 @@ public class PlaylistResource { | |||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@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); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
| 		return DataAccess.get(Playlist.class, id); | 			AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId); | ||||||
|  | 			return db.get(Playlist.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@DELETE | 	@DELETE | ||||||
| 	@Path("{id}/track/{trackId}") | 	@Path("{id}/track/{trackId}") | ||||||
| 	@RolesAllowed("ADMIN") | 	@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); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
| 		return DataAccess.get(Playlist.class, id); | 			AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId); | ||||||
|  | 			return db.get(Playlist.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@POST | 	@POST | ||||||
| @@ -90,16 +96,20 @@ public class PlaylistResource { | |||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	@AsyncType(Playlist.class) | 	@AsyncType(Playlist.class) | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, | 	public void uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) { | 			throws Exception { | ||||||
| 		return DataTools.uploadCover(Playlist.class, id, fileName, fileInputStream, fileMetaData); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			DataTools.uploadCover(db, Playlist.class, id, fileInputStream, fileMetaData); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@DELETE | 	@DELETE | ||||||
| 	@Path("{id}/cover/{coverId}") | 	@Path("{id}/cover/{coverId}") | ||||||
| 	@RolesAllowed("ADMIN") | 	@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 ObjectId coverId) throws Exception { | ||||||
| 		AddOnDataJson.removeLink(Playlist.class, id, "covers", coverId); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			AddOnDataJson.removeLink(db, Playlist.class, "id", id, "covers", coverId); | ||||||
| 			return DataAccess.get(Playlist.class, id); | 			return DataAccess.get(Playlist.class, id); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,23 +5,21 @@ import java.io.InputStream; | |||||||
| import java.sql.SQLException; | import java.sql.SQLException; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | import org.glassfish.jersey.media.multipart.FormDataParam; | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
|  | import org.kar.archidata.annotation.FormDataOptional; | ||||||
| import org.kar.archidata.annotation.TypeScriptProgress; | import org.kar.archidata.annotation.TypeScriptProgress; | ||||||
|  | import org.kar.archidata.dataAccess.DBAccess; | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.QueryCondition; | import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnDataJson; | import org.kar.archidata.dataAccess.options.CheckFunction; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; |  | ||||||
| import org.kar.archidata.dataAccess.options.Condition; |  | ||||||
| import org.kar.archidata.model.Data; | import org.kar.archidata.model.Data; | ||||||
| import org.kar.archidata.tools.DataTools; | import org.kar.archidata.tools.DataTools; | ||||||
| import org.kar.karusic.model.Album; |  | ||||||
| import org.kar.karusic.model.Artist; |  | ||||||
| import org.kar.karusic.model.Gender; |  | ||||||
| import org.kar.karusic.model.Track; | import org.kar.karusic.model.Track; | ||||||
|  | import org.kar.karusic.model.Track.TrackChecker; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -41,11 +39,12 @@ import jakarta.ws.rs.core.Response; | |||||||
| @Produces({ MediaType.APPLICATION_JSON }) | @Produces({ MediaType.APPLICATION_JSON }) | ||||||
| public class TrackResource { | public class TrackResource { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(TrackResource.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(TrackResource.class); | ||||||
|  | 	static final TrackChecker CHECKER = new TrackChecker(); | ||||||
|  |  | ||||||
| 	@GET | 	@GET | ||||||
| 	@Path("{id}") | 	@Path("{id}") | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	public static Track get(@PathParam("id") final Long id) throws Exception { | 	public Track get(@PathParam("id") final Long id) throws Exception { | ||||||
| 		return DataAccess.get(Track.class, id); | 		return DataAccess.get(Track.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -58,8 +57,8 @@ public class TrackResource { | |||||||
| 	@POST | 	@POST | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
| 	public Track post(@AsyncType(Track.class) final String jsonRequest) throws Exception { | 	public Track post(final Track data) throws Exception { | ||||||
| 		return DataAccess.insertWithJson(Track.class, jsonRequest); | 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@PATCH | 	@PATCH | ||||||
| @@ -67,7 +66,7 @@ public class TrackResource { | |||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) | 	@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); | 		DataAccess.updateWithJson(Track.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||||
| 		return DataAccess.get(Track.class, id); | 		return DataAccess.get(Track.class, id); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -83,92 +82,91 @@ public class TrackResource { | |||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	public Track addTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception { | 	public Track addTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception { | ||||||
| 		AddOnManyToMany.removeLink(Track.class, id, "artist", artistId); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			AddOnDataJson.removeLink(db, Track.class, "id", id, "artist", artistId); | ||||||
| 			return DataAccess.get(Track.class, id); | 			return DataAccess.get(Track.class, id); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	@DELETE | 	@DELETE | ||||||
| 	@Path("{id}/artist/{trackId}") | 	@Path("{id}/artist/{trackId}") | ||||||
| 	@RolesAllowed("ADMIN") | 	@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); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			AddOnDataJson.removeLink(db, Track.class, "id", id, "artist", artistId); | ||||||
| 			return DataAccess.get(Track.class, id); | 			return DataAccess.get(Track.class, id); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	@POST | 	@POST | ||||||
| 	@Path("{id}/cover") | 	@Path("{id}/cover") | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	@AsyncType(Track.class) |  | ||||||
| 	@TypeScriptProgress | 	@TypeScriptProgress | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @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) { | 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { | ||||||
| 		return DataTools.uploadCover(Track.class, id, fileName, fileInputStream, fileMetaData); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			if (uri != null) { | ||||||
|  | 				DataTools.uploadCoverFromUri(db, Track.class, id, uri); | ||||||
|  | 			} else { | ||||||
|  | 				DataTools.uploadCover(db, Track.class, id, fileInputStream, fileMetaData); | ||||||
|  | 			} | ||||||
|  | 			return DataAccess.get(Track.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@DELETE | 	@DELETE | ||||||
| 	@Path("{id}/cover/{coverId}") | 	@Path("{id}/cover/{coverId}") | ||||||
| 	@RolesAllowed("ADMIN") | 	@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 ObjectId coverId) throws Exception { | ||||||
| 		AddOnDataJson.removeLink(Track.class, id, "covers", coverId); | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
| 		return DataAccess.get(Track.class, id); | 			AddOnDataJson.removeLink(db, Track.class, "id", id, "covers", coverId); | ||||||
|  | 			return db.get(Track.class, id); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@POST | 	@POST | ||||||
| 	@Path("upload/") | 	@Path("upload/") | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	// Formatter:off |  | ||||||
| 	@AsyncType(Track.class) | 	@AsyncType(Track.class) | ||||||
| 	@TypeScriptProgress | 	@TypeScriptProgress | ||||||
| 	public Response uploadTrack( | 	public Response uploadTrack( // | ||||||
| 			@FormDataParam("fileName") String fileName, // |  | ||||||
| 			@FormDataParam("gender") String gender, // |  | ||||||
| 			@FormDataParam("artist") String artist, // |  | ||||||
| 			//@FormDataParam("seriesId") String seriesId, Not used ... |  | ||||||
| 			@FormDataParam("album") String album, // |  | ||||||
| 			@AsyncType(Long.class) @FormDataParam("trackId") String trackId, // |  | ||||||
| 			@FormDataParam("title") String title, // | 			@FormDataParam("title") String title, // | ||||||
|  | 			@FormDataOptional @AsyncType(Long.class) @FormDataParam("genderId") String genderId, // | ||||||
|  | 			@FormDataOptional @AsyncType(Long.class) @FormDataParam("artistId") String artistId, // | ||||||
|  | 			@FormDataOptional @AsyncType(Long.class) @FormDataParam("albumId") String albumId, // | ||||||
|  | 			@FormDataOptional @AsyncType(Long.class) @FormDataParam("trackId") String trackId, // | ||||||
| 			@FormDataParam("file") final InputStream fileInputStream, // | 			@FormDataParam("file") final InputStream fileInputStream, // | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData // | 			@FormDataParam("file") final FormDataContentDisposition fileMetaData // | ||||||
| 	) { | 	) { | ||||||
| 		// Formatter:on | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
| 		try { |  | ||||||
| 			// correct input string stream : | 			// correct input string stream : | ||||||
| 			fileName = DataTools.multipartCorrection(fileName); |  | ||||||
| 			gender = DataTools.multipartCorrection(gender); |  | ||||||
| 			artist = DataTools.multipartCorrection(artist); |  | ||||||
| 			album = DataTools.multipartCorrection(album); |  | ||||||
| 			trackId = DataTools.multipartCorrection(trackId); | 			trackId = DataTools.multipartCorrection(trackId); | ||||||
|  | 			albumId = DataTools.multipartCorrection(albumId); | ||||||
|  | 			artistId = DataTools.multipartCorrection(artistId); | ||||||
|  | 			genderId = DataTools.multipartCorrection(genderId); | ||||||
| 			title = DataTools.multipartCorrection(title); | 			title = DataTools.multipartCorrection(title); | ||||||
|  |  | ||||||
| 			//public NodeSmall uploadFile(final FormDataMultiPart form) { | 			// public NodeSmall uploadFile(final FormDataMultiPart form) { | ||||||
| 			LOGGER.info("Upload media file: " + fileMetaData); | 			LOGGER.info("Upload media file: " + fileMetaData); | ||||||
| 			LOGGER.info("    > fileName: " + fileName); | 			LOGGER.info("    > genderId: " + genderId); | ||||||
| 			LOGGER.info("    > gender: " + gender); | 			LOGGER.info("    > artistId: " + artistId); | ||||||
| 			LOGGER.info("    > artist: " + artist); | 			LOGGER.info("    > albumId: " + albumId); | ||||||
| 			LOGGER.info("    > album: " + album); |  | ||||||
| 			LOGGER.info("    > trackId: " + trackId); | 			LOGGER.info("    > trackId: " + trackId); | ||||||
| 			LOGGER.info("    > title: " + title); | 			LOGGER.info("    > title: " + title); | ||||||
| 			LOGGER.info("    > fileInputStream: " + fileInputStream); | 			LOGGER.info("    > fileInputStream: " + fileInputStream); | ||||||
| 			LOGGER.info("    > fileMetaData: " + fileMetaData); | 			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 long tmpUID = DataTools.getTmpDataId(); | ||||||
| 			final String sha512 = DataTools.saveTemporaryFile(fileInputStream, tmpUID); | 			final String sha512 = DataTools.saveTemporaryFile(fileInputStream, tmpUID); | ||||||
| 			Data data = DataTools.getWithSha512(sha512); | 			Data data = DataTools.getWithSha512(db, sha512); | ||||||
| 			if (data == null) { | 			if (data == null) { | ||||||
| 				LOGGER.info("Need to add the data in the BDD ... "); | 				LOGGER.info("Need to add the data in the BDD ... "); | ||||||
|  |  | ||||||
| 				try { | 				try { | ||||||
| 					data = DataTools.createNewData(tmpUID, fileName, sha512); | 					data = DataTools.createNewData(db, tmpUID, fileMetaData.getFileName(), sha512); | ||||||
| 				} catch (final IOException ex) { | 				} catch (final IOException ex) { | ||||||
| 					DataTools.removeTemporaryFile(tmpUID); | 					DataTools.removeTemporaryFile(tmpUID); | ||||||
| 					ex.printStackTrace(); | 					ex.printStackTrace(); | ||||||
| @@ -180,73 +178,26 @@ public class TrackResource { | |||||||
| 				} | 				} | ||||||
| 			} else if (data.deleted) { | 			} else if (data.deleted) { | ||||||
| 				LOGGER.info("Data already exist but deleted"); | 				LOGGER.info("Data already exist but deleted"); | ||||||
| 				DataTools.undelete(data.id); | 				DataTools.undelete(db, data.oid); | ||||||
| 				data.deleted = false; | 				data.deleted = false; | ||||||
| 			} else { | 			} else { | ||||||
| 				LOGGER.info("Data already exist ... all good"); | 				LOGGER.info("Data already exist ... all good"); | ||||||
| 			} | 			} | ||||||
| 			// Fist step: retrieve all the Id of each parents:... |  | ||||||
| 			LOGGER.info("Find typeNode"); |  | ||||||
| 			Gender genderElem = null; |  | ||||||
| 			if (gender != null) { |  | ||||||
| 				genderElem = DataAccess.getWhere(Gender.class, new Condition(new QueryCondition("name", "=", gender))); |  | ||||||
| 				if (genderElem == null) { |  | ||||||
| 					genderElem = new Gender(); |  | ||||||
| 					genderElem.name = gender; |  | ||||||
| 					genderElem = DataAccess.insert(genderElem); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			//            NodeSmall typeNode = TypeResource.getWithId(Long.parseLong(typeId)); |  | ||||||
| 			//            if (typeNode == null) { |  | ||||||
| 			//                DataTools.removeTemporaryFile(tmpUID); |  | ||||||
| 			//                return Response.notModified("TypeId does not exist ...").build(); |  | ||||||
| 			//            } |  | ||||||
| 			LOGGER.info("    ==> genderElem={}", genderElem); |  | ||||||
|  |  | ||||||
| 			Artist artistElem = null; |  | ||||||
| 			if (artist != null) { |  | ||||||
| 				LOGGER.info("    Try to find Artist: '{}'", artist); |  | ||||||
| 				artistElem = DataAccess.getWhere(Artist.class, new Condition(new QueryCondition("name", "=", artist))); |  | ||||||
| 				if (artistElem == null) { |  | ||||||
| 					LOGGER.info("        ** Create a new one..."); |  | ||||||
| 					artistElem = new Artist(); |  | ||||||
| 					artistElem.name = artist; |  | ||||||
| 					artistElem = DataAccess.insert(artistElem); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			LOGGER.info("    ==> artistElem={}", artistElem); |  | ||||||
|  |  | ||||||
| 			Album albumElem = null; |  | ||||||
| 			if (album != null) { |  | ||||||
| 				albumElem = DataAccess.getWhere(Album.class, new Condition(new QueryCondition("name", "=", album))); |  | ||||||
| 				if (albumElem == null) { |  | ||||||
| 					albumElem = new Album(); |  | ||||||
| 					albumElem.name = album; |  | ||||||
| 					albumElem = DataAccess.insert(albumElem); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			LOGGER.info("    ==> " + album); |  | ||||||
|  |  | ||||||
| 			LOGGER.info("add media"); | 			LOGGER.info("add media"); | ||||||
|  |  | ||||||
| 			Track trackElem = new Track(); | 			Track trackElem = new Track(); | ||||||
| 			trackElem.name = title; | 			trackElem.name = title; | ||||||
| 			trackElem.track = trackId != null ? Long.parseLong(trackId) : null; | 			trackElem.track = trackId != null ? Long.parseLong(trackId) : null; | ||||||
| 			trackElem.albumId = albumElem != null ? albumElem.id : null; | 			trackElem.albumId = albumId != null ? Long.parseLong(albumId) : null; | ||||||
| 			trackElem.genderId = genderElem != null ? genderElem.id : null; | 			trackElem.genderId = genderId != null ? Long.parseLong(genderId) : null; | ||||||
| 			trackElem.dataId = data.id; | 			trackElem.dataId = data.oid; | ||||||
| 			// Now list of artist has an internal management: | 			// Now list of artist has an internal management: | ||||||
| 			if (artistElem != null) { | 			if (artistId != null) { | ||||||
| 				trackElem.artists = new ArrayList<>(); | 				trackElem.artists = new ArrayList<>(); | ||||||
| 				trackElem.artists.add(artistElem.id); | 				trackElem.artists.add(artistId != null ? Long.parseLong(artistId) : null); | ||||||
| 			} | 			} | ||||||
| 			trackElem = DataAccess.insert(trackElem); | 			trackElem = DataAccess.insert(trackElem, new CheckFunction(CHECKER)); | ||||||
| 			/* | 			/* Old mode of artist insertion (removed due to the slowlest request of getting value if (artistElem != null) { this.dam.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(); | 			return Response.ok(trackElem).build(); | ||||||
| 		} catch (final Exception ex) { | 		} catch (final Exception ex) { | ||||||
| 			LOGGER.info("Catch an unexpected error ... {}", ex.getMessage()); | 			LOGGER.info("Catch an unexpected error ... {}", ex.getMessage()); | ||||||
|   | |||||||
| @@ -1,9 +1,12 @@ | |||||||
| package org.kar.karusic.api; | package org.kar.karusic.api; | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.filter.GenericContext; | import org.kar.archidata.filter.GenericContext; | ||||||
|  | import org.kar.karusic.api.UserResourceModel.PartRight; | ||||||
|  | import org.kar.karusic.api.UserResourceModel.UserMe; | ||||||
| import org.kar.karusic.model.UserKarusic; | import org.kar.karusic.model.UserKarusic; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| @@ -20,7 +23,7 @@ import jakarta.ws.rs.core.MediaType; | |||||||
| import jakarta.ws.rs.core.SecurityContext; | import jakarta.ws.rs.core.SecurityContext; | ||||||
|  |  | ||||||
| @Path("/users") | @Path("/users") | ||||||
| @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) | @Produces(MediaType.APPLICATION_JSON) | ||||||
| public class UserResource { | public class UserResource { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class); | ||||||
|  |  | ||||||
| @@ -74,10 +77,15 @@ public class UserResource { | |||||||
| 	@GET | 	@GET | ||||||
| 	@Path("me") | 	@Path("me") | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	public UserOut getMe(@Context final SecurityContext sc) { | 	public UserMe getMe(@Context final SecurityContext sc) { | ||||||
| 		LOGGER.debug("getMe()"); | 		LOGGER.debug("getMe()"); | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
| 		LOGGER.debug("== USER ? {}", gc.userByToken); | 		LOGGER.debug("== USER ? {}", gc.userByToken); | ||||||
| 		return new UserOut(gc.userByToken.id, gc.userByToken.name); | 		return new UserMe(gc.userByToken.id, gc.userByToken.name, // | ||||||
|  | 				Map.of(gc.userByToken.name, // | ||||||
|  | 						Map.of("admin", PartRight.READ_WRITE, // | ||||||
|  | 								"user", PartRight.READ_WRITE), // | ||||||
|  | 						"karusic", // | ||||||
|  | 						Map.of("user", PartRight.READ))); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,12 @@ | |||||||
|  | package org.kar.karusic.api.UserResourceModel; | ||||||
|  |  | ||||||
|  | import java.util.HashMap; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.annotation.NoWriteSpecificMode; | ||||||
|  |  | ||||||
|  | @NoWriteSpecificMode | ||||||
|  | public class ModuleAuthorizations extends HashMap<String, PartRight> { | ||||||
|  | 	private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  | 	public ModuleAuthorizations() {} | ||||||
|  | } | ||||||
| @@ -0,0 +1,29 @@ | |||||||
|  | package org.kar.karusic.api.UserResourceModel; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonValue; | ||||||
|  |  | ||||||
|  | public enum PartRight { | ||||||
|  | 	READ(1), // | ||||||
|  | 	WRITE(2), // | ||||||
|  | 	READ_WRITE(3); | ||||||
|  |  | ||||||
|  | 	private final int value; | ||||||
|  |  | ||||||
|  | 	PartRight(final int value) { | ||||||
|  | 		this.value = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@JsonValue | ||||||
|  | 	public int getValue() { | ||||||
|  | 		return this.value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static PartRight fromValue(final int value) { | ||||||
|  | 		for (final PartRight species : PartRight.values()) { | ||||||
|  | 			if (species.getValue() == value) { | ||||||
|  | 				return species; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		throw new IllegalArgumentException("PartRight: Unknown value: " + value); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								back/src/org/kar/karusic/api/UserResourceModel/UserMe.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								back/src/org/kar/karusic/api/UserResourceModel/UserMe.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | package org.kar.karusic.api.UserResourceModel; | ||||||
|  |  | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.annotation.NoWriteSpecificMode; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  |  | ||||||
|  | @NoWriteSpecificMode | ||||||
|  | public class UserMe { | ||||||
|  | 	public long id; | ||||||
|  | 	public String login; | ||||||
|  | 	@Schema(description = "Map<EntityName, Map<PartName, Right>>") | ||||||
|  | 	public Map<String, Map<String, PartRight>> rights; | ||||||
|  |  | ||||||
|  | 	public UserMe() {} | ||||||
|  |  | ||||||
|  | 	public UserMe(final long id, final String login, final Map<String, Map<String, PartRight>> rights) { | ||||||
|  | 		this.id = id; | ||||||
|  | 		this.login = login; | ||||||
|  | 		this.rights = rights; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -4,57 +4,57 @@ package org.kar.karusic.internal; | |||||||
| //import io.scenarium.logger.Logger; | //import io.scenarium.logger.Logger; | ||||||
|  |  | ||||||
| public class Log { | public class Log { | ||||||
| //	private static final String LIB_NAME = "logger"; | 	// private static final String LIB_NAME = "logger"; | ||||||
| //	private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); | 	// private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); | ||||||
| //	private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); | 	// private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); | ||||||
| //	private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR); | 	// private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR); | ||||||
| //	private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING); | 	// private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING); | ||||||
| //	private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO); | 	// private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO); | ||||||
| //	private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG); | 	// private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG); | ||||||
| //	private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); | 	// private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); | ||||||
| //	private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); | 	// private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); | ||||||
| //	private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); | 	// private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); | ||||||
| // | 	// | ||||||
| //	private Log() {} | 	// private Log() {} | ||||||
| // | 	// | ||||||
| //	public static void print(String data) { | 	// public static void print(String data) { | ||||||
| //		if (PRINT_PRINT) | 	// if (PRINT_PRINT) | ||||||
| //			Logger.print(LIB_NAME_DRAW, data); | 	// Logger.print(LIB_NAME_DRAW, data); | ||||||
| //	} | 	// } | ||||||
| // | 	// | ||||||
| //	public static void todo(String data) { | 	// public static void todo(String data) { | ||||||
| //		if (PRINT_TODO) | 	// if (PRINT_TODO) | ||||||
| //			Logger.todo(LIB_NAME_DRAW, data); | 	// Logger.todo(LIB_NAME_DRAW, data); | ||||||
| //	} | 	// } | ||||||
| // | 	// | ||||||
| //	public static void critical(String data) { | 	// public static void critical(String data) { | ||||||
| //		if (PRINT_CRITICAL) | 	// if (PRINT_CRITICAL) | ||||||
| //			Logger.critical(LIB_NAME_DRAW, data); | 	// Logger.critical(LIB_NAME_DRAW, data); | ||||||
| //	} | 	// } | ||||||
| // | 	// | ||||||
| //	public static void error(String data) { | 	// public static void error(String data) { | ||||||
| //		if (PRINT_ERROR) | 	// if (PRINT_ERROR) | ||||||
| //			Logger.error(LIB_NAME_DRAW, data); | 	// Logger.error(LIB_NAME_DRAW, data); | ||||||
| //	} | 	// } | ||||||
| // | 	// | ||||||
| //	public static void warning(String data) { | 	// public static void warning(String data) { | ||||||
| //		if (PRINT_WARNING) | 	// if (PRINT_WARNING) | ||||||
| //			Logger.warning(LIB_NAME_DRAW, data); | 	// Logger.warning(LIB_NAME_DRAW, data); | ||||||
| //	} | 	// } | ||||||
| // | 	// | ||||||
| //	public static void info(String data) { | 	// public static void info(String data) { | ||||||
| //		if (PRINT_INFO) | 	// if (PRINT_INFO) | ||||||
| //			Logger.info(LIB_NAME_DRAW, data); | 	// Logger.info(LIB_NAME_DRAW, data); | ||||||
| //	} | 	// } | ||||||
| // | 	// | ||||||
| //	public static void debug(String data) { | 	// public static void debug(String data) { | ||||||
| //		if (PRINT_DEBUG) | 	// if (PRINT_DEBUG) | ||||||
| //			Logger.debug(LIB_NAME_DRAW, data); | 	// Logger.debug(LIB_NAME_DRAW, data); | ||||||
| //	} | 	// } | ||||||
| // | 	// | ||||||
| //	public static void verbose(String data) { | 	// public static void verbose(String data) { | ||||||
| //		if (PRINT_VERBOSE) | 	// if (PRINT_VERBOSE) | ||||||
| //			Logger.verbose(LIB_NAME_DRAW, data); | 	// Logger.verbose(LIB_NAME_DRAW, data); | ||||||
| //	} | 	// } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ package org.kar.karusic.migration; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.dataAccess.DBAccess; | ||||||
| import org.kar.archidata.migration.MigrationSqlStep; | import org.kar.archidata.migration.MigrationSqlStep; | ||||||
| import org.kar.archidata.model.Data; | import org.kar.archidata.model.Data; | ||||||
| import org.kar.archidata.model.User; | import org.kar.archidata.model.User; | ||||||
| @@ -10,11 +11,14 @@ import org.kar.karusic.model.Artist; | |||||||
| import org.kar.karusic.model.Gender; | import org.kar.karusic.model.Gender; | ||||||
| import org.kar.karusic.model.Playlist; | import org.kar.karusic.model.Playlist; | ||||||
| import org.kar.karusic.model.Track; | import org.kar.karusic.model.Track; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| public class Initialization extends MigrationSqlStep { | public class Initialization extends MigrationSqlStep { | ||||||
|  | 	private static final Logger LOGGER = LoggerFactory.getLogger(Initialization.class); | ||||||
|  |  | ||||||
| 	public static final int KARSO_INITIALISATION_ID = 1; | 	public static final int KARSO_INITIALISATION_ID = 1; | ||||||
| 	public static final List<Class<?>> CLASSES_BASE = List.of(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 | 	@Override | ||||||
| 	public String getName() { | 	public String getName() { | ||||||
| @@ -31,35 +35,35 @@ public class Initialization extends MigrationSqlStep { | |||||||
| 			addClass(elem); | 			addClass(elem); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		addAction(""" | 		addAction((final DBAccess da) -> { | ||||||
| 				INSERT INTO `gender` (`id`, `name`, `description`) VALUES | 			final List<Gender> data = List.of(// | ||||||
| 				(1, 'Variété française',	NULL), | 					new Gender(1L, "Variété française"), // | ||||||
| 				(2, 'Pop',	NULL), | 					new Gender(2L, "Pop"), // | ||||||
| 				(3, 'inconnue',	NULL), | 					new Gender(3L, "inconnue"), // | ||||||
| 				(4, 'Disco',	NULL), | 					new Gender(4L, "Disco"), // | ||||||
| 				(5, 'Enfants',	NULL), | 					new Gender(5L, "Enfants"), // | ||||||
| 				(6, 'Portugaise',	NULL), | 					new Gender(6L, "Portugaise"), // | ||||||
| 				(7, 'Apprentissage',	NULL), | 					new Gender(7L, "Apprentissage"), // | ||||||
| 				(8, 'Blues',	NULL), | 					new Gender(8L, "Blues"), // | ||||||
| 				(9, 'Jazz',	NULL), | 					new Gender(9L, "Jazz"), // | ||||||
| 				(10, 'Chanson Noël',	NULL), | 					new Gender(10L, "Chanson Noël"), // | ||||||
| 				(11, 'DubStep',	NULL), | 					new Gender(11L, "DubStep"), // | ||||||
| 				(12, 'Rap français',	NULL), | 					new Gender(12L, "Rap français"), // | ||||||
| 				(13, 'Classique',	NULL), | 					new Gender(13L, "Classique"), // | ||||||
| 				(14, 'Rock',	NULL), | 					new Gender(14L, "Rock"), // | ||||||
| 				(15, 'Electro',	NULL), | 					new Gender(15L, "Electro"), // | ||||||
| 				(16, 'Celtique',	NULL), | 					new Gender(16L, "Celtique"), // | ||||||
| 				(17, 'Country',	NULL), | 					new Gender(17L, "Country"), // | ||||||
| 				(18, 'Variété Québéquoise',	NULL), | 					new Gender(18L, "Variété Québéquoise"), // | ||||||
| 				(19, 'Médiéval',	NULL), | 					new Gender(19L, "Médiéval"), // | ||||||
| 				(20, 'Variété Italienne',	NULL), | 					new Gender(20L, "Variété Italienne"), // | ||||||
| 				(21, 'Comédie Musicale',	NULL), | 					new Gender(21L, "Comédie Musicale"), // | ||||||
| 				(22, 'Vianney',	NULL), | 					new Gender(22L, "Vianney"), // | ||||||
| 				(23, 'Bande Original',	NULL), | 					new Gender(23L, "Bande Original"), // | ||||||
| 				(24, 'Bande Originale',	NULL), | 					new Gender(24L, "Bande Originale"), // | ||||||
| 				(25, 'Variété Belge',	NULL), | 					new Gender(25L, "Variété Belge"), // | ||||||
| 				(26, 'Gospel',	NULL); | 					new Gender(26L, "Gospel")); | ||||||
| 				"""); | 		}); | ||||||
| 		// set start increment element to permit to add after default elements | 		// set start increment element to permit to add after default elements | ||||||
| 		addAction(""" | 		addAction(""" | ||||||
| 				ALTER TABLE `album` AUTO_INCREMENT = 1000; | 				ALTER TABLE `album` AUTO_INCREMENT = 1000; | ||||||
| @@ -81,4 +85,25 @@ public class Initialization extends MigrationSqlStep { | |||||||
| 				""", "mysql"); | 				""", "mysql"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static void dropAll(final DBAccess da) { | ||||||
|  | 		for (final Class<?> element : CLASSES_BASE) { | ||||||
|  | 			try { | ||||||
|  | 				da.drop(element); | ||||||
|  | 			} catch (final Exception ex) { | ||||||
|  | 				LOGGER.error("Fail to drop table !!!!!!"); | ||||||
|  | 				ex.printStackTrace(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void cleanAll(final DBAccess da) { | ||||||
|  | 		for (final Class<?> element : CLASSES_BASE) { | ||||||
|  | 			try { | ||||||
|  | 				da.cleanAll(element); | ||||||
|  | 			} catch (final Exception ex) { | ||||||
|  | 				LOGGER.error("Fail to clean table !!!!!!"); | ||||||
|  | 				ex.printStackTrace(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,159 +11,4 @@ public class Migration20231126 extends MigrationSqlStep { | |||||||
| 		return "migration-2023-11-26: reorder the migration for the new API of archidata"; | 		return "migration-2023-11-26: reorder the migration for the new API of archidata"; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public Migration20231126() { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public void generateStep() throws Exception { |  | ||||||
| 		// update migration update (last one) |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `KAR_migration` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				ADD `version` int NOT NULL DEFAULT '2' AFTER `deleted`, |  | ||||||
| 				CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL COMMENT 'Name of the migration' AFTER `version`, |  | ||||||
| 				CHANGE `terminated` `terminated` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'if the migration is well terminated or not' AFTER `name`, |  | ||||||
| 				CHANGE `stepId` `stepId` int NULL COMMENT 'index in the migration progression' AFTER `terminated`, |  | ||||||
| 				CHANGE `count` `count` int NULL COMMENT 'number of element in the migration' AFTER `stepId`, |  | ||||||
| 				CHANGE `log` `log` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Log generate by the migration' AFTER `count`; |  | ||||||
| 				"""); |  | ||||||
| 		 |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `album` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`, |  | ||||||
| 				CHANGE `publication` `publication` date NULL AFTER `description`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `album_link_cover` |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `album_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `artist` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `firstName` `firstName` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `description`, |  | ||||||
| 				CHANGE `surname` `surname` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `firstName`, |  | ||||||
| 				CHANGE `birth` `birth` date NULL AFTER `surname`, |  | ||||||
| 				CHANGE `death` `death` date NULL AFTER `birth`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `artist_link_cover` |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `artist_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `data` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `sha512` `sha512` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Sha512 of the data' AFTER `deleted`, |  | ||||||
| 				CHANGE `mimeType` `mimeType` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Mime -type of the media' AFTER `sha512`, |  | ||||||
| 				CHANGE `size` `size` bigint NOT NULL COMMENT 'Size in Byte of the data' AFTER `mimeType`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `gender` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `gender_link_cover` |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `gender_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `playlist` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `playlist_link_cover` |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `playlist_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `playlist_link_track` |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `playlist_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `track_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `track` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`, |  | ||||||
| 				CHANGE `genderId` `genderId` bigint NULL AFTER `description`, |  | ||||||
| 				CHANGE `albumId` `albumId` bigint NULL AFTER `genderId`, |  | ||||||
| 				CHANGE `track` `track` bigint NULL AFTER `albumId`, |  | ||||||
| 				CHANGE `dataId` `dataId` bigint NULL AFTER `track`, |  | ||||||
| 				CHANGE `artists` `artists` text COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `dataId`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `track_link_cover` |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `track_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `user` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `login` `login` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `lastConnection` `lastConnection` timestamp(3) NULL AFTER `login`, |  | ||||||
| 				CHANGE `admin` `admin` tinyint(1) NOT NULL DEFAULT '0' AFTER `lastConnection`, |  | ||||||
| 				CHANGE `blocked` `blocked` tinyint(1) NOT NULL DEFAULT '0' AFTER `admin`, |  | ||||||
| 				CHANGE `removed` `removed` tinyint(1) NOT NULL DEFAULT '0' AFTER `blocked`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				CREATE TABLE `user_link_cover` ( |  | ||||||
| 					`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Primary key of the base' , |  | ||||||
| 					`createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' , |  | ||||||
| 					`updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT 'When update the object' , |  | ||||||
| 					`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' , |  | ||||||
| 					`object1Id` bigint NOT NULL COMMENT 'Object reference 1' , |  | ||||||
| 					`object2Id` bigint NOT NULL COMMENT 'Object reference 2' , |  | ||||||
| 				PRIMARY KEY (`id`) |  | ||||||
| 				) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; |  | ||||||
| 				"""); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,16 +11,4 @@ public class Migration20240225 extends MigrationSqlStep { | |||||||
| 		return "migration-2024-02-25: change model of thrack to use real json"; | 		return "migration-2024-02-25: change model of thrack to use real json"; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public Migration20240225() { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public void generateStep() throws Exception { |  | ||||||
| 		// update migration update (last one) |  | ||||||
| 		addAction(""" |  | ||||||
| 				UPDATE `track` SET artists = CONCAT('[', artists, ']') WHERE artists IS NOT NULL |  | ||||||
| 				"""); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,22 +1,6 @@ | |||||||
| package org.kar.karusic.migration; | package org.kar.karusic.migration; | ||||||
|  |  | ||||||
| import java.nio.file.Files; |  | ||||||
| import java.nio.file.Paths; |  | ||||||
| import java.nio.file.StandardCopyOption; |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.api.DataResource; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; |  | ||||||
| import org.kar.archidata.dataAccess.addOn.model.LinkTable; |  | ||||||
| import org.kar.archidata.dataAccess.options.AccessDeletedItems; |  | ||||||
| import org.kar.archidata.dataAccess.options.OverrideTableName; |  | ||||||
| import org.kar.archidata.migration.MigrationSqlStep; | import org.kar.archidata.migration.MigrationSqlStep; | ||||||
| import org.kar.archidata.tools.UuidUtils; |  | ||||||
| import org.kar.karusic.migration.model.CoverConversion; |  | ||||||
| import org.kar.karusic.migration.model.MediaConversion; |  | ||||||
| import org.kar.karusic.migration.model.UUIDConversion; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -30,106 +14,4 @@ public class Migration20240226 extends MigrationSqlStep { | |||||||
| 		return "migration-2024-02-26: convert base with UUID"; | 		return "migration-2024-02-26: convert base with UUID"; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public Migration20240226() { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public void generateStep() throws Exception { |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `data` ADD `uuid` binary(16) AFTER `id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(() -> { |  | ||||||
| 			final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); |  | ||||||
| 			for (final UUIDConversion elem: datas) { |  | ||||||
| 				elem.uuid = UuidUtils.nextUUID(); |  | ||||||
| 			} |  | ||||||
| 			for (final UUIDConversion elem: datas) { |  | ||||||
| 				DataAccess.update(elem, elem.id, List.of("uuid"), new OverrideTableName("data")); |  | ||||||
| 			} |  | ||||||
| 		}); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `data` CHANGE `uuid` `uuid` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE)); |  | ||||||
| 				"""); |  | ||||||
| 		final List<String> tableToTransform = List.of("album", "artist", "gender", "playlist", "track", "user"); |  | ||||||
| 		for (final String tableName : tableToTransform ) { |  | ||||||
| 			addAction("ALTER TABLE `" + tableName + "` ADD `covers` text NULL;"); |  | ||||||
| 			addAction(() -> { |  | ||||||
| 				final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); |  | ||||||
| 				final List<CoverConversion> medias = DataAccess.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName)); |  | ||||||
| 				final List<LinkTable> links = DataAccess.gets(LinkTable.class, new OverrideTableName(tableName + "_link_cover")); |  | ||||||
| 				LOGGER.info("Get somes data: {} {} {}", datas.size(), medias.size(), links.size()); |  | ||||||
| 				for (final CoverConversion media: medias) { |  | ||||||
| 					final List<UUID> values = new ArrayList<>(); |  | ||||||
| 					for (final LinkTable link: links) { |  | ||||||
| 						if (link.object1Id.equals(media.id)) { |  | ||||||
| 							for (final UUIDConversion data: datas) { |  | ||||||
| 								if (data.id.equals(link.object2Id)) { |  | ||||||
| 									values.add(data.uuid); |  | ||||||
| 									break; |  | ||||||
| 								} |  | ||||||
| 							} |  | ||||||
| 							break; |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 					if (values.size() != 0) { |  | ||||||
| 						media.covers = values; |  | ||||||
| 						LOGGER.info("    update: {} => {}", media.id, media.covers); |  | ||||||
| 						DataAccess.update(media, media.id, List.of("covers"), new OverrideTableName(tableName)); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 			addAction("DROP TABLE `" + tableName + "_link_cover`;"); |  | ||||||
| 		} |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `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")); |  | ||||||
| 			for (final MediaConversion media: medias) { |  | ||||||
| 				for (final UUIDConversion data: datas) { |  | ||||||
| 					if (data.id.equals(media.dataId)) { |  | ||||||
| 						media.dataUUID = data.uuid; |  | ||||||
| 						DataAccess.update(media, media.id, List.of("dataUUID"), new OverrideTableName("track")); |  | ||||||
| 						break; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		addAction(""" |  | ||||||
| 				DROP TABLE `playlist`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				DROP TABLE `playlist_link_track`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `track` DROP `dataId`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `track` CHANGE `dataUUID` `dataId` binary(16) NOT NULL; |  | ||||||
| 				"""); |  | ||||||
| 		// Move the files... |  | ||||||
| 		addAction(() -> { |  | ||||||
| 			final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); |  | ||||||
| 			for (final UUIDConversion data: datas) { |  | ||||||
| 				final String origin = DataResource.getFileDataOld(data.id); |  | ||||||
| 				final String destination = DataResource.getFileData(data.uuid); |  | ||||||
| 				LOGGER.info("move file = {}", origin); |  | ||||||
| 				LOGGER.info("        ==> {}", destination); |  | ||||||
| 				Files.move(Paths.get(origin), Paths.get(destination), StandardCopyOption.ATOMIC_MOVE); |  | ||||||
| 			} |  | ||||||
| 		}); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `data` DROP `id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `data` CHANGE `uuid` `id` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE)); |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `data` ADD PRIMARY KEY `id` (`id`); |  | ||||||
| 				"""); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								back/src/org/kar/karusic/migration/Migration20240907.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								back/src/org/kar/karusic/migration/Migration20240907.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | package org.kar.karusic.migration; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.migration.MigrationSqlStep; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | public class Migration20240907 extends MigrationSqlStep { | ||||||
|  | 	private static final Logger LOGGER = LoggerFactory.getLogger(Migration20240907.class); | ||||||
|  |  | ||||||
|  | 	public static final int KARSO_INITIALISATION_ID = 1; | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public String getName() { | ||||||
|  | 		return "migration-2024-09-07: convert data id in uuid"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public Migration20240907() { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void generateStep() throws Exception { | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `data` DROP INDEX `PRIMARY`; | ||||||
|  | 				"""); | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `data` CHANGE `id` `uuid` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE)); | ||||||
|  | 				"""); | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `data` ADD PRIMARY KEY `uuid` (`uuid`); | ||||||
|  | 				"""); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										144
									
								
								back/src/org/kar/karusic/migration/Migration20250104.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								back/src/org/kar/karusic/migration/Migration20250104.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | |||||||
|  | package org.kar.karusic.migration; | ||||||
|  |  | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.NoSuchFileException; | ||||||
|  | import java.nio.file.Paths; | ||||||
|  | import java.nio.file.StandardCopyOption; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.UUID; | ||||||
|  |  | ||||||
|  | import org.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.karusic.migration.model.CoverConversion; | ||||||
|  | import org.kar.karusic.migration.model.MediaConversion; | ||||||
|  | import org.kar.karusic.migration.model.OIDConversion; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | public class Migration20250104 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-01-04: convert base from UUID to OID"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void generateStep() throws Exception { | ||||||
|  | 		// Create a simple function to create objectId in the DB (for manual insertion ...) | ||||||
|  | 		// addAction(""" | ||||||
|  | 		// DELIMITER // | ||||||
|  | 		// | ||||||
|  | 		// CREATE FUNCTION generate_objectid() | ||||||
|  | 		// RETURNS BINARY(12) | ||||||
|  | 		// DETERMINISTIC | ||||||
|  | 		// BEGIN | ||||||
|  | 		// DECLARE ts BINARY(4); | ||||||
|  | 		// DECLARE random_part BINARY(5); | ||||||
|  | 		// DECLARE counter BINARY(3); | ||||||
|  | 		// SET ts = UNHEX(HEX(UNIX_TIMESTAMP())); | ||||||
|  | 		// SET random_part = UNHEX(HEX(FLOOR(RAND() * POW(2, 40)))); | ||||||
|  | 		// SET counter = UNHEX(HEX(FLOOR(RAND() * POW(2, 24)))); | ||||||
|  | 		// RETURN CONCAT(ts, random_part, counter); | ||||||
|  | 		// END // | ||||||
|  | 		// | ||||||
|  | 		// DELIMITER ; | ||||||
|  | 		// """); | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `data` ADD `_id` binary(12) AFTER `uuid`; | ||||||
|  | 				"""); | ||||||
|  | 		addAction((final DBAccess da) -> { | ||||||
|  | 			final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); | ||||||
|  | 			for (final OIDConversion elem : datas) { | ||||||
|  | 				elem._id = new ObjectId(); | ||||||
|  | 			} | ||||||
|  | 			for (final OIDConversion elem : datas) { | ||||||
|  | 				da.update(elem, elem.uuid, List.of("_id"), new OverrideTableName("data")); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		final List<String> tableToTransform = List.of("album", "artist", "gender", "track", "user"); | ||||||
|  | 		for (final String tableName : tableToTransform) { | ||||||
|  | 			addAction("ALTER TABLE `" + tableName + "` ADD `covers_oid` text NULL;"); | ||||||
|  | 			addAction((final DBAccess da) -> { | ||||||
|  | 				final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); | ||||||
|  | 				final List<CoverConversion> tableCoverTransforms = da.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName)); | ||||||
|  | 				LOGGER.info("Get somes data: {} {}", datas.size(), tableCoverTransforms.size()); | ||||||
|  | 				for (final CoverConversion tableTransform : tableCoverTransforms) { | ||||||
|  | 					final List<ObjectId> values = new ArrayList<>(); | ||||||
|  | 					if (tableTransform.covers == null) { | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 					for (final UUID link : tableTransform.covers) { | ||||||
|  | 						for (final OIDConversion data : datas) { | ||||||
|  | 							if (data.uuid.equals(link)) { | ||||||
|  | 								values.add(data._id); | ||||||
|  | 								break; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					if (values.size() != 0) { | ||||||
|  | 						tableTransform.covers_oid = values; | ||||||
|  | 						LOGGER.info("    update: {}: {} => {}", tableTransform.id, tableTransform.covers, tableTransform.covers_oid); | ||||||
|  | 						da.update(tableTransform, tableTransform.id, List.of("covers_oid"), new OverrideTableName(tableName)); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 			addAction("ALTER TABLE `" + tableName + "` DROP `covers`;"); | ||||||
|  | 			addAction("ALTER TABLE `" + tableName + "` CHANGE `covers_oid` `covers` text NULL;"); | ||||||
|  | 		} | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `track` ADD `dataOid` binary(12) AFTER dataId; | ||||||
|  | 				"""); | ||||||
|  | 		addAction((final DBAccess da) -> { | ||||||
|  | 			final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); | ||||||
|  | 			final List<MediaConversion> medias = da.gets(MediaConversion.class, new AccessDeletedItems(), new OverrideTableName("track")); | ||||||
|  | 			for (final MediaConversion media : medias) { | ||||||
|  | 				for (final OIDConversion data : datas) { | ||||||
|  | 					if (data.uuid.equals(media.dataId)) { | ||||||
|  | 						media.dataOid = data._id; | ||||||
|  | 						da.update(media, media.id, List.of("dataOid"), new OverrideTableName("track")); | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `track` DROP `dataId`; | ||||||
|  | 				"""); | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `track` CHANGE `dataOid` `dataId` binary(12) NOT NULL; | ||||||
|  | 				"""); | ||||||
|  | 		// Move the files... | ||||||
|  | 		addAction((final DBAccess da) -> { | ||||||
|  | 			final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); | ||||||
|  | 			for (final OIDConversion data : datas) { | ||||||
|  | 				final String origin = DataResource.getFileDataOld(data.uuid); | ||||||
|  | 				final String destination = DataResource.getFileData(data._id); | ||||||
|  | 				LOGGER.info("move file = {}", origin); | ||||||
|  | 				LOGGER.info("        ==> {}", destination); | ||||||
|  | 				try { | ||||||
|  | 					Files.move(Paths.get(origin), Paths.get(destination), StandardCopyOption.ATOMIC_MOVE); | ||||||
|  | 				} catch (final NoSuchFileException ex) { | ||||||
|  | 					LOGGER.warn("Fail to move file : {}", ex.getMessage()); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `data` DROP `uuid`; | ||||||
|  | 				"""); | ||||||
|  | 		// addAction(""" | ||||||
|  | 		// ALTER TABLE `data` CHANGE `_id` `_id` BINARY(12) DEFAULT (generate_objectid()); | ||||||
|  | 		// """); | ||||||
|  | 		addAction(""" | ||||||
|  | 				ALTER TABLE `data` ADD PRIMARY KEY `_id` (`_id`); | ||||||
|  | 				"""); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -3,6 +3,7 @@ package org.kar.karusic.migration.model; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.kar.archidata.annotation.DataJson; | import org.kar.archidata.annotation.DataJson; | ||||||
|  |  | ||||||
| import jakarta.persistence.Id; | import jakarta.persistence.Id; | ||||||
| @@ -12,4 +13,6 @@ public class CoverConversion { | |||||||
| 	public Long id = null; | 	public Long id = null; | ||||||
| 	@DataJson | 	@DataJson | ||||||
| 	public List<UUID> covers = null; | 	public List<UUID> covers = null; | ||||||
|  | 	@DataJson | ||||||
|  | 	public List<ObjectId> covers_oid = null; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,11 +2,13 @@ package org.kar.karusic.migration.model; | |||||||
|  |  | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  |  | ||||||
| import jakarta.persistence.Id; | import jakarta.persistence.Id; | ||||||
|  |  | ||||||
| public class MediaConversion { | public class MediaConversion { | ||||||
| 	@Id | 	@Id | ||||||
| 	public Long id = null; | 	public Long id = null; | ||||||
| 	public Long dataId = null; | 	public UUID dataId = null; | ||||||
| 	public UUID dataUUID = null; | 	public ObjectId dataOid = null; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,10 +2,12 @@ package org.kar.karusic.migration.model; | |||||||
| 
 | 
 | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
| 
 | 
 | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | 
 | ||||||
| import jakarta.persistence.Id; | import jakarta.persistence.Id; | ||||||
| 
 | 
 | ||||||
| public class UUIDConversion { | public class OIDConversion { | ||||||
| 	@Id | 	@Id | ||||||
| 	public Long id = null; |  | ||||||
| 	public UUID uuid = null; | 	public UUID uuid = null; | ||||||
|  | 	public ObjectId _id = null; | ||||||
| } | } | ||||||
| @@ -1,16 +1,41 @@ | |||||||
| package org.kar.karusic.model; | package org.kar.karusic.model; | ||||||
|  |  | ||||||
| import java.time.LocalDate; | import java.time.LocalDate; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; | import org.kar.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.kar.archidata.annotation.DataJson; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckJPA; | ||||||
|  | import org.kar.archidata.model.Data; | ||||||
|  | import org.kar.archidata.model.GenericDataSoftDelete; | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import dev.morphia.annotations.Entity; | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  |  | ||||||
|  | @Entity("Album") | ||||||
| @Table(name = "album") | @Table(name = "album") | ||||||
| @DataIfNotExists | @DataIfNotExists | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
| public class Album extends NodeSmall { | public class Album extends GenericDataSoftDelete { | ||||||
|  | 	public static class AlbumChecker extends CheckJPA<Album> { | ||||||
|  | 		public AlbumChecker() { | ||||||
|  | 			super(Album.class); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Column(length = 256) | ||||||
|  | 	public String name = null; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	public String description = null; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson(targetEntity = Data.class) | ||||||
|  | 	@Nullable | ||||||
|  | 	public List<ObjectId> covers = null; | ||||||
| 	public LocalDate publication = null; | 	public LocalDate publication = null; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,18 +1,42 @@ | |||||||
| package org.kar.karusic.model; | package org.kar.karusic.model; | ||||||
|  |  | ||||||
| import java.time.LocalDate; | import java.time.LocalDate; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; | import org.kar.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.kar.archidata.annotation.DataJson; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckJPA; | ||||||
|  | import org.kar.archidata.model.Data; | ||||||
|  | import org.kar.archidata.model.GenericDataSoftDelete; | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import dev.morphia.annotations.Entity; | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  |  | ||||||
|  | @Entity("Artist") | ||||||
| @Table(name = "artist") | @Table(name = "artist") | ||||||
| @DataIfNotExists | @DataIfNotExists | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
| public class Artist extends NodeSmall { | public class Artist extends GenericDataSoftDelete { | ||||||
|  | 	public static class ArtistChecker extends CheckJPA<Artist> { | ||||||
|  | 		public ArtistChecker() { | ||||||
|  | 			super(Artist.class); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Column(length = 256) | ||||||
|  | 	public String name = null; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	public String description = null; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson(targetEntity = Data.class) | ||||||
|  | 	@Nullable | ||||||
|  | 	public List<ObjectId> covers = null; | ||||||
| 	@Column(length = 256) | 	@Column(length = 256) | ||||||
| 	public String firstName = null; | 	public String firstName = null; | ||||||
| 	@Column(length = 256) | 	@Column(length = 256) | ||||||
|   | |||||||
| @@ -12,15 +12,48 @@ CREATE TABLE `node` ( | |||||||
| ) AUTO_INCREMENT=10; | ) AUTO_INCREMENT=10; | ||||||
| */ | */ | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; | import org.kar.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.kar.archidata.annotation.DataJson; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckJPA; | ||||||
|  | import org.kar.archidata.model.Data; | ||||||
|  | import org.kar.archidata.model.GenericDataSoftDelete; | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import dev.morphia.annotations.Entity; | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  |  | ||||||
|  | @Entity("Gender") | ||||||
| @Table(name = "gender") | @Table(name = "gender") | ||||||
| @DataIfNotExists | @DataIfNotExists | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
| public class Gender extends NodeSmall { | public class Gender extends GenericDataSoftDelete { | ||||||
|  | 	public static class GenderChecker extends CheckJPA<Gender> { | ||||||
|  | 		public GenderChecker() { | ||||||
|  | 			super(Gender.class); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Column(length = 256) | ||||||
|  | 	public String name = null; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	public String description = null; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson(targetEntity = Data.class) | ||||||
|  | 	@Nullable | ||||||
|  | 	public List<ObjectId> covers = null; | ||||||
|  |  | ||||||
|  | 	public Gender() {} | ||||||
|  |  | ||||||
|  | 	public Gender(final Long id, final String name) { | ||||||
|  | 		this.id = id; | ||||||
|  | 		this.name = name; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,36 +0,0 @@ | |||||||
| package org.kar.karusic.model; |  | ||||||
| /* |  | ||||||
| CREATE TABLE `node` ( |  | ||||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, |  | ||||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, |  | ||||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', |  | ||||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', |  | ||||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', |  | ||||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, |  | ||||||
|   `description` TEXT COLLATE 'utf8_general_ci', |  | ||||||
|   `parent_id` bigint |  | ||||||
| ) AUTO_INCREMENT=10; |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataJson; |  | ||||||
| import org.kar.archidata.model.Data; |  | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.persistence.Column; |  | ||||||
|  |  | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) |  | ||||||
| public class NodeSmall extends GenericDataSoftDelete { |  | ||||||
| 	@Column(length = 256) |  | ||||||
| 	public String name = null; |  | ||||||
| 	@Column(length = 0) |  | ||||||
| 	public String description = null; |  | ||||||
| 	@Schema(description = "List of Id of the specific covers") |  | ||||||
| 	@DataJson(targetEntity = Data.class) |  | ||||||
| 	public List<UUID> covers = null; |  | ||||||
| } |  | ||||||
| @@ -14,18 +14,42 @@ CREATE TABLE `node` ( | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; | import org.kar.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.kar.archidata.annotation.DataJson; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckJPA; | ||||||
|  | import org.kar.archidata.model.Data; | ||||||
|  | import org.kar.archidata.model.GenericDataSoftDelete; | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import dev.morphia.annotations.Entity; | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.FetchType; | import jakarta.persistence.FetchType; | ||||||
| import jakarta.persistence.ManyToMany; | import jakarta.persistence.ManyToMany; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  |  | ||||||
|  | @Entity("Playlist") | ||||||
| @Table(name = "playlist") | @Table(name = "playlist") | ||||||
| @DataIfNotExists | @DataIfNotExists | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
| public class Playlist extends NodeSmall { | public class Playlist extends GenericDataSoftDelete { | ||||||
|  | 	public static class PlaylistChecker extends CheckJPA<Playlist> { | ||||||
|  | 		public PlaylistChecker() { | ||||||
|  | 			super(Playlist.class); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Column(length = 256) | ||||||
|  | 	public String name = null; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	public String description = null; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson(targetEntity = Data.class) | ||||||
|  | 	@Nullable | ||||||
|  | 	public List<ObjectId> covers = null; | ||||||
| 	@ManyToMany(fetch = FetchType.LAZY, targetEntity = Track.class) | 	@ManyToMany(fetch = FetchType.LAZY, targetEntity = Track.class) | ||||||
| 	public List<Long> tracks = null; | 	public List<ObjectId> tracks = null; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,25 +13,47 @@ CREATE TABLE `node` ( | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; | import org.kar.archidata.annotation.DataIfNotExists; | ||||||
| import org.kar.archidata.annotation.DataJson; | import org.kar.archidata.annotation.DataJson; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckJPA; | ||||||
|  | import org.kar.archidata.model.Data; | ||||||
|  | import org.kar.archidata.model.GenericDataSoftDelete; | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import dev.morphia.annotations.Entity; | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  |  | ||||||
|  | @Entity("Track") | ||||||
| @Table(name = "track") | @Table(name = "track") | ||||||
| @DataIfNotExists | @DataIfNotExists | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
| public class Track extends NodeSmall { | public class Track extends GenericDataSoftDelete { | ||||||
|  |  | ||||||
|  | 	public static class TrackChecker extends CheckJPA<Track> { | ||||||
|  | 		public TrackChecker() { | ||||||
|  | 			super(Track.class); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Column(length = 256) | ||||||
|  | 	public String name = null; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	public String description = null; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson(targetEntity = Data.class) | ||||||
|  | 	@Nullable | ||||||
|  | 	public List<ObjectId> covers = null; | ||||||
| 	public Long genderId = null; | 	public Long genderId = null; | ||||||
| 	public Long albumId = null; | 	public Long albumId = null; | ||||||
| 	public Long track = null; | 	public Long track = null; | ||||||
| 	public UUID dataId = null; | 	public ObjectId dataId = null; | ||||||
| 	//@ManyToMany(fetch = FetchType.LAZY, targetEntity = Artist.class) | 	// @ManyToMany(fetch = FetchType.LAZY, targetEntity = Artist.class) | ||||||
| 	@DataJson | 	@DataJson | ||||||
| 	@Column(length = 0) | 	@Column(length = 0) | ||||||
| 	public List<Long> artists = null; | 	public List<Long> artists = null; | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ package org.kar.karusic.util; | |||||||
| public class ConfigVariable { | public class ConfigVariable { | ||||||
| 	public static final String BASE_NAME = "ORG_KARUSIC_"; | 	public static final String BASE_NAME = "ORG_KARUSIC_"; | ||||||
|  |  | ||||||
|      |  | ||||||
| 	public static String getFrontFolder() { | 	public static String getFrontFolder() { | ||||||
| 		String out = System.getenv(BASE_NAME + "FRONT_FOLDER"); | 		String out = System.getenv(BASE_NAME + "FRONT_FOLDER"); | ||||||
| 		if (out == null) { | 		if (out == null) { | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								back/src/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								back/src/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | <configuration> | ||||||
|  |     <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> | ||||||
|  |         <encoder> | ||||||
|  |             <pattern> | ||||||
|  |                 %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %logger - %msg%n | ||||||
|  |             </pattern> | ||||||
|  |             <!-- | ||||||
|  |             <pattern> | ||||||
|  |                 %d{HH:mm:ss.SSS} | %thread | %highlight(%-5level) | %logger - %msg%n | ||||||
|  |             </pattern> | ||||||
|  |             --> | ||||||
|  |         </encoder> | ||||||
|  |     </appender> | ||||||
|  |  | ||||||
|  |     <root level="info"> | ||||||
|  |         <appender-ref ref="CONSOLE" /> | ||||||
|  |     </root> | ||||||
|  | </configuration> | ||||||
| @@ -3,12 +3,14 @@ | |||||||
| # Default logging detail level for all instances of SimpleLogger. | # Default logging detail level for all instances of SimpleLogger. | ||||||
| # Must be one of ("trace", "debug", "info", "warn", or "error"). | # Must be one of ("trace", "debug", "info", "warn", or "error"). | ||||||
| # If not specified, defaults to "info". | # If not specified, defaults to "info". | ||||||
| org.slf4j.simpleLogger.defaultLogLevel=trace | org.slf4j.simpleLogger.defaultLogLevel=INFO | ||||||
|  |  | ||||||
| # Logging detail level for a SimpleLogger instance named "xxxxx". | # Logging detail level for a SimpleLogger instance named "xxxxx". | ||||||
| # Must be one of ("trace", "debug", "info", "warn", or "error"). | # Must be one of ("trace", "debug", "info", "warn", or "error"). | ||||||
| # If not specified, the default logging detail level is used. | # If not specified, the default logging detail level is used. | ||||||
| #org.slf4j.simpleLogger.log.xxxxx= | #org.slf4j.simpleLogger.log.xxxxx= | ||||||
|  | org.slf4j.simpleLogger.log.org.kar.archidata=TRACE | ||||||
|  | org.slf4j.simpleLogger.log.org.kar.karusic=TRACE | ||||||
|  |  | ||||||
| # Set to true if you want the current date and time to be included in output messages. | # Set to true if you want the current date and time to be included in output messages. | ||||||
| # Default is false, and will output the number of milliseconds elapsed since startup. | # Default is false, and will output the number of milliseconds elapsed since startup. | ||||||
| @@ -32,4 +34,9 @@ org.slf4j.simpleLogger.showThreadName=true | |||||||
| # Defaults to false. | # Defaults to false. | ||||||
| #org.slf4j.simpleLogger.showShortLogName=false | #org.slf4j.simpleLogger.showShortLogName=false | ||||||
|  |  | ||||||
|  | # Utilise les codes ANSI pour la couleur | ||||||
|  | org.slf4j.simpleLogger.warnColor=\u001B[33m | ||||||
|  | org.slf4j.simpleLogger.errorColor=\u001B[31m | ||||||
|  | org.slf4j.simpleLogger.infoColor=\u001B[32m | ||||||
|  | org.slf4j.simpleLogger.debugColor=\u001B[34m | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								back/test/src/test/kar/karusic/Common.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								back/test/src/test/kar/karusic/Common.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | package test.kar.karusic; | ||||||
|  |  | ||||||
|  | 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))); | ||||||
|  | } | ||||||
							
								
								
									
										126
									
								
								back/test/src/test/kar/karusic/ConfigureDb.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								back/test/src/test/kar/karusic/ConfigureDb.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | package test.kar.karusic; | ||||||
|  |  | ||||||
|  | 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.karusic.model.Album; | ||||||
|  | import org.kar.karusic.model.Artist; | ||||||
|  | import org.kar.karusic.model.Gender; | ||||||
|  | import org.kar.karusic.model.Playlist; | ||||||
|  | import org.kar.karusic.model.Track; | ||||||
|  | import org.kar.karusic.model.UserKarusic; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.InternalServerErrorException; | ||||||
|  |  | ||||||
|  | public class ConfigureDb { | ||||||
|  | 	final static private Logger LOGGER = LoggerFactory.getLogger(ConfigureDb.class); | ||||||
|  | 	final static private String modeTestForced = null;// "MONGO"; | ||||||
|  | 	public static DBAccess da = null; | ||||||
|  |  | ||||||
|  | 	public static void configure() throws IOException, InternalServerErrorException, DataAccessException { | ||||||
|  | 		String modeTest = System.getenv("TEST_E2E_MODE"); | ||||||
|  | 		if (modeTest == null || modeTest.isEmpty() || "false".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			modeTest = "SQLITE-MEMORY"; | ||||||
|  | 		} else if ("true".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			modeTest = "MY-SQL"; | ||||||
|  | 		} | ||||||
|  | 		// override the local test: | ||||||
|  | 		if (modeTestForced != null) { | ||||||
|  | 			modeTest = modeTestForced; | ||||||
|  | 		} | ||||||
|  | 		final List<Class<?>> listObject = List.of( // | ||||||
|  | 				Album.class, // | ||||||
|  | 				Artist.class, // | ||||||
|  | 				Gender.class, // | ||||||
|  | 				Playlist.class, // | ||||||
|  | 				Track.class, // | ||||||
|  | 				UserKarusic.class // | ||||||
|  | 		); | ||||||
|  | 		if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			ConfigBaseVariable.dbType = "sqlite"; | ||||||
|  | 			ConfigBaseVariable.bdDatabase = null; | ||||||
|  | 			ConfigBaseVariable.dbHost = "memory"; | ||||||
|  | 			// for test we need to connect all time the DB | ||||||
|  | 			ConfigBaseVariable.dbKeepConnected = "true"; | ||||||
|  | 		} else if ("SQLITE".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			ConfigBaseVariable.dbType = "sqlite"; | ||||||
|  | 			ConfigBaseVariable.bdDatabase = null; | ||||||
|  | 			ConfigBaseVariable.dbKeepConnected = "true"; | ||||||
|  | 		} else if ("MY-SQL".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			ConfigBaseVariable.dbType = "mysql"; | ||||||
|  | 			ConfigBaseVariable.bdDatabase = "test_karusic_db"; | ||||||
|  | 			ConfigBaseVariable.dbPort = "3906"; | ||||||
|  | 			ConfigBaseVariable.dbUser = "root"; | ||||||
|  | 		} else if ("MONGO".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			ConfigBaseVariable.dbType = "mongo"; | ||||||
|  | 			ConfigBaseVariable.bdDatabase = "test_karusic_db"; | ||||||
|  | 		} else { | ||||||
|  | 			// User local modification ... | ||||||
|  | 			ConfigBaseVariable.bdDatabase = "test_karusic_db"; | ||||||
|  | 			ConfigBaseVariable.dbPort = "3906"; | ||||||
|  | 			ConfigBaseVariable.dbUser = "root"; | ||||||
|  | 		} | ||||||
|  | 		removeDB(); | ||||||
|  | 		// Connect the dataBase... | ||||||
|  | 		da = DBAccess.createInterface(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void removeDB() { | ||||||
|  | 		String modeTest = System.getenv("TEST_E2E_MODE"); | ||||||
|  | 		if (modeTest == null || modeTest.isEmpty() || "false".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			modeTest = "SQLITE-MEMORY"; | ||||||
|  | 		} else if ("true".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			modeTest = "MY-SQL"; | ||||||
|  | 		} | ||||||
|  | 		// override the local test: | ||||||
|  | 		if (modeTestForced != null) { | ||||||
|  | 			modeTest = modeTestForced; | ||||||
|  | 		} | ||||||
|  | 		DbConfig config = null; | ||||||
|  | 		try { | ||||||
|  | 			config = new DbConfig(); | ||||||
|  | 		} catch (final DataAccessException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 			LOGGER.error("Fail to clean the DB"); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		config.setDbName(null); | ||||||
|  | 		LOGGER.info("Remove the DB and create a new one '{}'", config.getDbName()); | ||||||
|  | 		try (final DBAccess daRoot = DBAccess.createInterface(config)) { | ||||||
|  | 			if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) { | ||||||
|  | 				// nothing to do ... | ||||||
|  | 			} else if ("SQLITE".equalsIgnoreCase(modeTest)) { | ||||||
|  | 				daRoot.deleteDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 			} else if ("MY-SQL".equalsIgnoreCase(modeTest)) { | ||||||
|  | 				daRoot.deleteDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 			} else if ("MONGO".equalsIgnoreCase(modeTest)) { | ||||||
|  | 				daRoot.deleteDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 			} | ||||||
|  | 			daRoot.createDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 		} catch (final InternalServerErrorException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 			LOGGER.error("Fail to clean the DB"); | ||||||
|  | 			return; | ||||||
|  | 		} catch (final IOException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 			LOGGER.error("Fail to clean the DB"); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void clear() throws IOException { | ||||||
|  | 		LOGGER.info("Remove the test db"); | ||||||
|  | 		removeDB(); | ||||||
|  | 		// The connection is by default open ==> close it at the end of test: | ||||||
|  | 		da.close(); | ||||||
|  | 		DbIoFactory.closeAllForceMode(); | ||||||
|  | 		ConfigBaseVariable.clearAllValue(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -1,249 +1,49 @@ | |||||||
| package test.kar.karusic; | package test.kar.karusic; | ||||||
|  |  | ||||||
| import java.util.Map; |  | ||||||
|  |  | ||||||
| import org.junit.jupiter.api.AfterAll; | import org.junit.jupiter.api.AfterAll; | ||||||
| import org.junit.jupiter.api.Assertions; |  | ||||||
| import org.junit.jupiter.api.BeforeAll; | import org.junit.jupiter.api.BeforeAll; | ||||||
| import org.junit.jupiter.api.MethodOrderer; | import org.junit.jupiter.api.MethodOrderer; | ||||||
| import org.junit.jupiter.api.Order; |  | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.exception.RESTErrorResponseExeption; |  | ||||||
| import org.kar.archidata.model.GetToken; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
| import org.kar.archidata.tools.JWTWrapper; |  | ||||||
| import org.kar.archidata.tools.RESTApi; | import org.kar.archidata.tools.RESTApi; | ||||||
| import org.kar.karusic.api.HealthCheck.HealthResult; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| import com.nimbusds.jwt.JWTClaimsSet; |  | ||||||
|  |  | ||||||
| @ExtendWith(StepwiseExtension.class) | @ExtendWith(StepwiseExtension.class) | ||||||
| @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||||||
| public class TestBase { | public class TestBase { | ||||||
| 	private final static Logger LOGGER = LoggerFactory.getLogger(TestBase.class); | 	private final static Logger LOGGER = LoggerFactory.getLogger(TestBase.class); | ||||||
|  | 	public final static String ENDPOINT_NAME = "species/"; | ||||||
|  |  | ||||||
| 	static WebLauncherTest webInterface = null; | 	static WebLauncherTest webInterface = null; | ||||||
| 	static RESTApi api = null; | 	static RESTApi api = null; | ||||||
|  |  | ||||||
| 	public void login(final String login, final String password) { |  | ||||||
| 		try { |  | ||||||
| 			final GetToken token = api.post(GetToken.class, "users/get_token", DataGetToken.generate(login, "v1", "202515252", password)); |  | ||||||
| 			api.setToken(token.jwt()); |  | ||||||
| 		} catch (final Exception ex) { |  | ||||||
| 			Assertions.fail("Can not get Authentication for '" + login + "' ==> " + ex.getMessage()); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public void loginAdmin() { |  | ||||||
| 		login("karadmin", "adminA@666"); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
|  | 		ConfigureDb.configure(); | ||||||
| 		LOGGER.info("configure server ..."); | 		LOGGER.info("configure server ..."); | ||||||
| 		webInterface = new WebLauncherTest(); | 		webInterface = new WebLauncherTest(); | ||||||
| 		LOGGER.info("Create DB"); | 		LOGGER.info("Clean previous table"); | ||||||
| 		try { |  | ||||||
| 			webInterface.migrateDB(); |  | ||||||
| 		} catch (final Exception ex) { |  | ||||||
| 			ex.printStackTrace(); |  | ||||||
| 			LOGGER.error("Detect an error: {}", ex.getMessage()); |  | ||||||
| 		} |  | ||||||
| 		LOGGER.info("Start REST (BEGIN)"); | 		LOGGER.info("Start REST (BEGIN)"); | ||||||
| 		webInterface.process(); | 		webInterface.process(); | ||||||
| 		LOGGER.info("Start REST (DONE)"); | 		LOGGER.info("Start REST (DONE)"); | ||||||
| 		api = new RESTApi(ConfigBaseVariable.apiAdress); | 		api = new RESTApi(ConfigBaseVariable.apiAdress); | ||||||
|  | 		api.setToken(Common.ADMIN_TOKEN); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void stopWebServer() throws InterruptedException { | 	public static void stopWebServer() throws Exception { | ||||||
| 		LOGGER.info("Kill the web server"); | 		LOGGER.info("Kill the web server"); | ||||||
|  | 		webInterface.stop(); | ||||||
| 		webInterface = null; | 		webInterface = null; | ||||||
| 		// TODO: do it better... | 		ConfigureDb.clear(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) |  | ||||||
| 	@Test | 	@Test | ||||||
| 	//@RepeatedTest(10) | 	public static void TestEmpty() throws Exception { | ||||||
| 	public void checkHealthCheck() throws Exception { |  | ||||||
| 		final HealthResult result = api.get(HealthResult.class, "health_check"); |  | ||||||
| 		Assertions.assertEquals(result.value(), "alive and kicking"); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@Order(2) |  | ||||||
| 	@Test |  | ||||||
| 	public void checkHealthCheckWrongAPI() throws Exception { |  | ||||||
| 		Assertions.assertThrows(RESTErrorResponseExeption.class, () -> api.get(HealthResult.class, "health_checks")); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@Order(3) |  | ||||||
| 	@Test |  | ||||||
| 	public void firstUserConnect() throws Exception { |  | ||||||
| 		final GetToken result = api.post(GetToken.class, "users/get_token", DataGetToken.generate("karadmin", "v1", "202515252", "adminA@666")); |  | ||||||
| 		final String[] splitted = result.jwt().split("\\."); |  | ||||||
| 		Assertions.assertEquals(3, splitted.length); |  | ||||||
| 		final String authorization = result.jwt(); |  | ||||||
| 		LOGGER.debug(" validate token : " + authorization); |  | ||||||
| 		// Note with local access we get the internal key of the system. |  | ||||||
| 		final JWTClaimsSet ret = JWTWrapper.validateToken(authorization, "KarAuth", null); |  | ||||||
| 		// check the token is valid !!! (signed and coherent issuer... |  | ||||||
| 		Assertions.assertNotNull(ret); |  | ||||||
| 		// check userID |  | ||||||
| 		final String userUID = ret.getSubject(); |  | ||||||
| 		final long id = Long.parseLong(userUID); |  | ||||||
| 		Assertions.assertEquals(1, id); |  | ||||||
| 		final String name = (String) ret.getClaim("login"); |  | ||||||
| 		Assertions.assertEquals("karadmin", name); |  | ||||||
| 		 |  | ||||||
| 		final Object rowRight = ret.getClaim("right"); |  | ||||||
| 		Assertions.assertNotNull(rowRight); |  | ||||||
| 		final Map<String, Map<String, Object>> rights = (Map<String, Map<String, Object>>) ret.getClaim("right"); |  | ||||||
| 		// Check if the element contain the basic keys: |  | ||||||
| 		Assertions.assertEquals(rights.size(), 1); |  | ||||||
| 		Assertions.assertTrue(rights.containsKey("karusic")); |  | ||||||
| 		final Map<String, Object> applRight = rights.get("karusic"); |  | ||||||
| 		//logger.error("full right: {}", applRight); |  | ||||||
| 		Assertions.assertEquals(applRight.size(), 2); |  | ||||||
| 		Assertions.assertTrue(applRight.containsKey("ADMIN")); |  | ||||||
| 		Assertions.assertEquals(true, applRight.get("ADMIN")); |  | ||||||
| 		Assertions.assertTrue(applRight.containsKey("USER")); |  | ||||||
| 		Assertions.assertEquals(true, applRight.get("USER")); |  | ||||||
| 		 |  | ||||||
| 		//logger.debug("request user: '{}' right: '{}' row='{}'", userUID, applRight, rowRight); |  | ||||||
| 		 |  | ||||||
| 		//Assertions.assertEquals("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9", splitted[0]); |  | ||||||
| 		//Assertions.assertEquals("eyJzdWIiOiIwIiwiYXBwbGljYXRpb24iOiJrYXJzbyIsImlzcyI6IkthckF1dGgiLCJyaWdodCI6eyJrYXJzbyI6eyJBRE1JTiI6dHJ1ZSwiVVNFUiI6dHJ1ZX19LCJsb2dpbiI6ImthcmFkbWluIiwiZXhwIjoxNjg0MTk5MTkzLCJpYXQiOjE2ODI3NTU0MjV9", splitted[1]); |  | ||||||
| 		// TODO ... Assertions.assertEquals("????", splitted[2]); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public void checkFail(final String type, final String urlOffset, final int errorStatus) { |  | ||||||
| 		checkFail(type, urlOffset, errorStatus, null); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public void checkFail(final String type, final String urlOffset, final int errorStatus, final String data) { |  | ||||||
| 		LOGGER.info("Test API: url={} urlOffset={}", type, urlOffset); |  | ||||||
| 		try { |  | ||||||
| 			if ("GET".equals(type)) { |  | ||||||
| 				api.get(String.class, urlOffset); |  | ||||||
| 			} else if ("POST".equals(type)) { |  | ||||||
| 				api.post(String.class, urlOffset, data); |  | ||||||
| 			} else if ("PUT".equals(type)) { |  | ||||||
| 				api.put(String.class, urlOffset, data); |  | ||||||
| 			} else if ("DELETE".equals(type)) { |  | ||||||
| 				api.delete(String.class, urlOffset); |  | ||||||
| 			} |  | ||||||
| 			Assertions.fail("Request on URL does not fail as expected: '" + type + "' url='" + urlOffset + "'"); |  | ||||||
| 		} catch (final RESTErrorResponseExeption ex) { |  | ||||||
| 			if (errorStatus != ex.status) { |  | ||||||
| 				LOGGER.error("Fail in test with the wrong return errors: {}", ex.toString()); |  | ||||||
| 			} |  | ||||||
| 			Assertions.assertEquals(errorStatus, ex.status); |  | ||||||
| 		} catch (final Exception ex) { |  | ||||||
| 			LOGGER.error("Unexpected throw error: {}", ex); |  | ||||||
| 			Assertions.fail("Unexpected throws..."); |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public void checkWork(final String type, final String urlOffset) { |  | ||||||
| 		checkWork(type, urlOffset, null); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public void checkWork(final String type, final String urlOffset, final String data) { |  | ||||||
| 		LOGGER.info("Test API: url={} urlOffset={}", type, urlOffset); |  | ||||||
| 		try { |  | ||||||
| 			if ("GET".equals(type)) { |  | ||||||
| 				api.get(String.class, urlOffset); |  | ||||||
| 			} else if ("POST".equals(type)) { |  | ||||||
| 				api.post(String.class, urlOffset, data); |  | ||||||
| 			} else if ("PUT".equals(type)) { |  | ||||||
| 				api.put(String.class, urlOffset, data); |  | ||||||
| 			} else if ("DELETE".equals(type)) { |  | ||||||
| 				api.delete(String.class, urlOffset); |  | ||||||
| 			} |  | ||||||
| 			//Assertions.fail("Request on URL does not fail as expected: '" + type + "' url='" + urlOffset + "'"); |  | ||||||
| 		} catch (final RESTErrorResponseExeption ex) { |  | ||||||
| 			Assertions.fail("Must not fail ... " + ex.toString()); |  | ||||||
| 		} catch (final Exception ex) { |  | ||||||
| 			LOGGER.error("Unexpected throw error: {}", ex); |  | ||||||
| 			Assertions.fail("Unexpected throws..."); |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@Order(4) |  | ||||||
| 	@Test |  | ||||||
| 	public void checkUnAuthorizedAPI() throws Exception { |  | ||||||
| 		// /application/ |  | ||||||
| 		checkFail("GET", "application/", 401); |  | ||||||
| 		checkFail("POST", "application/", 401, "{}"); |  | ||||||
| 		checkFail("PUT", "application/", 405, "{}"); // does not exist |  | ||||||
| 		checkFail("DELETE", "application/", 405); // does not exist |  | ||||||
| 		// /application/{id} |  | ||||||
| 		checkFail("GET", "application/0", 401); |  | ||||||
| 		checkFail("PUT", "application/0", 401, "{}"); |  | ||||||
| 		checkFail("POST", "application/0", 405, "{}"); |  | ||||||
| 		checkFail("DELETE", "application/0", 401); |  | ||||||
| 		// /application/{id}/* |  | ||||||
| 		checkFail("GET", "application/0/users", 401); |  | ||||||
| 		// /application/* |  | ||||||
| 		checkFail("GET", "application/small", 401); |  | ||||||
| 		checkFail("GET", "application/get_token", 401); |  | ||||||
| 		checkFail("GET", "application/return", 401); |  | ||||||
| 		 |  | ||||||
| 		// /application_token/ section: |  | ||||||
| 		checkFail("GET", "application_token/0", 401); |  | ||||||
| 		checkFail("DELETE", "application_token/0/5", 401); |  | ||||||
| 		checkFail("DELETE", "application_token/0/create", 401); |  | ||||||
| 		 |  | ||||||
| 		// /front/* |  | ||||||
| 		checkFail("GET", "front", 404); // no index in test section |  | ||||||
| 		// health check |  | ||||||
| 		checkWork("GET", "health_check"); |  | ||||||
| 		 |  | ||||||
| 		// public_key (only application) |  | ||||||
| 		checkFail("GET", "public_key", 401); |  | ||||||
| 		checkFail("GET", "public_key/pem", 401); |  | ||||||
| 		 |  | ||||||
| 		// /right |  | ||||||
| 		checkFail("GET", "right", 401); |  | ||||||
| 		checkFail("POST", "right", 401, "{}"); |  | ||||||
| 		checkFail("GET", "right/0", 401); |  | ||||||
| 		checkFail("PUT", "right/0", 401, "{}"); |  | ||||||
| 		checkFail("DELETE", "right/0", 401); |  | ||||||
| 		 |  | ||||||
| 		// /system_config |  | ||||||
| 		checkWork("GET", "system_config/is_sign_up_availlable"); |  | ||||||
| 		checkFail("GET", "system_config/key/skjdfhkjsdhfkjsh", 401); |  | ||||||
| 		checkFail("PUT", "system_config/key/skjdfhkjsdhfkjsh", 401, "{}"); |  | ||||||
| 		 |  | ||||||
| 		// /users |  | ||||||
| 		checkFail("GET", "users", 401); |  | ||||||
| 		checkFail("GET", "users/0", 401); |  | ||||||
| 		checkFail("POST", "users/0/application/0/link", 401, "{}"); |  | ||||||
| 		checkFail("POST", "users/0/set_admin", 401, "{}"); |  | ||||||
| 		checkFail("POST", "users/0/set_blocked", 401, "{}"); |  | ||||||
| 		checkFail("POST", "users/create_new_user", 401, "{}"); |  | ||||||
| 		checkFail("GET", "users/me", 401, "{}"); |  | ||||||
| 		checkFail("POST", "users/password", 401, "{}"); |  | ||||||
| 		checkWork("GET", "users/check_login?login=karadmin"); |  | ||||||
| 		checkFail("GET", "users/check_login?login=jhkjhkjh", 404); |  | ||||||
| 		checkWork("GET", "users/check_email?email=admin@admin.ZZZ"); |  | ||||||
| 		checkFail("GET", "users/check_email?email=ksjhdkjfhskjdh", 404); |  | ||||||
| 		// not testable : get_token |  | ||||||
| 		 |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@Order(5) |  | ||||||
| 	@Test |  | ||||||
| 	public void testMeWithToken() throws Exception { |  | ||||||
| 		loginAdmin(); |  | ||||||
| 		final String result = api.get(String.class, "users/me"); |  | ||||||
| 		Assertions.assertEquals("{\"id\":1,\"login\":\"karadmin\"}", result); |  | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,6 @@ | |||||||
|  |  | ||||||
| package test.kar.karusic; | package test.kar.karusic; | ||||||
|  |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.kar.karusic.WebLauncher; | import org.kar.karusic.WebLauncher; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| @@ -9,20 +8,5 @@ import org.slf4j.LoggerFactory; | |||||||
| public class WebLauncherTest extends WebLauncher { | public class WebLauncherTest extends WebLauncher { | ||||||
| 	final private static Logger LOGGER = LoggerFactory.getLogger(WebLauncherTest.class); | 	final private static Logger LOGGER = LoggerFactory.getLogger(WebLauncherTest.class); | ||||||
|  |  | ||||||
| 	public WebLauncherTest() { | 	public WebLauncherTest() {} | ||||||
| 		LOGGER.debug("Configure REST system"); |  | ||||||
| 		// for local test: |  | ||||||
| 		ConfigBaseVariable.apiAdress = "http://127.0.0.1:12345/test/api/"; |  | ||||||
|  |  | ||||||
| 		ConfigBaseVariable.dbPort = "3306"; |  | ||||||
| 		// for the test we a in memory sqlite.. |  | ||||||
| 		ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 		ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 		// for test we need to connect all time the DB |  | ||||||
| 		ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		 |  | ||||||
| 		ConfigBaseVariable.dbHost = "localhost"; |  | ||||||
| 		ConfigBaseVariable.dbUser = "root"; |  | ||||||
| 		ConfigBaseVariable.dbPassword = "ZERTYSDGFVHSDFGHJYZSDFGSQxfgsqdfgsqdrf4564654"; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										56
									
								
								env_dev/docker-compose.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								env_dev/docker-compose.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | services: | ||||||
|  |   kar_db_service: | ||||||
|  |     image: mysql:latest | ||||||
|  |     restart: always | ||||||
|  |     environment: | ||||||
|  |       - MYSQL_ROOT_PASSWORD=base_db_password | ||||||
|  |     volumes: | ||||||
|  |       - ./data:/var/lib/mysql | ||||||
|  |     mem_limit: 300m | ||||||
|  |     ports: | ||||||
|  |       - 3906:3306 | ||||||
|  |     healthcheck: | ||||||
|  |       test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"] | ||||||
|  |       timeout: 10s | ||||||
|  |       retries: 5 | ||||||
|  |       # perform a 1 minute grace to let the DB to perform the initialization | ||||||
|  |       start_period: 1m | ||||||
|  |       start_interval: 1m | ||||||
|  |  | ||||||
|  |   kar_mongodb_service: | ||||||
|  |     image: mongo:latest | ||||||
|  |     restart: always | ||||||
|  |     environment: | ||||||
|  |       MONGO_INITDB_ROOT_USERNAME: root | ||||||
|  |       MONGO_INITDB_ROOT_PASSWORD: base_db_password | ||||||
|  |     ports: | ||||||
|  |       - 27017:27017 | ||||||
|  |     volumes: | ||||||
|  |       - ./dataMongo:/data/db | ||||||
|  |  | ||||||
|  |   kar_adminer_service: | ||||||
|  |     image: adminer:latest | ||||||
|  |     restart: always | ||||||
|  |     depends_on: | ||||||
|  |       kar_db_service: | ||||||
|  |         condition: service_healthy | ||||||
|  |     links: | ||||||
|  |       - kar_db_service:db | ||||||
|  |       - kar_mongodb_service:dbm | ||||||
|  |     ports: | ||||||
|  |       - 4079:8080 | ||||||
|  |     mem_limit: 50m | ||||||
|  |  | ||||||
|  |   mongo_express_service: | ||||||
|  |     image: mongo-express | ||||||
|  |     restart: always | ||||||
|  |     ports: | ||||||
|  |       - 4077:8081 | ||||||
|  |     links: | ||||||
|  |       - kar_mongodb_service:db | ||||||
|  |     environment: | ||||||
|  |       ME_CONFIG_MONGODB_ADMINUSERNAME: root | ||||||
|  |       ME_CONFIG_MONGODB_ADMINPASSWORD: base_db_password | ||||||
|  |       ME_CONFIG_MONGODB_URL: mongodb://root:base_db_password@db:27017/ | ||||||
|  |       ME_CONFIG_BASICAUTH: false | ||||||
|  |  | ||||||
| @@ -1,12 +0,0 @@ | |||||||
| # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. |  | ||||||
| # For additional information regarding the format and rule options, please see: |  | ||||||
| # https://github.com/browserslist/browserslist#queries |  | ||||||
|  |  | ||||||
| # You can see what browsers were selected by your queries by running: |  | ||||||
| #   npx browserslist |  | ||||||
|  |  | ||||||
| > 0.5% |  | ||||||
| last 2 versions |  | ||||||
| Firefox ESR |  | ||||||
| not dead |  | ||||||
| not IE 9-11 # For IE 9-11 support, remove 'not'. |  | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| # Editor configuration, see http://editorconfig.org |  | ||||||
| root = true |  | ||||||
|  |  | ||||||
| [*] |  | ||||||
| charset = utf-8 |  | ||||||
| indent_style = space |  | ||||||
| indent_size = 2 |  | ||||||
| insert_final_newline = true |  | ||||||
| trim_trailing_whitespace = true |  | ||||||
|  |  | ||||||
| [*.md] |  | ||||||
| max_line_length = off |  | ||||||
| trim_trailing_whitespace = false |  | ||||||
							
								
								
									
										2
									
								
								front/.env.production
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								front/.env.production
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | # URL for database connection | ||||||
|  | VITE_API_BASE_URL=karusic/api/ | ||||||
| @@ -1,4 +0,0 @@ | |||||||
| node_modules/* |  | ||||||
| build/* |  | ||||||
| out/* |  | ||||||
| dist/* |  | ||||||
| @@ -1,225 +0,0 @@ | |||||||
| var OFF = 0, WARN = 1, ERROR = 2; |  | ||||||
|  |  | ||||||
| module.exports = { |  | ||||||
|     'env': { |  | ||||||
|       'browser': true, |  | ||||||
|       'es2021': true, |  | ||||||
|     }, |  | ||||||
|     'extends': [ |  | ||||||
|       'eslint:recommended', |  | ||||||
|     ], |  | ||||||
|     'parser': '@typescript-eslint/parser', |  | ||||||
|     'parserOptions': { |  | ||||||
|       'ecmaVersion': 'latest', |  | ||||||
|       'sourceType': 'module', |  | ||||||
|     }, |  | ||||||
|     'plugins': [ |  | ||||||
|       '@typescript-eslint', |  | ||||||
|     ], |  | ||||||
|     "rules": { |  | ||||||
|         // Possible Errors (overrides from recommended set) |  | ||||||
|         "no-extra-parens": ERROR, |  | ||||||
|         "no-unexpected-multiline": ERROR, |  | ||||||
|         // All JSDoc comments must be valid |  | ||||||
|         "valid-jsdoc": [ OFF, { |  | ||||||
|             "requireReturn": false, |  | ||||||
|             "requireReturnDescription": false, |  | ||||||
|             "requireParamDescription": true, |  | ||||||
|             "prefer": { |  | ||||||
|                 "return": "returns" |  | ||||||
|             } |  | ||||||
|         }], |  | ||||||
|  |  | ||||||
|         // Best Practices |  | ||||||
|  |  | ||||||
|         // Allowed a getter without setter, but all setters require getters |  | ||||||
|         "accessor-pairs": [ OFF, { |  | ||||||
|             "getWithoutSet": false, |  | ||||||
|             "setWithoutGet": true |  | ||||||
|         }], |  | ||||||
|         "block-scoped-var": WARN, |  | ||||||
|         "consistent-return": OFF, |  | ||||||
|         "curly": ERROR, |  | ||||||
|         "default-case": WARN, |  | ||||||
|         // the dot goes with the property when doing multiline |  | ||||||
|         "dot-location": [ WARN, "property" ], |  | ||||||
|         "dot-notation": WARN, |  | ||||||
|         "eqeqeq": [ ERROR, "smart" ], |  | ||||||
|         "guard-for-in": WARN, |  | ||||||
|         "no-alert": ERROR, |  | ||||||
|         "no-caller": ERROR, |  | ||||||
|         "no-case-declarations": WARN, |  | ||||||
|         "no-div-regex": WARN, |  | ||||||
|         "no-else-return": WARN, |  | ||||||
|         "no-empty-pattern": WARN, |  | ||||||
|         "no-eq-null": ERROR, |  | ||||||
|         "no-eval": ERROR, |  | ||||||
|         "no-extend-native": ERROR, |  | ||||||
|         "no-extra-bind": WARN, |  | ||||||
|         "no-floating-decimal": WARN, |  | ||||||
|         "no-implicit-coercion": [ WARN, { |  | ||||||
|             "boolean": true, |  | ||||||
|             "number": true, |  | ||||||
|             "string": true |  | ||||||
|         }], |  | ||||||
|         "no-implied-eval": ERROR, |  | ||||||
|         "no-invalid-this": ERROR, |  | ||||||
|         "no-iterator": ERROR, |  | ||||||
|         "no-labels": WARN, |  | ||||||
|         "no-lone-blocks": WARN, |  | ||||||
|         "no-loop-func": ERROR, |  | ||||||
|         "no-magic-numbers": OFF, |  | ||||||
|         "no-multi-spaces": ERROR, |  | ||||||
|         "no-multi-str": WARN, |  | ||||||
|         "no-native-reassign": ERROR, |  | ||||||
|         "no-new-func": ERROR, |  | ||||||
|         "no-new-wrappers": ERROR, |  | ||||||
|         "no-new": ERROR, |  | ||||||
|         "no-octal-escape": ERROR, |  | ||||||
|         "no-param-reassign": ERROR, |  | ||||||
|         "no-process-env": WARN, |  | ||||||
|         "no-proto": ERROR, |  | ||||||
|         "no-redeclare": ERROR, |  | ||||||
|         "no-return-assign": ERROR, |  | ||||||
|         "no-script-url": ERROR, |  | ||||||
|         "no-self-compare": ERROR, |  | ||||||
|         "no-throw-literal": ERROR, |  | ||||||
|         "no-unused-expressions": ERROR, |  | ||||||
|         "no-useless-call": ERROR, |  | ||||||
|         "no-useless-concat": ERROR, |  | ||||||
|         "no-void": WARN, |  | ||||||
|         // Produce warnings when something is commented as TODO or FIXME |  | ||||||
|         "no-warning-comments": [ WARN, { |  | ||||||
|             "terms": [ "TODO", "FIXME" ], |  | ||||||
|             "location": "start" |  | ||||||
|         }], |  | ||||||
|         "no-with": WARN, |  | ||||||
|         "radix": WARN, |  | ||||||
|         "vars-on-top": ERROR, |  | ||||||
|         // Enforces the style of wrapped functions |  | ||||||
|         "wrap-iife": [ ERROR, "outside" ], |  | ||||||
|         "yoda": ERROR, |  | ||||||
|  |  | ||||||
|         // Strict Mode - for ES6, never use strict. |  | ||||||
|         "strict": [ ERROR, "never" ], |  | ||||||
|  |  | ||||||
|         // Variables |  | ||||||
|         "init-declarations": [ OFF, "always" ], |  | ||||||
|         "no-catch-shadow": WARN, |  | ||||||
|         "no-delete-var": ERROR, |  | ||||||
|         "no-label-var": ERROR, |  | ||||||
|         "no-shadow-restricted-names": ERROR, |  | ||||||
|         "no-shadow": WARN, |  | ||||||
|         // We require all vars to be initialized (see init-declarations) |  | ||||||
|         // If we NEED a var to be initialized to undefined, it needs to be explicit |  | ||||||
|         "no-undef-init": OFF, |  | ||||||
|         "no-undef": ERROR, |  | ||||||
|         "no-undefined": OFF, |  | ||||||
|         "no-unused-vars": OFF, |  | ||||||
|         // Disallow hoisting - let & const don't allow hoisting anyhow |  | ||||||
|         "no-use-before-define": ERROR, |  | ||||||
|  |  | ||||||
|         // Node.js and CommonJS |  | ||||||
|         "callback-return": [ WARN, [ "callback", "next" ]], |  | ||||||
|         "global-require": ERROR, |  | ||||||
|         "handle-callback-err": WARN, |  | ||||||
|         "no-mixed-requires": WARN, |  | ||||||
|         "no-new-require": ERROR, |  | ||||||
|         // Use path.concat instead |  | ||||||
|         "no-path-concat": ERROR, |  | ||||||
|         "no-process-exit": ERROR, |  | ||||||
|         "no-restricted-modules": OFF, |  | ||||||
|         "no-sync": WARN, |  | ||||||
|  |  | ||||||
|         // ECMAScript 6 support |  | ||||||
|         "arrow-body-style": [ ERROR, "always" ], |  | ||||||
|         "arrow-parens": [ ERROR, "always" ], |  | ||||||
|         "arrow-spacing": [ ERROR, { "before": true, "after": true }], |  | ||||||
|         "constructor-super": ERROR, |  | ||||||
|         "generator-star-spacing": [ ERROR, "before" ], |  | ||||||
|         "no-confusing-arrow": ERROR, |  | ||||||
|         "no-class-assign": ERROR, |  | ||||||
|         "no-const-assign": ERROR, |  | ||||||
|         "no-dupe-class-members": ERROR, |  | ||||||
|         "no-this-before-super": ERROR, |  | ||||||
|         "no-var": WARN, |  | ||||||
|         "object-shorthand": [ WARN, "never" ], |  | ||||||
|         "prefer-arrow-callback": WARN, |  | ||||||
|         "prefer-spread": WARN, |  | ||||||
|         "prefer-template": WARN, |  | ||||||
|         "require-yield": ERROR, |  | ||||||
|  |  | ||||||
|         // Stylistic - everything here is a warning because of style. |  | ||||||
|         "array-bracket-spacing": [ WARN, "always" ], |  | ||||||
|         "block-spacing": [ WARN, "always" ], |  | ||||||
|         "brace-style": [ WARN, "1tbs", { "allowSingleLine": false } ], |  | ||||||
|         "camelcase": WARN, |  | ||||||
|         "comma-spacing": [ WARN, { "before": false, "after": true } ], |  | ||||||
|         "comma-style": [ WARN, "last" ], |  | ||||||
|         "computed-property-spacing": [ WARN, "never" ], |  | ||||||
|         "consistent-this": [ WARN, "self" ], |  | ||||||
|         "eol-last": WARN, |  | ||||||
|         "func-names": WARN, |  | ||||||
|         "func-style": [ WARN, "declaration" ], |  | ||||||
|         "id-length": [ WARN, { "min": 2, "max": 32 } ], |  | ||||||
|         "indent": [ WARN, 'tab' ], |  | ||||||
|         "jsx-quotes": [ WARN, "prefer-double" ], |  | ||||||
|         "linebreak-style": [ WARN, "unix" ], |  | ||||||
|         "lines-around-comment": [ OFF, { "beforeBlockComment": true } ], |  | ||||||
|         "max-depth": [ WARN, 8 ], |  | ||||||
|         "max-len": [ WARN, 182 ], |  | ||||||
|         "max-nested-callbacks": [ WARN, 8 ], |  | ||||||
|         "max-params": [ WARN, 10 ], |  | ||||||
|         "new-cap": OFF, |  | ||||||
|         "new-parens": WARN, |  | ||||||
|         "no-array-constructor": WARN, |  | ||||||
|         "no-bitwise": OFF, |  | ||||||
|         "no-continue": OFF, |  | ||||||
|         "no-inline-comments": OFF, |  | ||||||
|         "no-lonely-if": OFF, |  | ||||||
|         "no-mixed-spaces-and-tabs": OFF, |  | ||||||
|         "no-multiple-empty-lines": WARN, |  | ||||||
|         "no-negated-condition": OFF, |  | ||||||
|         "no-nested-ternary": WARN, |  | ||||||
|         "no-new-object": WARN, |  | ||||||
|         "no-plusplus": OFF, |  | ||||||
|         "no-spaced-func": WARN, |  | ||||||
|         "no-ternary": OFF, |  | ||||||
|         "no-trailing-spaces": WARN, |  | ||||||
|         "no-underscore-dangle": WARN, |  | ||||||
|         "no-unneeded-ternary": WARN, |  | ||||||
|         "object-curly-spacing": [ WARN, "always" ], |  | ||||||
|         "one-var": OFF, |  | ||||||
|         "operator-assignment": [ WARN, "never" ], |  | ||||||
|         "operator-linebreak": [ WARN, "after" ], |  | ||||||
|         "padded-blocks": [ WARN, "never" ], |  | ||||||
|         "quote-props": [ WARN, "consistent-as-needed" ], |  | ||||||
|         "quotes": [ WARN, "single" ], |  | ||||||
|         "require-jsdoc": [ OFF, { |  | ||||||
|             "require": { |  | ||||||
|                 "FunctionDeclaration": true, |  | ||||||
|                 "MethodDefinition": true, |  | ||||||
|                 "ClassDeclaration": false |  | ||||||
|             } |  | ||||||
|         }], |  | ||||||
|         "semi-spacing": [ WARN, { "before": false, "after": true }], |  | ||||||
|         "semi": [ ERROR, "always" ], |  | ||||||
|         "sort-vars": OFF, |  | ||||||
|         "keyword-spacing": [WARN, { |  | ||||||
|             "overrides": { |  | ||||||
|                 "if": { "after": false }, |  | ||||||
|                 "for": { "after": false }, |  | ||||||
|                 "while": { "after": false }, |  | ||||||
|                 "static": { "after": false }, |  | ||||||
|                 "as": { "after": false } |  | ||||||
|             } |  | ||||||
|         }], |  | ||||||
|         "space-before-blocks": [ WARN, "always" ], |  | ||||||
|         "space-before-function-paren": [ WARN, "never" ], |  | ||||||
|         "space-in-parens": [ WARN, "never" ], |  | ||||||
|         "space-infix-ops": [ WARN, { "int32Hint": true } ], |  | ||||||
|         "space-unary-ops": ERROR, |  | ||||||
|         "spaced-comment": [ WARN, "always" ], |  | ||||||
|         "wrap-regex": WARN, |  | ||||||
|     }, |  | ||||||
|   }; |  | ||||||
							
								
								
									
										3
									
								
								front/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								front/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +0,0 @@ | |||||||
| /node_modules/ |  | ||||||
| /.angular/ |  | ||||||
| /.idea/ |  | ||||||
							
								
								
									
										27
									
								
								front/.storybook/main.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								front/.storybook/main.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | import type { StorybookConfig } from '@storybook/react-vite'; | ||||||
|  |  | ||||||
|  | const config: StorybookConfig = { | ||||||
|  |   framework: { | ||||||
|  |     name: '@storybook/react-vite', | ||||||
|  |     options: {}, | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   core: { | ||||||
|  |     disableTelemetry: true, | ||||||
|  |     builder: '@storybook/builder-vite', | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   stories: ['../src/**/*.@(mdx|stories.@(js|jsx|ts|tsx))'], | ||||||
|  |  | ||||||
|  |   addons: ['@storybook/addon-links', '@storybook/addon-essentials'], | ||||||
|  |  | ||||||
|  |   staticDirs: ['../public'], | ||||||
|  |  | ||||||
|  |   typescript: { | ||||||
|  |     reactDocgen: false, | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   docs: {}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default config; | ||||||
							
								
								
									
										16
									
								
								front/.storybook/preview-head.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								front/.storybook/preview-head.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | <style> | ||||||
|  |   html { | ||||||
|  |     background: transparent !important; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .docs-story > :first-child { | ||||||
|  |     padding: 0; | ||||||
|  |   } | ||||||
|  |   .docs-story > * { | ||||||
|  |     background: transparent !important; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   #root #start-ui-storybook-wrapper { | ||||||
|  |     min-height: 100vh; | ||||||
|  |   } | ||||||
|  | </style> | ||||||
							
								
								
									
										43
									
								
								front/.storybook/preview.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								front/.storybook/preview.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | import React from 'react'; | ||||||
|  |  | ||||||
|  | import { Box } from '@chakra-ui/react'; | ||||||
|  | import { ChakraProvider } from '@chakra-ui/react'; | ||||||
|  | import { MemoryRouter } from 'react-router-dom'; | ||||||
|  |  | ||||||
|  | import theme from '../src/theme'; | ||||||
|  |  | ||||||
|  | // .storybook/preview.js | ||||||
|  | export const parameters = { | ||||||
|  |   options: { | ||||||
|  |     storySort: { | ||||||
|  |       order: ['StyleGuide', 'Components', 'Fields', 'App Layout'], | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   actions: {}, | ||||||
|  |   layout: 'fullscreen', | ||||||
|  |   backgrounds: { disable: true, grid: { disable: true } }, | ||||||
|  |   chakra: { | ||||||
|  |     theme, | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const DocumentationWrapper = ({ children }) => { | ||||||
|  |   return ( | ||||||
|  |     <Box id="start-ui-storybook-wrapper" p="4" pb="8" flex="1"> | ||||||
|  |       {children} | ||||||
|  |     </Box> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const decorators = [ | ||||||
|  |   (Story, context) => ( | ||||||
|  |     <ChakraProvider theme={theme}> | ||||||
|  |       {/* Using MemoryRouter to avoid route clashing with Storybook */} | ||||||
|  |       <MemoryRouter> | ||||||
|  |         <DocumentationWrapper> | ||||||
|  |           <Story {...context} /> | ||||||
|  |         </DocumentationWrapper> | ||||||
|  |       </MemoryRouter> | ||||||
|  |     </ChakraProvider> | ||||||
|  |   ), | ||||||
|  | ]; | ||||||
| @@ -1,33 +0,0 @@ | |||||||
| # base image |  | ||||||
| FROM node:lts as build |  | ||||||
|  |  | ||||||
| # add `/application/node_modules/.bin` to $PATH |  | ||||||
| ENV PATH /application/node_modules/.bin:$PATH |  | ||||||
|  |  | ||||||
| ADD package-lock.json /application/ |  | ||||||
| ADD package.json /application/ |  | ||||||
| #ADD browserslist /application/ |  | ||||||
| ADD karma.conf.js /application/ |  | ||||||
| ADD protractor.conf.js /application/ |  | ||||||
| WORKDIR /application/ |  | ||||||
|  |  | ||||||
| # install and cache app dependencies |  | ||||||
| RUN npm install |  | ||||||
|  |  | ||||||
| ADD e2e /application/e2e |  | ||||||
| ADD tsconfig.json tslint.json angular.json ./ |  | ||||||
| ADD src /application/src |  | ||||||
|  |  | ||||||
| # generate build |  | ||||||
| RUN ng build --output-path=dist --configuration=production --base-href=/karideo/ --deploy-url=/karideo/  |  | ||||||
|  |  | ||||||
| ############ |  | ||||||
| ### prod ### |  | ||||||
| ############ |  | ||||||
|  |  | ||||||
| # base image |  | ||||||
| FROM httpd:latest |  | ||||||
|  |  | ||||||
| # copy artifact build from the 'build environment' |  | ||||||
| COPY --from=build /application/dist /usr/local/apache2/htdocs/ |  | ||||||
| COPY httpd/httpd.conf /usr/local/apache2/conf/httpd.conf |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| # base image |  | ||||||
| FROM node:latest |  | ||||||
|  |  | ||||||
| ADD src /application/src |  | ||||||
| ADD e2e /application/e2e |  | ||||||
| ADD package-lock.json /application/ |  | ||||||
| ADD package.json /application/ |  | ||||||
| ADD angular.json /application/ |  | ||||||
| ADD browserslist /application/ |  | ||||||
| ADD karma.conf.js /application/ |  | ||||||
| ADD protractor.conf.js /application/ |  | ||||||
| ADD tsconfig.json /application/ |  | ||||||
| ADD tslint.json /application/ |  | ||||||
| WORKDIR /application/ |  | ||||||
|  |  | ||||||
| # add `/app/node_modules/.bin` to $PATH |  | ||||||
| ENV PATH /app/node_modules/.bin:$PATH |  | ||||||
|  |  | ||||||
| # install and cache app dependencies |  | ||||||
| RUN npm install |  | ||||||
|  |  | ||||||
| # start app |  | ||||||
| CMD ["npx", "ng", "serve", "--host", "0.0.0.0"] |  | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								front/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								front/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | Proprietary | ||||||
|  | @copyright Edouard Dupin 2024 | ||||||
| @@ -1,172 +0,0 @@ | |||||||
| { |  | ||||||
|   "$schema": "./node_modules/@angular/cli/lib/config/schema.json", |  | ||||||
|   "version": 1, |  | ||||||
|   "newProjectRoot": "projects", |  | ||||||
|   "projects": { |  | ||||||
|     "karusic": { |  | ||||||
|       "root": "", |  | ||||||
|       "sourceRoot": "src", |  | ||||||
|       "projectType": "application", |  | ||||||
|       "architect": { |  | ||||||
|         "build": { |  | ||||||
|           "builder": "@angular-devkit/build-angular:browser", |  | ||||||
|           "options": { |  | ||||||
|             "outputPath": "dist", |  | ||||||
|             "index": "src/index.html", |  | ||||||
|             "main": "src/main.ts", |  | ||||||
|             "tsConfig": "src/tsconfig.app.json", |  | ||||||
|             "preserveSymlinks": true, |  | ||||||
|             "polyfills": [ |  | ||||||
|               "zone.js" |  | ||||||
|             ], |  | ||||||
|             "assets": [ |  | ||||||
|               "src/assets", |  | ||||||
|               "src/favicon.ico" |  | ||||||
|             ], |  | ||||||
|             "styles": [ |  | ||||||
|               "src/styles.less", |  | ||||||
|               "src/generic_page.less", |  | ||||||
|               "src/theme.color.blue.less", |  | ||||||
|               "src/theme.checkbox.less", |  | ||||||
|               "src/theme.modal.less" |  | ||||||
|             ], |  | ||||||
|             "scripts": [] |  | ||||||
|           }, |  | ||||||
|           "configurations": { |  | ||||||
|             "production": { |  | ||||||
|               "optimization": true, |  | ||||||
|               "outputHashing": "all", |  | ||||||
|               "sourceMap": false, |  | ||||||
|               "namedChunks": false, |  | ||||||
|               "aot": true, |  | ||||||
|               "extractLicenses": true, |  | ||||||
|               "vendorChunk": false, |  | ||||||
|               "buildOptimizer": true, |  | ||||||
|               "fileReplacements": [ |  | ||||||
|                 { |  | ||||||
|                   "replace": "src/environments/environment.ts", |  | ||||||
|                   "with": "src/environments/environment.prod.ts" |  | ||||||
|                 } |  | ||||||
|               ] |  | ||||||
|             }, |  | ||||||
|             "develop": { |  | ||||||
|               "optimization": false, |  | ||||||
|               "outputHashing": "none", |  | ||||||
|               "namedChunks": true, |  | ||||||
|               "aot": false, |  | ||||||
|               "extractLicenses": true, |  | ||||||
|               "vendorChunk": true, |  | ||||||
|               "buildOptimizer": false, |  | ||||||
|               "sourceMap": { |  | ||||||
|                 "scripts": true, |  | ||||||
|                 "styles": true, |  | ||||||
|                 "hidden": false, |  | ||||||
|                 "vendor": true |  | ||||||
|               } |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "serve": { |  | ||||||
|           "builder": "@angular-devkit/build-angular:dev-server", |  | ||||||
|           "options": { |  | ||||||
|             "buildTarget": "karusic:build" |  | ||||||
|           }, |  | ||||||
|           "configurations": { |  | ||||||
|             "production": { |  | ||||||
|               "buildTarget": "karusic:build:production" |  | ||||||
|             }, |  | ||||||
|             "develop": { |  | ||||||
|               "buildTarget": "karusic:build:develop" |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "extract-i18n": { |  | ||||||
|           "builder": "@angular-devkit/build-angular:extract-i18n", |  | ||||||
|           "options": { |  | ||||||
|             "buildTarget": "karusic:build" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "test": { |  | ||||||
|           "builder": "@angular-devkit/build-angular:karma", |  | ||||||
|           "options": { |  | ||||||
|             "main": "src/test.ts", |  | ||||||
|             "karmaConfig": "./karma.conf.js", |  | ||||||
|             "polyfills": [ |  | ||||||
|               "zone.js" |  | ||||||
|             ], |  | ||||||
|             "tsConfig": "src/tsconfig.spec.json", |  | ||||||
|             "scripts": [], |  | ||||||
|             "styles": [ |  | ||||||
|               "src/styles.less", |  | ||||||
|               "src/generic_page.less", |  | ||||||
|               "src/theme.color.blue.less", |  | ||||||
|               "src/theme.checkbox.less", |  | ||||||
|               "src/theme.modal.less" |  | ||||||
|             ], |  | ||||||
|             "assets": [ |  | ||||||
|               "src/assets", |  | ||||||
|               "src/favicon.ico" |  | ||||||
|             ] |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "lint": { |  | ||||||
|           "builder": "@angular-eslint/builder:lint", |  | ||||||
|           "options": { |  | ||||||
|             "fix": true, |  | ||||||
|             "eslintConfig": ".eslintrc.js", |  | ||||||
|             "lintFilePatterns": [ |  | ||||||
|               "src/**/*.spec.ts", |  | ||||||
|               "src/**/*.ts" |  | ||||||
|             ] |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "TTTTTTlint": { |  | ||||||
|           "builder": "@angular-devkit/build-angular:tslint", |  | ||||||
|           "options": { |  | ||||||
|             "tsConfig": [ |  | ||||||
|               "src/tsconfig.app.json", |  | ||||||
|               "src/tsconfig.spec.json" |  | ||||||
|             ], |  | ||||||
|             "exclude": [ |  | ||||||
|               "**/node_modules/**" |  | ||||||
|             ] |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "karusic-e2e": { |  | ||||||
|       "root": "e2e", |  | ||||||
|       "sourceRoot": "e2e", |  | ||||||
|       "projectType": "application", |  | ||||||
|       "architect": { |  | ||||||
|         "e2e": { |  | ||||||
|           "builder": "@angular-devkit/build-angular:protractor", |  | ||||||
|           "options": { |  | ||||||
|             "protractorConfig": "./protractor.conf.js", |  | ||||||
|             "devServerTarget": "karusic:serve" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "lint": { |  | ||||||
|           "builder": "@angular-devkit/build-angular:tslint", |  | ||||||
|           "options": { |  | ||||||
|             "tsConfig": [ |  | ||||||
|               "e2e/tsconfig.e2e.json" |  | ||||||
|             ], |  | ||||||
|             "exclude": [ |  | ||||||
|               "**/node_modules/**" |  | ||||||
|             ] |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   "schematics": { |  | ||||||
|     "@schematics/angular:component": { |  | ||||||
|       "prefix": "app", |  | ||||||
|       "style": "less" |  | ||||||
|     }, |  | ||||||
|     "@schematics/angular:directive": { |  | ||||||
|       "prefix": "app" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										6
									
								
								front/app-build.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								front/app-build.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | { | ||||||
|  |   "display": "2025-01-06", | ||||||
|  |   "version": "0.0.1-dev\n - 2025-01-06T00:49:52+01:00", | ||||||
|  |   "commit": "0.0.1-dev\n", | ||||||
|  |   "date": "2025-01-06T00:49:52+01:00" | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								front/build.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								front/build.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | const dayjs = require('dayjs'); | ||||||
|  |  | ||||||
|  | const fs = require('fs'); | ||||||
|  |  | ||||||
|  | const generateAppBuild = () => { | ||||||
|  |   const getVersion = () => fs.readFileSync('version.txt', 'utf8'); | ||||||
|  |  | ||||||
|  |   const commit = process.env.VERCEL_GIT_COMMIT_SHA | ||||||
|  |     ? process.env.VERCEL_GIT_COMMIT_SHA | ||||||
|  |     : getVersion(); | ||||||
|  |  | ||||||
|  |   const appBuildContent = { | ||||||
|  |     display: `${dayjs().format('YYYY-MM-DD')}`, | ||||||
|  |     version: `${commit} - ${dayjs().format()}`, | ||||||
|  |     commit, | ||||||
|  |     date: dayjs().format(), | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   fs.writeFileSync( | ||||||
|  |     './app-build.json', | ||||||
|  |     JSON.stringify(appBuildContent, null, 2) | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | generateAppBuild(); | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| version: '3' |  | ||||||
| services: |  | ||||||
|   karideo_service: |  | ||||||
|     build: . |  | ||||||
|     restart: always |  | ||||||
|     image: yui.heero/karideo |  | ||||||
|     container_name: karideo |  | ||||||
|     ports: |  | ||||||
|       #- 15081:4200 |  | ||||||
|       - 15081:80 |  | ||||||
|  |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
| import { AppPage } from './app.po'; |  | ||||||
|  |  | ||||||
| describe('karusic App', () => { |  | ||||||
|   let page: AppPage; |  | ||||||
|  |  | ||||||
|   beforeEach(() => { |  | ||||||
|     page = new AppPage(); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should display welcome message', () => { |  | ||||||
|     page.navigateTo(); |  | ||||||
|     expect(page.getParagraphText()).toEqual('Welcome to app!'); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| import { browser, by, element } from 'protractor'; |  | ||||||
|  |  | ||||||
| export class AppPage { |  | ||||||
|   navigateTo() { |  | ||||||
|     return browser.get('/'); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   getParagraphText() { |  | ||||||
|     return element(by.css('app-root h1')).getText(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
| { |  | ||||||
|   "extends": "../tsconfig.json", |  | ||||||
|   "compilerOptions": { |  | ||||||
|     "outDir": "../out-tsc/e2e", |  | ||||||
|     "baseUrl": "./", |  | ||||||
|     "module": "commonjs", |  | ||||||
|     "target": "es5", |  | ||||||
|     "types": [ |  | ||||||
|       "jasmine", |  | ||||||
|       "jasminewd2", |  | ||||||
|       "node" |  | ||||||
|     ] |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,541 +0,0 @@ | |||||||
| # |  | ||||||
| # This is the main Apache HTTP server configuration file.  It contains the |  | ||||||
| # configuration directives that give the server its instructions. |  | ||||||
| # See <URL:http://httpd.apache.org/docs/2.4/> for detailed information. |  | ||||||
| # In particular, see  |  | ||||||
| # <URL:http://httpd.apache.org/docs/2.4/mod/directives.html> |  | ||||||
| # for a discussion of each configuration directive. |  | ||||||
| # |  | ||||||
| # Do NOT simply read the instructions in here without understanding |  | ||||||
| # what they do.  They're here only as hints or reminders.  If you are unsure |  | ||||||
| # consult the online docs. You have been warned.   |  | ||||||
| # |  | ||||||
| # Configuration and logfile names: If the filenames you specify for many |  | ||||||
| # of the server's control files begin with "/" (or "drive:/" for Win32), the |  | ||||||
| # server will use that explicit path.  If the filenames do *not* begin |  | ||||||
| # with "/", the value of ServerRoot is prepended -- so "logs/access_log" |  | ||||||
| # with ServerRoot set to "/usr/local/apache2" will be interpreted by the |  | ||||||
| # server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"  |  | ||||||
| # will be interpreted as '/logs/access_log'. |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # ServerRoot: The top of the directory tree under which the server's |  | ||||||
| # configuration, error, and log files are kept. |  | ||||||
| # |  | ||||||
| # Do not add a slash at the end of the directory path.  If you point |  | ||||||
| # ServerRoot at a non-local disk, be sure to specify a local disk on the |  | ||||||
| # Mutex directive, if file-based mutexes are used.  If you wish to share the |  | ||||||
| # same ServerRoot for multiple httpd daemons, you will need to change at |  | ||||||
| # least PidFile. |  | ||||||
| # |  | ||||||
| ServerRoot "/usr/local/apache2" |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Mutex: Allows you to set the mutex mechanism and mutex file directory |  | ||||||
| # for individual mutexes, or change the global defaults |  | ||||||
| # |  | ||||||
| # Uncomment and change the directory if mutexes are file-based and the default |  | ||||||
| # mutex file directory is not on a local disk or is not appropriate for some |  | ||||||
| # other reason. |  | ||||||
| # |  | ||||||
| # Mutex default:logs |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Listen: Allows you to bind Apache to specific IP addresses and/or |  | ||||||
| # ports, instead of the default. See also the <VirtualHost> |  | ||||||
| # directive. |  | ||||||
| # |  | ||||||
| # Change this to Listen on specific IP addresses as shown below to  |  | ||||||
| # prevent Apache from glomming onto all bound IP addresses. |  | ||||||
| # |  | ||||||
| Listen 80 |  | ||||||
| Listen 443 |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Dynamic Shared Object (DSO) Support |  | ||||||
| # |  | ||||||
| # To be able to use the functionality of a module which was built as a DSO you |  | ||||||
| # have to place corresponding `LoadModule' lines at this location so the |  | ||||||
| # directives contained in it are actually available _before_ they are used. |  | ||||||
| # Statically compiled modules (those listed by `httpd -l') do not need |  | ||||||
| # to be loaded here. |  | ||||||
| # |  | ||||||
| # Example: |  | ||||||
| # LoadModule foo_module modules/mod_foo.so |  | ||||||
| # |  | ||||||
| LoadModule mpm_event_module modules/mod_mpm_event.so |  | ||||||
| #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so |  | ||||||
| #LoadModule mpm_worker_module modules/mod_mpm_worker.so |  | ||||||
| LoadModule authn_file_module modules/mod_authn_file.so |  | ||||||
| #LoadModule authn_dbm_module modules/mod_authn_dbm.so |  | ||||||
| #LoadModule authn_anon_module modules/mod_authn_anon.so |  | ||||||
| #LoadModule authn_dbd_module modules/mod_authn_dbd.so |  | ||||||
| #LoadModule authn_socache_module modules/mod_authn_socache.so |  | ||||||
| LoadModule authn_core_module modules/mod_authn_core.so |  | ||||||
| LoadModule authz_host_module modules/mod_authz_host.so |  | ||||||
| LoadModule authz_groupfile_module modules/mod_authz_groupfile.so |  | ||||||
| LoadModule authz_user_module modules/mod_authz_user.so |  | ||||||
| #LoadModule authz_dbm_module modules/mod_authz_dbm.so |  | ||||||
| #LoadModule authz_owner_module modules/mod_authz_owner.so |  | ||||||
| #LoadModule authz_dbd_module modules/mod_authz_dbd.so |  | ||||||
| LoadModule authz_core_module modules/mod_authz_core.so |  | ||||||
| #LoadModule authnz_ldap_module modules/mod_authnz_ldap.so |  | ||||||
| #LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so |  | ||||||
| LoadModule access_compat_module modules/mod_access_compat.so |  | ||||||
| LoadModule auth_basic_module modules/mod_auth_basic.so |  | ||||||
| #LoadModule auth_form_module modules/mod_auth_form.so |  | ||||||
| #LoadModule auth_digest_module modules/mod_auth_digest.so |  | ||||||
| #LoadModule allowmethods_module modules/mod_allowmethods.so |  | ||||||
| #LoadModule isapi_module modules/mod_isapi.so |  | ||||||
| #LoadModule file_cache_module modules/mod_file_cache.so |  | ||||||
| #LoadModule cache_module modules/mod_cache.so |  | ||||||
| #LoadModule cache_disk_module modules/mod_cache_disk.so |  | ||||||
| #LoadModule cache_socache_module modules/mod_cache_socache.so |  | ||||||
| #LoadModule socache_shmcb_module modules/mod_socache_shmcb.so |  | ||||||
| #LoadModule socache_dbm_module modules/mod_socache_dbm.so |  | ||||||
| #LoadModule socache_memcache_module modules/mod_socache_memcache.so |  | ||||||
| #LoadModule watchdog_module modules/mod_watchdog.so |  | ||||||
| #LoadModule macro_module modules/mod_macro.so |  | ||||||
| #LoadModule dbd_module modules/mod_dbd.so |  | ||||||
| #LoadModule bucketeer_module modules/mod_bucketeer.so |  | ||||||
| #LoadModule dumpio_module modules/mod_dumpio.so |  | ||||||
| #LoadModule echo_module modules/mod_echo.so |  | ||||||
| #LoadModule example_hooks_module modules/mod_example_hooks.so |  | ||||||
| #LoadModule case_filter_module modules/mod_case_filter.so |  | ||||||
| #LoadModule case_filter_in_module modules/mod_case_filter_in.so |  | ||||||
| #LoadModule example_ipc_module modules/mod_example_ipc.so |  | ||||||
| #LoadModule buffer_module modules/mod_buffer.so |  | ||||||
| #LoadModule data_module modules/mod_data.so |  | ||||||
| #LoadModule ratelimit_module modules/mod_ratelimit.so |  | ||||||
| LoadModule reqtimeout_module modules/mod_reqtimeout.so |  | ||||||
| #LoadModule ext_filter_module modules/mod_ext_filter.so |  | ||||||
| #LoadModule request_module modules/mod_request.so |  | ||||||
| #LoadModule include_module modules/mod_include.so |  | ||||||
| LoadModule filter_module modules/mod_filter.so |  | ||||||
| #LoadModule reflector_module modules/mod_reflector.so |  | ||||||
| #LoadModule substitute_module modules/mod_substitute.so |  | ||||||
| #LoadModule sed_module modules/mod_sed.so |  | ||||||
| #LoadModule charset_lite_module modules/mod_charset_lite.so |  | ||||||
| #LoadModule deflate_module modules/mod_deflate.so |  | ||||||
| LoadModule xml2enc_module modules/mod_xml2enc.so |  | ||||||
| LoadModule proxy_html_module modules/mod_proxy_html.so |  | ||||||
| LoadModule mime_module modules/mod_mime.so |  | ||||||
| #LoadModule ldap_module modules/mod_ldap.so |  | ||||||
| LoadModule log_config_module modules/mod_log_config.so |  | ||||||
| #LoadModule log_debug_module modules/mod_log_debug.so |  | ||||||
| #LoadModule log_forensic_module modules/mod_log_forensic.so |  | ||||||
| #LoadModule logio_module modules/mod_logio.so |  | ||||||
| #LoadModule lua_module modules/mod_lua.so |  | ||||||
| LoadModule env_module modules/mod_env.so |  | ||||||
| #LoadModule mime_magic_module modules/mod_mime_magic.so |  | ||||||
| #LoadModule cern_meta_module modules/mod_cern_meta.so |  | ||||||
| #LoadModule expires_module modules/mod_expires.so |  | ||||||
| LoadModule headers_module modules/mod_headers.so |  | ||||||
| #LoadModule ident_module modules/mod_ident.so |  | ||||||
| #LoadModule usertrack_module modules/mod_usertrack.so |  | ||||||
| #LoadModule unique_id_module modules/mod_unique_id.so |  | ||||||
| LoadModule setenvif_module modules/mod_setenvif.so |  | ||||||
| LoadModule version_module modules/mod_version.so |  | ||||||
| #LoadModule remoteip_module modules/mod_remoteip.so |  | ||||||
| LoadModule proxy_module modules/mod_proxy.so |  | ||||||
| #LoadModule proxy_connect_module modules/mod_proxy_connect.so |  | ||||||
| #LoadModule proxy_ftp_module modules/mod_proxy_ftp.so |  | ||||||
| LoadModule proxy_http_module modules/mod_proxy_http.so |  | ||||||
| #LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so |  | ||||||
| #LoadModule proxy_scgi_module modules/mod_proxy_scgi.so |  | ||||||
| #LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so |  | ||||||
| #LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so |  | ||||||
| #LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so |  | ||||||
| #LoadModule proxy_ajp_module modules/mod_proxy_ajp.so |  | ||||||
| #LoadModule proxy_balancer_module modules/mod_proxy_balancer.so |  | ||||||
| #LoadModule proxy_express_module modules/mod_proxy_express.so |  | ||||||
| #LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so |  | ||||||
| #LoadModule session_module modules/mod_session.so |  | ||||||
| #LoadModule session_cookie_module modules/mod_session_cookie.so |  | ||||||
| #LoadModule session_crypto_module modules/mod_session_crypto.so |  | ||||||
| #LoadModule session_dbd_module modules/mod_session_dbd.so |  | ||||||
| #LoadModule slotmem_shm_module modules/mod_slotmem_shm.so |  | ||||||
| #LoadModule slotmem_plain_module modules/mod_slotmem_plain.so |  | ||||||
| LoadModule ssl_module modules/mod_ssl.so |  | ||||||
| #LoadModule optional_hook_export_module modules/mod_optional_hook_export.so |  | ||||||
| #LoadModule optional_hook_import_module modules/mod_optional_hook_import.so |  | ||||||
| #LoadModule optional_fn_import_module modules/mod_optional_fn_import.so |  | ||||||
| #LoadModule optional_fn_export_module modules/mod_optional_fn_export.so |  | ||||||
| #LoadModule dialup_module modules/mod_dialup.so |  | ||||||
| #LoadModule http2_module modules/mod_http2.so |  | ||||||
| #LoadModule proxy_http2_module modules/mod_proxy_http2.so |  | ||||||
| #LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so |  | ||||||
| #LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so |  | ||||||
| #LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so |  | ||||||
| #LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so |  | ||||||
| LoadModule unixd_module modules/mod_unixd.so |  | ||||||
| #LoadModule heartbeat_module modules/mod_heartbeat.so |  | ||||||
| #LoadModule heartmonitor_module modules/mod_heartmonitor.so |  | ||||||
| #LoadModule dav_module modules/mod_dav.so |  | ||||||
| LoadModule status_module modules/mod_status.so |  | ||||||
| LoadModule autoindex_module modules/mod_autoindex.so |  | ||||||
| #LoadModule asis_module modules/mod_asis.so |  | ||||||
| #LoadModule info_module modules/mod_info.so |  | ||||||
| #LoadModule suexec_module modules/mod_suexec.so |  | ||||||
| <IfModule !mpm_prefork_module> |  | ||||||
| 	#LoadModule cgid_module modules/mod_cgid.so |  | ||||||
| </IfModule> |  | ||||||
| <IfModule mpm_prefork_module> |  | ||||||
| 	#LoadModule cgi_module modules/mod_cgi.so |  | ||||||
| </IfModule> |  | ||||||
| #LoadModule dav_fs_module modules/mod_dav_fs.so |  | ||||||
| #LoadModule dav_lock_module modules/mod_dav_lock.so |  | ||||||
| #LoadModule vhost_alias_module modules/mod_vhost_alias.so |  | ||||||
| #LoadModule negotiation_module modules/mod_negotiation.so |  | ||||||
| LoadModule dir_module modules/mod_dir.so |  | ||||||
| #LoadModule imagemap_module modules/mod_imagemap.so |  | ||||||
| #LoadModule actions_module modules/mod_actions.so |  | ||||||
| #LoadModule speling_module modules/mod_speling.so |  | ||||||
| #LoadModule userdir_module modules/mod_userdir.so |  | ||||||
| LoadModule alias_module modules/mod_alias.so |  | ||||||
| LoadModule rewrite_module modules/mod_rewrite.so |  | ||||||
|  |  | ||||||
| <IfModule unixd_module> |  | ||||||
| # |  | ||||||
| # If you wish httpd to run as a different user or group, you must run |  | ||||||
| # httpd as root initially and it will switch.   |  | ||||||
| # |  | ||||||
| # User/Group: The name (or #number) of the user/group to run httpd as. |  | ||||||
| # It is usually good practice to create a dedicated user and group for |  | ||||||
| # running httpd, as with most system services. |  | ||||||
| # |  | ||||||
| User daemon |  | ||||||
| Group daemon |  | ||||||
|  |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
| # 'Main' server configuration |  | ||||||
| # |  | ||||||
| # The directives in this section set up the values used by the 'main' |  | ||||||
| # server, which responds to any requests that aren't handled by a |  | ||||||
| # <VirtualHost> definition.  These values also provide defaults for |  | ||||||
| # any <VirtualHost> containers you may define later in the file. |  | ||||||
| # |  | ||||||
| # All of these directives may appear inside <VirtualHost> containers, |  | ||||||
| # in which case these default settings will be overridden for the |  | ||||||
| # virtual host being defined. |  | ||||||
| # |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # ServerAdmin: Your address, where problems with the server should be |  | ||||||
| # e-mailed.  This address appears on some server-generated pages, such |  | ||||||
| # as error documents.  e.g. admin@your-domain.com |  | ||||||
| # |  | ||||||
| ServerAdmin yui.heero@gmail.com |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # ServerName gives the name and port that the server uses to identify itself. |  | ||||||
| # This can often be determined automatically, but we recommend you specify |  | ||||||
| # it explicitly to prevent problems during startup. |  | ||||||
| # |  | ||||||
| # If your host doesn't have a registered DNS name, enter its IP address here. |  | ||||||
| # |  | ||||||
| #ServerName www.example.com:80 |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Deny access to the entirety of your server's filesystem. You must |  | ||||||
| # explicitly permit access to web content directories in other  |  | ||||||
| # <Directory> blocks below. |  | ||||||
| # |  | ||||||
| <Directory /> |  | ||||||
|     AllowOverride none |  | ||||||
|     Require all denied |  | ||||||
| </Directory> |  | ||||||
|  |  | ||||||
| # intermediate configuration, tweak to your needs |  | ||||||
| SSLProtocol             all -SSLv2 -SSLv3 |  | ||||||
| SSLCipherSuite          ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS |  | ||||||
| SSLHonorCipherOrder     on |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Note that from this point forward you must specifically allow |  | ||||||
| # particular features to be enabled - so if something's not working as |  | ||||||
| # you might expect, make sure that you have specifically enabled it |  | ||||||
| # below. |  | ||||||
| # |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # DocumentRoot: The directory out of which you will serve your |  | ||||||
| # documents. By default, all requests are taken from this directory, but |  | ||||||
| # symbolic links and aliases may be used to point to other locations. |  | ||||||
| # |  | ||||||
| <VirtualHost *:80> |  | ||||||
| 	ServerName my-app |  | ||||||
| 	DocumentRoot "/usr/local/apache2/htdocs" |  | ||||||
| 	<Directory "/usr/local/apache2/htdocs"> |  | ||||||
| 		Options Indexes FollowSymLinks |  | ||||||
| 		AllowOverride None |  | ||||||
| 		Require all granted |  | ||||||
| 		RewriteEngine on |  | ||||||
| 		# Don't rewrite files or directories |  | ||||||
| 		RewriteCond %{REQUEST_FILENAME} -f [OR] |  | ||||||
| 		RewriteCond %{REQUEST_FILENAME} -d |  | ||||||
| 		RewriteRule ^ - [L] |  | ||||||
| 		# Rewrite everything else to index.html to allow HTML5 state links |  | ||||||
| 		RewriteRule ^ index.html [L] |  | ||||||
| 	</Directory> |  | ||||||
| </VirtualHost> |  | ||||||
| # |  | ||||||
| # DirectoryIndex: sets the file that Apache will serve if a directory |  | ||||||
| # is requested. |  | ||||||
| # |  | ||||||
| <IfModule dir_module> |  | ||||||
|     DirectoryIndex index.html |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # The following lines prevent .htaccess and .htpasswd files from being  |  | ||||||
| # viewed by Web clients.  |  | ||||||
| # |  | ||||||
| <Files ".ht*"> |  | ||||||
|     Require all denied |  | ||||||
| </Files> |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # ErrorLog: The location of the error log file. |  | ||||||
| # If you do not specify an ErrorLog directive within a <VirtualHost> |  | ||||||
| # container, error messages relating to that virtual host will be |  | ||||||
| # logged here.  If you *do* define an error logfile for a <VirtualHost> |  | ||||||
| # container, that host's errors will be logged there and not here. |  | ||||||
| # |  | ||||||
| ErrorLog /proc/self/fd/2 |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # LogLevel: Control the number of messages logged to the error_log. |  | ||||||
| # Possible values include: debug, info, notice, warn, error, crit, |  | ||||||
| # alert, emerg. |  | ||||||
| # |  | ||||||
| LogLevel warn |  | ||||||
|  |  | ||||||
| <IfModule log_config_module> |  | ||||||
|     # |  | ||||||
|     # The following directives define some format nicknames for use with |  | ||||||
|     # a CustomLog directive (see below). |  | ||||||
|     # |  | ||||||
|     LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined |  | ||||||
|     LogFormat "%h %l %u %t \"%r\" %>s %b" common |  | ||||||
|  |  | ||||||
|     <IfModule logio_module> |  | ||||||
|       # You need to enable mod_logio.c to use %I and %O |  | ||||||
|       LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio |  | ||||||
|     </IfModule> |  | ||||||
|  |  | ||||||
|     # |  | ||||||
|     # The location and format of the access logfile (Common Logfile Format). |  | ||||||
|     # If you do not define any access logfiles within a <VirtualHost> |  | ||||||
|     # container, they will be logged here.  Contrariwise, if you *do* |  | ||||||
|     # define per-<VirtualHost> access logfiles, transactions will be |  | ||||||
|     # logged therein and *not* in this file. |  | ||||||
|     # |  | ||||||
|     CustomLog /proc/self/fd/1 common |  | ||||||
|  |  | ||||||
|     # |  | ||||||
|     # If you prefer a logfile with access, agent, and referer information |  | ||||||
|     # (Combined Logfile Format) you can use the following directive. |  | ||||||
|     # |  | ||||||
|     #CustomLog "logs/access_log" combined |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
| <IfModule alias_module> |  | ||||||
|     # |  | ||||||
|     # Redirect: Allows you to tell clients about documents that used to  |  | ||||||
|     # exist in your server's namespace, but do not anymore. The client  |  | ||||||
|     # will make a new request for the document at its new location. |  | ||||||
|     # Example: |  | ||||||
|     # Redirect permanent /foo http://www.example.com/bar |  | ||||||
|  |  | ||||||
|     # |  | ||||||
|     # Alias: Maps web paths into filesystem paths and is used to |  | ||||||
|     # access content that does not live under the DocumentRoot. |  | ||||||
|     # Example: |  | ||||||
|     # Alias /webpath /full/filesystem/path |  | ||||||
|     # |  | ||||||
|     # If you include a trailing / on /webpath then the server will |  | ||||||
|     # require it to be present in the URL.  You will also likely |  | ||||||
|     # need to provide a <Directory> section to allow access to |  | ||||||
|     # the filesystem path. |  | ||||||
|  |  | ||||||
|     # |  | ||||||
|     # ScriptAlias: This controls which directories contain server scripts.  |  | ||||||
|     # ScriptAliases are essentially the same as Aliases, except that |  | ||||||
|     # documents in the target directory are treated as applications and |  | ||||||
|     # run by the server when requested rather than as documents sent to the |  | ||||||
|     # client.  The same rules about trailing "/" apply to ScriptAlias |  | ||||||
|     # directives as to Alias. |  | ||||||
|     # |  | ||||||
|     ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/" |  | ||||||
|  |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
| <IfModule cgid_module> |  | ||||||
|     # |  | ||||||
|     # ScriptSock: On threaded servers, designate the path to the UNIX |  | ||||||
|     # socket used to communicate with the CGI daemon of mod_cgid. |  | ||||||
|     # |  | ||||||
|     #Scriptsock cgisock |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased |  | ||||||
| # CGI directory exists, if you have that configured. |  | ||||||
| # |  | ||||||
| <Directory "/usr/local/apache2/cgi-bin"> |  | ||||||
|     AllowOverride None |  | ||||||
|     Options None |  | ||||||
|     Require all granted |  | ||||||
| </Directory> |  | ||||||
|  |  | ||||||
| <IfModule headers_module> |  | ||||||
|     # |  | ||||||
|     # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied |  | ||||||
|     # backend servers which have lingering "httpoxy" defects. |  | ||||||
|     # 'Proxy' request header is undefined by the IETF, not listed by IANA |  | ||||||
|     # |  | ||||||
|     RequestHeader unset Proxy early |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
| <IfModule mime_module> |  | ||||||
|     # |  | ||||||
|     # TypesConfig points to the file containing the list of mappings from |  | ||||||
|     # filename extension to MIME-type. |  | ||||||
|     # |  | ||||||
|     TypesConfig conf/mime.types |  | ||||||
|  |  | ||||||
|     # |  | ||||||
|     # AddType allows you to add to or override the MIME configuration |  | ||||||
|     # file specified in TypesConfig for specific file types. |  | ||||||
|     # |  | ||||||
|     #AddType application/x-gzip .tgz |  | ||||||
|     # |  | ||||||
|     # AddEncoding allows you to have certain browsers uncompress |  | ||||||
|     # information on the fly. Note: Not all browsers support this. |  | ||||||
|     # |  | ||||||
|     #AddEncoding x-compress .Z |  | ||||||
|     #AddEncoding x-gzip .gz .tgz |  | ||||||
|     # |  | ||||||
|     # If the AddEncoding directives above are commented-out, then you |  | ||||||
|     # probably should define those extensions to indicate media types: |  | ||||||
|     # |  | ||||||
|     AddType application/x-compress .Z |  | ||||||
|     AddType application/x-gzip .gz .tgz |  | ||||||
|  |  | ||||||
|     # |  | ||||||
|     # AddHandler allows you to map certain file extensions to "handlers": |  | ||||||
|     # actions unrelated to filetype. These can be either built into the server |  | ||||||
|     # or added with the Action directive (see below) |  | ||||||
|     # |  | ||||||
|     # To use CGI scripts outside of ScriptAliased directories: |  | ||||||
|     # (You will also need to add "ExecCGI" to the "Options" directive.) |  | ||||||
|     # |  | ||||||
|     #AddHandler cgi-script .cgi |  | ||||||
|  |  | ||||||
|     # For type maps (negotiated resources): |  | ||||||
|     #AddHandler type-map var |  | ||||||
|  |  | ||||||
|     # |  | ||||||
|     # Filters allow you to process content before it is sent to the client. |  | ||||||
|     # |  | ||||||
|     # To parse .shtml files for server-side includes (SSI): |  | ||||||
|     # (You will also need to add "Includes" to the "Options" directive.) |  | ||||||
|     # |  | ||||||
|     #AddType text/html .shtml |  | ||||||
|     #AddOutputFilter INCLUDES .shtml |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # The mod_mime_magic module allows the server to use various hints from the |  | ||||||
| # contents of the file itself to determine its type.  The MIMEMagicFile |  | ||||||
| # directive tells the module where the hint definitions are located. |  | ||||||
| # |  | ||||||
| #MIMEMagicFile conf/magic |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Customizable error responses come in three flavors: |  | ||||||
| # 1) plain text 2) local redirects 3) external redirects |  | ||||||
| # |  | ||||||
| # Some examples: |  | ||||||
| #ErrorDocument 500 "The server made a boo boo." |  | ||||||
| #ErrorDocument 404 /missing.html |  | ||||||
| #ErrorDocument 404 "/cgi-bin/missing_handler.pl" |  | ||||||
| #ErrorDocument 402 http://www.example.com/subscription_info.html |  | ||||||
| # |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # MaxRanges: Maximum number of Ranges in a request before |  | ||||||
| # returning the entire resource, or one of the special |  | ||||||
| # values 'default', 'none' or 'unlimited'. |  | ||||||
| # Default setting is to accept 200 Ranges. |  | ||||||
| #MaxRanges unlimited |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # EnableMMAP and EnableSendfile: On systems that support it,  |  | ||||||
| # memory-mapping or the sendfile syscall may be used to deliver |  | ||||||
| # files.  This usually improves server performance, but must |  | ||||||
| # be turned off when serving from networked-mounted  |  | ||||||
| # filesystems or if support for these functions is otherwise |  | ||||||
| # broken on your system. |  | ||||||
| # Defaults: EnableMMAP On, EnableSendfile Off |  | ||||||
| # |  | ||||||
| #EnableMMAP off |  | ||||||
| #EnableSendfile on |  | ||||||
|  |  | ||||||
| # Supplemental configuration |  | ||||||
| # |  | ||||||
| # The configuration files in the conf/extra/ directory can be  |  | ||||||
| # included to add extra features or to modify the default configuration of  |  | ||||||
| # the server, or you may simply copy their contents here and change as  |  | ||||||
| # necessary. |  | ||||||
|  |  | ||||||
| # Server-pool management (MPM specific) |  | ||||||
| #Include conf/extra/httpd-mpm.conf |  | ||||||
|  |  | ||||||
| # Multi-language error messages |  | ||||||
| #Include conf/extra/httpd-multilang-errordoc.conf |  | ||||||
|  |  | ||||||
| # Fancy directory listings |  | ||||||
| #Include conf/extra/httpd-autoindex.conf |  | ||||||
|  |  | ||||||
| # Language settings |  | ||||||
| #Include conf/extra/httpd-languages.conf |  | ||||||
|  |  | ||||||
| # User home directories |  | ||||||
| #Include conf/extra/httpd-userdir.conf |  | ||||||
|  |  | ||||||
| # Real-time info on requests and configuration |  | ||||||
| #Include conf/extra/httpd-info.conf |  | ||||||
|  |  | ||||||
| # Virtual hosts |  | ||||||
| #Include conf/extra/httpd-vhosts.conf |  | ||||||
|  |  | ||||||
| # Local access to the Apache HTTP Server Manual |  | ||||||
| #Include conf/extra/httpd-manual.conf |  | ||||||
|  |  | ||||||
| # Distributed authoring and versioning (WebDAV) |  | ||||||
| #Include conf/extra/httpd-dav.conf |  | ||||||
|  |  | ||||||
| # Various default settings |  | ||||||
| #Include conf/extra/httpd-default.conf |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Configure mod_proxy_html to understand HTML4/XHTML1 |  | ||||||
| <IfModule proxy_html_module> |  | ||||||
| Include conf/extra/proxy-html.conf |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
| # Secure (SSL/TLS) connections |  | ||||||
| #Include conf/extra/httpd-ssl.conf |  | ||||||
| # |  | ||||||
| # Note: The following must must be present to support |  | ||||||
| #       starting without SSL on platforms with no /dev/random equivalent |  | ||||||
| #       but a statically compiled-in mod_ssl. |  | ||||||
| # |  | ||||||
| <IfModule ssl_module> |  | ||||||
| SSLRandomSeed startup builtin |  | ||||||
| SSLRandomSeed connect builtin |  | ||||||
| </IfModule> |  | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								front/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								front/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html lang="en"> | ||||||
|  |   <head> | ||||||
|  |     <meta charset="UTF-8" /> | ||||||
|  |     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||||
|  |     <title>Karusic</title> | ||||||
|  |     <link rel="icon" href="/favicon.ico" /> | ||||||
|  |   </head> | ||||||
|  |   <body style="width:100vw;height:100vh;min-width:100%;min-height:100%;"> | ||||||
|  |     <div id="root" style="width:100%;height:100%;min-width:100%;min-height:100%;"></div> | ||||||
|  |     <script type="module" src="/src/main.tsx"></script> | ||||||
|  |   </body> | ||||||
|  | </html> | ||||||
| @@ -1,31 +0,0 @@ | |||||||
| // Karma configuration file, see link for more information |  | ||||||
| // https://karma-runner.github.io/1.0/config/configuration-file.html |  | ||||||
|  |  | ||||||
| module.exports = function (config) { |  | ||||||
|   config.set({ |  | ||||||
|     basePath: '', |  | ||||||
|     frameworks: ['jasmine', '@angular-devkit/build-angular'], |  | ||||||
|     plugins: [ |  | ||||||
|       require('karma-jasmine'), |  | ||||||
|       require('karma-chrome-launcher'), |  | ||||||
|       require('karma-jasmine-html-reporter'), |  | ||||||
|       require('karma-coverage-istanbul-reporter'), |  | ||||||
|       require('@angular-devkit/build-angular/plugins/karma') |  | ||||||
|     ], |  | ||||||
|     client:{ |  | ||||||
|       clearContext: false // leave Jasmine Spec Runner output visible in browser |  | ||||||
|     }, |  | ||||||
|     coverageIstanbulReporter: { |  | ||||||
|       dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ], |  | ||||||
|       fixWebpackSourcePaths: true |  | ||||||
|     }, |  | ||||||
|      |  | ||||||
|     reporters: ['progress', 'kjhtml'], |  | ||||||
|     port: 9876, |  | ||||||
|     colors: true, |  | ||||||
|     logLevel: config.LOG_INFO, |  | ||||||
|     autoWatch: true, |  | ||||||
|     browsers: ['Chrome'], |  | ||||||
|     singleRun: false |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
							
								
								
									
										18
									
								
								front/knip.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								front/knip.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | import type { KnipConfig } from 'knip'; | ||||||
|  |  | ||||||
|  | const config: KnipConfig = { | ||||||
|  |   // Ignoring mostly shell binaries | ||||||
|  |   ignoreBinaries: ['export', 'sleep'], | ||||||
|  |   ignore: [ | ||||||
|  |     // Related to tests | ||||||
|  |     'tests/**', | ||||||
|  |     '**.conf.js', | ||||||
|  |     'steps.d.ts', | ||||||
|  |     'steps_file.js', | ||||||
|  |     'env_ci/codecept.conf.js', | ||||||
|  |     // Generic components are useful. | ||||||
|  |     'src/components/**', | ||||||
|  |   ], | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default config; | ||||||
| @@ -1,49 +1,111 @@ | |||||||
| { | { | ||||||
|   "name": "karusic", |   "name": "karusic", | ||||||
|   "version": "0.0.0", |  | ||||||
|   "license": "MPL-2", |  | ||||||
|   "scripts": { |  | ||||||
|     "all": "npm run build && pnpm run test", |  | ||||||
|     "ng": "ng", |  | ||||||
|     "dev": "ng serve --configuration=develop --watch --port 4203", |  | ||||||
|     "build": "ng build --prod", |  | ||||||
|     "test": "ng test", |  | ||||||
|     "lint": "ng lint", |  | ||||||
|     "style": "prettier --write .", |  | ||||||
|     "e2e": "ng e2e", |  | ||||||
|     "update_packages": "ncu --upgrade", |  | ||||||
|     "install_dependency": "pnpm install --force", |  | ||||||
|     "link_kar_cw": "pnpm link ../../kar-cw/dist/kar-cw/", |  | ||||||
|     "unlink_kar_cw": "pnpm unlink ../../kar-cw/dist/kar-cw/" |  | ||||||
|   }, |  | ||||||
|   "private": true, |   "private": true, | ||||||
|  |   "version": "0.0.1", | ||||||
|  |   "description": "KAR web music application", | ||||||
|  |   "author": { | ||||||
|  |     "name": "Edouard DUPIN", | ||||||
|  |     "email": "yui.heero@gmail.farm" | ||||||
|  |   }, | ||||||
|  |   "license": "PROPRIETARY", | ||||||
|  |   "engines": { | ||||||
|  |     "node": ">=20" | ||||||
|  |   }, | ||||||
|  |   "scripts": { | ||||||
|  |     "update_packages": "ncu --upgrade", | ||||||
|  |     "install_dependency": "pnpm install", | ||||||
|  |     "test": "vitest run", | ||||||
|  |     "test:watch": "vitest watch", | ||||||
|  |     "build": "tsc && vite build", | ||||||
|  |     "static:build": "node build.js && pnpm build", | ||||||
|  |     "dev": "vite", | ||||||
|  |     "pretty": "prettier -w .", | ||||||
|  |     "lint": "pnpm tsc --noEmit", | ||||||
|  |     "storybook": "storybook dev -p 3001", | ||||||
|  |     "storybook:build": "storybook build && mv ./storybook-static ./public/storybook" | ||||||
|  |   }, | ||||||
|  |   "lint-staged": { | ||||||
|  |     "*.{ts,tsx,js,jsx,json}": "prettier --write" | ||||||
|  |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@angular/animations": "^17.3.4", |     "@chakra-ui/anatomy": "2.2.2", | ||||||
|     "@angular/cdk": "^17.3.4", |     "@chakra-ui/cli": "2.4.1", | ||||||
|     "@angular/common": "^17.3.4", |     "@chakra-ui/react": "2.8.2", | ||||||
|     "@angular/compiler": "^17.3.4", |     "@chakra-ui/theme-tools": "2.2.6", | ||||||
|     "@angular/core": "^17.3.4", |     "@dnd-kit/core": "6.3.1", | ||||||
|     "@angular/forms": "^17.3.4", |     "@dnd-kit/modifiers": "9.0.0", | ||||||
|     "@angular/material": "^17.3.4", |     "@dnd-kit/sortable": "10.0.0", | ||||||
|     "@angular/platform-browser": "^17.3.4", |     "@dnd-kit/utilities": "3.2.2", | ||||||
|     "@angular/platform-browser-dynamic": "^17.3.4", |     "@emotion/react": "11.14.0", | ||||||
|     "@angular/router": "^17.3.4", |     "@emotion/styled": "11.14.0", | ||||||
|     "rxjs": "^7.8.1", |     "@formiz/core": "2.4.5", | ||||||
|     "zone.js": "^0.14.4", |     "@formiz/validations": "2.0.1", | ||||||
|     "zod": "3.22.4", |     "allotment": "1.20.2", | ||||||
|     "@kangaroo-and-rabbit/kar-cw": "^0.2.0" |     "css-mediaquery": "0.1.2", | ||||||
|  |     "dayjs": "1.11.13", | ||||||
|  |     "history": "5.3.0", | ||||||
|  |     "react": "18.3.1", | ||||||
|  |     "react-color-palette": "7.3.0", | ||||||
|  |     "react-currency-input-field": "3.9.0", | ||||||
|  |     "react-custom-scrollbars": "4.2.1", | ||||||
|  |     "react-day-picker": "9.5.0", | ||||||
|  |     "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.2", | ||||||
|  |     "react-select": "5.9.0", | ||||||
|  |     "react-simple-keyboard": "3.8.33", | ||||||
|  |     "react-sticky-el": "2.1.1", | ||||||
|  |     "react-use": "17.6.0", | ||||||
|  |     "react-use-draggable-scroll": "0.4.7", | ||||||
|  |     "react-virtuoso": "4.12.3", | ||||||
|  |     "ts-pattern": "5.6.0", | ||||||
|  |     "uuid": "11.0.4", | ||||||
|  |     "zod": "3.24.1", | ||||||
|  |     "zustand": "5.0.2" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@angular-devkit/build-angular": "^17.3.4", |     "@chakra-ui/styled-system": "2.12.0", | ||||||
|     "@angular-eslint/builder": "17.3.0", |     "@playwright/test": "1.49.1", | ||||||
|     "@angular-eslint/eslint-plugin": "17.3.0", |     "@storybook/addon-actions": "8.4.7", | ||||||
|     "@angular-eslint/eslint-plugin-template": "17.3.0", |     "@storybook/addon-essentials": "8.4.7", | ||||||
|     "@angular-eslint/schematics": "17.3.0", |     "@storybook/addon-links": "8.4.7", | ||||||
|     "@angular-eslint/template-parser": "17.3.0", |     "@storybook/addon-mdx-gfm": "8.4.7", | ||||||
|     "@angular/cli": "^17.3.4", |     "@storybook/react": "8.4.7", | ||||||
|     "@angular/compiler-cli": "^17.3.4", |     "@storybook/react-vite": "8.4.7", | ||||||
|     "@angular/language-service": "^17.3.4", |     "@storybook/theming": "8.4.7", | ||||||
|     "npm-check-updates": "^16.14.18", |     "@testing-library/jest-dom": "6.6.3", | ||||||
|     "tslib": "^2.6.2" |     "@testing-library/react": "16.1.0", | ||||||
|  |     "@testing-library/user-event": "14.5.2", | ||||||
|  |     "@trivago/prettier-plugin-sort-imports": "5.2.1", | ||||||
|  |     "@types/jest": "29.5.14", | ||||||
|  |     "@types/node": "22.10.5", | ||||||
|  |     "@types/react": "18.3.8", | ||||||
|  |     "@types/react-dom": "18.3.0", | ||||||
|  |     "@types/react-sticky-el": "1.0.7", | ||||||
|  |     "@typescript-eslint/eslint-plugin": "8.19.0", | ||||||
|  |     "@typescript-eslint/parser": "8.19.0", | ||||||
|  |     "@vitejs/plugin-react": "4.3.4", | ||||||
|  |     "eslint": "9.17.0", | ||||||
|  |     "eslint-plugin-codeceptjs": "1.3.0", | ||||||
|  |     "eslint-plugin-import": "2.31.0", | ||||||
|  |     "eslint-plugin-react": "7.37.3", | ||||||
|  |     "eslint-plugin-react-hooks": "5.1.0", | ||||||
|  |     "eslint-plugin-storybook": "0.11.2", | ||||||
|  |     "jest": "29.7.0", | ||||||
|  |     "jest-environment-jsdom": "29.7.0", | ||||||
|  |     "knip": "5.41.1", | ||||||
|  |     "lint-staged": "15.3.0", | ||||||
|  |     "npm-check-updates": "^17.1.13", | ||||||
|  |     "prettier": "3.4.2", | ||||||
|  |     "puppeteer": "23.11.1", | ||||||
|  |     "react-is": "19.0.0", | ||||||
|  |     "storybook": "8.4.7", | ||||||
|  |     "ts-node": "10.9.2", | ||||||
|  |     "typescript": "5.7.2", | ||||||
|  |     "vite": "6.0.7", | ||||||
|  |     "vitest": "2.1.8" | ||||||
|   } |   } | ||||||
| } | } | ||||||
							
								
								
									
										18438
									
								
								front/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										18438
									
								
								front/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										16
									
								
								front/prettier.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								front/prettier.config.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | // Using a JS file, allowing us to add comments | ||||||
|  | module.exports = { | ||||||
|  |   // This plugins line is mandatory for the plugin to work with pnpm. | ||||||
|  |   // https://github.com/trivago/prettier-plugin-sort-imports/blob/61d069711008c530f5a41ca4e254781abc5de358/README.md?plain=1#L89-L96 | ||||||
|  |   plugins: ['@trivago/prettier-plugin-sort-imports'], | ||||||
|  |   endOfLine: 'lf', | ||||||
|  |   semi: true, | ||||||
|  |   singleQuote: true, | ||||||
|  |   tabWidth: 2, | ||||||
|  |   trailingComma: 'es5', | ||||||
|  |   arrowParens: 'always', | ||||||
|  |   importOrder: ['^react$', '^(?!^react$|^@/|^[./]).*', '^@/(.*)$', '^[./]'], | ||||||
|  |   importOrderSeparation: true, | ||||||
|  |   importOrderSortSpecifiers: true, | ||||||
|  |   importOrderParserPlugins: ['jsx', 'typescript'], | ||||||
|  | }; | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| // Protractor configuration file, see link for more information |  | ||||||
| // https://github.com/angular/protractor/blob/master/lib/config.ts |  | ||||||
|  |  | ||||||
| const { SpecReporter } = require('jasmine-spec-reporter'); |  | ||||||
|  |  | ||||||
| exports.config = { |  | ||||||
|   allScriptsTimeout: 11000, |  | ||||||
|   specs: [ |  | ||||||
|     './e2e/**/*.e2e-spec.ts' |  | ||||||
|   ], |  | ||||||
|   capabilities: { |  | ||||||
|     'browserName': 'chrome' |  | ||||||
|   }, |  | ||||||
|   directConnect: true, |  | ||||||
|   baseUrl: 'http://localhost:4200/', |  | ||||||
|   framework: 'jasmine', |  | ||||||
|   jasmineNodeOpts: { |  | ||||||
|     showColors: true, |  | ||||||
|     defaultTimeoutInterval: 30000, |  | ||||||
|     print: function() {} |  | ||||||
|   }, |  | ||||||
|   onPrepare() { |  | ||||||
|     require('ts-node').register({ |  | ||||||
|       project: 'e2e/tsconfig.e2e.json' |  | ||||||
|     }); |  | ||||||
|     jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB | 
| @@ -1,43 +0,0 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| Start the application: |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ``` |  | ||||||
| npm install |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| upgrade package |  | ||||||
| ``` |  | ||||||
| npm audit fix |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ## npm install -g angular-cli |  | ||||||
|  |  | ||||||
| start the application: |  | ||||||
| ``` |  | ||||||
| npx ng serve --watch |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| plus facilement: |  | ||||||
| npm install @angular-devkit/build-angular@0.901.9 |  | ||||||
| npm start |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| Apply linter: |  | ||||||
| ============== |  | ||||||
| ``` |  | ||||||
| npx ng lint |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| build the local image: |  | ||||||
|  |  | ||||||
| docker build -t gitea.atria-soft.org/kangaroo-and-rabbit/karusic:latest . |  | ||||||
|  |  | ||||||
| docker login gitea.atria-soft.org |  | ||||||
|  |  | ||||||
| docker push gitea.atria-soft.org/kangaroo-and-rabbit/karusic:latest |  | ||||||
|  |  | ||||||
							
								
								
									
										118
									
								
								front/src/App.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								front/src/App.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | |||||||
|  | import { useState } from 'react'; | ||||||
|  |  | ||||||
|  | import { ChakraProvider, Select } from '@chakra-ui/react'; | ||||||
|  | import { | ||||||
|  |   Box, | ||||||
|  |   Button, | ||||||
|  |   Modal, | ||||||
|  |   ModalBody, | ||||||
|  |   ModalCloseButton, | ||||||
|  |   ModalContent, | ||||||
|  |   ModalFooter, | ||||||
|  |   ModalHeader, | ||||||
|  |   ModalOverlay, | ||||||
|  |   Stack, | ||||||
|  |   Text, | ||||||
|  |   useDisclosure, | ||||||
|  | } from '@chakra-ui/react'; | ||||||
|  |  | ||||||
|  | import { environment } from '@/environment'; | ||||||
|  | import { App as SpaApp } from '@/scene/App'; | ||||||
|  | import { USERS } from '@/service/session'; | ||||||
|  | import theme from '@/theme'; | ||||||
|  | import { hashLocalData } from '@/utils/sso'; | ||||||
|  |  | ||||||
|  | const AppEnvHint = () => { | ||||||
|  |   const modal = useDisclosure(); | ||||||
|  |   const [selectUserTest, setSelectUserTest] = useState<string>('NO_USER'); | ||||||
|  |   //const setUser = useRightsStore((store) => store.setUser); | ||||||
|  |   const buildEnv = | ||||||
|  |     process.env.NODE_ENV === 'development' | ||||||
|  |       ? 'Development' | ||||||
|  |       : import.meta.env.VITE_DEV_ENV_NAME; | ||||||
|  |   const envName: Array<string> = []; | ||||||
|  |   !!buildEnv && envName.push(buildEnv); | ||||||
|  |   if (!envName.length) { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  |   const handleChange = (selectedOption) => { | ||||||
|  |     console.log(`SELECT: [${selectedOption.target.value}]`); | ||||||
|  |     setSelectUserTest(selectedOption.target.value); | ||||||
|  |   }; | ||||||
|  |   const onClose = () => { | ||||||
|  |     modal.onClose(); | ||||||
|  |     if (selectUserTest == 'NO_USER') { | ||||||
|  |       window.location.href = `/${environment.applName}/sso/${hashLocalData()}/false/__LOGOUT__`; | ||||||
|  |     } else { | ||||||
|  |       window.location.href = `/${environment.applName}/sso/${hashLocalData()}/true/${USERS[selectUserTest]}`; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <> | ||||||
|  |       <Box | ||||||
|  |         zIndex="100000" | ||||||
|  |         position="fixed" | ||||||
|  |         top="0" | ||||||
|  |         insetStart="0" | ||||||
|  |         insetEnd="0" | ||||||
|  |         h="2px" | ||||||
|  |         bg="warning.400" | ||||||
|  |         as="button" | ||||||
|  |         cursor="pointer" | ||||||
|  |         data-test-id="devtools" | ||||||
|  |         onClick={modal.onOpen} | ||||||
|  |       > | ||||||
|  |         <Text | ||||||
|  |           position="fixed" | ||||||
|  |           top="0" | ||||||
|  |           insetStart="4" | ||||||
|  |           bg="warning.400" | ||||||
|  |           color="warning.900" | ||||||
|  |           fontSize="0.6rem" | ||||||
|  |           fontWeight="bold" | ||||||
|  |           px="10px" | ||||||
|  |           marginLeft="25%" | ||||||
|  |           borderBottomStartRadius="sm" | ||||||
|  |           borderBottomEndRadius="sm" | ||||||
|  |           textTransform="uppercase" | ||||||
|  |         > | ||||||
|  |           {envName.join(' : ')} | ||||||
|  |         </Text> | ||||||
|  |       </Box> | ||||||
|  |       <Modal isOpen={modal.isOpen} onClose={modal.onClose}> | ||||||
|  |         <ModalOverlay /> | ||||||
|  |         <ModalContent> | ||||||
|  |           <ModalHeader>Outils développeurs</ModalHeader> | ||||||
|  |           <ModalCloseButton /> | ||||||
|  |           <ModalBody> | ||||||
|  |             <Stack> | ||||||
|  |               <Text>Utilisateur</Text> | ||||||
|  |               <Select placeholder="Select test user" onChange={handleChange}> | ||||||
|  |                 {Object.keys(USERS).map((key) => ( | ||||||
|  |                   <option value={key} key={key}> | ||||||
|  |                     {key} | ||||||
|  |                   </option> | ||||||
|  |                 ))} | ||||||
|  |               </Select> | ||||||
|  |             </Stack> | ||||||
|  |           </ModalBody> | ||||||
|  |           <ModalFooter> | ||||||
|  |             <Button onClick={onClose}>Apply</Button> | ||||||
|  |           </ModalFooter> | ||||||
|  |         </ModalContent> | ||||||
|  |       </Modal> | ||||||
|  |     </> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const App = () => { | ||||||
|  |   return ( | ||||||
|  |     <ChakraProvider theme={theme}> | ||||||
|  |       <AppEnvHint /> | ||||||
|  |       <SpaApp /> | ||||||
|  |     </ChakraProvider> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default App; | ||||||
| @@ -1,184 +0,0 @@ | |||||||
| /** @file |  | ||||||
|  * @author Edouard DUPIN |  | ||||||
|  * @copyright 2018, Edouard DUPIN, all right reserved |  | ||||||
|  * @license PROPRIETARY (see license file) |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| import { NgModule } from '@angular/core'; |  | ||||||
| import { Routes, RouterModule } from '@angular/router'; // CLI imports router |  | ||||||
|  |  | ||||||
| import { |  | ||||||
| 	HelpScene, HomeScene, AlbumEditScene, AlbumsScene, ArtistEditScene, ArtistScene, SettingsScene, |  | ||||||
| 	GenderScene, PlaylistScene, TrackEditScene, TrackScene, UploadScene, ArtistsScene, ArtistAlbumScene, AlbumScene |  | ||||||
| } from './scene'; |  | ||||||
| import { ForbiddenScene, OnlyUsersGuardHome, HomeOutScene, OnlyUnregisteredGuardHome, SsoScene, OnlyAdminGuard, OnlyUsersGuard, NotFound404Scene } from '@kangaroo-and-rabbit/kar-cw'; |  | ||||||
|  |  | ||||||
| // import { HelpComponent } from './help/help.component'; |  | ||||||
|  |  | ||||||
| // see https://angular.io/guide/router |  | ||||||
|  |  | ||||||
|  |  | ||||||
| const routes: Routes = [ |  | ||||||
| 	{ path: '', redirectTo: '/home', pathMatch: 'full' }, |  | ||||||
|  |  | ||||||
| 	{ path: 'forbidden', component: ForbiddenScene }, |  | ||||||
|  |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- home global interface |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	{ |  | ||||||
| 		path: 'home', |  | ||||||
| 		component: HomeScene, |  | ||||||
| 		canActivate: [OnlyUsersGuardHome], // this route to unregistered path when not logged ==> permit to simplify display |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		path: 'unregistered', |  | ||||||
| 		component: HomeOutScene, |  | ||||||
| 		canActivate: [OnlyUnregisteredGuardHome], // jump to the home when registered |  | ||||||
| 	}, |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- SSO Generic interface |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	{ path: 'sso/:data/:keepConnected/:token', component: SsoScene }, |  | ||||||
| 	{ path: 'sso/:keepConnected/:token', component: SsoScene }, |  | ||||||
| 	{ path: 'sso', component: SsoScene }, |  | ||||||
|  |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- Generic pages |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	{ path: 'help/:page', component: HelpScene }, |  | ||||||
| 	{ path: 'help', component: HelpScene }, |  | ||||||
|  |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- upload new data: |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	{ |  | ||||||
| 		path: 'upload', |  | ||||||
| 		component: UploadScene, |  | ||||||
| 		canActivate: [OnlyAdminGuard], |  | ||||||
| 	}, |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- gender: |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// display all gender |  | ||||||
| 	{ |  | ||||||
| 		path: 'gender', |  | ||||||
| 		component: GenderScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
| 	// display all (artist | album | tracks) |  | ||||||
| 	{ |  | ||||||
| 		path: 'gender/:genderId', |  | ||||||
| 		component: GenderScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
| 	//{ path: 'gender-edit/:genderId', component: GenderEditScene }, |  | ||||||
|  |  | ||||||
| 	//{ path: 'gender/:genderId', component: GenderScene }, |  | ||||||
| 	//{ path: 'gender/:genderId/:artistId/:albumId/:trackId', component: GenderScene }, |  | ||||||
|  |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- playlist: |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	{ |  | ||||||
| 		path: 'playlist', |  | ||||||
| 		component: PlaylistScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		path: 'playlist/:playlistId', |  | ||||||
| 		component: PlaylistScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
|  |  | ||||||
| 	//{ path: 'playlist-edit/:playlistId', component: PlaylistEditScene }, |  | ||||||
|  |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- Artist: |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// display list of all artist |  | ||||||
| 	{ |  | ||||||
| 		path: 'artist', |  | ||||||
| 		component: ArtistsScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
| 	// display list af all artist with a specific gender |  | ||||||
| 	{ |  | ||||||
| 		path: 'artist/:artistId', |  | ||||||
| 		component: ArtistScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		path: 'artist/:artistId/edit', |  | ||||||
| 		component: ArtistEditScene, |  | ||||||
| 		canActivate: [OnlyAdminGuard], |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		path: 'artist/:artistId/:albumId', |  | ||||||
| 		component: ArtistAlbumScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
|  |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- Album: |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// display all Album |  | ||||||
| 	{ |  | ||||||
| 		path: 'album', |  | ||||||
| 		component: AlbumsScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		path: 'album/:albumId/edit', |  | ||||||
| 		component: AlbumEditScene, |  | ||||||
| 		canActivate: [OnlyAdminGuard], |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		path: 'album/:albumId', |  | ||||||
| 		component: AlbumScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
|  |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- Tracks: |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	{ |  | ||||||
| 		path: 'track/:trackId/edit', |  | ||||||
| 		component: TrackEditScene, |  | ||||||
| 		canActivate: [OnlyAdminGuard], |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		path: 'track/:genderId/:artistId/:albumId/:trackId', |  | ||||||
| 		component: TrackScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
|  |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	// -- setting: |  | ||||||
| 	// ------------------------------------ |  | ||||||
| 	{ |  | ||||||
| 		path: 'settings', |  | ||||||
| 		component: SettingsScene, |  | ||||||
| 		canActivate: [OnlyUsersGuard], |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		path: '**', |  | ||||||
| 		component: NotFound404Scene, |  | ||||||
| 	}, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| @NgModule({ |  | ||||||
| 	imports: [ |  | ||||||
| 		RouterModule.forRoot( |  | ||||||
| 			routes, |  | ||||||
| 			{ |  | ||||||
| 				//enableTracing: true, // <-- debugging purposes only |  | ||||||
| 			}, |  | ||||||
| 		), |  | ||||||
| 	], |  | ||||||
| 	exports: [ |  | ||||||
| 		RouterModule, |  | ||||||
| 	] |  | ||||||
| }) |  | ||||||
| export class AppRoutingModule { } |  | ||||||
|  |  | ||||||
| @@ -1,17 +0,0 @@ | |||||||
| <!-- Generic global menu --> |  | ||||||
| <karcw-top-menu [menu]="currentMenu" (callback)="eventOnMenu($event)"/> |  | ||||||
| <!-- all interfaced pages --> |  | ||||||
| <div class="main-content"> |  | ||||||
| @if(autoConnectedDone) { |  | ||||||
| 	<router-outlet ></router-outlet> |  | ||||||
| } |  | ||||||
| @else { |  | ||||||
| 	<div class="generic-page"> |  | ||||||
| 		<div class="fill-all colomn_mutiple"> |  | ||||||
| 			<b style="color:red;">Auto-connection in progress</b> |  | ||||||
| 			<div class="clear"></div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| } |  | ||||||
| </div> |  | ||||||
| <app-element-player-audio></app-element-player-audio> |  | ||||||
| @@ -1,46 +0,0 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| #create-exercice-button { |  | ||||||
| 	position: fixed; |  | ||||||
| 	display: block; |  | ||||||
| 	right: 0; |  | ||||||
| 	bottom: 0; |  | ||||||
| 	margin-right: 40px; |  | ||||||
| 	margin-bottom: 40px; |  | ||||||
| 	z-index: 900; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #save-exercice-button { |  | ||||||
| 	position: fixed; |  | ||||||
| 	display: block; |  | ||||||
| 	right: 0; |  | ||||||
| 	bottom: 0; |  | ||||||
| 	margin-right: 110px; |  | ||||||
| 	margin-bottom: 40px; |  | ||||||
| 	z-index: 900; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .main-content { |  | ||||||
| 	position: absolute; |  | ||||||
| 	//width: ~"calc(calc(100% / 5 ) * 5)"; |  | ||||||
| 	width: 100%; |  | ||||||
| 	height: ~"calc(100% - 56px)"; |  | ||||||
| 	top: 56px; |  | ||||||
| 	left: 0; |  | ||||||
| 	margin: 0; |  | ||||||
| 	padding: 0; |  | ||||||
| 	display: block; |  | ||||||
| 	position: fixed; |  | ||||||
| 	overflow-y: auto; |  | ||||||
| 	//background-color:#FF0; |  | ||||||
| 	/* |  | ||||||
| 	.main-reduce { |  | ||||||
| 		width: 40%; |  | ||||||
| 		height: 100%; |  | ||||||
| 		margin: 0; |  | ||||||
| 		padding: 0px 10% 0px 10%; |  | ||||||
| 		display: block; |  | ||||||
| 		overflow-y:scroll; |  | ||||||
| 	} |  | ||||||
| 	*/ |  | ||||||
| } |  | ||||||
| @@ -1,300 +0,0 @@ | |||||||
| /** @file |  | ||||||
|  * @author Edouard DUPIN |  | ||||||
|  * @copyright 2018, Edouard DUPIN, all right reserved |  | ||||||
|  * @license PROPRIETARY (see license file) |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| import { Component, OnInit } from '@angular/core'; |  | ||||||
| import { ArianeService } from './service'; |  | ||||||
| import { |  | ||||||
| 	MenuItem, |  | ||||||
| 	SSOService, |  | ||||||
| 	SessionService, |  | ||||||
| 	UserService, |  | ||||||
| 	UserRoles222, |  | ||||||
| 	EventOnMenu, |  | ||||||
| 	MenuPosition, |  | ||||||
| 	isNullOrUndefined, |  | ||||||
| } from '@kangaroo-and-rabbit/kar-cw'; |  | ||||||
|  |  | ||||||
| enum MenuEventType { |  | ||||||
| 	SSO_LOGIN = "SSO_CALL_LOGIN", |  | ||||||
| 	SSO_LOGOUT = "SSO_CALL_LOGOUT", |  | ||||||
| 	SSO_SIGNUP = "SSO_CALL_SIGNUP", |  | ||||||
| 	SEGMENT = "SEGMENT", |  | ||||||
| 	TYPE = "TYPE", |  | ||||||
| 	ARTIST = "ARTIST", |  | ||||||
| 	ALBUM = "ALBUM", |  | ||||||
| 	TRACK = "TRACK", |  | ||||||
| 	PLAYLIST = "PLAYLIST", |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @Component({ |  | ||||||
| 	selector: 'app-root', |  | ||||||
| 	templateUrl: './app.component.html', |  | ||||||
| 	styleUrls: [ |  | ||||||
| 		'./app.component.less', |  | ||||||
| 	] |  | ||||||
| }) |  | ||||||
| export class AppComponent implements OnInit { |  | ||||||
| 	title: string = 'Karideo'; |  | ||||||
| 	autoConnectedDone: boolean = false; |  | ||||||
| 	isConnected: boolean = false; |  | ||||||
| 	signUpEnable: boolean = true; |  | ||||||
| 	currentMenu: MenuItem[] = []; |  | ||||||
| 	location: string = "home"; |  | ||||||
|  |  | ||||||
| 	constructor( |  | ||||||
| 		private sessionService: SessionService, |  | ||||||
| 		private ssoService: SSOService, |  | ||||||
| 		private arianeService: ArianeService, |  | ||||||
| 		private userService: UserService |  | ||||||
| 	) { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ngOnInit() { |  | ||||||
| 		this.autoConnectedDone = false; |  | ||||||
| 		this.isConnected = false; |  | ||||||
| 		this.updateMainMenu(); |  | ||||||
| 		let self = this; |  | ||||||
| 		this.sessionService.change.subscribe((isConnected) => { |  | ||||||
| 			console.log(`receive event from session ...${isConnected}`); |  | ||||||
| 			self.isConnected = isConnected; |  | ||||||
| 			self.autoConnectedDone = true; |  | ||||||
| 			self.updateMainMenu(); |  | ||||||
| 		}); |  | ||||||
| 		this.ssoService.checkSignUpEnable() |  | ||||||
| 			.then((value: boolean) => { |  | ||||||
| 				console.log(`Get value signUp = ${value}`); |  | ||||||
| 				self.signUpEnable = value; |  | ||||||
| 				self.updateMainMenu(); |  | ||||||
| 			}).catch((error: any) => { |  | ||||||
| 				console.log(`Can not call the sso to check the sign-up_interface: ${error}`); |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 		this.userService.checkAutoConnect().then(() => { |  | ||||||
| 			console.log(`    ==>>>>> Autoconnect THEN !!!`); |  | ||||||
| 			self.autoConnectedDone = true; |  | ||||||
| 		}).catch(() => { |  | ||||||
| 			console.log(`    ==>>>>> Autoconnect CATCH !!!`); |  | ||||||
| 			self.autoConnectedDone = true; |  | ||||||
| 		}).finally(() => { |  | ||||||
| 			console.log(`    ==>>>>> Autoconnect FINALLY !!!`); |  | ||||||
| 			self.autoConnectedDone = true; |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.arianeService.segmentChange.subscribe((_segmentName: string) => { |  | ||||||
| 			//console.log(`>>> change typeId=${typeId}`); |  | ||||||
| 			self.updateMainMenu(); |  | ||||||
| 		}); |  | ||||||
| 		this.arianeService.typeChange.subscribe((_typeId: number) => { |  | ||||||
| 			//console.log(`>>> change typeId=${typeId}`); |  | ||||||
| 			self.updateMainMenu(); |  | ||||||
| 		}); |  | ||||||
| 		this.arianeService.playlistChange.subscribe((_universId: number) => { |  | ||||||
| 			//console.log(`>>> change universId=${universId}`); |  | ||||||
| 			self.updateMainMenu(); |  | ||||||
| 		}); |  | ||||||
| 		this.arianeService.artistChange.subscribe((_artistId: number) => { |  | ||||||
| 			//console.log(`>>> change artistId=${artistId}`); |  | ||||||
| 			self.updateMainMenu(); |  | ||||||
| 		}); |  | ||||||
| 		this.arianeService.albumChange.subscribe((_albumId: number) => { |  | ||||||
| 			//console.log(`>>> change albumId=${albumId}`); |  | ||||||
| 			self.updateMainMenu(); |  | ||||||
| 		}); |  | ||||||
| 		this.arianeService.trackChange.subscribe((_trackId: number) => { |  | ||||||
| 			//console.log(`>>> change trackId=${trackId}`); |  | ||||||
| 			self.updateMainMenu(); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	eventOnMenu(data: EventOnMenu): void { |  | ||||||
| 		console.log(`Get event on menu: ${JSON.stringify(data, null, 4)}`); |  | ||||||
| 		switch (data.menu.otherData) { |  | ||||||
| 			case MenuEventType.SSO_LOGIN: |  | ||||||
| 				this.ssoService.requestSignIn(); |  | ||||||
| 				break; |  | ||||||
| 			case MenuEventType.SSO_LOGOUT: |  | ||||||
| 				this.ssoService.requestSignOut(); |  | ||||||
| 				break; |  | ||||||
| 			case MenuEventType.SSO_SIGNUP: |  | ||||||
| 				this.ssoService.requestSignUp(); |  | ||||||
| 				break; |  | ||||||
| 			case MenuEventType.SEGMENT: |  | ||||||
| 				if (this.arianeService.getCurrrentSegment() === "artist") { |  | ||||||
| 					this.arianeService.navigateArtist({}); |  | ||||||
| 				} else if (this.arianeService.getCurrrentSegment() === "gender") { |  | ||||||
| 					this.arianeService.navigateGender({}); |  | ||||||
| 				} else if (this.arianeService.getCurrrentSegment() === "playlist") { |  | ||||||
| 					this.arianeService.navigatePlaylist({}); |  | ||||||
| 				} else if (this.arianeService.getCurrrentSegment() === "track") { |  | ||||||
| 					this.arianeService.navigateTrack({}); |  | ||||||
| 				} else if (this.arianeService.getCurrrentSegment() === "album") { |  | ||||||
| 					this.arianeService.navigateAlbum({}); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 			case MenuEventType.TYPE: |  | ||||||
|  |  | ||||||
| 				break; |  | ||||||
| 			case MenuEventType.ARTIST: |  | ||||||
| 				if (this.arianeService.getCurrrentSegment() === "artist") { |  | ||||||
| 					this.arianeService.navigateArtist({ artistId: this.arianeService.getArtistId() }); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 			case MenuEventType.ALBUM: |  | ||||||
| 				break; |  | ||||||
| 			case MenuEventType.TRACK: |  | ||||||
| 				break; |  | ||||||
| 			case MenuEventType.PLAYLIST: |  | ||||||
| 				break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	updateMainMenu(): void { |  | ||||||
| 		console.log("update main menu :"); |  | ||||||
|  |  | ||||||
| 		if (this.isConnected) { |  | ||||||
| 			this.currentMenu = [ |  | ||||||
| 				{ |  | ||||||
| 					position: MenuPosition.LEFT, |  | ||||||
| 					hover: "lkjljlk", //`You are logged as: ${this.sessionService.getLogin()}`, |  | ||||||
| 					icon: "menu", |  | ||||||
| 					title: "Menu", |  | ||||||
| 					subMenu: [ |  | ||||||
| 						{ |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							hover: "Go to Home page", |  | ||||||
| 							icon: "home", |  | ||||||
| 							title: "Home", |  | ||||||
| 							navigateTo: "home", |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "group_work", |  | ||||||
| 							title: this.getSegmentDisplayable(), |  | ||||||
| 							otherData: MenuEventType.SEGMENT, |  | ||||||
| 							callback: true, |  | ||||||
| 							enable: this.getSegmentDisplayable() !== "", |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "piano", |  | ||||||
| 							title: this.getSegmentDisplayable(), |  | ||||||
| 							otherData: MenuEventType.TYPE, |  | ||||||
| 							callback: true, |  | ||||||
| 							enable: !isNullOrUndefined(this.arianeService.getTypeId()), |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "person", |  | ||||||
| 							title: this.arianeService.getArtistName(), |  | ||||||
| 							otherData: MenuEventType.ARTIST, |  | ||||||
| 							callback: true, |  | ||||||
| 							enable: !isNullOrUndefined(this.arianeService.getArtistId()), |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "album", |  | ||||||
| 							title: this.arianeService.getAlbumName(), |  | ||||||
| 							otherData: MenuEventType.ALBUM, |  | ||||||
| 							callback: true, |  | ||||||
| 							enable: !isNullOrUndefined(this.arianeService.getAlbumId()), |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "music_note", |  | ||||||
| 							title: this.arianeService.getTrackName(), |  | ||||||
| 							otherData: MenuEventType.TRACK, |  | ||||||
| 							callback: true, |  | ||||||
| 							enable: !isNullOrUndefined(this.arianeService.getTrackId()), |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "queue_music", |  | ||||||
| 							title: "true",//this.arianeService.getPlaylistName(), |  | ||||||
| 							otherData: MenuEventType.PLAYLIST, |  | ||||||
| 							callback: true, |  | ||||||
| 							enable: !isNullOrUndefined(this.arianeService.getPlaylistId()), |  | ||||||
| 						} |  | ||||||
| 					], |  | ||||||
| 				}, { |  | ||||||
| 					position: MenuPosition.RIGHT, |  | ||||||
| 					image: "assets/images/avatar_generic.svg", |  | ||||||
| 					title: "", |  | ||||||
| 					subMenu: [ |  | ||||||
| 						{ |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							hover: `You are logged as: <b>${this.sessionService.getLogin()}</b>`, |  | ||||||
| 							title: `Sign in as ${this.sessionService.getLogin()}`, |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "add_circle", |  | ||||||
| 							title: "Add media", |  | ||||||
| 							navigateTo: "upload", |  | ||||||
| 							enable: this.sessionService.hasRight(UserRoles222.admin), |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "settings", |  | ||||||
| 							title: "Settings", |  | ||||||
| 							navigateTo: "settings", |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							icon: "help", |  | ||||||
| 							title: "Help", |  | ||||||
| 							navigateTo: "help", |  | ||||||
| 						}, { |  | ||||||
| 							position: MenuPosition.LEFT, |  | ||||||
| 							hover: "Exit connection", |  | ||||||
| 							icon: "exit_to_app", |  | ||||||
| 							title: "Sign out", |  | ||||||
| 							callback: true, |  | ||||||
| 							otherData: MenuEventType.SSO_LOGOUT, |  | ||||||
| 						}, |  | ||||||
| 					], |  | ||||||
| 				}, |  | ||||||
| 			]; |  | ||||||
| 		} else { |  | ||||||
| 			this.currentMenu = [ |  | ||||||
| 				{ |  | ||||||
| 					position: MenuPosition.LEFT, |  | ||||||
| 					hover: "Go to Home page", |  | ||||||
| 					icon: "home", |  | ||||||
| 					title: "Home", |  | ||||||
| 					navigateTo: "home", |  | ||||||
| 				}, { |  | ||||||
| 					position: MenuPosition.RIGHT, |  | ||||||
| 					hover: "Create a new account", |  | ||||||
| 					icon: "add_circle_outline", |  | ||||||
| 					title: "Sign-up", |  | ||||||
| 					callback: true, |  | ||||||
| 					model: this.signUpEnable ? undefined : "disable", |  | ||||||
| 					otherData: MenuEventType.SSO_SIGNUP, |  | ||||||
| 				}, { |  | ||||||
| 					position: MenuPosition.RIGHT, |  | ||||||
| 					hover: "Login page", |  | ||||||
| 					icon: "account_circle", |  | ||||||
| 					title: "Sign-in", |  | ||||||
| 					callback: true, |  | ||||||
| 					otherData: MenuEventType.SSO_LOGIN, |  | ||||||
| 				}, |  | ||||||
| 			]; |  | ||||||
| 		} |  | ||||||
| 		console.log(" ==> DONE"); |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
| 	getSegmentDisplayable(): string { |  | ||||||
| 		let segment = this.arianeService.getCurrrentSegment(); |  | ||||||
| 		if (segment === "artist") { |  | ||||||
| 			return "Artists" |  | ||||||
| 		} |  | ||||||
| 		if (segment === "gender") { |  | ||||||
| 			return "Genders" |  | ||||||
| 		} |  | ||||||
| 		if (segment === "album") { |  | ||||||
| 			return "Albums" |  | ||||||
| 		} |  | ||||||
| 		if (segment === "track") { |  | ||||||
| 			return "Tracks" |  | ||||||
| 		} |  | ||||||
| 		if (segment === "playlist") { |  | ||||||
| 			return "Playlist" |  | ||||||
| 		} |  | ||||||
| 		return ""; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @@ -1,96 +0,0 @@ | |||||||
| /** @file |  | ||||||
|  * @author Edouard DUPIN |  | ||||||
|  * @copyright 2018, Edouard DUPIN, all right reserved |  | ||||||
|  * @license PROPRIETARY (see license file) |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| import { BrowserModule } from '@angular/platform-browser'; |  | ||||||
| import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, NgModule } from '@angular/core'; |  | ||||||
| import { RouterModule } from '@angular/router'; |  | ||||||
| import { HttpClientModule } from '@angular/common/http'; |  | ||||||
| import { AppRoutingModule } from './app-routing.module'; |  | ||||||
|  |  | ||||||
| import { ElementDataImageComponent } from './component/data-image/data-image'; |  | ||||||
| import { ElementTypeComponent } from './component/element-type/element-type'; |  | ||||||
|  |  | ||||||
| import { PopInCreateType } from './popin/create-type/create-type'; |  | ||||||
|  |  | ||||||
| import { AppComponent } from './app.component'; |  | ||||||
| import { |  | ||||||
| 	HomeScene, HelpScene, GenderScene, PlaylistScene, ArtistScene, AlbumScene, AlbumsScene, TrackScene, SettingsScene, |  | ||||||
| 	TrackEditScene, AlbumEditScene, ArtistEditScene, ArtistsScene, ArtistAlbumScene |  | ||||||
| } from './scene'; |  | ||||||
| import { GenderService, DataService, PlaylistService, ArtistService, AlbumService, TrackService, ArianeService, PlayerService } from './service'; |  | ||||||
| import { UploadScene } from './scene/upload/upload'; |  | ||||||
| import { ElementSeriesComponent, ElementTrackComponent, ElementSeasonComponent, ElementVideoComponent, ElementPlayerAudioComponent, DescriptionAreaComponent } from './component'; |  | ||||||
| import { KarCWModule } from '@kangaroo-and-rabbit/kar-cw'; |  | ||||||
| import { environment } from 'environments/environment'; |  | ||||||
|  |  | ||||||
| import { FormsModule, ReactiveFormsModule } from "@angular/forms"; |  | ||||||
| import { CommonModule } from "@angular/common"; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @NgModule({ |  | ||||||
| 	declarations: [ |  | ||||||
| 		AppComponent, |  | ||||||
| 		ElementDataImageComponent, |  | ||||||
| 		ElementTypeComponent, |  | ||||||
| 		ElementSeriesComponent, |  | ||||||
| 		ElementTrackComponent, |  | ||||||
| 		ElementSeasonComponent, |  | ||||||
| 		ElementVideoComponent, |  | ||||||
| 		ElementPlayerAudioComponent, |  | ||||||
| 		DescriptionAreaComponent, |  | ||||||
| 		PopInCreateType, |  | ||||||
| 		HomeScene, |  | ||||||
| 		HelpScene, |  | ||||||
| 		GenderScene, |  | ||||||
| 		PlaylistScene, |  | ||||||
| 		ArtistAlbumScene, |  | ||||||
| 		ArtistsScene, |  | ||||||
| 		ArtistScene, |  | ||||||
| 		AlbumScene, |  | ||||||
| 		AlbumsScene, |  | ||||||
| 		TrackScene, |  | ||||||
| 		SettingsScene, |  | ||||||
| 		TrackEditScene, |  | ||||||
| 		AlbumEditScene, |  | ||||||
| 		ArtistEditScene, |  | ||||||
| 		UploadScene, |  | ||||||
| 	], |  | ||||||
| 	imports: [ |  | ||||||
| 		FormsModule, |  | ||||||
| 		ReactiveFormsModule, |  | ||||||
| 		CommonModule, |  | ||||||
|  |  | ||||||
| 		BrowserModule, |  | ||||||
| 		RouterModule, |  | ||||||
| 		AppRoutingModule, |  | ||||||
| 		HttpClientModule, |  | ||||||
| 		KarCWModule, |  | ||||||
| 	], |  | ||||||
| 	providers: [ |  | ||||||
| 		{ provide: 'ENVIRONMENT', useValue: environment }, |  | ||||||
| 		ArianeService, |  | ||||||
| 		PlayerService, |  | ||||||
| 		GenderService, |  | ||||||
| 		DataService, |  | ||||||
| 		PlaylistService, |  | ||||||
| 		ArtistService, |  | ||||||
| 		AlbumService, |  | ||||||
| 		TrackService, |  | ||||||
| 	], |  | ||||||
| 	exports: [ |  | ||||||
| 		AppComponent, |  | ||||||
| 		ElementTypeComponent, |  | ||||||
| 		ElementSeriesComponent, |  | ||||||
| 		ElementSeasonComponent, |  | ||||||
| 		ElementVideoComponent, |  | ||||||
| 		PopInCreateType, |  | ||||||
| 	], |  | ||||||
| 	bootstrap: [ |  | ||||||
| 		AppComponent |  | ||||||
| 	], |  | ||||||
| 	schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], |  | ||||||
| }) |  | ||||||
| export class AppModule { } |  | ||||||
| @@ -1,8 +0,0 @@ | |||||||
| /** |  | ||||||
|  * API of the server (auto-generated code) |  | ||||||
|  */ |  | ||||||
| import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools" |  | ||||||
| import {} from "./model" |  | ||||||
| export namespace Front { |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| /** |  | ||||||
|  * API of the server (auto-generated code) |  | ||||||
|  */ |  | ||||||
| import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools" |  | ||||||
| import {HealthResult, isHealthResult, } from "./model" |  | ||||||
| export namespace HealthCheck { |  | ||||||
|  |  | ||||||
| 	export function getHealth({ restConfig, }: { |  | ||||||
| 		restConfig: RESTConfig, |  | ||||||
| 	}): Promise<HealthResult> { |  | ||||||
| 		return RESTRequestJson({ |  | ||||||
| 			restModel: { |  | ||||||
| 				endPoint: "/health_check", |  | ||||||
| 				requestType: HTTPRequestModel.GET, |  | ||||||
| 				accept: HTTPMimeType.JSON, |  | ||||||
| 			}, |  | ||||||
| 			restConfig, |  | ||||||
| 		}, isHealthResult); |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| /** |  | ||||||
|  * Global import of the package |  | ||||||
|  */ |  | ||||||
| export * from "./model"; |  | ||||||
| export * from "./album-resource"; |  | ||||||
| export * from "./artist-resource"; |  | ||||||
| export * from "./front"; |  | ||||||
| export * from "./gender-resource"; |  | ||||||
| export * from "./health-check"; |  | ||||||
| export * from "./playlist-resource"; |  | ||||||
| export * from "./user-resource"; |  | ||||||
| export * from "./track-resource"; |  | ||||||
| export * from "./data-resource"; |  | ||||||
| @@ -1,407 +0,0 @@ | |||||||
| /** |  | ||||||
|  * Interface of the server (auto-generated code) |  | ||||||
|  */ |  | ||||||
| import { z as zod } from "zod"; |  | ||||||
|  |  | ||||||
| export const ZodUUID = zod.string().uuid(); |  | ||||||
| export type UUID = zod.infer<typeof ZodUUID>; |  | ||||||
| export function isUUID(data: any): data is UUID { |  | ||||||
| 	try { |  | ||||||
| 		ZodUUID.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodLong = zod.number(); |  | ||||||
| export type Long = zod.infer<typeof ZodLong>; |  | ||||||
| export function isLong(data: any): data is Long { |  | ||||||
| 	try { |  | ||||||
| 		ZodLong.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodInteger = zod.number().safe(); |  | ||||||
| export type Integer = zod.infer<typeof ZodInteger>; |  | ||||||
| export function isInteger(data: any): data is Integer { |  | ||||||
| 	try { |  | ||||||
| 		ZodInteger.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodFloat = zod.number(); |  | ||||||
| export type Float = zod.infer<typeof ZodFloat>; |  | ||||||
| export function isFloat(data: any): data is Float { |  | ||||||
| 	try { |  | ||||||
| 		ZodFloat.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodInstant = zod.string(); |  | ||||||
| export type Instant = zod.infer<typeof ZodInstant>; |  | ||||||
| export function isInstant(data: any): data is Instant { |  | ||||||
| 	try { |  | ||||||
| 		ZodInstant.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodDate = zod.date(); |  | ||||||
| export type Date = zod.infer<typeof ZodDate>; |  | ||||||
| export function isDate(data: any): data is Date { |  | ||||||
| 	try { |  | ||||||
| 		ZodDate.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodTimestamp = zod.date(); |  | ||||||
| export type Timestamp = zod.infer<typeof ZodTimestamp>; |  | ||||||
| export function isTimestamp(data: any): data is Timestamp { |  | ||||||
| 	try { |  | ||||||
| 		ZodTimestamp.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodLocalDate = zod.date(); |  | ||||||
| export type LocalDate = zod.infer<typeof ZodLocalDate>; |  | ||||||
| export function isLocalDate(data: any): data is LocalDate { |  | ||||||
| 	try { |  | ||||||
| 		ZodLocalDate.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodLocalTime = zod.date(); |  | ||||||
| export type LocalTime = zod.infer<typeof ZodLocalTime>; |  | ||||||
| export function isLocalTime(data: any): data is LocalTime { |  | ||||||
| 	try { |  | ||||||
| 		ZodLocalTime.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodRestErrorResponse = zod.object({ |  | ||||||
| 	uuid: ZodUUID.optional(), |  | ||||||
| 	time: zod.string().max(255).optional(), |  | ||||||
| 	error: zod.string().max(255).optional(), |  | ||||||
| 	message: zod.string().max(255).optional(), |  | ||||||
| 	status: ZodInteger, |  | ||||||
| 	statusMessage: zod.string().max(255).optional() |  | ||||||
| }); |  | ||||||
| export type RestErrorResponse = zod.infer<typeof ZodRestErrorResponse>; |  | ||||||
| export function isRestErrorResponse(data: any): data is RestErrorResponse { |  | ||||||
| 	try { |  | ||||||
| 		ZodRestErrorResponse.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodGenericTiming = zod.object({ |  | ||||||
| 	// Create time of the object |  | ||||||
| 	createdAt: ZodDate.readonly().optional(), |  | ||||||
| 	// When update the object |  | ||||||
| 	updatedAt: ZodDate.readonly().optional() |  | ||||||
| }); |  | ||||||
| export type GenericTiming = zod.infer<typeof ZodGenericTiming>; |  | ||||||
| export function isGenericTiming(data: any): data is GenericTiming { |  | ||||||
| 	try { |  | ||||||
| 		ZodGenericTiming.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodGenericData = ZodGenericTiming.extend({ |  | ||||||
| 	// Unique Id of the object |  | ||||||
| 	id: ZodLong.readonly().optional() |  | ||||||
| }); |  | ||||||
| export type GenericData = zod.infer<typeof ZodGenericData>; |  | ||||||
| export function isGenericData(data: any): data is GenericData { |  | ||||||
| 	try { |  | ||||||
| 		ZodGenericData.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodGenericDataSoftDelete = ZodGenericData.extend({ |  | ||||||
| 	// Deleted state |  | ||||||
| 	deleted: zod.boolean().readonly().optional() |  | ||||||
| }); |  | ||||||
| export type GenericDataSoftDelete = zod.infer<typeof ZodGenericDataSoftDelete>; |  | ||||||
| export function isGenericDataSoftDelete(data: any): data is GenericDataSoftDelete { |  | ||||||
| 	try { |  | ||||||
| 		ZodGenericDataSoftDelete.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodNodeSmall = ZodGenericDataSoftDelete.extend({ |  | ||||||
| 	name: zod.string().max(256).optional(), |  | ||||||
| 	description: zod.string().optional(), |  | ||||||
| 	// List of Id of the specific covers |  | ||||||
| 	covers: zod.array(ZodUUID).optional() |  | ||||||
| }); |  | ||||||
| export type NodeSmall = zod.infer<typeof ZodNodeSmall>; |  | ||||||
| export function isNodeSmall(data: any): data is NodeSmall { |  | ||||||
| 	try { |  | ||||||
| 		ZodNodeSmall.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodAlbum = ZodNodeSmall.extend({ |  | ||||||
| 	publication: ZodLocalDate.optional() |  | ||||||
| }); |  | ||||||
| export type Album = zod.infer<typeof ZodAlbum>; |  | ||||||
| export function isAlbum(data: any): data is Album { |  | ||||||
| 	try { |  | ||||||
| 		ZodAlbum.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodArtist = ZodNodeSmall.extend({ |  | ||||||
| 	firstName: zod.string().max(256).optional(), |  | ||||||
| 	surname: zod.string().max(256).optional(), |  | ||||||
| 	birth: ZodLocalDate.optional(), |  | ||||||
| 	death: ZodLocalDate.optional() |  | ||||||
| }); |  | ||||||
| export type Artist = zod.infer<typeof ZodArtist>; |  | ||||||
| export function isArtist(data: any): data is Artist { |  | ||||||
| 	try { |  | ||||||
| 		ZodArtist.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodGender = ZodNodeSmall.extend({ |  | ||||||
| }); |  | ||||||
| export type Gender = zod.infer<typeof ZodGender>; |  | ||||||
| export function isGender(data: any): data is Gender { |  | ||||||
| 	try { |  | ||||||
| 		ZodGender.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodHealthResult = zod.object({ |  | ||||||
| }); |  | ||||||
| export type HealthResult = zod.infer<typeof ZodHealthResult>; |  | ||||||
| export function isHealthResult(data: any): data is HealthResult { |  | ||||||
| 	try { |  | ||||||
| 		ZodHealthResult.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodPlaylist = ZodNodeSmall.extend({ |  | ||||||
| 	tracks: zod.array(ZodLong).optional() |  | ||||||
| }); |  | ||||||
| export type Playlist = zod.infer<typeof ZodPlaylist>; |  | ||||||
| export function isPlaylist(data: any): data is Playlist { |  | ||||||
| 	try { |  | ||||||
| 		ZodPlaylist.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodUser = ZodGenericDataSoftDelete.extend({ |  | ||||||
| 	login: zod.string().max(128).optional(), |  | ||||||
| 	lastConnection: ZodTimestamp.optional(), |  | ||||||
| 	admin: zod.boolean(), |  | ||||||
| 	blocked: zod.boolean(), |  | ||||||
| 	removed: zod.boolean(), |  | ||||||
| 	covers: zod.array(ZodLong).optional() |  | ||||||
| }); |  | ||||||
| export type User = zod.infer<typeof ZodUser>; |  | ||||||
| export function isUser(data: any): data is User { |  | ||||||
| 	try { |  | ||||||
| 		ZodUser.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodUserKarusic = ZodUser.extend({ |  | ||||||
| }); |  | ||||||
| export type UserKarusic = zod.infer<typeof ZodUserKarusic>; |  | ||||||
| export function isUserKarusic(data: any): data is UserKarusic { |  | ||||||
| 	try { |  | ||||||
| 		ZodUserKarusic.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodUserOut = zod.object({ |  | ||||||
| 	id: ZodLong, |  | ||||||
| 	login: zod.string().max(255).optional() |  | ||||||
| }); |  | ||||||
| export type UserOut = zod.infer<typeof ZodUserOut>; |  | ||||||
| export function isUserOut(data: any): data is UserOut { |  | ||||||
| 	try { |  | ||||||
| 		ZodUserOut.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodTrack = ZodNodeSmall.extend({ |  | ||||||
| 	genderId: ZodLong.optional(), |  | ||||||
| 	albumId: ZodLong.optional(), |  | ||||||
| 	track: ZodLong.optional(), |  | ||||||
| 	dataId: ZodUUID.optional(), |  | ||||||
| 	artists: zod.array(ZodLong).optional() |  | ||||||
| }); |  | ||||||
| export type Track = zod.infer<typeof ZodTrack>; |  | ||||||
| export function isTrack(data: any): data is Track { |  | ||||||
| 	try { |  | ||||||
| 		ZodTrack.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodUUIDGenericData = ZodGenericTiming.extend({ |  | ||||||
| 	// Unique UUID of the object |  | ||||||
| 	id: ZodUUID.readonly().optional() |  | ||||||
| }); |  | ||||||
| export type UUIDGenericData = zod.infer<typeof ZodUUIDGenericData>; |  | ||||||
| export function isUUIDGenericData(data: any): data is UUIDGenericData { |  | ||||||
| 	try { |  | ||||||
| 		ZodUUIDGenericData.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodUUIDGenericDataSoftDelete = ZodUUIDGenericData.extend({ |  | ||||||
| 	// Deleted state |  | ||||||
| 	deleted: zod.boolean().readonly().optional() |  | ||||||
| }); |  | ||||||
| export type UUIDGenericDataSoftDelete = zod.infer<typeof ZodUUIDGenericDataSoftDelete>; |  | ||||||
| export function isUUIDGenericDataSoftDelete(data: any): data is UUIDGenericDataSoftDelete { |  | ||||||
| 	try { |  | ||||||
| 		ZodUUIDGenericDataSoftDelete.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export const ZodData = ZodUUIDGenericDataSoftDelete.extend({ |  | ||||||
| 	// Sha512 of the data |  | ||||||
| 	sha512: zod.string().max(128).optional(), |  | ||||||
| 	// Mime -type of the media |  | ||||||
| 	mimeType: zod.string().max(128).optional(), |  | ||||||
| 	// Size in Byte of the data |  | ||||||
| 	size: ZodLong.optional() |  | ||||||
| }); |  | ||||||
| export type Data = zod.infer<typeof ZodData>; |  | ||||||
| export function isData(data: any): data is Data { |  | ||||||
| 	try { |  | ||||||
| 		ZodData.parse(data); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e: any) { |  | ||||||
| 		console.log(`Fail to parse data ${e}`); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1,246 +0,0 @@ | |||||||
| /** @file |  | ||||||
|  * @author Edouard DUPIN |  | ||||||
|  * @copyright 2024, Edouard DUPIN, all right reserved |  | ||||||
|  * @license MPL-2 |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| import { RestErrorResponse } from "./model" |  | ||||||
|  |  | ||||||
| export enum HTTPRequestModel { |  | ||||||
|     DELETE = 'DELETE', |  | ||||||
|     GET = 'GET', |  | ||||||
|     PATCH = 'PATCH', |  | ||||||
|     POST = 'POST', |  | ||||||
|     PUT = 'PUT', |  | ||||||
| } |  | ||||||
| export enum HTTPMimeType { |  | ||||||
|     ALL = '*/*', |  | ||||||
|     CSV = 'text/csv', |  | ||||||
|     IMAGE = 'image/*', |  | ||||||
|     IMAGE_JPEG = 'image/jpeg', |  | ||||||
|     IMAGE_PNG = 'image/png', |  | ||||||
|     JSON = 'application/json', |  | ||||||
|     MULTIPART = 'multipart/form-data', |  | ||||||
|     OCTET_STREAM = 'application/octet-stream', |  | ||||||
|     TEXT_PLAIN = 'text/plain', |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export interface RESTConfig { |  | ||||||
|     // base of the server: http(s)://my.server.org/plop/api/ |  | ||||||
|     server: string; |  | ||||||
|     // Token to access of the data. |  | ||||||
|     token?: string; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export interface RESTModel { |  | ||||||
|     // base of the local API request: "sheep/{id}". |  | ||||||
|     endPoint: string; |  | ||||||
|     // Type of the request. |  | ||||||
|     requestType?: HTTPRequestModel; |  | ||||||
|     // Input type requested. |  | ||||||
|     accept?: HTTPMimeType; |  | ||||||
|     // Content of the local data. |  | ||||||
|     contentType?: HTTPMimeType; |  | ||||||
|     // Mode of the TOKEN in urk or Header |  | ||||||
|     tokenInUrl?: boolean; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export interface ModelResponseHttp { |  | ||||||
|     status: number; |  | ||||||
|     data: any; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function isArrayOf<TYPE>( |  | ||||||
|     data: any, |  | ||||||
|     typeChecker: (subData: any) => subData is TYPE, |  | ||||||
|     length?: number |  | ||||||
| ): data is TYPE[] { |  | ||||||
|     if (!Array.isArray(data)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!data.every(typeChecker)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (length !== undefined && data.length != length) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export type RESTRequestType = { |  | ||||||
|     restModel: RESTModel, |  | ||||||
|     restConfig: RESTConfig, |  | ||||||
|     data?: any, |  | ||||||
|     params?: object, |  | ||||||
|     queries?: object, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| function removeTrailingSlashes(input: string): string { |  | ||||||
|     return input.replace(/\/+$/, ''); |  | ||||||
| } |  | ||||||
| function removeLeadingSlashes(input: string): string { |  | ||||||
|     return input.replace(/^\/+/, ''); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function RESTUrl({ restModel, restConfig, data, params, queries }: RESTRequestType): string { |  | ||||||
|     // Create the URL PATH: |  | ||||||
|     let generateUrl = `${removeTrailingSlashes(restConfig.server)}/${removeLeadingSlashes(restModel.endPoint)}`; |  | ||||||
|     if (params !== undefined) { |  | ||||||
|         for (let key of Object.keys(params)) { |  | ||||||
|             generateUrl = generateUrl.replaceAll(`{${key}}`, `${params[key]}`); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     if (queries === undefined && (restConfig.token === undefined || restModel.tokenInUrl !== true)) { |  | ||||||
|         return generateUrl; |  | ||||||
|     } |  | ||||||
|     const searchParams = new URLSearchParams(); |  | ||||||
|     if (queries !== undefined) { |  | ||||||
|         for (let key of Object.keys(queries)) { |  | ||||||
|             const value = queries[key]; |  | ||||||
|             if (Array.isArray(value)) { |  | ||||||
|                 for (let iii = 0; iii < value.length; iii++) { |  | ||||||
|                     searchParams.append(`${key}`, `${value[iii]}`); |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 searchParams.append(`${key}`, `${value}`); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     if (restConfig.token !== undefined && restModel.tokenInUrl === true) { |  | ||||||
|         searchParams.append('Authorization', `Bearer ${restConfig.token}`); |  | ||||||
|     } |  | ||||||
|     return generateUrl + "?" + searchParams.toString(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function RESTRequest({ restModel, restConfig, data, params, queries }: RESTRequestType): Promise<ModelResponseHttp> { |  | ||||||
|     // Create the URL PATH: |  | ||||||
|     let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries }); |  | ||||||
|     let headers: any = {}; |  | ||||||
|     if (restConfig.token !== undefined && restModel.tokenInUrl !== true) { |  | ||||||
|         headers['Authorization'] = `Bearer ${restConfig.token}`; |  | ||||||
|     } |  | ||||||
|     if (restModel.accept !== undefined) { |  | ||||||
|         headers['Accept'] = restModel.accept; |  | ||||||
|     } |  | ||||||
|     if (restModel.requestType !== HTTPRequestModel.GET) { |  | ||||||
|         // if Get we have not a content type, the body is empty |  | ||||||
|         if (restModel.contentType !== HTTPMimeType.MULTIPART) { |  | ||||||
|             // special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****" |  | ||||||
|             headers['Content-Type'] = restModel.contentType; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     let body = data; |  | ||||||
|     if (restModel.contentType === HTTPMimeType.JSON) { |  | ||||||
|         body = JSON.stringify(data); |  | ||||||
|     } else if (restModel.contentType === HTTPMimeType.MULTIPART) { |  | ||||||
|         const formData = new FormData(); |  | ||||||
|         for (const name in data) { |  | ||||||
|             formData.append(name, data[name]); |  | ||||||
|         } |  | ||||||
|         body = formData |  | ||||||
|     } |  | ||||||
|     console.log(`Call ${generateUrl}`) |  | ||||||
|     return new Promise((resolve, reject) => { |  | ||||||
|         fetch(generateUrl, { |  | ||||||
|             method: restModel.requestType, |  | ||||||
|             headers, |  | ||||||
|             body, |  | ||||||
|         }).then((response: Response) => { |  | ||||||
|             if (response.status >= 200 && response.status <= 299) { |  | ||||||
|                 const contentType = response.headers.get('Content-Type'); |  | ||||||
|                 if (restModel.accept !== contentType) { |  | ||||||
|                     reject({ |  | ||||||
|                         time: Date().toString(), |  | ||||||
|                         status: 901, |  | ||||||
|                         error: `REST check wrong type: ${restModel.accept} != ${contentType}`, |  | ||||||
|                         statusMessage: "Fetch error", |  | ||||||
|                         message: "rest-tools.ts Wrong type in the message return type" |  | ||||||
|                     } as RestErrorResponse); |  | ||||||
|                 } else if (contentType === HTTPMimeType.JSON) { |  | ||||||
|                     response |  | ||||||
|                         .json() |  | ||||||
|                         .then((value: any) => { |  | ||||||
|                             //console.log(`RECEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`); |  | ||||||
|                             resolve({ status: response.status, data: value }); |  | ||||||
|                         }) |  | ||||||
|                         .catch((reason: any) => { |  | ||||||
|                             reject({ |  | ||||||
|                                 time: Date().toString(), |  | ||||||
|                                 status: 902, |  | ||||||
|                                 error: `REST parse json fail: ${reason}`, |  | ||||||
|                                 statusMessage: "Fetch parse error", |  | ||||||
|                                 message: "rest-tools.ts Wrong message model to parse" |  | ||||||
|                             } as RestErrorResponse); |  | ||||||
|                         }); |  | ||||||
|                 } else { |  | ||||||
|                     resolve({ status: response.status, data: response.body }); |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 reject({ |  | ||||||
|                     time: Date().toString(), |  | ||||||
|                     status: response.status, |  | ||||||
|                     error: `${response.body}`, |  | ||||||
|                     statusMessage: "Fetch code error", |  | ||||||
|                     message: "rest-tools.ts Wrong return code" |  | ||||||
|                 } as RestErrorResponse); |  | ||||||
|             } |  | ||||||
|         }).catch((error: any) => { |  | ||||||
|             reject({ |  | ||||||
|                 time: Date(), |  | ||||||
|                 status: 999, |  | ||||||
|                 error: error, |  | ||||||
|                 statusMessage: "Fetch catch error", |  | ||||||
|                 message: "http-wrapper.ts detect an error in the fetch request" |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function RESTRequestJson<TYPE>(request: RESTRequestType, checker: (data: any) => data is TYPE): Promise<TYPE> { |  | ||||||
|     return new Promise((resolve, reject) => { |  | ||||||
|         RESTRequest(request).then((value: ModelResponseHttp) => { |  | ||||||
|             if (checker(value.data)) { |  | ||||||
|                 resolve(value.data); |  | ||||||
|             } else { |  | ||||||
|                 reject({ |  | ||||||
|                     time: Date().toString(), |  | ||||||
|                     status: 950, |  | ||||||
|                     error: "REST Fail to verify the data", |  | ||||||
|                     statusMessage: "API cast ERROR", |  | ||||||
|                     message: "api.ts Check type as fail" |  | ||||||
|                 } as RestErrorResponse); |  | ||||||
|             } |  | ||||||
|         }).catch((reason: RestErrorResponse) => { |  | ||||||
|             reject(reason); |  | ||||||
|         }); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| export function RESTRequestJsonArray<TYPE>(request: RESTRequestType, checker: (data: any) => data is TYPE): Promise<TYPE[]> { |  | ||||||
|     return new Promise((resolve, reject) => { |  | ||||||
|         RESTRequest(request).then((value: ModelResponseHttp) => { |  | ||||||
|             if (isArrayOf(value.data, checker)) { |  | ||||||
|                 resolve(value.data); |  | ||||||
|             } else { |  | ||||||
|                 reject({ |  | ||||||
|                     time: Date().toString(), |  | ||||||
|                     status: 950, |  | ||||||
|                     error: "REST Fail to verify the data", |  | ||||||
|                     statusMessage: "API cast ERROR", |  | ||||||
|                     message: "api.ts Check type as fail" |  | ||||||
|                 } as RestErrorResponse); |  | ||||||
|             } |  | ||||||
|         }).catch((reason: RestErrorResponse) => { |  | ||||||
|             reject(reason); |  | ||||||
|         }); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function RESTRequestVoid(request: RESTRequestType): Promise<void> { |  | ||||||
|     return new Promise((resolve, reject) => { |  | ||||||
|         RESTRequest(request).then((value: ModelResponseHttp) => { |  | ||||||
|             resolve(); |  | ||||||
|         }).catch((reason: RestErrorResponse) => { |  | ||||||
|             reject(reason); |  | ||||||
|         }); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| @@ -1,51 +0,0 @@ | |||||||
| /** |  | ||||||
|  * API of the server (auto-generated code) |  | ||||||
|  */ |  | ||||||
| import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools" |  | ||||||
| import {UserOut, Long, UserKarusic, isUserOut, isUserKarusic, } from "./model" |  | ||||||
| export namespace UserResource { |  | ||||||
|  |  | ||||||
| 	export function get({ restConfig, params, produce, }: { |  | ||||||
| 		restConfig: RESTConfig, |  | ||||||
| 		params: { |  | ||||||
| 			id: Long, |  | ||||||
| 		}, |  | ||||||
| 		produce: HTTPMimeType.JSON, |  | ||||||
| 	}): Promise<UserKarusic> { |  | ||||||
| 		return RESTRequestJson({ |  | ||||||
| 			restModel: { |  | ||||||
| 				endPoint: "/users/{id}", |  | ||||||
| 				requestType: HTTPRequestModel.GET, |  | ||||||
| 				accept: produce, |  | ||||||
| 			}, |  | ||||||
| 			restConfig, |  | ||||||
| 			params, |  | ||||||
| 		}, isUserKarusic); |  | ||||||
| 	}; |  | ||||||
| 	export function gets({ restConfig, produce, }: { |  | ||||||
| 		restConfig: RESTConfig, |  | ||||||
| 		produce: HTTPMimeType.JSON, |  | ||||||
| 	}): Promise<UserKarusic[]> { |  | ||||||
| 		return RESTRequestJsonArray({ |  | ||||||
| 			restModel: { |  | ||||||
| 				endPoint: "/users", |  | ||||||
| 				requestType: HTTPRequestModel.GET, |  | ||||||
| 				accept: produce, |  | ||||||
| 			}, |  | ||||||
| 			restConfig, |  | ||||||
| 		}, isUserKarusic); |  | ||||||
| 	}; |  | ||||||
| 	export function getMe({ restConfig, produce, }: { |  | ||||||
| 		restConfig: RESTConfig, |  | ||||||
| 		produce: HTTPMimeType.JSON, |  | ||||||
| 	}): Promise<UserOut> { |  | ||||||
| 		return RESTRequestJson({ |  | ||||||
| 			restModel: { |  | ||||||
| 				endPoint: "/users/me", |  | ||||||
| 				requestType: HTTPRequestModel.GET, |  | ||||||
| 				accept: produce, |  | ||||||
| 			}, |  | ||||||
| 			restConfig, |  | ||||||
| 		}, isUserOut); |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| <!--<canvas width="200" height="250" style="border:1px solid #d3d3d3;" id="imageCanvas" #imageCanvas></canvas>--> |  | ||||||
| <img src="{{cover}}"/> |  | ||||||
| @@ -1,5 +0,0 @@ | |||||||
|  |  | ||||||
| img { |  | ||||||
| 	max-height: 250px; |  | ||||||
| 	max-width: 200px; |  | ||||||
| } |  | ||||||
| @@ -1,58 +0,0 @@ | |||||||
| /** @file |  | ||||||
|  * @author Edouard DUPIN |  | ||||||
|  * @copyright 2018, Edouard DUPIN, all right reserved |  | ||||||
|  * @license PROPRIETARY (see license file) |  | ||||||
|  */ |  | ||||||
| import { Component, OnInit, Input } from '@angular/core'; |  | ||||||
| //import { ModelResponseHttp } from '@app/service/http-wrapper'; |  | ||||||
| import { DataService } from 'app/service/data'; |  | ||||||
|  |  | ||||||
| @Component({ |  | ||||||
| 	selector: 'data-image', |  | ||||||
| 	templateUrl: './data-image.html', |  | ||||||
| 	styleUrls: ['./data-image.less'] |  | ||||||
| }) |  | ||||||
| export class ElementDataImageComponent implements OnInit { |  | ||||||
| 	// input parameters |  | ||||||
| 	@Input() id: string = "0"; |  | ||||||
| 	cover: string = ''; |  | ||||||
| 	/* |  | ||||||
| 		imageCanvas:any; |  | ||||||
| 		@ViewChild('imageCanvas') |  | ||||||
| 		  set mainDivEl(el: ElementRef) { |  | ||||||
| 			if(el !== null && el !== undefined) { |  | ||||||
| 				this.imageCanvas = el.nativeElement; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	*/ |  | ||||||
| 	constructor(private dataService: DataService) { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
| 	ngOnInit() { |  | ||||||
| 		this.cover = this.dataService.getThumbnailUrl(this.id); |  | ||||||
| 		/* |  | ||||||
| 		let canvas = this.imageCanvas.nativeElement; |  | ||||||
| 		let ctx = canvas.getContext("2d"); |  | ||||||
| 		console.log(`Request thumbnail for ---> ${this.id}`); |  | ||||||
| 		this.dataService.getImageThumbnail(this.id) |  | ||||||
| 			.then((result:ModelResponseHttp) => { |  | ||||||
| 				console.log(`plop ---> ${result.status}`); |  | ||||||
| 				const response = result.data as Response; |  | ||||||
| 				response.blob().then((value:Blob) => { |  | ||||||
| 					let img = new Image(); |  | ||||||
| 					img.onload = function() { |  | ||||||
| 						//ctx.drawImage(img, 0, 0) |  | ||||||
| 					} |  | ||||||
| 					let imageUrl = URL.createObjectURL(value); |  | ||||||
| 					console.log(`get new image url blob: ${imageUrl}`); |  | ||||||
| 					//img.src = imageUrl; |  | ||||||
| 				}) |  | ||||||
|  |  | ||||||
| 			}).catch(()=>{ |  | ||||||
| 				console.log("plop ---> "); |  | ||||||
| 			}); |  | ||||||
| 		//img.src = "../../assets/aCRF-PRV111_CLN-001 v1.4-images/aCRF-PRV111_CLN-001 v1.4-blank_0.jpg"; |  | ||||||
| 		//ctx.drawImage(img, 10, 10, 250, 250); |  | ||||||
| 		*/ |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,42 +0,0 @@ | |||||||
| <div class="fill-title"> |  | ||||||
| 	<div class="description-area"> |  | ||||||
| 		@if(title) { |  | ||||||
| 			<div class="shadow-text title"> |  | ||||||
| 				{{title}} |  | ||||||
| 			</div> |  | ||||||
| 		} |  | ||||||
| 		@if(name) { |  | ||||||
| 			<div class="shadow-text sub-title-main"> |  | ||||||
| 				{{name}} |  | ||||||
| 			</div> |  | ||||||
| 		} |  | ||||||
| 		@if(description) { |  | ||||||
| 			<div class="description"> |  | ||||||
| 				{{description}} |  | ||||||
| 			</div> |  | ||||||
| 		} |  | ||||||
| 		<div class="button-area"> |  | ||||||
| 			<button class="circular-button" (click)="playAll($event)" type="submit"> |  | ||||||
| 				<i class="material-icons">play_arrow</i> |  | ||||||
| 			</button> |  | ||||||
| 			<button class="circular-button" (click)="playShuffle($event)" type="submit"> |  | ||||||
| 				<i class="material-icons">shuffle</i> |  | ||||||
| 			</button> |  | ||||||
| 			<div style="flex:1;"></div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	@if (cover1 && cover1.length > 0) { |  | ||||||
| 		<div class="cover-area"> |  | ||||||
| 			<div class="cover"> |  | ||||||
| 				<img src="{{cover1[0]}}"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	} |  | ||||||
| 	@if (cover2 && cover2.length > 0) { |  | ||||||
| 		<div class="cover-area"> |  | ||||||
| 			<div class="cover"> |  | ||||||
| 				<img src="{{cover2[0]}}"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	} |  | ||||||
| </div> |  | ||||||
| @@ -1,31 +0,0 @@ | |||||||
| /** @file |  | ||||||
|  * @author Edouard DUPIN |  | ||||||
|  * @copyright 2018, Edouard DUPIN, all right reserved |  | ||||||
|  * @license PROPRIETARY (see license file) |  | ||||||
|  */ |  | ||||||
| import { Component, Input, Output, EventEmitter } from '@angular/core'; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @Component({ |  | ||||||
| 	selector: 'description-area', |  | ||||||
| 	templateUrl: './description-area.html', |  | ||||||
| 	styleUrls: ['./description-area.less'] |  | ||||||
| }) |  | ||||||
| export class DescriptionAreaComponent { |  | ||||||
| 	@Input() title: string; |  | ||||||
| 	@Input() name?: string; |  | ||||||
| 	@Input() description?: string; |  | ||||||
| 	@Input() cover1?: number[]; |  | ||||||
| 	@Input() cover2?: number[]; |  | ||||||
|  |  | ||||||
| 	@Output() play = new EventEmitter<void>(); |  | ||||||
| 	@Output() shuffle = new EventEmitter<void>(); |  | ||||||
|  |  | ||||||
| 	playShuffle(event: any): void { |  | ||||||
| 		this.shuffle.emit(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	playAll(event: any): void { |  | ||||||
| 		this.play.emit(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,52 +0,0 @@ | |||||||
| @if(mediaSource) { |  | ||||||
| 	<div> |  | ||||||
| 		<audio width="1" height="1" src="{{mediaSource}}" |  | ||||||
| 			#mediaPlayer |  | ||||||
| 			preload |  | ||||||
| 			(play)="changeStateToPlay()" |  | ||||||
| 			(pause)="changeStateToPause()" |  | ||||||
| 			(timeupdate)="changeTimeupdate($event.currentTime)" |  | ||||||
| 			(durationchange)="changeDurationchange($event.duration)" |  | ||||||
| 			(loadedmetadata)="changeMetadata()" |  | ||||||
| 			autoplay |  | ||||||
| 			(ended)="onAudioEnded()" |  | ||||||
| 			> |  | ||||||
| 		</audio> |  | ||||||
| 		<div class="controls"> |  | ||||||
| 			<div class="controls-inner"> |  | ||||||
| 				<div class="title text-ellipsis"> |  | ||||||
| 					<label class="unselectable">{{dataTitle}}</label> |  | ||||||
| 				</div> |  | ||||||
| 				<div class="text-ellipsis"> |  | ||||||
| 					<label class="unselectable">{{dataAuthor}} / {{dataAlbum}}</label> |  | ||||||
| 				</div> |  | ||||||
| 				<div class="timer-slider"> |  | ||||||
| 					<input type="range" min="0" class="slider" |  | ||||||
| 							[value]="currentTime" |  | ||||||
| 							[max]="duration" |  | ||||||
| 							(input)="seek($event.target)"> |  | ||||||
| 				</div> |  | ||||||
| 				<div class="flex-row"> |  | ||||||
| 					<label class="unselectable">{{currentTimeDisplay}}</label> |  | ||||||
| 					<label class="unselectable flex-row-last">{{durationDisplay}}</label> |  | ||||||
| 				</div> |  | ||||||
| 				<div class="control"> |  | ||||||
| 					@if(!isPlaying) { |  | ||||||
| 						<button (click)="onPlay()"><i class="material-icons">play_arrow</i></button> |  | ||||||
| 					} |  | ||||||
| 					@else { |  | ||||||
| 						<button (click)="onPause()"><i class="material-icons">pause</i></button> |  | ||||||
| 					} |  | ||||||
| 					<button (click)="onStop()"><i class="material-icons">stop</i></button> |  | ||||||
| 					<div style="margin:auto"></div> |  | ||||||
| 					<button [disabled]="havePrevious" (click)="onBefore()"><i class="material-icons">navigate_before</i></button> |  | ||||||
| 					<button (click)="onRewind()"><i class="material-icons">fast_rewind</i></button> |  | ||||||
| 					<button (click)="onForward()"><i class="material-icons">fast_forward</i></button> |  | ||||||
| 					<button [disabled]="haveNext" (click)="onNext()"><i class="material-icons">navigate_next</i></button> |  | ||||||
| 					<div style="margin:auto"></div> |  | ||||||
| 					<button (click)="onPlayMode()"><i class="material-icons">{{playMode}}</i></button> |  | ||||||
| 				</div> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| } |  | ||||||
| @@ -1,113 +0,0 @@ | |||||||
| .controls { |  | ||||||
| 	//visibility: hidden; |  | ||||||
| 	opacity: 0.85; |  | ||||||
| 	width: 96%; |  | ||||||
| 	//height: 150px; |  | ||||||
| 	border-radius: 10px; |  | ||||||
| 	position: absolute; |  | ||||||
| 	bottom: 20px; |  | ||||||
| 	left: 2%; |  | ||||||
| 	//margin-left: -200px; |  | ||||||
| 	background-color: black; |  | ||||||
| 	box-shadow: 3px 3px 5px black; |  | ||||||
| 	transition: 1s all; |  | ||||||
| 	display: flex; |  | ||||||
| 	font-size: 40px; |  | ||||||
| 	min-width: 380px; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	.controls-inner { |  | ||||||
| 		position: relative; |  | ||||||
| 		width: 100%; |  | ||||||
| 		height: 100%; |  | ||||||
| 		min-width: 350px; |  | ||||||
| 		font-family: monospace; |  | ||||||
| 		color: white; |  | ||||||
| 		margin: 10px 15px 1px 15px; |  | ||||||
| 		font-size: 20px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.material-icons { |  | ||||||
| 		color: #FFF; |  | ||||||
| 		font-size: 40px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	button { |  | ||||||
| 		border: none; |  | ||||||
| 		background: none; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	button:disabled, |  | ||||||
| 	button[disabled] { |  | ||||||
| 		.material-icons { |  | ||||||
| 			color: rgb(46, 46, 46); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.slider { |  | ||||||
| 		position: relative; |  | ||||||
| 		//-webkit-appearance: none; |  | ||||||
| 		width: 100%; |  | ||||||
| 		height: 10px; |  | ||||||
| 		top: 5px; |  | ||||||
| 		border-radius: 5px; |  | ||||||
| 		background: #d3d3d3; |  | ||||||
| 		outline: none; |  | ||||||
| 		opacity: 0.7; |  | ||||||
| 		-webkit-transition: .2s; |  | ||||||
| 		transition: opacity .2s; |  | ||||||
| 		flex: 5; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.slider::-webkit-slider-thumb { |  | ||||||
| 		-webkit-appearance: none; |  | ||||||
| 		appearance: none; |  | ||||||
| 		width: 25px; |  | ||||||
| 		height: 25px; |  | ||||||
| 		border-radius: 50%; |  | ||||||
| 		background: #4CAF50; |  | ||||||
| 		cursor: pointer; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.slider::-moz-range-thumb { |  | ||||||
| 		width: 25px; |  | ||||||
| 		height: 25px; |  | ||||||
| 		border-radius: 50%; |  | ||||||
| 		background: #4CAF50; |  | ||||||
| 		cursor: pointer; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.text-ellipsis { |  | ||||||
| 		overflow: hidden; |  | ||||||
| 		text-overflow: ellipsis; |  | ||||||
| 		white-space: nowrap; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.title { |  | ||||||
| 		font-size: 24px; |  | ||||||
| 		font-weight: bold; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.timer-slider { |  | ||||||
| 		width: 100%; |  | ||||||
| 		margin: 4px 0px 4px 0px; |  | ||||||
| 		font-size: 20px; |  | ||||||
| 		padding-bottom: 10px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	.control { |  | ||||||
| 		width: 100%; |  | ||||||
| 		font-size: 30px; |  | ||||||
| 		font-weight: bold; |  | ||||||
| 		display: flex; |  | ||||||
| 		justify-content: center; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| button:before { |  | ||||||
| 	font-family: HeydingsControlsRegular; |  | ||||||
| 	font-size: 30px; |  | ||||||
| 	position: relative; |  | ||||||
| 	color: #FFF; |  | ||||||
| } |  | ||||||
| @@ -1,359 +0,0 @@ | |||||||
| /** @file |  | ||||||
|  * @author Edouard DUPIN |  | ||||||
|  * @copyright 2018, Edouard DUPIN, all right reserved |  | ||||||
|  * @license PROPRIETARY (see license file) |  | ||||||
|  */ |  | ||||||
| import { Component, OnInit, ViewChild, ElementRef, Inject } from '@angular/core'; |  | ||||||
|  |  | ||||||
| import { DataService, PlayerService, TrackService, AlbumService, ArtistService } from 'app/service'; |  | ||||||
| import { PlaylistCurrent } from 'app/service/player'; |  | ||||||
| import { Title } from '@angular/platform-browser'; |  | ||||||
| import { Album, Artist, Track } from 'app/back-api'; |  | ||||||
| import { isArray, isNullOrUndefined, Environment } from '@kangaroo-and-rabbit/kar-cw'; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export enum PlayMode { |  | ||||||
| 	PLAY_ONE = "check", |  | ||||||
| 	PLAY_ALL = "trending_flat", |  | ||||||
| 	PLAY_ONE_LOOP = "repeat_one", |  | ||||||
| 	PLAY_ALL_LOOP = "repeat", |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // note: all the input is managed with the player service ... |  | ||||||
| @Component({ |  | ||||||
| 	selector: 'app-element-player-audio', |  | ||||||
| 	templateUrl: './element-player-audio.html', |  | ||||||
| 	styleUrls: ['./element-player-audio.less'] |  | ||||||
| }) |  | ||||||
| export class ElementPlayerAudioComponent implements OnInit { |  | ||||||
| 	mediaPlayer: HTMLAudioElement; |  | ||||||
| 	duration: number; |  | ||||||
| 	durationDisplay: string; |  | ||||||
| 	@ViewChild('mediaPlayer') |  | ||||||
| 	set mainVideoEl(el: ElementRef) { |  | ||||||
| 		if (el !== null && el !== undefined) { |  | ||||||
| 			this.mediaPlayer = el.nativeElement; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	public mediaSource: string = undefined; |  | ||||||
|  |  | ||||||
| 	public name: string = 'rr'; |  | ||||||
| 	public description: string; |  | ||||||
|  |  | ||||||
| 	public countTrack: number; |  | ||||||
|  |  | ||||||
| 	public covers: string[]; |  | ||||||
|  |  | ||||||
| 	public volume_value: number = 100; |  | ||||||
| 	public volume_displayMenu: boolean = false; |  | ||||||
|  |  | ||||||
| 	dataTitle: string; |  | ||||||
| 	dataAlbum: string; |  | ||||||
| 	dataAuthor: string; |  | ||||||
| 	playStream: boolean; |  | ||||||
| 	isPlaying: boolean; |  | ||||||
| 	currentTime: any; |  | ||||||
| 	currentTimeDisplay: string; |  | ||||||
| 	havePrevious: boolean = false; |  | ||||||
| 	haveNext: boolean = false; |  | ||||||
| 	playMode: PlayMode = PlayMode.PLAY_ALL; |  | ||||||
| 	onPlayMode() { |  | ||||||
| 		if (this.playMode === PlayMode.PLAY_ONE) { |  | ||||||
| 			this.playMode = PlayMode.PLAY_ALL; |  | ||||||
| 		} else if (this.playMode === PlayMode.PLAY_ALL) { |  | ||||||
| 			this.playMode = PlayMode.PLAY_ONE_LOOP; |  | ||||||
| 		} else if (this.playMode === PlayMode.PLAY_ONE_LOOP) { |  | ||||||
| 			this.playMode = PlayMode.PLAY_ALL_LOOP; |  | ||||||
| 		} else { |  | ||||||
| 			this.playMode = PlayMode.PLAY_ONE; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	constructor( |  | ||||||
| 		@Inject('ENVIRONMENT') private environment: Environment, |  | ||||||
| 		private playerService: PlayerService, |  | ||||||
| 		private trackService: TrackService, |  | ||||||
| 		private dataService: DataService, |  | ||||||
| 		private albumService: AlbumService, |  | ||||||
| 		private artistService: ArtistService, |  | ||||||
| 		private titleService: Title) { |  | ||||||
| 		// nothing to do... |  | ||||||
| 	} |  | ||||||
| 	private currentLMedia: Track; |  | ||||||
| 	private localIdStreaming: number; |  | ||||||
| 	private localListStreaming: number[] = []; |  | ||||||
| 	ngOnInit() { |  | ||||||
| 		/* |  | ||||||
| 		export interface PlaylistCurrent { |  | ||||||
| 			playTrackList: number[]; |  | ||||||
| 			trackLocalId?: number; |  | ||||||
| 		} |  | ||||||
| 		*/ |  | ||||||
| 		let self = this; |  | ||||||
| 		this.playerService.playChange.subscribe((newProperty: PlaylistCurrent) => { |  | ||||||
| 			self.localIdStreaming = newProperty.trackLocalId; |  | ||||||
| 			self.localListStreaming = newProperty.playTrackList; |  | ||||||
| 			self.updateMediaStreamed(); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| 	updateMediaStreamed() { |  | ||||||
| 		if (isNullOrUndefined(this.localIdStreaming)) { |  | ||||||
| 			this.mediaSource = undefined; |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		let self = this; |  | ||||||
| 		this.havePrevious = this.localIdStreaming <= 0; |  | ||||||
| 		this.haveNext = this.localIdStreaming >= this.localListStreaming.length - 1; |  | ||||||
| 		this.trackService.get(this.localListStreaming[this.localIdStreaming]) |  | ||||||
| 			.then((response: Track) => { |  | ||||||
| 				console.log(`get response of video : ${JSON.stringify(response, null, 2)}`); |  | ||||||
| 				self.currentLMedia = response; |  | ||||||
| 				self.dataTitle = response.name; |  | ||||||
| 				if (!isNullOrUndefined(response.albumId)) { |  | ||||||
| 					this.albumService.get(response.albumId) |  | ||||||
| 						.then((response2: Album) => { |  | ||||||
| 							self.dataAlbum = response2.name; |  | ||||||
| 							self.updateTitle(); |  | ||||||
| 						}) |  | ||||||
| 						.catch(() => { }); |  | ||||||
| 				} |  | ||||||
| 				if (!isNullOrUndefined(response.artists) && isArray(response.artists) && response.artists.length > 0) { |  | ||||||
| 					this.artistService.get(response.artists[0]) |  | ||||||
| 						.then((response2: Artist) => { |  | ||||||
| 							self.dataAuthor = response2.name; |  | ||||||
| 						}) |  | ||||||
| 						.catch(() => { }); |  | ||||||
| 				} |  | ||||||
| 				if (isNullOrUndefined(self.currentLMedia)) { |  | ||||||
| 					console.log("Can not retrieve the media ...") |  | ||||||
| 					return; |  | ||||||
| 				} |  | ||||||
| 				if (isNullOrUndefined(self.currentLMedia.dataId)) { |  | ||||||
| 					console.log("Can not retrieve the media ... null or undefined data ID") |  | ||||||
| 					return; |  | ||||||
| 				} |  | ||||||
| 				self.mediaSource = self.dataService.getUrl(self.currentLMedia.dataId, "unknownMediaName.webm"); |  | ||||||
| 			}).catch((error) => { |  | ||||||
| 				console.error(`error not unmanaged in audio player ... 111 ${error}`); |  | ||||||
| 			}) |  | ||||||
| 	} |  | ||||||
| 	updateTitle() { |  | ||||||
| 		let title = this.dataTitle; |  | ||||||
| 		if (!isNullOrUndefined(this.dataAlbum)) { |  | ||||||
| 			title = `${this.dataAlbum} - ${title}`; |  | ||||||
| 		} |  | ||||||
| 		if (!isNullOrUndefined(this.dataAuthor)) { |  | ||||||
| 			title = `${title} (${this.dataAuthor})`; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		this.titleService.setTitle(`${this.environment.applName} > ${title}`) |  | ||||||
| 	} |  | ||||||
| 	changeMetadata() { |  | ||||||
| 		console.log('list of the stream:'); |  | ||||||
| 	} |  | ||||||
| 	myPeriodicCheckFunction() { |  | ||||||
| 		console.log('check ... '); |  | ||||||
| 	} |  | ||||||
| 	onRequirePlay() { |  | ||||||
| 		this.playStream = true; |  | ||||||
| 	} |  | ||||||
| 	onRequireStop() { |  | ||||||
|  |  | ||||||
| 		this.playStream = false; |  | ||||||
| 	} |  | ||||||
| 	onAudioEnded() { |  | ||||||
| 		if (this.playMode === PlayMode.PLAY_ONE) { |  | ||||||
| 			this.playStream = false; |  | ||||||
| 		} else if (this.playMode === PlayMode.PLAY_ALL) { |  | ||||||
| 			this.onNext(); |  | ||||||
| 		} else if (this.playMode === PlayMode.PLAY_ONE_LOOP) { |  | ||||||
| 			this.mediaPlayer.currentTime = 0; |  | ||||||
| 			this.onPlay(); |  | ||||||
| 		} else { |  | ||||||
| 			if (this.localIdStreaming == this.localListStreaming.length - 1) { |  | ||||||
| 				this.localIdStreaming = 0; |  | ||||||
| 				this.updateMediaStreamed(); |  | ||||||
| 				if (this.localListStreaming.length == 1) { |  | ||||||
| 					this.mediaPlayer.currentTime = 0; |  | ||||||
| 					this.onPlay(); |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				this.onNext(); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	changeStateToPlay() { |  | ||||||
| 		this.isPlaying = true; |  | ||||||
| 	} |  | ||||||
| 	changeStateToPause() { |  | ||||||
| 		this.isPlaying = false; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	convertInDisplayTime(time: number): string { |  | ||||||
| 		let temporaryValue = parseInt(`${time}`, 10); |  | ||||||
| 		let hours = parseInt(`${temporaryValue / 3600}`, 10); |  | ||||||
| 		temporaryValue = temporaryValue - hours * 3600; |  | ||||||
| 		let minutes = parseInt(`${temporaryValue / 60}`, 10); |  | ||||||
| 		let seconds = temporaryValue - minutes * 60; |  | ||||||
| 		let out = ''; |  | ||||||
| 		if (hours !== 0) { |  | ||||||
| 			out = `${out}${hours}:`; |  | ||||||
| 		} |  | ||||||
| 		if (minutes >= 10) { |  | ||||||
| 			out = `${out}${minutes}:`; |  | ||||||
| 		} else { |  | ||||||
| 			out = `${out}0${minutes}:`; |  | ||||||
| 		} |  | ||||||
| 		if (seconds >= 10) { |  | ||||||
| 			out = out + seconds; |  | ||||||
| 		} else { |  | ||||||
| 			out = `${out}0${seconds}`; |  | ||||||
| 		} |  | ||||||
| 		return out; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	changeTimeupdate(currentTime: any) { |  | ||||||
| 		// console.log("time change "); |  | ||||||
| 		// console.log("    ==> " + this.audioPlayer.currentTime); |  | ||||||
| 		this.currentTime = this.mediaPlayer.currentTime; |  | ||||||
| 		this.currentTimeDisplay = this.convertInDisplayTime(this.currentTime); |  | ||||||
| 		// console.log("    ==> " + this.currentTimeDisplay); |  | ||||||
| 	} |  | ||||||
| 	changeDurationchange(duration: any) { |  | ||||||
| 		console.log('duration change '); |  | ||||||
| 		console.log(`    ==> ${this.mediaPlayer.duration}`); |  | ||||||
| 		this.duration = this.mediaPlayer.duration; |  | ||||||
| 		this.durationDisplay = this.convertInDisplayTime(this.duration); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onPlay() { |  | ||||||
| 		console.log('play'); |  | ||||||
| 		if (isNullOrUndefined(this.mediaPlayer)) { |  | ||||||
| 			console.log(`error element: ${this.mediaPlayer}`); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		this.lockPlayerEnable(); |  | ||||||
| 		this.mediaPlayer.play(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onPause() { |  | ||||||
| 		console.log('pause'); |  | ||||||
| 		if (isNullOrUndefined(this.mediaPlayer)) { |  | ||||||
| 			console.log(`error element: ${this.mediaPlayer}`); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		this.unlockPlayerEnable(); |  | ||||||
| 		this.mediaPlayer.pause(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onPauseToggle() { |  | ||||||
| 		console.log('pause toggle ...'); |  | ||||||
| 		if (this.isPlaying === true) { |  | ||||||
| 			this.onPause(); |  | ||||||
| 		} else { |  | ||||||
| 			this.onPlay(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onStop() { |  | ||||||
| 		console.log('stop'); |  | ||||||
| 		if (this.mediaPlayer.paused && this.mediaPlayer.currentTime == 0) { |  | ||||||
| 			this.mediaSource = null; |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		if (isNullOrUndefined(this.mediaPlayer)) { |  | ||||||
| 			console.log(`error element: ${this.mediaPlayer}`); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		this.unlockPlayerEnable(); |  | ||||||
| 		this.mediaPlayer.pause(); |  | ||||||
| 		this.mediaPlayer.currentTime = 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onBefore() { |  | ||||||
| 		console.log('before'); |  | ||||||
| 		if (this.localIdStreaming <= 0) { |  | ||||||
| 			console.error("have no previous !!!"); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		this.localIdStreaming--; |  | ||||||
| 		this.updateMediaStreamed(); |  | ||||||
| 		this.playerService.previous(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onNext() { |  | ||||||
| 		console.log('next'); |  | ||||||
| 		if (this.localIdStreaming >= this.localListStreaming.length - 1) { |  | ||||||
| 			console.error("have no next !!!"); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		this.localIdStreaming++; |  | ||||||
| 		this.updateMediaStreamed(); |  | ||||||
| 		this.playerService.next(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	seek(newValue: any) { |  | ||||||
| 		console.log(`seek ${newValue.value}`); |  | ||||||
| 		if (isNullOrUndefined(this.mediaPlayer)) { |  | ||||||
| 			console.log(`error element: ${this.mediaPlayer}`); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		this.mediaPlayer.currentTime = newValue.value; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onRewind() { |  | ||||||
| 		console.log('rewind'); |  | ||||||
| 		if (isNullOrUndefined(this.mediaPlayer)) { |  | ||||||
| 			console.log(`error element: ${this.mediaPlayer}`); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		this.mediaPlayer.currentTime = this.currentTime - 10; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onForward() { |  | ||||||
| 		console.log('forward'); |  | ||||||
| 		if (isNullOrUndefined(this.mediaPlayer)) { |  | ||||||
| 			console.log(`error element: ${this.mediaPlayer}`); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		this.mediaPlayer.currentTime = this.currentTime + 10; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	onMore() { |  | ||||||
| 		console.log('more'); |  | ||||||
| 		if (isNullOrUndefined(this.mediaPlayer)) { |  | ||||||
| 			console.log(`error element: ${this.mediaPlayer}`); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	// these element is to permit to not stop music when sceen is off !!  |  | ||||||
| 	wakeLock = null; |  | ||||||
| 	unlockPlayerEnable() { |  | ||||||
| 		let temporaryValue = this.wakeLock; |  | ||||||
| 		this.wakeLock = null; |  | ||||||
| 		if (!isNullOrUndefined(temporaryValue)) { |  | ||||||
| 			console.log(`plopppp ${temporaryValue}`); |  | ||||||
| 			temporaryValue.release(); |  | ||||||
| 		} |  | ||||||
| 		try { |  | ||||||
| 			let tmp = navigator as any; |  | ||||||
| 			this.wakeLock = tmp.wakeLock.request('screen'); |  | ||||||
| 		} catch (err) { |  | ||||||
| 			// The Wake Lock request has failed - usually system related, such as battery. |  | ||||||
| 			console.log(`Can not lock screen element: ${err.name}, ${err.message}`); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	async lockPlayerEnable() { |  | ||||||
| 		if ('wakeLock' in navigator) { |  | ||||||
| 			try { |  | ||||||
| 				let tmp = navigator as any; |  | ||||||
| 				this.wakeLock = await tmp.wakeLock.request('screen'); |  | ||||||
| 			} catch (err) { |  | ||||||
| 				// The Wake Lock request has failed - usually system related, such as battery. |  | ||||||
| 				console.log(`Can not lock screen element: ${err.name}, ${err.message}`); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,45 +0,0 @@ | |||||||
|  |  | ||||||
| <div class="imgContainer-small"> |  | ||||||
| 	@if(covers && covers.length > 0) { |  | ||||||
| 		<div> |  | ||||||
| 			<img src="{{covers[0]}}"/> |  | ||||||
| 		</div> |  | ||||||
| 	} |  | ||||||
| 	@else { |  | ||||||
| 		<div class="noImage"></div> |  | ||||||
| 	} |  | ||||||
| </div> |  | ||||||
| <div class="season-small"> |  | ||||||
| 	{{prefixName}} {{numberAlbum}} |  | ||||||
| </div> |  | ||||||
| @if(countSubType) { |  | ||||||
| 	<div class="description-small"> |  | ||||||
| 	@if(!count || count == 0) { |  | ||||||
| 		No {{countSubType}} |  | ||||||
| 	} |  | ||||||
| 	@else { |  | ||||||
| 		{{count}} {{countSubType}}{{count>1?"s":""}} |  | ||||||
| 	} |  | ||||||
| 	</div> |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @if(countSubType2) { |  | ||||||
| 	<div class="description-small"> |  | ||||||
| 	@if(!count2 || count2 == 0) { |  | ||||||
| 		No {{countSubType2}} |  | ||||||
| 	} |  | ||||||
| 	@else { |  | ||||||
| 		{{count2}} {{countSubType2}}{{count2>1?"s":""}} |  | ||||||
| 	} |  | ||||||
| 	</div> |  | ||||||
| } |  | ||||||
| @if(subValueData) { |  | ||||||
| 	<div class="description-small"> |  | ||||||
| 		{{subValues}}: {{subValueData}} |  | ||||||
| 	</div> |  | ||||||
| } |  | ||||||
| @if(!description) { |  | ||||||
| 	<div class="description-small"> |  | ||||||
| 		{{description}} |  | ||||||
| 	</div> |  | ||||||
| } |  | ||||||
| @@ -1,35 +0,0 @@ | |||||||
|  |  | ||||||
| .imgContainer-small { |  | ||||||
| 	text-align: center; |  | ||||||
| 	width: 100px; |  | ||||||
| 	margin: 4px 15px 4px 10px; |  | ||||||
| 	height: 100px; |  | ||||||
| 	img { |  | ||||||
| 		max-height: 100px; |  | ||||||
| 		max-width: 100px; |  | ||||||
| 	} |  | ||||||
| 	.noImage { |  | ||||||
| 		height: 95px; |  | ||||||
| 		width: 95px; |  | ||||||
| 		//box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.7); |  | ||||||
| 		border: solid 2px; |  | ||||||
| 		border-color: rgba(0, 0, 0, 0.7); |  | ||||||
| 		margin: auto; |  | ||||||
| 	} |  | ||||||
| 	float: left; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .title-small { |  | ||||||
| 	height: 50px; |  | ||||||
| 	//width: 100%; |  | ||||||
| 	font-size: 35px; |  | ||||||
| 	display:inline-block; |  | ||||||
| 	font-weight: bold; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .description-small { |  | ||||||
| 	height: 30px; |  | ||||||
| 	font-size: 16px; |  | ||||||
| 	overflow:hidden; |  | ||||||
| 	vertical-align: middle; |  | ||||||
| } |  | ||||||
| @@ -1,92 +0,0 @@ | |||||||
| /** @file |  | ||||||
|  * @author Edouard DUPIN |  | ||||||
|  * @copyright 2018, Edouard DUPIN, all right reserved |  | ||||||
|  * @license PROPRIETARY (see license file) |  | ||||||
|  */ |  | ||||||
| import { Component, OnInit, Input } from '@angular/core'; |  | ||||||
| import { isNullOrUndefined } from '@kangaroo-and-rabbit/kar-cw'; |  | ||||||
| import { NodeSmall } from 'app/back-api'; |  | ||||||
|  |  | ||||||
| import { AlbumService, DataService } from 'app/service'; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @Component({ |  | ||||||
| 	selector: 'app-element-season', |  | ||||||
| 	templateUrl: './element-season.html', |  | ||||||
| 	styleUrls: ['./element-season.less'] |  | ||||||
| }) |  | ||||||
| export class ElementSeasonComponent implements OnInit { |  | ||||||
| 	// input parameters |  | ||||||
| 	@Input() element: NodeSmall; |  | ||||||
| 	@Input() prefix: String; |  | ||||||
| 	@Input() countSubTypeCallBack: (arg0: number) => Promise<number>; |  | ||||||
| 	@Input() countSubType: String; |  | ||||||
| 	@Input() countSubType2CallBack: (arg0: number) => Promise<number>; |  | ||||||
| 	@Input() countSubType2: String; |  | ||||||
| 	@Input() subValuesCallBack: (arg0: number) => Promise<string[]>; |  | ||||||
| 	@Input() subValues: String; |  | ||||||
|  |  | ||||||
| 	prefixName: string = ""; |  | ||||||
| 	numberAlbum: string; |  | ||||||
| 	count: number; |  | ||||||
| 	count2: number; |  | ||||||
| 	subValueData: String; |  | ||||||
| 	covers: string[]; |  | ||||||
| 	description: string; |  | ||||||
|  |  | ||||||
| 	constructor( |  | ||||||
| 		private albumService: AlbumService, |  | ||||||
| 		private dataService: DataService) { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
| 	ngOnInit() { |  | ||||||
| 		this.prefix = this.prefixName ?? ""; |  | ||||||
| 		this.count = undefined; |  | ||||||
| 		this.count2 = undefined; |  | ||||||
| 		//console.log(`element: ${JSON.stringify(this.element, null, 2)}`); |  | ||||||
|  |  | ||||||
| 		if (isNullOrUndefined(this.element)) { |  | ||||||
| 			this.numberAlbum = undefined; |  | ||||||
| 			this.covers = undefined; |  | ||||||
| 			this.description = undefined; |  | ||||||
| 		} |  | ||||||
| 		this.numberAlbum = this.element.name; |  | ||||||
| 		this.description = this.element.description; |  | ||||||
| 		this.covers = this.dataService.getListThumbnailUrl(this.element.covers); |  | ||||||
| 		let self = this; |  | ||||||
| 		if (!isNullOrUndefined(this.countSubTypeCallBack)) { |  | ||||||
| 			this.countSubTypeCallBack(this.element.id) |  | ||||||
| 				.then((response) => { |  | ||||||
| 					self.count = response; |  | ||||||
| 					//console.log(`get values: ${this.element.id} ==> ${self.count}`) |  | ||||||
| 				}).catch((response) => { |  | ||||||
| 					self.count = undefined; |  | ||||||
| 				}); |  | ||||||
| 		} |  | ||||||
| 		if (!isNullOrUndefined(this.countSubType2CallBack)) { |  | ||||||
| 			this.countSubType2CallBack(this.element.id) |  | ||||||
| 				.then((response) => { |  | ||||||
| 					self.count2 = response; |  | ||||||
| 					//console.log(`get values: ${this.element.id} ==> ${self.count}`) |  | ||||||
| 				}).catch((response) => { |  | ||||||
| 					self.count2 = undefined; |  | ||||||
| 				}); |  | ||||||
| 		} |  | ||||||
| 		if (!isNullOrUndefined(this.subValuesCallBack)) { |  | ||||||
| 			//console.log(`Value call back define ==> call values`) |  | ||||||
| 			this.subValuesCallBack(this.element.id) |  | ||||||
| 				.then((response: string[]) => { |  | ||||||
| 					this.subValueData = ""; |  | ||||||
| 					for (let kkk = 0; kkk < response.length; kkk++) { |  | ||||||
| 						if (kkk != 0) { |  | ||||||
| 							this.subValueData += ", "; |  | ||||||
| 						} |  | ||||||
| 						this.subValueData += response[kkk]; |  | ||||||
| 					} |  | ||||||
| 					//console.log(`get values: ${this.element.id} ==> ${self.subValueData}`) |  | ||||||
| 				}).catch((response) => { |  | ||||||
| 					self.count2 = undefined; |  | ||||||
| 				}); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,23 +0,0 @@ | |||||||
| <div> |  | ||||||
| 	<div class="count-base"> |  | ||||||
| 		@if(countTrack) { |  | ||||||
| 			<div class="count"> |  | ||||||
| 				{{countTrack}} |  | ||||||
| 			</div> |  | ||||||
| 		} |  | ||||||
| 	</div> |  | ||||||
| 	<div class="imgContainer-small"> |  | ||||||
| 		@if(covers && covers.length > 0) { |  | ||||||
| 			<div> |  | ||||||
| 				<!--<data-image id="{{cover}}"></data-image>--> |  | ||||||
| 				<img src="{{covers[0]}}"/> |  | ||||||
| 			</div> |  | ||||||
| 		} |  | ||||||
| 		@else { |  | ||||||
| 			<div class="noImage"></div> |  | ||||||
| 		} |  | ||||||
| 	</div> |  | ||||||
| 	<div class="title-small"> |  | ||||||
| 		{{name}} |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| @@ -1,63 +0,0 @@ | |||||||
|  |  | ||||||
| .count-base { |  | ||||||
| 	height: 0px; |  | ||||||
| 	width: 0px; |  | ||||||
| 	.count { |  | ||||||
| 		height: 30px; |  | ||||||
| 		width: 30px; |  | ||||||
| 		font-size: 17px; |  | ||||||
| 		line-height: 30px; |  | ||||||
| 		overflow:hidden; |  | ||||||
| 		position:relative; |  | ||||||
| 		z-index: 12; |  | ||||||
| 		left: 165px; |  | ||||||
| 		top: 2px; |  | ||||||
| 		text-align: center; |  | ||||||
| 		//padding: 5px 10px; |  | ||||||
| 		color: rgba(0, 0, 0, 1.0); |  | ||||||
| 		background: rgba(256, 256, 256, 0.3); |  | ||||||
| 		border: 1px solid; |  | ||||||
| 		border-color: rgba(256, 256, 256, 0.8); |  | ||||||
| 		border-radius: 15px; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .imgContainer-small { |  | ||||||
| 	right: 2px; |  | ||||||
| 	top: 2px; |  | ||||||
| 	text-align: center; |  | ||||||
| 	width: 200px; |  | ||||||
| 	margin: 0 auto; |  | ||||||
| 	height: 250px; |  | ||||||
| 	img { |  | ||||||
| 		//width: 100%; |  | ||||||
| 		max-height: 250px; |  | ||||||
| 		max-width: 200px; |  | ||||||
| 	} |  | ||||||
| 	.noImage { |  | ||||||
| 		height: 243px; |  | ||||||
| 		width: 193px; |  | ||||||
| 		border: solid 3px; |  | ||||||
| 		border-color: rgba(0, 0, 0, 0.7); |  | ||||||
| 		margin: auto; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .title-small { |  | ||||||
| 	height: 40px; |  | ||||||
| 	width: 200px; |  | ||||||
| 	font-size: 17px; |  | ||||||
| 	overflow:hidden; |  | ||||||
| 	display:inline-block; |  | ||||||
| 	text-align: center; |  | ||||||
| 	padding:auto; |  | ||||||
| 	background: rgba(256, 256, 256, 0.3); |  | ||||||
| 	border-radius: 7px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .description-small { |  | ||||||
| 	height: 30px; |  | ||||||
| 	font-size: 12px; |  | ||||||
| 	overflow:hidden; |  | ||||||
| 	vertical-align: middle; |  | ||||||
| } |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user