diff --git a/astroplant-frontend/src/api/index.ts b/astroplant-frontend/src/api/index.ts index 6f31ee5..ea41d3a 100644 --- a/astroplant-frontend/src/api/index.ts +++ b/astroplant-frontend/src/api/index.ts @@ -616,6 +616,21 @@ export class Api extends BaseApi { }); }; + /** + * Delete media. + * @throws {ErrorResponse} + */ + deleteMedia = ({ + mediaId, + }: { + mediaId: string; + }): Observable> => { + return this.request({ + path: `/media/${encodeURI(mediaId)}`, + method: "DELETE", + }); + }; + /** * @throws {ErrorResponse} */ diff --git a/astroplant-frontend/src/permissions.ts b/astroplant-frontend/src/permissions.ts index 6b57a79..18e0663 100644 --- a/astroplant-frontend/src/permissions.ts +++ b/astroplant-frontend/src/permissions.ts @@ -1,6 +1,7 @@ import { KitMembership } from "~/modules/me/reducer"; export interface KitPermissions { + deleteMedia: boolean; resetPassword: boolean; editDetails: boolean; editConfiguration: boolean; @@ -13,6 +14,7 @@ export interface KitPermissions { } export const NO_PERMISSIONS: KitPermissions = { + deleteMedia: false, resetPassword: false, editDetails: false, editConfiguration: false, @@ -35,6 +37,7 @@ export function kitPermissionsFromMembership( // This corresponds to // https://github.com/AstroPlant/astroplant-api/blob/3cc10c726b1d1cbb4185193d756febe19a0c8e09/astroplant-api/src/authorization/mod.rs#L39-L81 return { + deleteMedia: accessConfigure, resetPassword: accessSuper, editDetails: accessConfigure, editConfiguration: accessConfigure, diff --git a/astroplant-frontend/src/scenes/kit/kit-data/Media.module.css b/astroplant-frontend/src/scenes/kit/kit-data/Media.module.css new file mode 100644 index 0000000..3dcf61f --- /dev/null +++ b/astroplant-frontend/src/scenes/kit/kit-data/Media.module.css @@ -0,0 +1,5 @@ +.buttons { + display: flex; + flex-direction: row; + gap: 10px; +} diff --git a/astroplant-frontend/src/scenes/kit/kit-data/Media.tsx b/astroplant-frontend/src/scenes/kit/kit-data/Media.tsx index 860dd99..39652f8 100644 --- a/astroplant-frontend/src/scenes/kit/kit-data/Media.tsx +++ b/astroplant-frontend/src/scenes/kit/kit-data/Media.tsx @@ -1,6 +1,7 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, useContext } from "react"; import { Container, Image, Table } from "semantic-ui-react"; import { DateTime } from "luxon"; +import { IconTrash } from "@tabler/icons-react"; import RelativeTime from "~/Components/RelativeTime"; import Loading from "~/Components/Loading"; @@ -12,10 +13,19 @@ import { import { api, schemas } from "~/api"; import { rtkApi } from "~/services/astroplant"; import { firstValueFrom } from "rxjs"; -import { useAppSelector } from "~/hooks"; +import { useAppDispatch, useAppSelector } from "~/hooks"; +import { default as apiButton } from "~/Components/ApiButton"; import { Button } from "~/Components/Button"; import { ModalDialog } from "~/Components/ModalDialog"; +import { PermissionsContext } from "../contexts"; + +import style from "./Media.module.css"; +import { notificationSuccess } from "~/modules/notification"; +import { addNotificationRequest } from "~/modules/notification/actions"; + +const ApiButton = apiButton(); + export type Props = { kitState: KitState; configuration: KitConfigurationState; @@ -23,11 +33,14 @@ export type Props = { export default function Media({ kitState, configuration }: Props) { const peripherals = useAppSelector(peripheralSelectors.selectEntities); + const permissions = useContext(PermissionsContext); + const dispatch = useAppDispatch(); const { data: mediaList, error: mediaListError, isLoading: mediaListIsLoading, + refetch, } = rtkApi.useListMediaQuery({ kitSerial: kitState.details!.serial, configuration: configuration.id, @@ -151,7 +164,7 @@ export default function Media({ kitState, configuration }: Props) { {media.name} {media.type} {media.size} - + {/* )} + {permissions.deleteMedia && ( + setDisplayMedia(media), + title: "Delete this media", + }} + confirm={() => ({ + content: ( + <> + Are you sure you wish to permanently delete this + media? This cannot be undone. + + ), + })} + send={() => + api.deleteMedia({ + mediaId: media.id, + }) + } + onResponse={(_response) => { + refetch(); + const notification = notificationSuccess( + "Media deleted", + "The media was successfully deleted.", + ); + dispatch(addNotificationRequest(notification)); + }} + > + + + )} );