Browse Source

Add media deletion

Jeremie Pardou-Piquemal 3 years ago
parent
commit
895068f78d

+ 0 - 1
backend/src/index.js

@@ -1,4 +1,3 @@
-import { replaceImageUrl } from "./migrations";
 import { ownerOrNewHooks, onlySelfOrPublicGames } from "./hooks";
 
 const SESSION_DURATION = 60; // Session duration in days

+ 61 - 6
src/components/mediaLibrary/MediaLibraryModal.jsx

@@ -6,6 +6,9 @@ import styled from "styled-components";
 import { API_BASE } from "../../utils/settings";
 import backgroundGrid from "../../images/background-grid.png";
 
+import { confirmAlert } from "react-confirm-alert";
+import { toast } from "react-toastify";
+
 import Modal from "../../ui/Modal";
 
 import { useMediaLibrary } from ".";
@@ -14,6 +17,9 @@ import { useDropzone } from "react-dropzone";
 const ImageGrid = styled.div`
   display: flex;
   flex-wrap: wrap;
+  & > div {
+    position: relative;
+  }
   & img {
     height: 100px;
     margin: 0.5em;
@@ -25,12 +31,22 @@ const ImageGrid = styled.div`
       border: 1px dotted var(--color-primary);
     }
   }
+  & .remove {
+    position: absolute;
+    top: 15px;
+    right: 5px;
+  }
 `;
 
 const MediaLibraryModal = ({ show, setShow, onSelect }) => {
   const { t } = useTranslation();
 
-  const { getLibraryMedia, addMedia, libraries } = useMediaLibrary();
+  const {
+    getLibraryMedia,
+    addMedia,
+    removeMedia,
+    libraries,
+  } = useMediaLibrary();
 
   const queryClient = useQueryClient();
   const [tab, setTab] = React.useState(libraries[0].id);
@@ -72,6 +88,37 @@ const MediaLibraryModal = ({ show, setShow, onSelect }) => {
     }
   );
 
+  const onRemove = React.useCallback((key) => {
+    confirmAlert({
+      title: t("Confirmation"),
+      message: t("Do you really want to remove this media?"),
+      buttons: [
+        {
+          label: t("Yes"),
+          onClick: async () => {
+            try {
+              await removeMedia(key);
+              toast.success(t("Media deleted"), { autoClose: 1500 });
+            } catch (e) {
+              if (e.message === "Forbidden") {
+                toast.error(t("Action forbidden. Try logging in again."));
+              } else {
+                console.log(e);
+                toast.error(
+                  t("Error while deleting media. Try again later...")
+                );
+              }
+            }
+          },
+        },
+        {
+          label: t("No"),
+          onClick: () => {},
+        },
+      ],
+    });
+  }, []);
+
   const { getRootProps, getInputProps } = useDropzone({
     onDrop: uploadMediaMutation.mutate,
   });
@@ -122,11 +169,19 @@ const MediaLibraryModal = ({ show, setShow, onSelect }) => {
                 {!isLoading && (
                   <ImageGrid>
                     {data.map((key) => (
-                      <img
-                        src={`${API_BASE}/${key}`}
-                        key={key}
-                        onClick={() => handleSelect(key)}
-                      />
+                      <div key={key}>
+                        <img
+                          src={`${API_BASE}/${key}`}
+                          onClick={() => handleSelect(key)}
+                        />
+                        <button
+                          onClick={() => onRemove(key)}
+                          className="button icon-only remove"
+                          title={t("Remove")}
+                        >
+                          X
+                        </button>
+                      </div>
                     ))}
                   </ImageGrid>
                 )}

+ 10 - 3
src/components/mediaLibrary/MediaLibraryProvider.jsx

@@ -1,6 +1,9 @@
 import React, { useContext } from "react";
-import { uploadResourceImage } from "../../utils/api";
-import { listResourceImage } from "../../utils/api";
+import {
+  uploadResourceImage,
+  listResourceImage,
+  deleteResourceImage,
+} from "../../utils/api";
 
 export const MediaLibraryContext = React.createContext({});
 
@@ -13,6 +16,10 @@ export const MediaLibraryProvider = ({ children, libraries = [] }) => {
     };
   }, []);
 
+  const removeMedia = React.useCallback(async (key) => {
+    return await deleteResourceImage(key);
+  }, []);
+
   const getLibraryMedia = React.useCallback(
     async ({ boxId, resourceId }) => listResourceImage(boxId, resourceId),
     []
@@ -20,7 +27,7 @@ export const MediaLibraryProvider = ({ children, libraries = [] }) => {
 
   return (
     <MediaLibraryContext.Provider
-      value={{ addMedia, getLibraryMedia, libraries }}
+      value={{ addMedia, getLibraryMedia, libraries, removeMedia }}
     >
       {children}
     </MediaLibraryContext.Provider>

+ 4 - 1
src/i18n/en.json

@@ -236,5 +236,8 @@
   "Add file": "Add file",
   "Game": "Game",
   "Session": "Session",
-  "External": "External"
+  "External": "External",
+  "Do you really want to remove this media?": "Do you really want to remove this media?",
+  "Media deleted": "Media deleted",
+  "Error while deleting media. Try again later...": "Error while deleting media. Try again later..."
 }

+ 4 - 1
src/i18n/fr.json

@@ -234,5 +234,8 @@
   "Add file": "Ajouter un fichier",
   "Game": "Jeu",
   "Session": "Partie",
-  "External": "Externe"
+  "External": "Externe",
+  "Do you really want to remove this media?": "Souhaitez-vous supprimer ce media ?",
+  "Media deleted": "Media supprimé",
+  "Error while deleting media. Try again later...": "Suppression du media impossible. Essayez plus tard."
 }

+ 2 - 2
src/utils/api.js

@@ -1,4 +1,4 @@
-import { API_ENDPOINT, IS_PRODUCTION } from "./settings";
+import { API_ENDPOINT, IS_PRODUCTION, API_BASE } from "./settings";
 
 import testGame from "../games/testGame";
 import perfGame from "../games/perfGame";
@@ -49,7 +49,7 @@ export const listResourceImage = async (boxId, resourceId) => {
 };
 
 export const deleteResourceImage = async (filePath) => {
-  const result = await fetch(`${API_ENDPOINT}/${filePath}`, {
+  const result = await fetch(`${API_BASE}/${filePath}`, {
     method: "DELETE",
     credentials: "include",
   });