This commit is contained in:
Theophyl Hoguet committed 2023-03-03 22:18:39 +01:00
1 parent 2db6811b55
commit 17399d7c7a
14 files changed
+240 -226

No files matched your search

+14 -11
View File
@@ -1,13 +1,16 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8" /> <head>
<link rel="icon" href="/favicon.ico" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="icon" href="/favicon.ico" />
<title>PDL L3 - Galerie</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head> <title>PDL L3 - Galerie</title>
<body> </head>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script> <body>
</body> <div id="app"></div>
</html> <script type="module" src="/src/main.ts"></script>
</body>
</html>
+19 -18
View File
@@ -1,23 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<modelVersion>4.0.0</modelVersion> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>frontend</artifactId> <modelVersion>4.0.0</modelVersion>
<artifactId>frontend</artifactId>
<parent> <parent>
<groupId>pdl</groupId> <groupId>pdl</groupId>
<artifactId>client-serveur</artifactId> <artifactId>client-serveur</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </parent>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId> <artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version> <version>1.3.2</version>
<executions> <executions>
<!-- Required: The following will ensure `npm install` is called <!-- Required: The following will ensure `npm install` is called
before anything else during the 'Default Lifecycle' --> before anything else during the 'Default Lifecycle' -->
<execution> <execution>
<id>npm install (initialize)</id> <id>npm install (initialize)</id>
@@ -47,7 +48,7 @@
</arguments> </arguments>
</configuration> </configuration>
</execution> </execution>
<!-- Required: This following calls `npm run build` where 'build' is <!-- Required: This following calls `npm run build` where 'build' is
the script name I used in my project, change this if yours is the script name I used in my project, change this if yours is
different --> different -->
<execution> <execution>
@@ -64,7 +65,7 @@
</arguments> </arguments>
</configuration> </configuration>
</execution> </execution>
<!-- <execution> <!-- <execution>
<id>npm run clean (clean)</id> <id>npm run clean (clean)</id>
<goals> <goals>
<goal>exec</goal> <goal>exec</goal>
@@ -78,8 +79,8 @@
</arguments> </arguments>
</configuration> </configuration>
</execution> --> </execution> -->
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>
+41 -37
View File
@@ -2,55 +2,59 @@
</script> </script>
<template> <template>
<div id="app"> <div id="app">
<nav> <nav>
<ul> <ul>
<li> <li>
<router-link to="/">Home</router-link> <router-link to="/">Home</router-link>
</li> </li>
<li> <li>
<router-link to="/gallery">Gallery</router-link> <router-link to="/gallery">Gallery</router-link>
</li> </li>
<li> <li>
<router-link to="/upload">Upload</router-link> <router-link to="/upload">Upload</router-link>
</li> </li>
</ul> </ul>
</nav> </nav>
<div> <div>
<h1>PDL - L3</h1> <h1>PDL - L3</h1>
<router-view /> <router-view />
</div> </div>
</div> </div>
</template> </template>
<style> <style>
#app { #app {
text-align: center; text-align: center;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
color: #2c3e50; color: #2c3e50;
} }
ul { ul {
list-style-type: none; list-style-type: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden;
background-color: #333; background-color: #333;
} }
li { li {
float: left; float: left;
} }
li a { li a {
display: block; display: block;
color: white; color: white;
text-align: center; text-align: center;
padding: 14px 16px; padding: 14px 16px;
text-decoration: none; text-decoration: none;
} }
.error { .error {
color: red; color: red;
font-weight: bold; font-weight: bold;
list-style-type: none; list-style-type: none;
margin-top: 1em; margin-top: 1em;
} }
</style> </style>
+11 -12
View File
@@ -7,20 +7,19 @@ import Image from './Image.vue';
const imageList = ref<ImageType[]>([]); const imageList = ref<ImageType[]>([]);
api.getImageList() api.getImageList()
.then((data) => { .then((data) => {
imageList.value = data; imageList.value = data;
}) })
.catch(e => { .catch(e => {
console.log(e.message); console.log(e.message);
}); });
</script> </script>
<template> <template>
<div> <div>
<h3>Gallery</h3> <h3>Gallery</h3>
<Image v-for="image in imageList" :id="image.id" /> <Image v-for="image in imageList" :id="image.id" />
</div> </div>
</template> </template>
<style scoped> <style scoped></style>
</style>
+15 -16
View File
@@ -9,28 +9,27 @@ const imageList = ref<ImageType[]>([]);
getImageList(); getImageList();
function getImageList() { function getImageList() {
api.getImageList().then((data) => { api.getImageList().then((data) => {
imageList.value = data; imageList.value = data;
}).catch(e => { }).catch(e => {
console.log(e.message); console.log(e.message);
}); });
} }
function showImage() { function showImage() {
router.push({ name: 'image', params: { id: selectedId.value } }) router.push({ name: 'image', params: { id: selectedId.value } })
} }
</script> </script>
<template> <template>
<div> <div>
<h3>Choose an image</h3> <h3>Choose an image</h3>
<div> <div>
<select v-model="selectedId" @change="showImage"> <select v-model="selectedId" @change="showImage">
<option v-for="image in imageList" :value="image.id" :key="image.id">{{ image.name }}</option> <option v-for="image in imageList" :value="image.id" :key="image.id">{{ image.name }}</option>
</select> </select>
</div> </div>
</div> </div>
</template> </template>
<style scoped> <style scoped></style>
</style>
+18 -18
View File
@@ -5,27 +5,27 @@ import { api } from '@/http-api';
const props = defineProps<{ id: number }>() const props = defineProps<{ id: number }>()
api.getImage(props.id) api.getImage(props.id)
.then((data: Blob) => { .then((data: Blob) => {
const reader = new window.FileReader(); const reader = new window.FileReader();
reader.readAsDataURL(data); reader.readAsDataURL(data);
reader.onload = () => { reader.onload = () => {
const galleryElt = document.getElementById("gallery-"+props.id); const galleryElt = document.getElementById("gallery-" + props.id);
if (galleryElt !== null) { if (galleryElt !== null) {
const imgElt = document.createElement("img"); const imgElt = document.createElement("img");
galleryElt.appendChild(imgElt); galleryElt.appendChild(imgElt);
if (imgElt !== null && reader.result as string) { if (imgElt !== null && reader.result as string) {
imgElt.setAttribute("src", (reader.result as string)); imgElt.setAttribute("src", (reader.result as string));
} }
} }
}; };
}) })
.catch(e => { .catch(e => {
console.log(e.message); console.log(e.message);
}); });
</script> </script>
<template> <template>
<figure :id="'gallery-'+id"></figure> <figure :id="'gallery-' + id"></figure>
</template> </template>
<style></style> <style></style>
+24 -25
View File
@@ -5,37 +5,36 @@ import { api } from '@/http-api';
const target = ref<HTMLInputElement>(); const target = ref<HTMLInputElement>();
function submitFile() { function submitFile() {
if (target.value !== null && target.value !== undefined && target.value.files !== null) { if (target.value !== null && target.value !== undefined && target.value.files !== null) {
const file = target.value.files[0]; const file = target.value.files[0];
if (file === undefined) if (file === undefined)
return; return;
let formData = new FormData(); let formData = new FormData();
formData.append("file", file); formData.append("file", file);
api.createImage(formData).then(() => { api.createImage(formData).then(() => {
if (target.value !== undefined) if (target.value !== undefined)
target.value.value = ''; target.value.value = '';
}).catch(e => { }).catch(e => {
console.log(e.message); console.log(e.message);
}); });
} }
} }
function handleFileUpload(event: Event) { function handleFileUpload(event: Event) {
target.value = (event.target as HTMLInputElement); target.value = (event.target as HTMLInputElement);
} }
</script> </script>
<template> <template>
<div> <div>
<h3>Upload an image</h3> <h3>Upload an image</h3>
<div> <div>
<input type="file" id="file" ref="file" @change="handleFileUpload" /> <input type="file" id="file" ref="file" @change="handleFileUpload" />
</div> </div>
<div> <div>
<button @click="submitFile">Submit</button> <button @click="submitFile">Submit</button>
</div> </div>
</div> </div>
</template> </template>
<style scoped> <style scoped></style>
</style>
+4 -4
View File
@@ -1,8 +1,8 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
declare module '*.vue' { declare module '*.vue' {
import { DefineComponent } from 'vue' import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any> const component: DefineComponent<{}, {}, any>
export default component export default component
} }
+10 -10
View File
@@ -2,22 +2,22 @@ import axios, { AxiosResponse, AxiosError } from 'axios';
import { ImageType } from '@/image'; import { ImageType } from '@/image';
const instance = axios.create({ const instance = axios.create({
baseURL: "/", baseURL: "/",
timeout: 15000, timeout: 15000,
}); });
const responseBody = (response: AxiosResponse) => response.data; const responseBody = (response: AxiosResponse) => response.data;
const requests = { const requests = {
get: (url: string, param: {}) => instance.get(url, param).then(responseBody), 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), 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), put: (url: string, body: {}) => instance.put(url, body).then(responseBody),
delete: (url: string) => instance.delete(url).then(responseBody) delete: (url: string) => instance.delete(url).then(responseBody)
}; };
export const api = { export const api = {
getImageList: (): Promise<ImageType[]> => requests.get('images', {}), getImageList: (): Promise<ImageType[]> => requests.get('images', {}),
getImage: (id: number): Promise<Blob> => requests.get(`images/${id}`, { responseType: "blob" }), getImage: (id: number): Promise<Blob> => requests.get(`images/${id}`, { responseType: "blob" }),
createImage: (form: FormData): Promise<ImageType> => requests.post('images', form), createImage: (form: FormData): Promise<ImageType> => requests.post('images', form),
deleteImage: (id: number): Promise<void> => requests.delete(`images/${id}`), deleteImage: (id: number): Promise<void> => requests.delete(`images/${id}`),
}; };
+2 -2
View File
@@ -1,4 +1,4 @@
export interface ImageType { export interface ImageType {
id: number; id: number;
name: string; name: string;
} }
+26 -26
View File
@@ -2,35 +2,35 @@ import { createWebHistory, createRouter } from "vue-router";
import { RouteRecordRaw } from "vue-router"; import { RouteRecordRaw } from "vue-router";
const routes: Array<RouteRecordRaw> = [ const routes: Array<RouteRecordRaw> = [
{ {
path: "/", path: "/",
name: "home", name: "home",
component: () => import("./components/Home.vue"), component: () => import("./components/Home.vue"),
props: true props: true
}, },
{ {
path: "/gallery", path: "/gallery",
name: "gallery", name: "gallery",
component: () => import("./components/Gallery.vue"), component: () => import("./components/Gallery.vue"),
props: true props: true
}, },
{ {
path: "/image/:id", path: "/image/:id",
name: "image", name: "image",
component: () => import("./components/Image.vue"), component: () => import("./components/Image.vue"),
props: ({ params }) => ({ id: Number(params.id) || 0 }) props: ({ params }) => ({ id: Number(params.id) || 0 })
}, },
{ {
path: "/upload", path: "/upload",
name: "upload", name: "upload",
component: () => import("./components/Upload.vue"), component: () => import("./components/Upload.vue"),
props: true props: true
} }
]; ];
const router = createRouter({ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),
routes, routes,
}); });
export default router; export default router;
+27 -19
View File
@@ -1,20 +1,28 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "esnext",
"useDefineForClassFields": true, "useDefineForClassFields": true,
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"strict": true, "strict": true,
"jsx": "preserve", "jsx": "preserve",
"sourceMap": true, "sourceMap": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["esnext", "dom"], "lib": [
"paths": { "esnext",
"@/*": [ "dom"
"./src/*" ],
] "paths": {
} "@/*": [
}, "./src/*"
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], ]
} }
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
}
+17 -17
View File
@@ -4,21 +4,21 @@ import path from "path";
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
resolve: { resolve: {
alias: { alias: {
"@": path.resolve(__dirname, "./src"), "@": path.resolve(__dirname, "./src"),
}, },
}, },
server: { server: {
proxy: { proxy: {
'^/images': { '^/images': {
target: 'http://localhost:8080' // Spring boot backend address target: 'http://localhost:8080' // Spring boot backend address
} }
} }
}, },
build: { build: {
outDir: 'target/dist', outDir: 'target/dist',
assetsDir: 'static' assetsDir: 'static'
} }
}) })
+12 -11
View File
@@ -1,15 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<modelVersion>4.0.0</modelVersion> 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>pdl</groupId> <groupId>pdl</groupId>
<artifactId>client-serveur</artifactId> <artifactId>client-serveur</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<modules> <modules>
<module>frontend</module> <module>frontend</module>
<module>backend</module> <module>backend</module>
</modules> </modules>
</project> </project>