diff --git a/backend/modules/event/graphql.js b/backend/modules/event/graphql.js index 67eb99c50..16a9e37f8 100644 --- a/backend/modules/event/graphql.js +++ b/backend/modules/event/graphql.js @@ -248,6 +248,9 @@ const EventInput = new GraphQLInputObjectType({ challenge_instructions: { type: GraphQLString, }, + map: { + type: CloudinaryImageInput, + }, faq: { type: GraphQLString, }, @@ -496,9 +499,9 @@ const EventType = new GraphQLObjectType({ meetingRooms: { type: GraphQLList(MeetingRoom), }, - // map: { - // type: MongoFile, - // }, + map: { + type: CloudinaryImage, + }, // Implement userprofile in graphql // TODO: Figure this stuff out // winners: { diff --git a/backend/modules/event/model.js b/backend/modules/event/model.js index 2dd6a5108..14822c3cd 100644 --- a/backend/modules/event/model.js +++ b/backend/modules/event/model.js @@ -10,7 +10,6 @@ const ChallengeSchema = require('@hackjunction/shared/schemas/Challenge') const HackerpackSchema = require('@hackjunction/shared/schemas/Hackerpack') const CloudinaryImageSchema = require('@hackjunction/shared/schemas/CloudinaryImage') const Certificate = require('@hackjunction/shared/schemas/Certificate') -const mongoFile = require('@hackjunction/shared/schemas/MongoFile') const RegistrationSectionSchema = require('@hackjunction/shared/schemas/RegistrationSection') const TrackSchema = require('@hackjunction/shared/schemas/Track') const EventRecruitersSchema = require('@hackjunction/shared/schemas/Recruiter') @@ -93,7 +92,7 @@ const EventSchema = new mongoose.Schema({ coverImage: CloudinaryImageSchema.mongoose, logo: CloudinaryImageSchema.mongoose, certificate: Certificate.mongoose, - //map: mongoFile.mongoose, + map: CloudinaryImageSchema.mongoose, /** Event configuration */ eventType: { type: String, diff --git a/backend/modules/upload/helper.js b/backend/modules/upload/helper.js index 11183c9b1..9f972cf22 100644 --- a/backend/modules/upload/helper.js +++ b/backend/modules/upload/helper.js @@ -72,6 +72,9 @@ const UploadHelper = { generateCertificateTag: slug => { return `${cloudinaryRootPath}-event-${slug}-certificate` }, + generateMapTag: slug => { + return `${cloudinaryRootPath}-event-${slug}-map` + }, generateHackerpackTag: id => { return `${cloudinaryRootPath}-hackerpac-${id}` }, @@ -230,6 +233,20 @@ const UploadHelper = { }).single('image') }, + uploadEventMap: (slug) => { + const storage = createStorageWithPath( + `events/maps/`, + {}, + { + tag: UploadHelper.generateMapTag(slug), + }, + ) + return multer({ + storage, + limits: { fileSize: 5 * 1024 * 1024 }, + }).single('image') + }, + uploadHackerpackIcon: slug => { const storage = createStorageWithPath( `hackerpack`, diff --git a/backend/modules/upload/routes.js b/backend/modules/upload/routes.js index 91c8f6bce..72d13706d 100644 --- a/backend/modules/upload/routes.js +++ b/backend/modules/upload/routes.js @@ -1,7 +1,7 @@ const express = require('express') const mongoose = require('mongoose') const { GridFsStorage } = require('multer-gridfs-storage') -const ObjectId = require('mongodb').ObjectId +const { ObjectId } = require('mongodb') const router = express.Router() const { Auth } = require('@hackjunction/shared') @@ -11,8 +11,8 @@ const { hasPermission } = require('../../common/middleware/permissions') const { hasToken } = require('../../common/middleware/token') const { ForbiddenError, NotFoundError } = require('../../common/errors/errors') -const storage = require('../../misc/gridfs').storage -const upload = require('../../misc/gridfs').upload +const { storage } = require('../../misc/gridfs') +const { upload } = require('../../misc/gridfs') // console.log(mongoose.connections[0].db) // let gfs = new mongoose.mongo.GridFSBucket(mongoose.connections[0].db, { @@ -183,6 +183,34 @@ router.post( }, ) +router.post( + '/events/:slug/map', + hasToken, + hasPermission(Auth.Permissions.MANAGE_EVENT), + isEventOrganiser, + (req, res, next) => { + helper.uploadEventMap(req.event.slug)( + req, + res, + + function (err) { + if (err) { + if (err.code === 'LIMIT_FILE_SIZE') { + next(new ForbiddenError(err.message)) + } else { + next(err) + } + } else { + res.status(200).json({ + url: req.file.secure_url || req.file.url, + publicId: req.file.public_id, + }) + } + }, + ) + }, +) + /** * Upload background image for a team */ @@ -297,8 +325,8 @@ router.post('/organization/:slug/icon', (req, res, next) => { }) }) -//Upload, download and delete general files over 16mb -//TODO: add hasToken for all calls. Left out for testing with postman +// Upload, download and delete general files over 16mb +// TODO: add hasToken for all calls. Left out for testing with postman router.post('/files', hasToken, upload.single('file'), (req, res, next) => { console.log('Routes: Upload > POST > /files > file data', req.file) // console.log('Res', res) @@ -315,7 +343,7 @@ router.post('/files', hasToken, upload.single('file'), (req, res, next) => { router.get('/files/:id', hasToken, (req, res, next) => { console.log('Routes: Upload > GET > /files/:id > data', req) - var gfs = new mongoose.mongo.GridFSBucket(mongoose.connections[0].db, { + const gfs = new mongoose.mongo.GridFSBucket(mongoose.connections[0].db, { bucketName: 'uploads', }) @@ -331,17 +359,17 @@ router.get('/files/:id', hasToken, (req, res, next) => { gfs.openDownloadStream(ObjectId(req.params.id)).pipe(res) }) }) -//TODO: make periodic delete function calling this +// TODO: make periodic delete function calling this router.delete('/files/:id', hasToken, (req, res, next) => { console.log('Routes: Upload > DELETE > /files/:id > data', req) - var gfs = new mongoose.mongo.GridFSBucket(mongoose.connections[0].db, { + const gfs = new mongoose.mongo.GridFSBucket(mongoose.connections[0].db, { bucketName: 'uploads', }) console.log(req.params.id) gfs.delete(ObjectId(req.params.id), (err, data) => { if (err) { - return res.status(404).json({ err: err }) + return res.status(404).json({ err }) } res.status(200).json({ diff --git a/frontend/src/pages/_dashboard/renderDashboard/generalPages/map/index.js b/frontend/src/pages/_dashboard/renderDashboard/generalPages/map/index.js index f4bbfeef0..79ee7c3cc 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/generalPages/map/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/generalPages/map/index.js @@ -1,65 +1,33 @@ -import React, { useEffect, useRef } from 'react' -import { useRouteMatch, useLocation } from 'react-router' +import React, { useEffect, useState } from 'react' +import { useRouteMatch } from 'react-router' -import FormControl from '@material-ui/core/FormControl' -import FormGroup from '@material-ui/core/FormGroup' -import FormControlLabel from '@material-ui/core/FormControlLabel' -import Checkbox from '@material-ui/core/Checkbox' -import { useDispatch, useSelector } from 'react-redux' +import { useSelector } from 'react-redux' import PageWrapper from 'components/layouts/PageWrapper' -import MaterialTabsLayout from 'components/layouts/MaterialTabsLayout' import PageHeader from 'components/generic/PageHeader' -import Image from 'components/generic/Image' import GradientBox from 'components/generic/GradientBox' -import LayoutMap1 from 'assets/images/venueMap2023/LayoutMap-venue-01.jpg' -import LayoutMap2 from 'assets/images/venueMap2023/LayoutMap-venue-02.jpg' -import LayoutMap3 from 'assets/images/venueMap2023/LayoutMap-venue-03.jpg' -import { Grid, Typography } from '@material-ui/core' +import * as DashboardSelectors from '../../../../../redux/dashboard/selectors' export default () => { const match = useRouteMatch() - const location = useLocation() + const { slug } = match.params + const event = useSelector(DashboardSelectors.event) + const [venueMap, setVenueMap] = useState([]) - const floorNeg1 = () => { + const VenueMap = () => { return ( - {"Venue + {'Venue ) } - const floor1 = () => { - return ( - - {"Venue - - ) - } - - - const floor2 = () => { - return ( - - {"Venue - - ) - } - - + useEffect(() => { + if (event) { + setVenueMap(event.map) + } + }, [event, slug]) return ( <> @@ -83,37 +51,15 @@ export default () => { > */} - +
+ + +
- floorNeg1() - }, - { - path: '/-1', - key: '-1', - label: 'Floor -1', - component: () => floor1() - }, - { - path: '/2', - key: '2', - label: 'Floor 2', - component: () => floor2() - }, - ]} - location={location} - baseRoute={match.url} - />
) diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/other/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/other/index.js index 1c180f03f..c53389a82 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/other/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/other/index.js @@ -1,6 +1,6 @@ import React from 'react' import { useSelector } from 'react-redux' -import { Grid } from '@material-ui/core' +import { Box, Grid } from '@material-ui/core' import { FastField, Field } from 'formik' import FormControl from 'components/inputs/FormControl' import EventTagsForm from './EventTagsForm' @@ -9,12 +9,13 @@ import MetaTagsForm from './MetaTagsForm' import CertificateForm from './CertificateForm' import PageScriptsForm from './PageScriptsForm' -import FileInput from '../submission/components/inputs/FileInput' -import PdfUpload from 'components/inputs/PdfUpload' import Switch from 'components/generic/Switch' import { hasSuperAdmin } from 'redux/auth/selectors' +import ImageUpload from 'components/inputs/ImageUpload' +import * as OrganiserSelectors from 'redux/organiser/selectors' export default () => { + const event = useSelector(OrganiserSelectors.event) const isSuperAdmin = useSelector(hasSuperAdmin) console.log('isSuperAdmin', isSuperAdmin) return ( @@ -40,7 +41,6 @@ export default () => { { - console.log(field) return ( { error={form.errors[field.name]} touched={form.touched[field.name]} > - - form.setFieldValue(field.name, value) - } - config={{ - settings: { - allowedTypes: ['jpg'], - }, - }} - /> - - {/* { - form.setFieldValue(field.name, value) - form.setFieldTouched(field.name) - }} - uploadUrl={`/api/upload/events/${event.slug}/map`} - resizeMode="cover" - /> */} + + { + form.setFieldValue( + field.name, + value, + ) + form.setFieldTouched(field.name) + }} + uploadUrl={`/api/upload/events/${event.slug}/map`} + /> + ) }} diff --git a/shared/schemas/validation/eventSchema.js b/shared/schemas/validation/eventSchema.js index ca7fba1dd..6aa1800e6 100644 --- a/shared/schemas/validation/eventSchema.js +++ b/shared/schemas/validation/eventSchema.js @@ -180,7 +180,7 @@ export default yup.object().shape({ description: yup.string(), }), ), - map: mongoFile, + map: cloudinaryImage, published: yup.boolean().required(), galleryOpen: yup.boolean(), owner: yup.string(),