From 37145ee076440277b174ac24b860d9bed8309894 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Sat, 17 Apr 2021 11:47:01 +0200 Subject: [PATCH] lowdb persistence - bug: while creating a new entry, the database briefly returns an empty array which causes the interface to flash --- .gitignore | 1 + server/controllers/eventsController.js | 191 +++++++++++++++---------- server/data/dataModel.json | 3 + server/package.json | 1 + server/routes/eventsRouter.js | 6 +- server/yarn.lock | 38 +++++ 6 files changed, 163 insertions(+), 77 deletions(-) create mode 100644 server/data/dataModel.json diff --git a/.gitignore b/.gitignore index 6e37e924c..bec48db07 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ TODO.md # working stuff _SS/ .vscode/launch.json +server/db.json diff --git a/server/controllers/eventsController.js b/server/controllers/eventsController.js index c28d2ef2a..750ecbdce 100644 --- a/server/controllers/eventsController.js +++ b/server/controllers/eventsController.js @@ -1,31 +1,61 @@ +// CONST +const filename = 'db.json'; +const tableName = 'events'; +const countfield = 'eventCount'; + +// data +const low = require('lowdb'); +const FileSync = require('lowdb/adapters/FileSync'); +const adapter = new FileSync('db.json'); +const db = low(adapter); + +db.defaults({ events: [] }).write(); + // utils const { nanoid } = require('nanoid'); - -// import json with initial data -let events = require('../data/eventsData.json'); const eventDefs = require('../data/eventsDefinition.js'); -// aux -const replaceAt = (array, index, value) => { - const ret = array.slice(0); - ret[index] = value; - return ret; -}; +// incrementFrom +function incrementFrom(start, incr = 1) { + try { + let entries = db.get('events').sortBy('order').value(); -const getEvents = () => { - return global.timer.events; -}; + entries.map((e) => { + if (e.order < start) return; + db.get('events') + .find({ id: e.id }) + .assign({ order: e.order + incr }) + .write(); + }); + } catch (error) { + console.log('error on increment function', error); + } +} -// Create controller for GET request to '/events/all' +function _getEventsCount() { + return db.get('events').size().value(); +} + +function _pushNew(entry) { + return db.get('events').push(entry).write(); +} + +function _removeById(eventId) { + return db.get('events').remove({ id: eventId }).write(); +} + +// Create controller for GET request to '/events' // Returns - exports.eventsGetAll = async (req, res) => { - res.json(events); + const results = db.get('events').sortBy('order').value(); + res.json(results); }; -// Create controller for GET request to '/events/:Id' +// Create controller for GET request to '/events/:eventId' // Returns - exports.eventsGetById = async (req, res) => { - // TODO + const e = db.get('events').find({ id: req.params.eventId }).value(); + res.json(e); }; // Create controller for POST request to '/events/' @@ -33,7 +63,7 @@ exports.eventsGetById = async (req, res) => { exports.eventsPost = async (req, res) => { // TODO: Validate event if (!req.body) { - res.sendStatus(400); + res.status(400).send(`No object found in request`); return; } @@ -53,89 +83,102 @@ exports.eventsPost = async (req, res) => { break; default: - res.sendStatus(400); + res + .status(400) + .send(`Object type missing or unrecognised: ${req.body.type}`); break; } - // Torbjorn: hmmmmmmm, can we look here? - if (newEvent.order <= 0) { - newEvent.order = 0; - // insert at top - events.forEach((e) => { - e.order = e.order + 1; - }); - events = [newEvent, ...events]; - } else if (newEvent.order >= events.length) { - newEvent.order = events.length; - events = [...events, newEvent]; - } else { - let before = events.slice(0, newEvent.order); - let after = events.slice(newEvent.order); - // move all items one element down, starting from new position - after.forEach((e) => { - e.order = e.order + 1; - }); - events = [...before, newEvent, ...after]; + try { + // increment count if necessary + const c = _getEventsCount(); + + if (c > 0 && newEvent.order < c) incrementFrom(newEvent.order); + + // add new event + _pushNew(newEvent); + + res.sendStatus(201); + } catch (error) { + res.status(400).send(error); } - console.log('added', events); - res.sendStatus(201); }; -// Create controller for PUT request to '/events/:id' +// Create controller for PUT request to '/events/' // Returns - exports.eventsPut = async (req, res) => { - const itemIndex = events.findIndex((e) => e.id == req.body.id); - - // Item with index not found - if (itemIndex === -1) { - res.sendStatus(400); + // no valid params + if (!req.body) { + res.status(400).send(`No object found`); return; } - // Torbjorn: bad syntax? - const newEvents = replaceAt(events, itemIndex, req.body); - events = [...newEvents]; - res.sendStatus(200); + let eventId = req.body.id; + if (!eventId) { + res.status(400).send(`No id found`); + return; + } + + try { + db.get('events') + .find({ id: req.body.id }) + .assign({ ...req.body }) + .write() + .then(res.sendStatus(200)); + } catch (error) { + res.status(400).send(error); + } }; -// Create controller for PATCH request to '/events/:id' +// Create controller for PATCH request to '/events/' // Returns - exports.eventsPatch = async (req, res) => { - const itemIndex = events.findIndex((e) => e.id == req.body.id); - - // Item with index not found - if (itemIndex === -1) { - res.sendStatus(400); + // no valid params + if (!req.body) { + res.status(400).send(`No object found`); return; } - // Get current object - const eventToUpdate = events[itemIndex]; + let eventId = req.body.id; + if (!eventId) { + res.status(400).send(`No id found`); + return; + } - // Update and replace - const updatedEvent = { ...eventToUpdate, ...req.body }; - const newEvents = replaceAt(events, itemIndex, updatedEvent); + try { + db.get('events') + .find({ id: req.body.id }) + .assign({ ...req.body }) + .write(); - events = [...newEvents]; - res.send(updatedEvent); + res.sendStatus(200); + } catch (error) { + res.status(400).send(error); + } }; -// Create controller for DELETE request to '/events/' +// Create controller for DELETE request to '/events/:eventId' // Returns - +// TODO: should reorder al events down exports.eventsDelete = async (req, res) => { - if (!req.params.id) { - res.sendStatus(400); + // no valid params + if (!req.params.eventId) { + res.status(400).send(`No id found in request`); + return; } - const itemIndex = events.findIndex((e) => e.id == req.params.id); + try { + // increment count if necessary + const c = _getEventsCount(); + const e = db.get('events').find({ id: req.params.eventId }).value(); - if (itemIndex === -1) { - res.sendStatus(400); - return; - } else if (itemIndex === 0) events.shift(); - else events.splice(itemIndex, 1); + if (c > 0 && e.order < c) incrementFrom(e.order, -1); - // Update events - events = [...events]; - res.sendStatus(200); + // add new event + _removeById(req.params.eventId); + + res.sendStatus(201); + } catch (error) { + res.status(400).send(error); + } }; diff --git a/server/data/dataModel.json b/server/data/dataModel.json new file mode 100644 index 000000000..6cc4cc517 --- /dev/null +++ b/server/data/dataModel.json @@ -0,0 +1,3 @@ +{ + "events": [] +} \ No newline at end of file diff --git a/server/package.json b/server/package.json index e8b645df4..94b6b299c 100644 --- a/server/package.json +++ b/server/package.json @@ -6,6 +6,7 @@ "body-parser": "~1.19.0", "express": "~4.17.1", "express-session": "~1.17.1", + "lowdb": "^1.0.0", "nanoid": "^3.1.22", "passport": "~0.4.1", "passport-local": "~1.0.0", diff --git a/server/routes/eventsRouter.js b/server/routes/eventsRouter.js index 1535e877b..cc16adb1e 100644 --- a/server/routes/eventsRouter.js +++ b/server/routes/eventsRouter.js @@ -2,13 +2,13 @@ const express = require('express'); const router = express.Router(); // import playback controller -const eventsController = require('../controllers/eventsController'); + const eventsController = require('../controllers/eventsController'); // create route between controller and '/events' endpoint router.get('/', eventsController.eventsGetAll); // create route between controller and '/events/:id' endpoint -router.get('/:id', eventsController.eventsGetById); +router.get('/:eventId', eventsController.eventsGetById); // create route between controller and '/events/' endpoint router.post('/', eventsController.eventsPost); @@ -20,6 +20,6 @@ router.put('/', eventsController.eventsPut); router.patch('/', eventsController.eventsPatch); // create route between controller and '/events/:id' endpoint -router.delete('/:id', eventsController.eventsDelete); +router.delete('/:eventId', eventsController.eventsDelete); module.exports = router; diff --git a/server/yarn.lock b/server/yarn.lock index 0e26cbf62..7c5a3fd23 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -248,6 +248,11 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +graceful-fs@^4.1.3: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + http-errors@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" @@ -292,6 +297,27 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-promise@^2.1.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + +lodash@4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lowdb@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowdb/-/lowdb-1.0.0.tgz#5243be6b22786ccce30e50c9a33eac36b20c8064" + integrity sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ== + dependencies: + graceful-fs "^4.1.3" + is-promise "^2.1.0" + lodash "4" + pify "^3.0.0" + steno "^0.4.1" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -401,6 +427,11 @@ pause@0.0.1: resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -517,6 +548,13 @@ socket.io@^4.0.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +steno@^0.4.1: + version "0.4.4" + resolved "https://registry.yarnpkg.com/steno/-/steno-0.4.4.tgz#071105bdfc286e6615c0403c27e9d7b5dcb855cb" + integrity sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs= + dependencies: + graceful-fs "^4.1.3" + toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"