From deb5583be3848c1560c5a0165f0b447119b069b6 Mon Sep 17 00:00:00 2001 From: Vaishnavi Kadam Date: Sun, 16 Jun 2024 17:41:39 +0530 Subject: [PATCH 1/2] task2 changes --- server.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/server.js b/server.js index 7ba16d7..c3020f7 100644 --- a/server.js +++ b/server.js @@ -127,7 +127,72 @@ app.put('/api/v1/clients/:id', (req, res) => { /* ---------- Update code below ----------*/ + if (priority !== undefined) { + const { valid, messageObj } = validatePriority(priority); + if (!valid) { + res.status(400).send(messageObj); + } + } + else priority = Infinity; + + const updatedClients = []; + + const oldStatusClients = clients.filter( + c => c.id !== client.id && c.status === client.status + ); + + + oldStatusClients.forEach(c => { + if (c.id !== id && c.priority > client.priority) { + updatedClients.push([c.status, c.priority - 1, c.id]); + } + }); + + if (status === undefined) status = client.status; + const newStatusClients = clients.filter(c => c.status === status); + + let newMaxPriority = 0; + + newStatusClients.forEach(c => { + if (c.id !== id && c.priority >= priority) { + updatedClients.push([c.status, c.priority + 1, c.id]); + newMaxPriority = c.priority + 1; + } + }); + + if (priority === Infinity) priority = newMaxPriority + 1; + updatedClients.push([status, priority, client.id]); + updateClients(updatedClients); + + return res.status(200).send(db.prepare("select * from clients").all()); +}); + +// Allow all CORS for local testing +app.use(function (req, res, next) { + res.header("Access-Control-Allow-Origin", "*"); + res.header( + "Access-Control-Allow-Headers", + "Origin, X-Requested-With, Content-Type, Accept" + ); + next(); +}); + +const clientUpdate = db.prepare( + "UPDATE clients SET status=?, priority=? WHERE id=?" +); + +/** updatedClients array entry format: + * + * [ + * [client status, client priorotiy, client id], + * ... + * ] + * + */ +const updateClients = db.transaction(updatedClients => { + for (const client of updatedClients) clientUpdate.run(...client); +}); return res.status(200).send(clients); }); From 341a8dc50811b47ddb08cdc5ee6dbac9ad55abb4 Mon Sep 17 00:00:00 2001 From: Vaishnavi Kadam Date: Sun, 16 Jun 2024 23:37:42 +0530 Subject: [PATCH 2/2] final --- 0001-task2-changes.patch | 89 ++++++++++++++++++++++++++++++++ server.js | 106 ++++++++++++++++++++++++--------------- 2 files changed, 155 insertions(+), 40 deletions(-) create mode 100644 0001-task2-changes.patch diff --git a/0001-task2-changes.patch b/0001-task2-changes.patch new file mode 100644 index 0000000..b638ee4 --- /dev/null +++ b/0001-task2-changes.patch @@ -0,0 +1,89 @@ +From deb5583be3848c1560c5a0165f0b447119b069b6 Mon Sep 17 00:00:00 2001 +From: Vaishnavi Kadam +Date: Sun, 16 Jun 2024 17:41:39 +0530 +Subject: [PATCH] task2 changes + +--- + server.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +diff --git a/server.js b/server.js +index 7ba16d7..c3020f7 100644 +--- a/server.js ++++ b/server.js +@@ -127,7 +127,72 @@ app.put('/api/v1/clients/:id', (req, res) => { + + /* ---------- Update code below ----------*/ + ++ if (priority !== undefined) { ++ const { valid, messageObj } = validatePriority(priority); ++ if (!valid) { ++ res.status(400).send(messageObj); ++ } ++ } ++ else priority = Infinity; ++ ++ const updatedClients = []; ++ ++ const oldStatusClients = clients.filter( ++ c => c.id !== client.id && c.status === client.status ++ ); ++ ++ ++ oldStatusClients.forEach(c => { ++ if (c.id !== id && c.priority > client.priority) { ++ updatedClients.push([c.status, c.priority - 1, c.id]); ++ } ++ }); ++ ++ if (status === undefined) status = client.status; ++ const newStatusClients = clients.filter(c => c.status === status); ++ ++ let newMaxPriority = 0; ++ ++ newStatusClients.forEach(c => { ++ if (c.id !== id && c.priority >= priority) { ++ updatedClients.push([c.status, c.priority + 1, c.id]); ++ newMaxPriority = c.priority + 1; ++ } ++ }); ++ ++ if (priority === Infinity) priority = newMaxPriority + 1; ++ updatedClients.push([status, priority, client.id]); + ++ updateClients(updatedClients); ++ ++ return res.status(200).send(db.prepare("select * from clients").all()); ++}); ++ ++// Allow all CORS for local testing ++app.use(function (req, res, next) { ++ res.header("Access-Control-Allow-Origin", "*"); ++ res.header( ++ "Access-Control-Allow-Headers", ++ "Origin, X-Requested-With, Content-Type, Accept" ++ ); ++ next(); ++}); ++ ++const clientUpdate = db.prepare( ++ "UPDATE clients SET status=?, priority=? WHERE id=?" ++); ++ ++/** updatedClients array entry format: ++ * ++ * [ ++ * [client status, client priorotiy, client id], ++ * ... ++ * ] ++ * ++ */ ++const updateClients = db.transaction(updatedClients => { ++ for (const client of updatedClients) clientUpdate.run(...client); ++}); + + return res.status(200).send(clients); + }); +-- +2.35.1.windows.2 + diff --git a/server.js b/server.js index c3020f7..dbafd34 100644 --- a/server.js +++ b/server.js @@ -1,88 +1,99 @@ -import express from 'express'; -import Database from 'better-sqlite3'; +import express from "express"; +import Database from "better-sqlite3"; const app = express(); app.use(express.json()); -app.get('/', (req, res) => { - return res.status(200).send({'message': 'SHIPTIVITY API. Read documentation to see API docs'}); +app.get("/", (req, res) => { + return res + .status(200) + .send({ message: "SHIPTIVITY API. Read documentation to see API docs" }); }); // We are keeping one connection alive for the rest of the life application for simplicity -const db = new Database('./clients.db'); +const db = new Database("./clients.db"); // Don't forget to close connection when server gets terminated const closeDb = () => db.close(); -process.on('SIGTERM', closeDb); -process.on('SIGINT', closeDb); +process.on("SIGTERM", closeDb); +process.on("SIGINT", closeDb); /** * Validate id input * @param {any} id */ -const validateId = (id) => { +const validateId = id => { if (Number.isNaN(id)) { return { valid: false, messageObj: { - 'message': 'Invalid id provided.', - 'long_message': 'Id can only be integer.', - }, + message: "Invalid id provided.", + long_message: "Id can only be integer." + } }; } - const client = db.prepare('select * from clients where id = ? limit 1').get(id); + const client = db + .prepare("select * from clients where id = ? limit 1") + .get(id); if (!client) { return { valid: false, messageObj: { - 'message': 'Invalid id provided.', - 'long_message': 'Cannot find client with that id.', - }, + message: "Invalid id provided.", + long_message: "Cannot find client with that id." + } }; } return { - valid: true, + valid: true }; -} +}; /** * Validate priority input * @param {any} priority */ -const validatePriority = (priority) => { +const validatePriority = priority => { if (Number.isNaN(priority)) { return { valid: false, messageObj: { - 'message': 'Invalid priority provided.', - 'long_message': 'Priority can only be positive integer.', - }, + message: "Invalid priority provided.", + long_message: "Priority can only be positive integer." + } }; } return { - valid: true, - } -} + valid: true + }; +}; /** * Get all of the clients. Optional filter 'status' * GET /api/v1/clients?status={status} - list all clients, optional parameter status: 'backlog' | 'in-progress' | 'complete' */ -app.get('/api/v1/clients', (req, res) => { +app.get("/api/v1/clients", (req, res) => { const status = req.query.status; if (status) { // status can only be either 'backlog' | 'in-progress' | 'complete' - if (status !== 'backlog' && status !== 'in-progress' && status !== 'complete') { + if ( + status !== "backlog" && + status !== "in-progress" && + status !== "complete" + ) { return res.status(400).send({ - 'message': 'Invalid status provided.', - 'long_message': 'Status can only be one of the following: [backlog | in-progress | complete].', + message: "Invalid status provided.", + long_message: + "Status can only be one of the following: [backlog | in-progress | complete]." }); } - const clients = db.prepare('select * from clients where status = ?').all(status); + const clients = db + .prepare("select * from clients where status = ?") + .all(status); return res.status(200).send(clients); } - const statement = db.prepare('select * from clients'); + const statement = db.prepare("select * from clients"); const clients = statement.all(); return res.status(200).send(clients); }); @@ -91,13 +102,15 @@ app.get('/api/v1/clients', (req, res) => { * Get a client based on the id provided. * GET /api/v1/clients/{client_id} - get client by id */ -app.get('/api/v1/clients/:id', (req, res) => { - const id = parseInt(req.params.id , 10); +app.get("/api/v1/clients/:id", (req, res) => { + const id = parseInt(req.params.id, 10); const { valid, messageObj } = validateId(id); if (!valid) { res.status(400).send(messageObj); } - return res.status(200).send(db.prepare('select * from clients where id = ?').get(id)); + return res + .status(200) + .send(db.prepare("select * from clients where id = ?").get(id)); }); /** @@ -105,7 +118,7 @@ app.get('/api/v1/clients/:id', (req, res) => { * When status is provided, the client status will be changed * When priority is provided, the client priority will be changed with the rest of the clients accordingly * Note that priority = 1 means it has the highest priority (should be on top of the swimlane). - * No client on the same status should not have the same priority. + * No two clients on the same status should have the same priority. * This API should return list of clients on success * * PUT /api/v1/clients/{client_id} - change the status of a client @@ -114,45 +127,56 @@ app.get('/api/v1/clients/:id', (req, res) => { * priority (optional): integer, * */ -app.put('/api/v1/clients/:id', (req, res) => { - const id = parseInt(req.params.id , 10); +app.put("/api/v1/clients/:id", (req, res) => { + // Validate the id + const id = parseInt(req.params.id, 10); const { valid, messageObj } = validateId(id); if (!valid) { res.status(400).send(messageObj); } let { status, priority } = req.body; - let clients = db.prepare('select * from clients').all(); + let clients = db.prepare("select * from clients").all(); const client = clients.find(client => client.id === id); /* ---------- Update code below ----------*/ + // Validate the priority if (priority !== undefined) { const { valid, messageObj } = validatePriority(priority); if (!valid) { + // Immediately send reponse if invalid res.status(400).send(messageObj); } } + // If priority wasn't passed, set to lowest priority else priority = Infinity; + // Store array of updated clients const updatedClients = []; + // Get all clients from old status const oldStatusClients = clients.filter( c => c.id !== client.id && c.status === client.status ); + // Decrement those that were greater than the changed client oldStatusClients.forEach(c => { if (c.id !== id && c.priority > client.priority) { updatedClients.push([c.status, c.priority - 1, c.id]); } }); + // Get all clients from new status if (status === undefined) status = client.status; const newStatusClients = clients.filter(c => c.status === status); + // Watch for new max priority in case priority was not passed let newMaxPriority = 0; + // Update clients with priorities greater than + // changed Client's new proirity newStatusClients.forEach(c => { if (c.id !== id && c.priority >= priority) { updatedClients.push([c.status, c.priority + 1, c.id]); @@ -160,11 +184,14 @@ app.put('/api/v1/clients/:id', (req, res) => { } }); + // Update changed client if (priority === Infinity) priority = newMaxPriority + 1; updatedClients.push([status, priority, client.id]); + // Send updates to database updateClients(updatedClients); + // Reutnr list of all clients return res.status(200).send(db.prepare("select * from clients").all()); }); @@ -178,10 +205,12 @@ app.use(function (req, res, next) { next(); }); +// Database update query for single client const clientUpdate = db.prepare( "UPDATE clients SET status=?, priority=? WHERE id=?" ); +// Database update for array of clients /** updatedClients array entry format: * * [ @@ -194,8 +223,5 @@ const updateClients = db.transaction(updatedClients => { for (const client of updatedClients) clientUpdate.run(...client); }); - return res.status(200).send(clients); -}); - app.listen(3001); console.log('app running on port ', 3001);