diff --git a/backend/src/index.js b/backend/src/index.js index a34f1bb..2f642de 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -37,7 +37,7 @@ const schedulesRoutes = require('./routes/schedules'); const guestsRoutes = require('./routes/guests'); const budgetsRoutes = require('./routes/budgets'); - +const publicRoutes = require('./routes/public'); const getBaseUrl = (url) => { if (!url) return ''; @@ -90,6 +90,7 @@ require('./auth/auth'); app.use(bodyParser.json()); +app.use('/api/public', publicRoutes); app.use('/api/auth', authRoutes); app.use('/api/file', fileRoutes); app.use('/api/pexels', pexelsRoutes); diff --git a/backend/src/routes/events.js b/backend/src/routes/events.js index 5cdf433..f644156 100644 --- a/backend/src/routes/events.js +++ b/backend/src/routes/events.js @@ -1,4 +1,3 @@ - const express = require('express'); const EventsService = require('../services/events'); @@ -15,11 +14,430 @@ const { checkCrudPermissions, } = require('../middlewares/check-permissions'); -router.get('/public', wrapAsync(async (req, res) => { - const payload = await EventsDBApi.findAll(req.query); +router.use(checkCrudPermissions('events')); + + +/** + * @swagger + * components: + * schemas: + * Events: + * type: object + * properties: + + * name: + * type: string + * default: name + * description: + * type: string + * default: description + + + * budget_total: + * type: integer + * format: int64 + + * + */ + +/** + * @swagger + * tags: + * name: Events + * description: The Events managing API + */ + +/** +* @swagger +* /api/events: +* post: +* security: +* - bearerAuth: [] +* tags: [Events] +* summary: Add new item +* description: Add new item +* requestBody: +* required: true +* content: +* application/json: +* schema: +* properties: +* data: +* description: Data of the updated item +* type: object +* $ref: "#/components/schemas/Events" +* responses: +* 200: +* description: The item was successfully added +* content: +* application/json: +* schema: +* $ref: "#/components/schemas/Events" +* 401: +* $ref: "#/components/responses/UnauthorizedError" +* 405: +* description: Invalid input data +* 500: +* description: Some server error +*/ +router.post('/', wrapAsync(async (req, res) => { + const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`; + const link = new URL(referer); + await EventsService.create(req.body.data, req.currentUser, true, link.host); + const payload = true; + res.status(200).send(payload); +})); + +/** + * @swagger + * /api/budgets/bulk-import: + * post: + * security: + * - bearerAuth: [] + * tags: [Events] + * summary: Bulk import items + * description: Bulk import items + * requestBody: + * required: true + * content: + * application/json: + * schema: + * properties: + * data: + * description: Data of the updated items + * type: array + * items: + * $ref: "#/components/schemas/Events" + * responses: + * 200: + * description: The items were successfully imported + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/Events" + * 401: + * $ref: "#/components/responses/UnauthorizedError" + * 405: + * description: Invalid input data + * 500: + * description: Some server error + * + */ +router.post('/bulk-import', wrapAsync(async (req, res) => { + const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`; + const link = new URL(referer); + await EventsService.bulkImport(req, res, true, link.host); + const payload = true; + res.status(200).send(payload); +})); + +/** + * @swagger + * /api/events/{id}: + * put: + * security: + * - bearerAuth: [] + * tags: [Events] + * summary: Update the data of the selected item + * description: Update the data of the selected item + * parameters: + * - in: path + * name: id + * description: Item ID to update + * required: true + * schema: + * type: string + * requestBody: + * description: Set new item data + * required: true + * content: + * application/json: + * schema: + * properties: + * id: + * description: ID of the updated item + * type: string + * data: + * description: Data of the updated item + * type: object + * $ref: "#/components/schemas/Events" + * required: + * - id + * responses: + * 200: + * description: The item data was successfully updated + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/Events" + * 400: + * description: Invalid ID supplied + * 401: + * $ref: "#/components/responses/UnauthorizedError" + * 404: + * description: Item not found + * 500: + * description: Some server error + */ +router.put('/:id', wrapAsync(async (req, res) => { + await EventsService.update(req.body.data, req.body.id, req.currentUser); + const payload = true; res.status(200).send(payload); })); -router.use(checkCrudPermissions('events')); +/** + * @swagger + * /api/events/{id}: + * delete: + * security: + * - bearerAuth: [] + * tags: [Events] + * summary: Delete the selected item + * description: Delete the selected item + * parameters: + * - in: path + * name: id + * description: Item ID to delete + * required: true + * schema: + * type: string + * responses: + * 200: + * description: The item was successfully deleted + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/Events" + * 400: + * description: Invalid ID supplied + * 401: + * $ref: "#/components/responses/UnauthorizedError" + * 404: + * description: Item not found + * 500: + * description: Some server error + */ +router.delete('/:id', wrapAsync(async (req, res) => { + await EventsService.remove(req.params.id, req.currentUser); + const payload = true; + res.status(200).send(payload); +})); -module.exports = router; +/** + * @swagger + * /api/events/deleteByIds: + * post: + * security: + * - bearerAuth: [] + * tags: [Events] + * summary: Delete the selected item list + * description: Delete the selected item list + * requestBody: + * required: true + * content: + * application/json: + * schema: + * properties: + * ids: + * description: IDs of the updated items + * type: array + * responses: + * 200: + * description: The items was successfully deleted + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/Events" + * 401: + * $ref: "#/components/responses/UnauthorizedError" + * 404: + * description: Items not found + * 500: + * description: Some server error + */ +router.post('/deleteByIds', wrapAsync(async (req, res) => { + await EventsService.deleteByIds(req.body.data, req.currentUser); + const payload = true; + res.status(200).send(payload); + })); + +/** + * @swagger + * /api/events: + * get: + * security: + * - bearerAuth: [] + * tags: [Events] + * summary: Get all events + * description: Get all events + * responses: + * 200: + * description: Events list successfully received + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: "#/components/schemas/Events" + * 401: + * $ref: "#/components/responses/UnauthorizedError" + * 404: + * description: Data not found + * 500: + * description: Some server error +*/ +router.get('/', wrapAsync(async (req, res) => { + const filetype = req.query.filetype + + const currentUser = req.currentUser; + + const { sort, ...otherFilters } = req.query; + let order = {}; + if (sort) { + const [field, direction] = sort.split(','); + order = { field, sort: direction }; + } + + const payload = await EventsDBApi.findAll( + { ...otherFilters, ...order }, { currentUser } + ); + if (filetype && filetype === 'csv') { + const fields = ['id','name','description', + + 'budget_total', + 'start_datetime','end_datetime', + ]; + const opts = { fields }; + try { + const csv = parse(payload.rows, opts); + res.status(200).attachment(csv); + res.send(csv) + + } catch (err) { + console.error(err); + } + } else { + res.status(200).send(payload); + } + +})); + +/** + * @swagger + * /api/events/count: + * get: + * security: + * - bearerAuth: [] + * tags: [Events] + * summary: Count all events + * description: Count all events + * responses: + * 200: + * description: Events count successfully received + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: "#/components/schemas/Events" + * 401: + * $ref: "#/components/responses/UnauthorizedError" + * 404: + * description: Data not found + * 500: + * description: Some server error + */ +router.get('/count', wrapAsync(async (req, res) => { + + const currentUser = req.currentUser; + const payload = await EventsDBApi.findAll( + req.query, + null, + { countOnly: true, currentUser } + ); + + res.status(200).send(payload); +})); + +/** + * @swagger + * /api/events/autocomplete: + * get: + * security: + * - bearerAuth: [] + * tags: [Events] + * summary: Find all events that match search criteria + * description: Find all events that match search criteria + * responses: + * 200: + * description: Events list successfully received + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: "#/components/schemas/Events" + * 401: + * $ref: "#/components/responses/UnauthorizedError" + * 404: + * description: Data not found + * 500: + * description: Some server error + */ +router.get('/autocomplete', async (req, res) => { + + const payload = await EventsDBApi.findAllAutocomplete( + req.query.query, + req.query.limit, + req.query.offset, + + ); + + res.status(200).send(payload); +}); + +/** + * @swagger + * /api/events/{id}: + * get: + * security: + * - bearerAuth: [] + * tags: [Events] + * summary: Get selected item + * description: Get selected item + * parameters: + * - in: path + * name: id + * description: ID of item to get + * required: true + * schema: + * type: string + * responses: + * 200: + * description: Selected item successfully received + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/Events" + * 400: + * description: Invalid ID supplied + * 401: + * $ref: "#/components/responses/UnauthorizedError" + * 404: + * description: Item not found + * 500: + * description: Some server error + */ +router.get('/:id', wrapAsync(async (req, res) => { + const payload = await EventsDBApi.findBy( + { id: req.params.id }, + ); + + + + res.status(200).send(payload); +})); + +router.use('/', require('../helpers').commonErrorHandler); + +module.exports = router; \ No newline at end of file diff --git a/backend/src/routes/public.js b/backend/src/routes/public.js new file mode 100644 index 0000000..8f0d0b5 --- /dev/null +++ b/backend/src/routes/public.js @@ -0,0 +1,12 @@ +const express = require('express'); +const wrapAsync = require('../helpers').wrapAsync; +const EventsDBApi = require('../db/api/events'); + +const router = express.Router(); + +router.get('/events', wrapAsync(async (req, res) => { + const payload = await EventsDBApi.findAll(req.query); + res.status(200).send(payload); +})); + +module.exports = router; diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx index 2cdbbb0..08a5878 100644 --- a/frontend/src/pages/index.tsx +++ b/frontend/src/pages/index.tsx @@ -28,7 +28,7 @@ export default function LandingPage() { useEffect(() => { const fetchEvents = async () => { try { - const response = await axios.get(`/api/events/public`); + const response = await axios.get(`/public/events`); setEvents(response.data.rows); setLoading(false); } catch (err) {