diff --git a/src/controllers/REAL_TIME_timerController.js b/src/controllers/REAL_TIME_timerController.js deleted file mode 100644 index 699dcddef..000000000 --- a/src/controllers/REAL_TIME_timerController.js +++ /dev/null @@ -1,155 +0,0 @@ - -const logger = require('../startup/logger'); -const OldTimer = require('../models/oldTimer'); - -const timerController = function (Timer) { - const getTimerFromDatabase = async ({ userId }) => { - try { - const timerObject = await Timer.findOne({ userId }).exec(); - if (!timerObject) { - const newRecord = { - userId, - totalSeconds: 0, - isRunning: false, - isApplicationPaused: false, - isUserPaused: false, - }; - const newTimer = await Timer.create(newRecord); - return newTimer; - } - return timerObject; - } catch (e) { - logger.logException(e); - throw new Error('Issue trying to retrieve timer data from MongoDB'); - } - }; - - const setTimerToDatabase = async ({ - userId, - timerObject: { - totalSeconds, - isRunning, - isUserPaused, - isApplicationPaused, - } = {}, - } = {}) => { - try { - const update = { - $set: { - totalSeconds, - isRunning, - isUserPaused, - isApplicationPaused, - }, - }; - - const options = { - upsert: true, - new: true, - setDefaultsOnInsert: true, - rawResult: true, - }; - - return await Timer.findOneAndUpdate({ userId }, update, options).exec(); - } catch (e) { - logger.logException(e); - throw new Error('Issue trying to set timer data from MongoDB'); - } - }; - - const putTimer = function (req, res) { - const { userId } = req.params; - - const query = { userId }; - const update = { - $set: { - pausedAt: req.body.pausedAt, - isWorking: req.body.isWorking, - started: req.body.isWorking ? Date.now() : null, - lastAccess: Date.now(), - }, - }; - const options = { - upsert: true, new: true, setDefaultsOnInsert: true, rawResult: true, - }; - - OldTimer.findOneAndUpdate(query, update, options, (error, rawResult) => { - if (error) { - return res.status(500).send({ error }); - } - - if (rawResult === null || rawResult.value === undefined || rawResult.value === null - || rawResult.lastErrorObject === null || rawResult.lastErrorObject === undefined - || rawResult.value.length === 0) { - return res.status(500).send('Update/Upsert timer date failed'); - } - - if (rawResult.lastErrorObject.updatedExisting === true) { - return res.status(200).send({ message: 'updated timer data' }); - } - if (rawResult.lastErrorObject.updatedExisting === false - && rawResult.lastErrorObject.upserted !== undefined && rawResult.lastErrorObject.upserted !== null) { - return res.status(201).send({ _id: rawResult.lastErrorObject.upserted }); - } - return res.status(500).send('Update/Upsert timer date failed'); - }); - }; - - const timePassed = (timer) => { - if (!timer.started) { return 0; } - const now = timer.timedOut ? timer.lastAccess : Date.now(); - return Math.floor((now - timer.started) / 1000); - }; - - const adjust = (timer, cb) => { - const oneMin = 60 * 1000; - const fiveMin = 5 * oneMin; - const timeSinceLastAccess = timer.lastAccess ? (Date.now() - timer.lastAccess) : 0; - const setLastAccess = !timer.lastAccess || (timeSinceLastAccess > oneMin); - - timer.timedOut = timer.isWorking && (timeSinceLastAccess > fiveMin); - timer.seconds = timer.pausedAt + timePassed(timer); - - if (timer.timedOut) { - return OldTimer.findOneAndUpdate({ userId: timer.userId }, { - isWorking: false, - pauseAt: timer.seconds, - started: null, - lastAccess: Date.now(), - }).then(() => cb(timer)); - } - if (setLastAccess) { - return OldTimer.findOneAndUpdate({ userId: timer.userId }, { lastAccess: Date.now() }).then(() => cb(timer)); - } - - return cb(timer); - }; - - const getTimer = function (req, res) { - const { userId } = req.params; - - OldTimer.findOne({ userId }).lean().exec((error, record) => { - if (error) { - return res.status(500).send(error); - } - if (record === null) { - if (req.body.requestor.requestorId === userId) { - const newRecord = { - userId, - pausedAt: 0, - isWorking: false, - }; - return OldTimer.create(newRecord).then(result => res.status(200).send(result)).catch(() => res.status(400).send('Timer record not found for the given user ID')); - } - return res.status(400).send('Timer record not found for the given user ID'); - } - return adjust(record, (timer) => { res.status(200).send(timer); }); - }); - }; - - return { - putTimer, getTimer, getTimerFromDatabase, setTimerToDatabase, - }; -}; - -module.exports = timerController; diff --git a/src/models/REAL_TIME_timer.js b/src/models/REAL_TIME_timer.js deleted file mode 100644 index 4e143aeaa..000000000 --- a/src/models/REAL_TIME_timer.js +++ /dev/null @@ -1,13 +0,0 @@ -const mongoose = require('mongoose'); - -const { Schema } = mongoose; - -const timerSchema = new Schema({ - userId: { type: Schema.Types.ObjectId, required: true, ref: 'userProfile' }, - totalSeconds: { type: Number, default: 0 }, - isRunning: { type: Boolean, default: false }, - isUserPaused: { type: Boolean, default: false }, - isApplicationPaused: { type: Boolean, default: false }, -}); - -module.exports = mongoose.model('newTimer', timerSchema, 'newTimers'); diff --git a/src/models/oldTimer.js b/src/models/oldTimer.js deleted file mode 100644 index dca0ade1a..000000000 --- a/src/models/oldTimer.js +++ /dev/null @@ -1,14 +0,0 @@ -const mongoose = require('mongoose'); - -const { Schema } = mongoose; - -const timerSchema = new Schema({ - userId: { type: Schema.Types.ObjectId, required: true, ref: 'userProfile' }, - pausedAt: { type: Number, default: 0 }, - isWorking: { type: Boolean, default: false }, - started: { type: Date }, - lastAccess: { type: Date }, - }); - - -module.exports = mongoose.model('timer', timerSchema, 'timers'); diff --git a/src/models/timer.js b/src/models/timer.js index 8afbad119..f50921fb3 100644 --- a/src/models/timer.js +++ b/src/models/timer.js @@ -8,6 +8,8 @@ const timerSchema = new Schema({ startAt: { type: Date, default: Date.now }, time: { type: Number, default: 900000 }, goal: { type: Number, default: 900000 }, + initialGoal: { type: Number, default: 900000 }, + chiming: { type: Boolean, default: false }, paused: { type: Boolean, default: false }, forcedPause: { type: Boolean, default: false }, started: { type: Boolean, default: false }, diff --git a/src/routes/timerRouter.js b/src/routes/timerRouter.js deleted file mode 100644 index 094b2ba81..000000000 --- a/src/routes/timerRouter.js +++ /dev/null @@ -1,15 +0,0 @@ -const express = require('express'); - -const routes = function (Timer) { - const TimerRouter = express.Router(); - - const controller = require('../controllers/REAL_TIME_timerController')(Timer); - - TimerRouter.route('/timer/:userId') - .put(controller.putTimer) - .get(controller.getTimer); - - return TimerRouter; -}; - -module.exports = routes; diff --git a/src/startup/routes.js b/src/startup/routes.js index 2fd7337a6..eae746e24 100644 --- a/src/startup/routes.js +++ b/src/startup/routes.js @@ -7,7 +7,6 @@ const actionItem = require('../models/actionItem'); const notification = require('../models/notification'); const wbs = require('../models/wbs'); const task = require('../models/task'); -const timer = require('../models/timer'); const popup = require('../models/popupEditor'); const popupBackup = require('../models/popupEditorBackup'); const taskNotification = require('../models/taskNotification'); @@ -38,7 +37,6 @@ const forcePwdRouter = require('../routes/forcePwdRouter')(userProfile); const reportsRouter = require('../routes/reportsRouter')(); const wbsRouter = require('../routes/wbsRouter')(wbs); const taskRouter = require('../routes/taskRouter')(task); -const timerRouter = require('../routes/timerRouter')(timer); const popupRouter = require('../routes/popupEditorRouter')(popup); const popupBackupRouter = require('../routes/popupEditorBackupRouter')(popupBackup); const taskNotificationRouter = require('../routes/taskNotificationRouter')(taskNotification); @@ -76,7 +74,6 @@ module.exports = function (app) { app.use('/api', reportsRouter); app.use('/api', wbsRouter); app.use('/api', taskRouter); - app.use('/api', timerRouter); app.use('/api', popupRouter); app.use('/api', popupBackupRouter); app.use('/api', taskNotificationRouter); diff --git a/src/websockets/TimerService/clientsHandler.js b/src/websockets/TimerService/clientsHandler.js index 6990ead71..60eb33fa4 100644 --- a/src/websockets/TimerService/clientsHandler.js +++ b/src/websockets/TimerService/clientsHandler.js @@ -4,13 +4,6 @@ const moment = require('moment'); const Timer = require('../../models/timer'); const logger = require('../../startup/logger'); -/** - * Here we get the timer. - * If the timer already exists in memory, we return it. - * If it doesn't exist, we try to get it from MongoDB. - * If it doesn't exist in MongoDB, we create it and save it to MongoDB. - * Then we save it to memory and return it. - */ export const getClient = async (clients, userId) => { // In case of there is already a connection that is open for this user // for example user open a new connection @@ -29,13 +22,6 @@ export const getClient = async (clients, userId) => { return clients.get(userId); }; -/** - * Save client info to database - * Save under these conditions: - * connection is normally closed (paused and closed); - * connection is forced-paused (timer still on and connection closed) - * message: STOP_TIMER - */ export const saveClient = async (client) => { try { await Timer.findOneAndUpdate({ userId: client.userId }, client); @@ -47,10 +33,6 @@ export const saveClient = async (client) => { } }; -/** - * This is the contract between client and server. - * The client can send one of the following messages to the server: - */ export const action = { START_TIMER: 'START_TIMER', PAUSE_TIMER: 'PAUSE_TIMER', @@ -61,6 +43,7 @@ export const action = { REMOVE_GOAL: 'REMOVE_FROM_GOAL=', FORCED_PAUSE: 'FORCED_PAUSE', ACK_FORCED: 'ACK_FORCED', + START_CHIME: 'START_CHIME', }; const MAX_HOURS = 5; @@ -75,12 +58,6 @@ const updatedTimeSinceStart = (client) => { return updatedTime > 0 ? updatedTime : 0; }; -/** - * Here we start the timer, if it is not already started. - * We set the last access time to now, and set the paused and stopped flags to false. - * If the timer was paused, we need to check if it was paused by the user or by the server. - * If it was paused by the server, we need to set the forcedPause flag to true. - */ const startTimer = (client) => { client.startAt = moment.utc(); client.paused = false; @@ -91,81 +68,54 @@ const startTimer = (client) => { if (client.forcedPause) client.forcedPause = false; }; -/** - * Here we pause the timer, if it is not already paused. - * We get the total elapsed time since the last access, and set it as the new time. - * We set the last access time to now, and set the paused flag to true. - * If the timer was paused by the server, we need to set the forcedPause flag to true. - * It'll only be triggered when the user closes the connection sudenlly or lacks of ACKs. - */ const pauseTimer = (client, forced = false) => { client.time = updatedTimeSinceStart(client); - client.startAt = moment.invalid(); + if (client.time === 0) client.chiming = true; + client.startAt = moment.invalid(); // invalid can not be saved in database client.paused = true; if (forced) client.forcedPause = true; }; -// Here we acknowledge the forced pause. To prevent the modal for beeing displayed again. +const startChime = (client, msg) => { + const state = msg.split('=')[1]; + client.chiming = state === 'true'; +}; + const ackForcedPause = (client) => { client.forcedPause = false; client.paused = true; client.startAt = moment.invalid(); }; -/** - * Here we stop the timer. - * We pause the timer and set the stopped flag to true. - */ const stopTimer = (client) => { + if (client.started) pauseTimer(client); client.startAt = moment.invalid(); client.started = false; client.pause = false; client.forcedPause = false; + if (client.chiming) client.chiming = false; + if (client.time === 0) { + client.goal = client.initialGoal; + client.time = client.goal; + } else { + client.goal = client.time; + } }; -/** - * Here we clear the timer. - * We pause the timer and check it's mode to set the time to 0 or the goal. - * Then we set the stopped flag to false. - */ const clearTimer = (client) => { stopTimer(client); - client.goal = moment.duration(2, 'hours').asMilliseconds(); + client.goal = client.initialGoal; + client.chiming = false; client.time = client.goal; }; -// Here we set the goal and time to the goal time. -/** - * Here we set the goal. - * if timer has not started, we set both time and goal to the new goal - * if timer has started, we calculate the passed time and remove that from new goal - * and if passed time is greater than new goal, then set time to 0, but this should - * not be prohibited by frontend. - */ const setGoal = (client, msg) => { const newGoal = parseInt(msg.split('=')[1]); - if (!client.started) { - client.goal = newGoal; - client.time = newGoal; - } else { - const passedTime = client.goal - client.time; - if (passedTime >= newGoal) { - client.time = 0; - client.goal = passedTime; - } else { - client.time = newGoal - passedTime; - client.goal = newGoal; - } - } + client.goal = newGoal; + client.time = newGoal; + client.initialGoal = newGoal; }; -/** - * Here we add the goal time. - * Each addition add 15min - * First we get the goal time from the message. - * Then we add it to the current goal time and set it as the new goal time. - * We also add it to the current time and set it as the new time. - */ const addGoal = (client, msg) => { const duration = parseInt(msg.split('=')[1]); const goalAfterAddition = moment @@ -187,14 +137,6 @@ const addGoal = (client, msg) => { .toFixed(); }; -/** - * Here we try to remove a goal time. - * First we get the goal time from the message. - * Then we subtract it from the current goal time and set it as the new goal time. - * We also subtract it from the current time and set it as the new time. - * If the new goal time is less than 15 minutes, we don't do anything. - * If the new time is less than 0, we set it to 0. - */ const removeGoal = (client, msg) => { const duration = parseInt(msg.split('=')[1]); const goalAfterRemoval = moment @@ -220,16 +162,6 @@ const removeGoal = (client, msg) => { .toFixed(); }; - -/** - * Here is were we handle the messages. - * First we check if the user is in memory, if not, we throw an error. - * Then we parse the request and check which action it is and call the corresponding function. - * If we don't have a match, we just return an error. - * The only operation that we write to Mongo it's the stop timer. Other operations are just in memory. - * So the slowest part of the app is the save to Mongo. - * Then we update the current client in hash map and return the response. - */ export const handleMessage = async (msg, clients, userId) => { if (!clients.has(userId)) { throw new Error('It should have this user in memory'); @@ -252,6 +184,9 @@ export const handleMessage = async (msg, clients, userId) => { case req.match(/REMOVE_FROM_GOAL=/i)?.input: removeGoal(client, req); break; + case req.match(/START_CHIME=/i)?.input: + startChime(client, req); + break; case action.PAUSE_TIMER: pauseTimer(client); break;