diff --git a/src/frontend/manage/storageManager.eta.html b/src/frontend/manage/storageManager.eta.html index e316755..52ee58b 100644 --- a/src/frontend/manage/storageManager.eta.html +++ b/src/frontend/manage/storageManager.eta.html @@ -62,8 +62,8 @@
- + <% it.address.forEach(function(address){ %> <% }) %> @@ -71,6 +71,7 @@
Select or create a new address.
+
@@ -82,13 +83,13 @@
- +
6a
- +
123456
@@ -195,10 +196,10 @@ <%= units.name %> <%= units.contactInfo.street %> <%= units.contactInfo.houseNumber %>, <%= units.contactInfo.city %> <%= units.contactInfo.country %> - - + <% }) %> diff --git a/src/frontend/partials/head.eta.html b/src/frontend/partials/head.eta.html index bcff16e..cfec940 100644 --- a/src/frontend/partials/head.eta.html +++ b/src/frontend/partials/head.eta.html @@ -11,6 +11,7 @@ + diff --git a/src/routes/api/v1/storageUnits.ts b/src/routes/api/v1/storageUnits.ts index 76f5a6a..aecd451 100644 --- a/src/routes/api/v1/storageUnits.ts +++ b/src/routes/api/v1/storageUnits.ts @@ -1,18 +1,19 @@ import { Request, Response } from 'express'; import { prisma, __path, log } from '../../../index.js'; +import { contactType } from '@prisma/client'; // Get storageUnit. function get(req: Request, res: Response) { if (req.query.getAll === undefined) { // Check if required fields are present. - if (!req.query.name) { + if (!req.query.id) { res.status(400).render(__path + '/src/frontend/errors/400.eta.html'); return; } prisma.storageUnit .findUnique({ where: { - name: req.query.name.toString() + id: parseInt(req.query.id.toString()) }, // Get category name from relation. include: { @@ -54,36 +55,120 @@ function get(req: Request, res: Response) { // Create storageUnit. function post(req: Request, res: Response) { - log.web.debug(JSON.stringify(req.body)); -/* // Check if required fields are present. - if (!req.body.name) { + // If the frontend wants to create a StorageUnit with non-existing ContactInfo. + if (req.body.locationId === 'META_CREATENEW') { + // Check if required fields are present. + if (!req.body.street || !req.body.houseNumber || !req.body.zipCode || !req.body.city || !req.body.country || !req.body.name) { + res.status(400).render(__path + '/src/frontend/errors/400.eta.html'); + return; + } + + // Create storageUnit and location. + prisma.storageUnit + .create({ + data: { + name: req.body.name, + contactInfo: { + create: { + type: contactType.storageUnit, + street: req.body.street, + houseNumber: req.body.houseNumber, + zipCode: req.body.zipCode, + city: req.body.city, + country: req.body.country + } + } + } + }) + .then(() => { + res.status(201).json({ status: 'created' }); + }) + .catch((err) => { + // Check if an entry already exists. + if (err.code === 'P2002') { + // P2002 -> "Unique constraint failed on the {constraint}" + // https://www.prisma.io/docs/reference/api-reference/error-reference + res.status(409).json({ error: 'storageUnit already exists.' }); + } else { + log.db.error(err); + res.status(500).render(__path + '/src/frontend/errors/dbError.eta.html', { error: err }); + } + }); + } else { + // Check if required fields are present. + if (!req.body.name || !req.body.locationId) { + res.status(400).render(__path + '/src/frontend/errors/400.eta.html'); + return; + } + // Create storageUnit with existing location. + prisma.storageUnit + .create({ + data: { + name: req.body.name, + contactInfo: { + connect: { + id: parseInt(req.body.locationId) + } + } + } + }) + .then(() => { + res.status(201).json({ status: 'created' }); + }) + .catch((err) => { + // Check if an entry already exists. + if (err.code === 'P2002') { + // P2002 -> "Unique constraint failed on the {constraint}" + // https://www.prisma.io/docs/reference/api-reference/error-reference + res.status(409).json({ error: 'storageUnit already exists.' }); + } else { + log.db.error(err); + res.status(500).render(__path + '/src/frontend/errors/dbError.eta.html', { error: err }); + } + }); + } +} + +// Update storageUnit. -> Only existing contactInfo. +async function patch(req: Request, res: Response) { + // Check if required fields are present. + if (!req.body.id || !req.body.name || !req.body.locationId) { res.status(400).render(__path + '/src/frontend/errors/400.eta.html'); return; } - // Save data. - prisma.storageUnit - .create({ - data: { - name: req.body.name + // Check if the storageUnit id exists. If not return 410 Gone. + try { + const result = await prisma.storageUnit.findUnique({ + where: { + id: parseInt(req.body.id) } - }) - .then(() => { - res.status(201).json({ status: 'created' }); - }) - .catch((err) => { - // TODO Catch if is a duplicate error and show a message to the user - log.db.error(err); - res.status(500).render(__path + '/src/frontend/errors/dbError.eta.html', { error: err }); - }); */ -} + }); -// Update category. -function patch(req: Request, res: Response) { - // Check if required fields are present. - if (!req.body.id || !req.body.name) { - res.status(400).render(__path + '/src/frontend/errors/400.eta.html'); - return; + if (result === null) { + res.status(410).json({ error: 'storageUnit does not exist.' }); + return; + } + } catch (err) { + log.db.error(err); + res.status(500).render(__path + '/src/frontend/errors/dbError.eta.html', { error: err }); + } + + // Check if the locationId(contactInfo) exists. If not return 410 Gone. + try { + const result = await prisma.contactInfo.findUnique({ + where: { + id: parseInt(req.body.locationId) + } + }); + + if (result === null) { + res.status(410).json({ error: 'locationId does not exist.' }); + return; + } + } catch (err) { + log.db.error(err); + res.status(500).render(__path + '/src/frontend/errors/dbError.eta.html', { error: err }); } prisma.storageUnit @@ -92,20 +177,31 @@ function patch(req: Request, res: Response) { id: parseInt(req.body.id) }, data: { - name: req.body.name + name: req.body.name, + contactInfo: { + connect: { + id: parseInt(req.body.locationId) + } + } } }) .then(() => { res.status(201).json({ status: 'updated' }); }) .catch((err) => { - // TODO Catch if is a duplicate error and show a message to the user - log.db.error(err); - res.status(500).render(__path + '/src/frontend/errors/dbError.eta.html', { error: err }); + // Check if an entry already exists. + if (err.code === 'P2002') { + // P2002 -> "Unique constraint failed on the {constraint}" + // https://www.prisma.io/docs/reference/api-reference/error-reference + res.status(409).json({ error: 'storageUnit already exists.' }); + } else { + log.db.error(err); + res.status(500).render(__path + '/src/frontend/errors/dbError.eta.html', { error: err }); + } }); } -// Delete category. +// Delete storageUnit. async function del(req: Request, res: Response) { // Check if required fields are present. if (!req.body.id) { @@ -122,7 +218,7 @@ async function del(req: Request, res: Response) { }); if (result === null) { - res.status(410).json({ error: 'Storage Unit does not exist.' }); + res.status(410).json({ error: 'storageUnit does not exist.' }); return; } } catch (err) { @@ -137,7 +233,7 @@ async function del(req: Request, res: Response) { } }) .then(() => { - res.status(201).json({ status: 'deleted' }); + res.status(200).json({ status: 'deleted' }); }) .catch((err) => { log.db.error(err); diff --git a/static/js/editCategory.js b/static/js/editCategory.js index a8eab1f..50edd96 100644 --- a/static/js/editCategory.js +++ b/static/js/editCategory.js @@ -20,7 +20,7 @@ function getDataForEdit(name) { $('.loader-overlay').removeClass('active'); // Close the modal $('.modal').modal('hide'); - $('#generalToast').removeClass('text-bg-primary'); + normalizeToast() $('#generalToast').addClass('text-bg-danger'); $('#generalToast').toast('show'); $('#generalToast').children('.d-flex').children('.toast-body').html(' Something went wrong. The category does no longer exist.'); @@ -81,14 +81,13 @@ function deleteEntry(id) { error: function (data) { // hide the staticBackdrop modal $('#staticBackdrop').modal('hide'); - $('#generalToast').removeClass('text-bg-primary'); + normalizeToast() + $('#generalToast').addClass('text-bg-danger'); $('#generalToast').toast('show'); $('#generalToast').children('.d-flex').children('.toast-body').html(' Something went wrong. Please try again later.'); setTimeout(() => { $('#generalToast').toast('hide'); - $('#generalToast').removeClass('text-bg-danger'); - $('#generalToast').addClass('text-bg-primary'); }, 3000); } }); @@ -118,7 +117,7 @@ function preFillDeleteModal(name) { document.getElementById('deleteNamePlaceholder').innerText = 'Deleted'; $('#staticBackdrop').modal('hide'); - $('#generalToast').removeClass('text-bg-primary'); + normalizeToast() $('#generalToast').addClass('text-bg-danger'); $('#generalToast').toast('show'); $('#generalToast').children('.d-flex').children('.toast-body').html(' Something went wrong. The category does no longer exist.'); diff --git a/static/js/editStorages.js b/static/js/editStorages.js index 701a583..b233dec 100644 --- a/static/js/editStorages.js +++ b/static/js/editStorages.js @@ -26,6 +26,9 @@ $('.nav-link').on('click', function (e) { function primeCreateNew() { const form = document.getElementById('storageUnitModalForm'); const form2 = document.getElementById('storageLocationModal'); + document.getElementById('createNewLocationSelection').disabled = false; + document.getElementById('storageUnitModalLocationSelectText').innerText= "Select or create a new location."; + document.getElementById('storageUnitModalLabel').innerText = "Create new storage unit"; form.setAttribute('method', 'POST'); form2.setAttribute('method', 'POST'); return true; @@ -34,6 +37,12 @@ function primeCreateNew() { function primeEdit() { const form = document.getElementById('storageUnitModalForm'); const form2 = document.getElementById('storageLocationModal'); + // Disable create new location + document.getElementById('createNewLocationSelection').disabled = true; + document.getElementById('storageUnitModalLocationSelectText').innerText= "While editing you can only select already existing locations. Use the settings to create new ones."; + document.getElementById('storageUnitModalLabel').innerText = "Edit a storage unit"; + document.getElementById('storageUnitModalLocationSelect').value = 1 + handleSelector() form.setAttribute('method', 'PATCH'); form2.setAttribute('method', 'PATCH'); return true; @@ -52,4 +61,135 @@ function handleSelector(){ console.log(value); } + + +function preFillDeleteModal(id) { + $.ajax({ + type: 'get', + url: `/api/v1/storageUnits?id=${id}`, + success: function (data) { + const result = JSON.parse(data); + + // Get elements inside the editCategoryModal + const modal_categoryName = document.getElementById('deleteNamePlaceholder'); + const modal_deleteButton = document.getElementById('deleteActionBtn'); + //const modal_categoryDescription = document.getElementById('editCategoryModalDescription'); + //const modal_categoryid = document.getElementById('editCategoryModalId'); + + modal_categoryName.innerText = result.name; + modal_deleteButton.setAttribute('onclick', `deleteEntry(${result.id})`); + + //modal_categoryDescription.value = result.description; + //modal_categoryid.value = result.id; + }, + error: function (data) { + console.log('!!!! ERROR !!!!', data); + document.getElementById('deleteNamePlaceholder').innerText = 'Deleted'; + + $('#staticBackdrop').modal('hide'); + normalizeToast() + + $('#generalToast').addClass('text-bg-danger'); + $('#generalToast').toast('show'); + $('#generalToast').children('.d-flex').children('.toast-body').html(' Something went wrong. The storageUnit does no longer exist.'); + setTimeout(() => { + window.location.reload(); + }, 3000); + } + }); +} + + +function deleteEntry(id) { + $.ajax({ + type: 'delete', + url: `/api/v1/storageUnits`, + data: { id: id }, + success: function (data) { + $('#staticBackdrop').modal('hide'); + normalizeToast() + + $('#generalToast').addClass('text-bg-success'); + $('#generalToast').toast('show'); + $('#generalToast').children('.d-flex').children('.toast-body').html(' Storage Unit deleted successfully.'); + confetti({ + spread: 360, + ticks: 100, + gravity: 0.1, + decay: 0.94, + startVelocity: 30, + particleCount: 20, + scalar: 2, + shapes: ['text'], + shapeOptions: { + text: { + value: ['❌', '🗑️', '🚫'] + } + } + }); + setTimeout(() => { + $('#generalToast').toast('hide'); + window.location.reload(); + }, 2000); + }, + error: function (data) { + // hide the staticBackdrop modal + $('#staticBackdrop').modal('hide'); + normalizeToast() + $('#generalToast').addClass('text-bg-danger'); + $('#generalToast').toast('show'); + $('#generalToast').children('.d-flex').children('.toast-body').html(' Something went wrong. Please try again later.'); + setTimeout(() => { + $('#generalToast').toast('hide'); + }, 3000); + } + }); +} + + +function getDataForEdit(id) { + $.ajax({ + type: 'get', + url: `/api/v1/storageUnits?id=${id}`, + success: function (data) { + const result = JSON.parse(data); + + // Get elements inside the editCategoryModal + const modal_unitName = document.getElementById('storageUnitModalName'); + const modal_unitLocation = document.getElementById('storageUnitModalLocationSelect'); + const modal_unitId = document.getElementById('storageUnitModalLocationSelectHidden'); + // const modal_categoryid = document.getElementById('editCategoryModalId'); + + modal_unitName.value = result.name; + modal_unitId.value = result.id; + + // Select the correct location from the select based on the value of the option + for(var i, j = 0; i = modal_unitLocation.options[j]; j++) { + console.log(i.value, result.contactInfoId); + if(i.value == result.contactInfoId) { + console.log("Found it"); + modal_unitLocation.selectedIndex = j; + break; + } + } + + + }, + error: function (data) { + console.log('!!!! ERROR !!!!', data); + // Hide overlay with spinner + $('.loader-overlay').removeClass('active'); + // Close the modal + $('.modal').modal('hide'); + normalizeToast() + $('#generalToast').addClass('text-bg-danger'); + $('#generalToast').toast('show'); + $('#generalToast').children('.d-flex').children('.toast-body').html(' Something went wrong. The storage unit does no longer exist.'); + setTimeout(() => { + window.location.reload(); + }, 3000); + } + }); +} + handleSelector() \ No newline at end of file diff --git a/static/js/formHandler.js b/static/js/formHandler.js index e836785..81fb579 100644 --- a/static/js/formHandler.js +++ b/static/js/formHandler.js @@ -26,14 +26,12 @@ $('.frontendForm').each(function() { // Clear all fields form.find('input, textarea').val(''); - $('#generalToast').removeClass('text-bg-primary'); + normalizeToast() $('#generalToast').addClass('text-bg-success'); $('#generalToast').toast('show'); $('#generalToast').children('.d-flex').children('.toast-body').html(' Changes saved successfully.'); setTimeout(() => { $('#generalToast').toast('hide');; - $('#generalToast').removeClass('text-bg-success'); - $('#generalToast').addClass('text-bg-primary'); window.location.reload(); }, 1500); }, @@ -41,15 +39,20 @@ $('.frontendForm').each(function() { console.log('error'); // Hide overlay with spinner $('.loader-overlay').removeClass('loaderActive'); - - $('#generalToast').removeClass('text-bg-primary'); + + // Check for response code 409 + normalizeToast() $('#generalToast').addClass('text-bg-danger'); $('#generalToast').toast('show'); - $('#generalToast').children('.d-flex').children('.toast-body').html(' Something went wrong. Please try again later.'); + + + if (data.status == 409) { + $('#generalToast').children('.d-flex').children('.toast-body').html(' The element you tried to create already exists.'); + }else { + $('#generalToast').children('.d-flex').children('.toast-body').html(' Something went wrong. Please try again later.'); + } setTimeout(() => { $('#generalToast').toast('hide'); - $('#generalToast').removeClass('text-bg-danger'); - $('#generalToast').addClass('text-bg-primary'); }, 3000); } }); diff --git a/static/js/normalizeToast.js b/static/js/normalizeToast.js new file mode 100644 index 0000000..351d2b8 --- /dev/null +++ b/static/js/normalizeToast.js @@ -0,0 +1,7 @@ +function normalizeToast(){ + $('#generalToast').removeClass('text-bg-primary'); + $('#generalToast').removeClass('text-bg-success'); + $('#generalToast').removeClass('text-bg-danger'); + $('#generalToast').removeClass('text-bg-warning'); + $('#generalToast').removeClass('text-bg-info'); +}