From 9cce1dd794024f1ff14523ff11c451425b54361a Mon Sep 17 00:00:00 2001 From: keahorvath Date: Fri, 3 Mar 2023 15:43:36 +0100 Subject: [PATCH] ajout correction tp1-2 --- .gitignore | 2 + README.md | 2 + backend/.gitignore | 35 ++ backend/mvnw | 310 ++++++++++++++++++ backend/mvnw.cmd | 182 ++++++++++ backend/pom.xml | 67 ++++ .../java/pdl/backend/BackendApplication.java | 13 + backend/src/main/java/pdl/backend/Dao.java | 17 + backend/src/main/java/pdl/backend/Image.java | 30 ++ .../java/pdl/backend/ImageController.java | 94 ++++++ .../src/main/java/pdl/backend/ImageDao.java | 58 ++++ .../src/main/resources/application.properties | 1 + backend/src/main/resources/test.jpg | Bin 0 -> 13107 bytes .../pdl/backend/BackendApplicationTests.java | 13 + .../pdl/backend/ImageControllerTests.java | 92 ++++++ frontend/.gitignore | 10 + frontend/index.html | 13 + frontend/package.json | 24 ++ frontend/pom.xml | 85 +++++ frontend/public/favicon.ico | Bin 0 -> 4286 bytes frontend/src/App.vue | 56 ++++ frontend/src/assets/logo.png | Bin 0 -> 6849 bytes frontend/src/components/Gallery.vue | 26 ++ frontend/src/components/Home.vue | 36 ++ frontend/src/components/Image.vue | 31 ++ frontend/src/components/Upload.vue | 41 +++ frontend/src/env.d.ts | 8 + frontend/src/http-api.ts | 23 ++ frontend/src/image.ts | 4 + frontend/src/main.ts | 5 + frontend/src/router.ts | 36 ++ frontend/tsconfig.json | 20 ++ frontend/vite.config.ts | 24 ++ pom.xml | 15 + 34 files changed, 1373 insertions(+) create mode 100644 .gitignore create mode 100644 backend/.gitignore create mode 100644 backend/mvnw create mode 100644 backend/mvnw.cmd create mode 100644 backend/pom.xml create mode 100644 backend/src/main/java/pdl/backend/BackendApplication.java create mode 100644 backend/src/main/java/pdl/backend/Dao.java create mode 100644 backend/src/main/java/pdl/backend/Image.java create mode 100644 backend/src/main/java/pdl/backend/ImageController.java create mode 100644 backend/src/main/java/pdl/backend/ImageDao.java create mode 100644 backend/src/main/resources/application.properties create mode 100644 backend/src/main/resources/test.jpg create mode 100644 backend/src/test/java/pdl/backend/BackendApplicationTests.java create mode 100644 backend/src/test/java/pdl/backend/ImageControllerTests.java create mode 100644 frontend/.gitignore create mode 100644 frontend/index.html create mode 100644 frontend/package.json create mode 100644 frontend/pom.xml create mode 100644 frontend/public/favicon.ico create mode 100644 frontend/src/App.vue create mode 100644 frontend/src/assets/logo.png create mode 100644 frontend/src/components/Gallery.vue create mode 100644 frontend/src/components/Home.vue create mode 100644 frontend/src/components/Image.vue create mode 100644 frontend/src/components/Upload.vue create mode 100644 frontend/src/env.d.ts create mode 100644 frontend/src/http-api.ts create mode 100644 frontend/src/image.ts create mode 100644 frontend/src/main.ts create mode 100644 frontend/src/router.ts create mode 100644 frontend/tsconfig.json create mode 100644 frontend/vite.config.ts create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..06ca89e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode/launch.json +pdl.code-workspace diff --git a/README.md b/README.md index e69de29..8f06169 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,2 @@ +# client-serveur + diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..7b849e2 --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,35 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +src/main/resources/public/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ +.mvn/ \ No newline at end of file diff --git a/backend/mvnw b/backend/mvnw new file mode 100644 index 0000000..a16b543 --- /dev/null +++ b/backend/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/backend/mvnw.cmd b/backend/mvnw.cmd new file mode 100644 index 0000000..c8d4337 --- /dev/null +++ b/backend/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/backend/pom.xml b/backend/pom.xml new file mode 100644 index 0000000..41fb5b2 --- /dev/null +++ b/backend/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.7 + + + pdl + backend + 0.0.1-SNAPSHOT + backend + Demo project for Spring Boot + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + maven-resources-plugin + + + copy Vue.js frontend content + generate-resources + + copy-resources + + + src/main/resources/public + true + + + ../frontend/target/dist + + static/ + index.html + favicon.ico + + + + + + + + + + + diff --git a/backend/src/main/java/pdl/backend/BackendApplication.java b/backend/src/main/java/pdl/backend/BackendApplication.java new file mode 100644 index 0000000..0f4ada0 --- /dev/null +++ b/backend/src/main/java/pdl/backend/BackendApplication.java @@ -0,0 +1,13 @@ +package pdl.backend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class BackendApplication { + + public static void main(String[] args) { + SpringApplication.run(BackendApplication.class, args); + } + +} diff --git a/backend/src/main/java/pdl/backend/Dao.java b/backend/src/main/java/pdl/backend/Dao.java new file mode 100644 index 0000000..4c4ae7c --- /dev/null +++ b/backend/src/main/java/pdl/backend/Dao.java @@ -0,0 +1,17 @@ +package pdl.backend; + +import java.util.Optional; +import java.util.List; + +public interface Dao { + + void create(final T t); + + Optional retrieve(final long id); + + List retrieveAll(); + + void update(final T t, final String[] params); + + void delete(final T t); +} diff --git a/backend/src/main/java/pdl/backend/Image.java b/backend/src/main/java/pdl/backend/Image.java new file mode 100644 index 0000000..130e0ec --- /dev/null +++ b/backend/src/main/java/pdl/backend/Image.java @@ -0,0 +1,30 @@ +package pdl.backend; + +public class Image { + private static Long count = Long.valueOf(0); + private Long id; + private String name; + private byte[] data; + + public Image(final String name, final byte[] data) { + id = count++; + this.name = name; + this.data = data; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public byte[] getData() { + return data; + } +} diff --git a/backend/src/main/java/pdl/backend/ImageController.java b/backend/src/main/java/pdl/backend/ImageController.java new file mode 100644 index 0000000..6c38402 --- /dev/null +++ b/backend/src/main/java/pdl/backend/ImageController.java @@ -0,0 +1,94 @@ +package pdl.backend; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Optional; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.InputStreamResource; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@RestController +public class ImageController { + + @Autowired + private ObjectMapper mapper; + + private final ImageDao imageDao; + + @Autowired + public ImageController(ImageDao imageDao) { + this.imageDao = imageDao; + } + + @RequestMapping(value = "/images/{id}", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE) + public ResponseEntity getImage(@PathVariable("id") long id) { + + Optional image = imageDao.retrieve(id); + + if (image.isPresent()) { + InputStream inputStream = new ByteArrayInputStream(image.get().getData()); + return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(new InputStreamResource(inputStream)); + } + return new ResponseEntity<>("Image id=" + id + " not found.", HttpStatus.NOT_FOUND); + } + + @RequestMapping(value = "/images/{id}", method = RequestMethod.DELETE) + public ResponseEntity deleteImage(@PathVariable("id") long id) { + + Optional image = imageDao.retrieve(id); + + if (image.isPresent()) { + imageDao.delete(image.get()); + return new ResponseEntity<>("Image id=" + id + " deleted.", HttpStatus.OK); + } + return new ResponseEntity<>("Image id=" + id + " not found.", HttpStatus.NOT_FOUND); + } + + @RequestMapping(value = "/images", method = RequestMethod.POST) + public ResponseEntity addImage(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { + + String contentType = file.getContentType(); + if (!contentType.equals(MediaType.IMAGE_JPEG.toString())) { + return new ResponseEntity<>("Only JPEG file format supported", HttpStatus.UNSUPPORTED_MEDIA_TYPE); + } + + try { + imageDao.create(new Image(file.getOriginalFilename(), file.getBytes())); + } catch (IOException e) { + return new ResponseEntity<>("Failure to read file", HttpStatus.NO_CONTENT); + } + return new ResponseEntity<>("Image uploaded", HttpStatus.OK); + } + + @RequestMapping(value = "/images", method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public ArrayNode getImageList() { + List images = imageDao.retrieveAll(); + ArrayNode nodes = mapper.createArrayNode(); + for (Image image : images) { + ObjectNode objectNode = mapper.createObjectNode(); + objectNode.put("id", image.getId()); + objectNode.put("name", image.getName()); + nodes.add(objectNode); + } + return nodes; + } + +} diff --git a/backend/src/main/java/pdl/backend/ImageDao.java b/backend/src/main/java/pdl/backend/ImageDao.java new file mode 100644 index 0000000..1908f44 --- /dev/null +++ b/backend/src/main/java/pdl/backend/ImageDao.java @@ -0,0 +1,58 @@ +package pdl.backend; + +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Repository; + +@Repository +public class ImageDao implements Dao { + + private final Map images = new HashMap<>(); + + public ImageDao() { + final ClassPathResource imgFile = new ClassPathResource("test.jpg"); + byte[] fileContent; + try { + fileContent = Files.readAllBytes(imgFile.getFile().toPath()); + Image img = new Image("test.jpg", fileContent); + images.put(img.getId(), img); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + @Override + public Optional retrieve(final long id) { + return Optional.ofNullable(images.get(id)); + } + + @Override + public List retrieveAll() { + return new ArrayList(images.values()); + } + + @Override + public void create(final Image img) { + images.put(img.getId(), img); + } + + @Override + public void update(final Image img, final String[] params) { + img.setName(Objects.requireNonNull(params[0], "Name cannot be null")); + + images.put(img.getId(), img); + } + + @Override + public void delete(final Image img) { + images.remove(img.getId()); + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/backend/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/backend/src/main/resources/test.jpg b/backend/src/main/resources/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bb7b4da5c75ffc5943e2a728c7631d48813864c1 GIT binary patch literal 13107 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 literal 0 HcmV?d00001 diff --git a/backend/src/test/java/pdl/backend/BackendApplicationTests.java b/backend/src/test/java/pdl/backend/BackendApplicationTests.java new file mode 100644 index 0000000..b316b44 --- /dev/null +++ b/backend/src/test/java/pdl/backend/BackendApplicationTests.java @@ -0,0 +1,13 @@ +package pdl.backend; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class BackendApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/backend/src/test/java/pdl/backend/ImageControllerTests.java b/backend/src/test/java/pdl/backend/ImageControllerTests.java new file mode 100644 index 0000000..568fa57 --- /dev/null +++ b/backend/src/test/java/pdl/backend/ImageControllerTests.java @@ -0,0 +1,92 @@ +package pdl.backend; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +@SpringBootTest +@AutoConfigureMockMvc +@TestMethodOrder(OrderAnnotation.class) +public class ImageControllerTests { + + @Autowired + private MockMvc mockMvc; + + @BeforeAll + public static void reset() { + // reset Image class static counter + ReflectionTestUtils.setField(Image.class, "count", Long.valueOf(0)); + } + + @Test + @Order(1) + public void getImageListShouldReturnSuccess() throws Exception { + this.mockMvc.perform(get("/images")).andDo(print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)); + } + + @Test + @Order(2) + public void getImageShouldReturnNotFound() throws Exception { + this.mockMvc.perform(get("/images/1")).andDo(print()).andExpect(status().isNotFound()); + } + + @Test + @Order(3) + public void getImageShouldReturnSuccess() throws Exception { + this.mockMvc.perform(get("/images/0")).andExpect(status().isOk()); + } + + @Test + @Order(4) + public void deleteImagesShouldReturnMethodNotAllowed() throws Exception { + this.mockMvc.perform(delete("/images")).andDo(print()).andExpect(status().isMethodNotAllowed()); + } + + @Test + @Order(5) + public void deleteImageShouldReturnNotFound() throws Exception { + this.mockMvc.perform(delete("/images/1")).andDo(print()).andExpect(status().isNotFound()); + } + + @Test + @Order(6) + public void deleteImageShouldReturnSuccess() throws Exception { + this.mockMvc.perform(delete("/images/0")).andDo(print()).andExpect(status().isOk()); + } + + @Test + @Order(7) + public void createImageShouldReturnSuccess() throws Exception { + final ClassPathResource imgFile = new ClassPathResource("test.jpg"); + MockMultipartFile multipartFile = new MockMultipartFile("file", "test.jpg", "image/jpeg", imgFile.getInputStream()); + this.mockMvc.perform(MockMvcRequestBuilders.multipart("/images").file(multipartFile)).andDo(print()) + .andExpect(status().isOk()); + } + + @Test + @Order(8) + public void createImageShouldReturnUnsupportedMediaType() throws Exception { + MockMultipartFile multipartFile = new MockMultipartFile("file", "test.jpg", "text/plain", "Test".getBytes()); + this.mockMvc.perform(MockMvcRequestBuilders.multipart("/images").file(multipartFile)).andDo(print()) + .andExpect(status().isUnsupportedMediaType()); + } + +} diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..e9056c4 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,10 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local +target +package-lock.json +.classpath +.settings/ +.vscode/ \ No newline at end of file diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..a8ca635 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + PDL L3 - Galerie + + +
+ + + diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..c28a350 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,24 @@ +{ + "name": "frontend-ts", + "version": "0.1.0", + "scripts": { + "dev": "vite", + "build": "vue-tsc --noEmit && vite build", + "serve": "vite preview" + }, + "dependencies": { + "@babel/core": "^7.20.12", + "@popperjs/core": "^2.11.6", + "axios": "^1.3.3", + "path": "^0.12.7", + "vue": "^3.2.47", + "vue-router": "^4.1.6" + }, + "devDependencies": { + "@types/node": "^18.14.0", + "@vitejs/plugin-vue": "^4.0.0", + "typescript": "^4.9.5", + "vite": "^4.1.3", + "vue-tsc": "^1.1.4" + } +} diff --git a/frontend/pom.xml b/frontend/pom.xml new file mode 100644 index 0000000..a6aedf5 --- /dev/null +++ b/frontend/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + frontend + + + pdl + client-serveur + 0.0.1-SNAPSHOT + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.3.2 + + + + npm install (initialize) + + exec + + initialize + + npm + + install + + + + + + npm install (clean) + + exec + + pre-clean + + npm + + install + + + + + + npm run build (compile) + + exec + + compile + + npm + + run + build + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/frontend/src/App.vue b/frontend/src/App.vue new file mode 100644 index 0000000..0006d53 --- /dev/null +++ b/frontend/src/App.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/frontend/src/assets/logo.png b/frontend/src/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d2503fc2a44b5053b0837ebea6e87a2d339a43 GIT binary patch literal 6849 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 +import { ref } from 'vue' +import { api } from '@/http-api'; +import { ImageType } from '@/image' +import Image from './Image.vue'; + +const imageList = ref([]); + +api.getImageList() + .then((data) => { + imageList.value = data; + }) + .catch(e => { + console.log(e.message); + }); + + + + + diff --git a/frontend/src/components/Home.vue b/frontend/src/components/Home.vue new file mode 100644 index 0000000..0cf45d1 --- /dev/null +++ b/frontend/src/components/Home.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/frontend/src/components/Image.vue b/frontend/src/components/Image.vue new file mode 100644 index 0000000..1a54811 --- /dev/null +++ b/frontend/src/components/Image.vue @@ -0,0 +1,31 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/components/Upload.vue b/frontend/src/components/Upload.vue new file mode 100644 index 0000000..0c60aea --- /dev/null +++ b/frontend/src/components/Upload.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/frontend/src/env.d.ts b/frontend/src/env.d.ts new file mode 100644 index 0000000..d27eb5a --- /dev/null +++ b/frontend/src/env.d.ts @@ -0,0 +1,8 @@ +/// + +declare module '*.vue' { + import { DefineComponent } from 'vue' + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types + const component: DefineComponent<{}, {}, any> + export default component +} diff --git a/frontend/src/http-api.ts b/frontend/src/http-api.ts new file mode 100644 index 0000000..c6e90c5 --- /dev/null +++ b/frontend/src/http-api.ts @@ -0,0 +1,23 @@ +import axios, { AxiosResponse, AxiosError } from 'axios'; +import { ImageType } from '@/image'; + +const instance = axios.create({ + baseURL: "/", + timeout: 15000, +}); + +const responseBody = (response: AxiosResponse) => response.data; + +const requests = { + get: (url: string, param: {}) => instance.get(url, param).then(responseBody), + post: (url: string, body: {}) => instance.post(url, body, { headers: { "Content-Type": "multipart/form-data" }, }).then(responseBody), + put: (url: string, body: {}) => instance.put(url, body).then(responseBody), + delete: (url: string) => instance.delete(url).then(responseBody) +}; + +export const api = { + getImageList: (): Promise => requests.get('images', {}), + getImage: (id: number): Promise => requests.get(`images/${id}`, { responseType: "blob" }), + createImage: (form: FormData): Promise => requests.post('images', form), + deleteImage: (id: number): Promise => requests.delete(`images/${id}`), +}; \ No newline at end of file diff --git a/frontend/src/image.ts b/frontend/src/image.ts new file mode 100644 index 0000000..7950e45 --- /dev/null +++ b/frontend/src/image.ts @@ -0,0 +1,4 @@ +export interface ImageType { + id: number; + name: string; +} \ No newline at end of file diff --git a/frontend/src/main.ts b/frontend/src/main.ts new file mode 100644 index 0000000..265d847 --- /dev/null +++ b/frontend/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import App from './App.vue' +import router from './router'; + +createApp(App).use(router).mount('#app') diff --git a/frontend/src/router.ts b/frontend/src/router.ts new file mode 100644 index 0000000..a3b2437 --- /dev/null +++ b/frontend/src/router.ts @@ -0,0 +1,36 @@ +import { createWebHistory, createRouter } from "vue-router"; +import { RouteRecordRaw } from "vue-router"; + +const routes: Array = [ + { + path: "/", + name: "home", + component: () => import("./components/Home.vue"), + props: true + }, + { + path: "/gallery", + name: "gallery", + component: () => import("./components/Gallery.vue"), + props: true + }, + { + path: "/image/:id", + name: "image", + component: () => import("./components/Image.vue"), + props: ({ params }) => ({ id: Number(params.id) || 0 }) + }, + { + path: "/upload", + name: "upload", + component: () => import("./components/Upload.vue"), + props: true + } +]; + +const router = createRouter({ + history: createWebHistory(), + routes, +}); + +export default router; \ No newline at end of file diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..2f0cbd7 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "moduleResolution": "node", + "strict": true, + "jsx": "preserve", + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "lib": ["esnext", "dom"], + "paths": { + "@/*": [ + "./src/*" + ] + } + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..522b738 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from "path"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), + }, + }, + server: { + proxy: { + '^/images': { + target: 'http://localhost:8080' // Spring boot backend address + } + } + }, + build: { + outDir: 'target/dist', + assetsDir: 'static' + } +}) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..2755b71 --- /dev/null +++ b/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + pdl + client-serveur + 0.0.1-SNAPSHOT + pom + + + frontend + backend + + \ No newline at end of file