diff --git a/client/src/pages/both/homepage/Dashboard.tsx b/client/src/pages/both/homepage/Dashboard.tsx
index cf6314dd8..23546bf03 100644
--- a/client/src/pages/both/homepage/Dashboard.tsx
+++ b/client/src/pages/both/homepage/Dashboard.tsx
@@ -32,7 +32,7 @@ export function Dashboard() {
result={getMakerspacesResult}
render={(data) => {
const makerspaces: MakerspaceWithHours[] = data.makerspaces;
- const filteredSpaces: MakerspaceWithHours[] = makerspaces.filter((_makerspace: MakerspaceWithHours) => true); // TODO: grab the 'archieved' field from the db and check it (more logic than that required)
+ const filteredSpaces: MakerspaceWithHours[] = makerspaces.filter((_makerspace: MakerspaceWithHours) => true);
const sortedSpaces = filteredSpaces.sort((a: MakerspaceWithHours, b: MakerspaceWithHours) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase())
);
diff --git a/client/src/pages/makerspace_page/ManageMakerspacePage.tsx b/client/src/pages/makerspace_page/ManageMakerspacePage.tsx
index e1f33418f..8a71314a7 100644
--- a/client/src/pages/makerspace_page/ManageMakerspacePage.tsx
+++ b/client/src/pages/makerspace_page/ManageMakerspacePage.tsx
@@ -1,10 +1,13 @@
import { useMutation, useQuery } from "@apollo/client";
-import { useParams } from "react-router-dom";
-import { FullMakerspace, GET_MAKERSPACE_BY_ID } from "../../queries/makerspaceQueries";
+import { useNavigate, useParams } from "react-router-dom";
+import { ARCHIVE_MAKERSPACE, DELETE_MAKERSPACE, FullMakerspace, GET_MAKERSPACE_BY_ID, UNARCHIVE_MAKERSPACE } from "../../queries/makerspaceQueries";
import { Box, Button, Divider, Stack, TextField, Typography } from "@mui/material";
import RequestWrapper2 from "../../common/RequestWrapper2";
import { useState } from "react";
-import AddIcon from '@mui/icons-material/Add';
+import AddIcon from "@mui/icons-material/Add";
+import ArchiveIcon from "@mui/icons-material/Archive";
+import PublishIcon from "@mui/icons-material/Publish";
+import DeleteIcon from "@mui/icons-material/Delete";
import { CREATE_ROOM } from "../../queries/roomQueries";
import Room from "../../types/Room";
import RoomCard from "./RoomCard";
@@ -14,15 +17,21 @@ import ManageWelcomReadersCard from "./ManageWelcomeReadersCard";
import ManageMakerspaceTrainings from "./ManageMakerspaceTrainings";
import ManageMakerspaceHours from "./ManageMakerspaceHours";
import ManageMakerspaceInformation from "./ManageMakerspaceInformation";
+import { toast } from "react-toastify";
export default function ManageMakerspacePage() {
const { makerspaceID } = useParams<{ makerspaceID: string }>();
const isMobile = useIsMobile();
+ const navigate = useNavigate();
const getMakerspace = useQuery(GET_MAKERSPACE_BY_ID, { variables: { id: makerspaceID } });
+ const [archiveMakerspace] = useMutation(ARCHIVE_MAKERSPACE);
+ const [unarchiveMakerspace] = useMutation(UNARCHIVE_MAKERSPACE);
+ const [deleteMakerspace] = useMutation(DELETE_MAKERSPACE);
+
const [createRoom] = useMutation(CREATE_ROOM);
const [newRoomName, setNewRoomName] = useState("");
@@ -31,75 +40,116 @@ export default function ManageMakerspacePage() {
return (
{
- const space: FullMakerspace = data.makerspaceByID;
+ const space: FullMakerspace = data.makerspaceByID;
- const handleCreateRoom = async () => {
- await createRoom({
- variables: { name: newRoomName, makerspaceID: makerspaceID },
- //refetchQueries: [{ }],
- });
- window.location.reload();
- };
+ const handleCreateRoom = async () => {
+ await createRoom({
+ variables: { name: newRoomName, makerspaceID: makerspaceID },
+ //refetchQueries: [{ }],
+ });
+ window.location.reload();
+ };
- return (
-
- {`Manage ${space.name} | Make @ RIT`}
-
- {`Manage ${space.name} [ID: ${space.id}]`}
-
-
+ const handleArchiveMakerspace = async () => {
+ try {
+ await archiveMakerspace({ variables: { id: makerspaceID } });
+ toast.success("Room archived");
+ getMakerspace.refetch();
+ } catch (error: any) {
+ toast.error(error.message);
+ }
+ }
+
+ const handleUnarchiveMakerspace = async () => {
+ try {
+ await unarchiveMakerspace({ variables: { id: makerspaceID } });
+ toast.success("Room unarchived");
+ getMakerspace.refetch();
+ } catch (error: any) {
+ toast.error(error.message);
+ }
+ }
+
+ const handleDeleteMakerspace = async () => {
+ if (window.confirm("Are you sure you want to delete this makerspace? This cannot be undone.")) {
+ await deleteMakerspace({ variables: { id: makerspaceID } });
+
+ navigate(`/`);
+ }
+ };
+
+ return (
+
+ {`Manage ${space.name} | Make @ RIT`}
+
+ {`Manage ${space.name} [ID: ${space.id}]`}
+
+ {space.archived
+ ? } onClick={handleUnarchiveMakerspace}>Publish
+ : } onClick={handleArchiveMakerspace}>Archive
+ }
+ } onClick={handleDeleteMakerspace}>
+ Delete
+
+
+
+
} justifyContent={"space-between"} width={"100%"}>
- } width={"48%"}>
-
-
-
+ } width={"48%"}>
+
+
+
Rooms
} onClick={() => (setNewRoomModal(true))}>New Room
{ setNewRoomModal(false) }}>
-
- Creating a new room in {space.name} Makerspace
+
+ Creating a new room in {space.name} Makerspace
(setNewRoomName(e.target.value))} />
-
+
+
-
-
-
+
+
{
space.rooms.map((room: Room) => (
))
}
+
+
+ } width={"48%"}>
+
+
-
- } width={"48%"}>
-
-
-
- );
+ );
}} />
);
diff --git a/client/src/queries/makerspaceQueries.ts b/client/src/queries/makerspaceQueries.ts
index 1c3b05784..3fdb223d1 100644
--- a/client/src/queries/makerspaceQueries.ts
+++ b/client/src/queries/makerspaceQueries.ts
@@ -5,18 +5,19 @@ import { TrainingModule } from "../common/TrainingModuleUtils";
import MakerspaceHours from "../types/MakerspaceHours";
export const GET_MAKERSPACES = gql`
- query GetMakerspaces {
- makerspaces {
- id
- name
- imageUrl
+ query GetMakerspaces {
+ makerspaces {
+ id
+ name
+ imageUrl
+ }
}
- }
`;
export interface MakerspaceWithHours {
id: number;
name: string;
+ archived: boolean;
subtitle: string | null;
location: string | null;
description: string;
@@ -28,12 +29,13 @@ export interface MakerspaceWithHours {
export interface FullMakerspace {
id: number;
name: string;
+ archived: boolean;
subtitle: string | null;
location: string | null;
description: string;
docsLink: string;
hours: MakerspaceHours[];
- rooms: Room[]
+ rooms: Room[];
imageUrl: string;
trainingModules: TrainingModule[];
}
@@ -49,24 +51,25 @@ export interface MakerspaceWithItems {
}
export const GET_MAKERSPACES_WITH_HOURS = gql`
- query GetMakerspacesWithHours {
- makerspaces {
- id
- name
- subtitle
- location
- description
- docsLink
- hours {
+ query GetMakerspacesWithHours {
+ makerspaces {
+ id
+ name
+ archived
+ subtitle
+ location
+ description
+ docsLink
+ hours {
day
makerspaceID
open
close
closed
}
- imageUrl
+ imageUrl
+ }
}
- }
`;
export const GET_FULL_MAKERSPACES = gql`
@@ -74,6 +77,7 @@ export const GET_FULL_MAKERSPACES = gql`
makerspaces {
id
name
+ archived
subtitle
location
description
@@ -110,42 +114,42 @@ export const GET_FULL_MAKERSPACES = gql`
`;
export const GET_MAKERSPACES_WITH_ITEMS = gql`
- query GetMakerspacesWithItems($storefrontVisible: Boolean) {
- makerspaces(storefrontVisible: $storefrontVisible) {
- id
- name
- name
- subtitle
- location
- description
- docsLink
- items {
+ query GetMakerspacesWithItems($storefrontVisible: Boolean) {
+ makerspaces(storefrontVisible: $storefrontVisible) {
id
- image
name
- labels
- unit
- pluralUnit
- count
- pricePerUnit
- threshold
- staffOnly
- storefrontVisible
- notes
+ name
+ subtitle
+ location
description
- makerspaceID
- makerspace {
+ docsLink
+ items {
id
+ image
name
- }
- tags {
- id
- label
- color
+ labels
+ unit
+ pluralUnit
+ count
+ pricePerUnit
+ threshold
+ staffOnly
+ storefrontVisible
+ notes
+ description
+ makerspaceID
+ makerspace {
+ id
+ name
+ }
+ tags {
+ id
+ label
+ color
+ }
}
}
}
- }
`;
export const GET_MAKERSPACE_BY_ID = gql`
@@ -153,6 +157,7 @@ export const GET_MAKERSPACE_BY_ID = gql`
makerspaceByID(id: $id) {
id
name
+ archived
subtitle
location
description
@@ -212,7 +217,14 @@ export const UPDATE_MAKERSPACE = gql`
) {
updateMakerspace(
id: $id
- newMakerspace: { name: $name, subtitle: $subtitle, location: $location, description: $description, docsLink: $docsLink, imageUrl: $imageUrl }
+ newMakerspace: {
+ name: $name
+ subtitle: $subtitle
+ location: $location
+ description: $description
+ docsLink: $docsLink
+ imageUrl: $imageUrl
+ }
) {
id
}
@@ -253,4 +265,20 @@ export const DELETE_SPECIAL_HOURS = gql`
mutation DeleteSpecialHours($day: DateTime!, $makerspaceID: ID!) {
deleteSpecialHours(day: $day, makerspaceID: $makerspaceID)
}
-`;
\ No newline at end of file
+`;
+
+export const ARCHIVE_MAKERSPACE = gql`
+ mutation ArchiveMakerspace($id: ID!) {
+ archiveMakerspace(id: $id) {
+ id
+ }
+ }
+`;
+
+export const UNARCHIVE_MAKERSPACE = gql`
+ mutation UnarchiveMakerspace($id: ID!) {
+ unarchiveMakerspace(id: $id) {
+ id
+ }
+ }
+`;
diff --git a/server/src/repositories/Makerspaces/MakerspaceRespository.ts b/server/src/repositories/Makerspaces/MakerspaceRespository.ts
index f5478687a..fc734134e 100644
--- a/server/src/repositories/Makerspaces/MakerspaceRespository.ts
+++ b/server/src/repositories/Makerspaces/MakerspaceRespository.ts
@@ -13,8 +13,8 @@ import * as ModuleRepo from '../Training/ModuleRepository.js';
* Fetch all Makerspaces
* @returns all Makerspaces
*/
-export async function getMakerspaces(archived = false): Promise {
- return await knex('Makerspaces').select().where({ archived: archived });
+export async function getMakerspaces(): Promise {
+ return await knex('Makerspaces').select();
}
/**
@@ -65,7 +65,7 @@ export async function updateMakerspace(
* @returns 1
*/
export async function deleteMakerspace(id: number): Promise {
- await knex('OpenHours').update({ makerspaceID: null }).where({ makerspaceID: id })
+ await knex('DefaultHours').delete().where({ makerspaceID: id });
await knex('Rooms').update({ makerspaceID: null }).where({ makerspaceID: id })
return await knex('Makerspaces').delete().where({ id });
@@ -126,4 +126,8 @@ export async function archiveMakerspace(id: number, archive = true): Promise {
+ return await archiveMakerspace(id, false);
}
\ No newline at end of file
diff --git a/server/src/resolvers/makerspaceResolver.ts b/server/src/resolvers/makerspaceResolver.ts
index 98e3d305c..4622f5341 100644
--- a/server/src/resolvers/makerspaceResolver.ts
+++ b/server/src/resolvers/makerspaceResolver.ts
@@ -1,5 +1,5 @@
import { ApolloContext } from "../context.js";
-import { addTrainingToMakerspace, archiveMakerspace, createMakerspace, deleteMakerspace, getMakerspaceByID, getMakerspaces, getTrainingsByMakerspace, removeTrainingFromMakerspace, updateMakerspace } from "../repositories/Makerspaces/MakerspaceRespository.js";
+import { addTrainingToMakerspace, archiveMakerspace, createMakerspace, deleteMakerspace, getMakerspaceByID, getMakerspaces, getTrainingsByMakerspace, removeTrainingFromMakerspace, unarchiveMakerspace, updateMakerspace } from "../repositories/Makerspaces/MakerspaceRespository.js";
import { MakerspaceRow } from "../db/tables.js";
import { getRoomsByMakerspace } from "../repositories/Rooms/RoomRepository.js";
import { MakerspaceInput } from "../schemas/makerspacesSchema.js";
@@ -51,8 +51,21 @@ const MakerspacesResolver = {
makerspaces: async (
_parent: any,
_args: any,
+ context: any
) => {
- return await getMakerspaces();
+ const makerspaces = await getMakerspaces();
+
+ if (context.user) {
+ // All makerspaces if admin
+ if(context.user.admin) {
+ return makerspaces;
+ }
+ // All published makerspaces and any archived ones the user manages
+ const managedIDs = context.user.manager || [];
+ return makerspaces.filter((makerspace) => !makerspace.archived || managedIDs.includes(makerspace.id));
+ }
+ // Only published makerspaces for other users
+ return makerspaces.filter((makerspace) => !makerspace.archived);
},
/**
@@ -63,8 +76,9 @@ const MakerspacesResolver = {
makerspaceByID: async (
_parent: any,
args: { id: number },
+ context: any,
) => {
- return await getMakerspaceByID(args.id);
+ return getMakerspaceByID(args.id);;
},
},
@@ -81,7 +95,7 @@ const MakerspacesResolver = {
{ isAdmin }: ApolloContext) =>
isAdmin(async () => {
const res = await createMakerspace(args.name);
- return res
+ return res;
}),
updateMakerspace: async (
@@ -90,7 +104,7 @@ const MakerspacesResolver = {
{ isManagerFor }: ApolloContext) =>
isManagerFor(args.id, async () => {
const res = await updateMakerspace(args.id, args.newMakerspace);
- return res
+ return res;
}),
/**
@@ -116,8 +130,8 @@ const MakerspacesResolver = {
},
{ isManagerFor }: ApolloContext
) => isManagerFor(args.makerspaceID, async () => {
- return await addTrainingToMakerspace(args.makerspaceID, args.moduleID);
- }),
+ return await addTrainingToMakerspace(args.makerspaceID, args.moduleID);
+ }),
removeTrainingFromMakerspace: async (
_parent: any,
@@ -127,8 +141,8 @@ const MakerspacesResolver = {
},
{ isManagerFor }: ApolloContext
) => isManagerFor(args.makerspaceID, async () => {
- return await removeTrainingFromMakerspace(args.makerspaceID, args.moduleID);
- }),
+ return await removeTrainingFromMakerspace(args.makerspaceID, args.moduleID);
+ }),
archiveMakerspace: async (
_parent: any,
@@ -140,7 +154,14 @@ const MakerspacesResolver = {
createLog(`{user} archived makerspace ${args.id}`, "admin",
{ id: user.id, label: getUsersFullName(user) }
)
- return await archiveMakerspace(args.id);
+ return await archiveMakerspace(args.id);
+ }),
+
+ unarchiveMakerspace: async (_parent: any, args: { id: number }, { isAdmin }: ApolloContext) => isAdmin(async (user) => {
+ createLog(`{user} unarchived makerspace ${args.id}`, "admin",
+ { id: user.id, label: getUsersFullName(user) }
+ )
+ return await unarchiveMakerspace(args.id);
})
}
diff --git a/server/src/schemas/makerspacesSchema.ts b/server/src/schemas/makerspacesSchema.ts
index aadd484eb..ff5550310 100644
--- a/server/src/schemas/makerspacesSchema.ts
+++ b/server/src/schemas/makerspacesSchema.ts
@@ -18,6 +18,7 @@ export const MakerspacesTypeDefs = gql`
type Makerspace {
id: ID!
name: String!
+ archived: Boolean!
subtitle: String
location: String
description: String
@@ -47,6 +48,7 @@ export const MakerspacesTypeDefs = gql`
deleteMakerspace(id: ID!): Makerspace
addMakerspace(name: String!): Makerspace
archiveMakerspace(id: ID!): Makerspace
+ unarchiveMakerspace(id: ID!): Makerspace
updateMakerspace(id: ID!, newMakerspace: MakerspaceInput): Makerspace
addTrainingToMakerspace(makerspaceID: ID!, moduleID: ID!): [TrainingModule]
removeTrainingFromMakerspace(makerspaceID: ID!, moduleID: ID!): [TrainingModule]