From 0c9cd6349c6f221b44e57806b24feb545caf37da Mon Sep 17 00:00:00 2001 From: LilleBRG Date: Thu, 3 Apr 2025 14:35:45 +0200 Subject: [PATCH] device crud works --- backend/Api/Api.sln | 6 -- backend/Api/BusinessLogic/DeviceLogic.cs | 17 ++--- backend/Api/Controllers/DeviceController.cs | 14 ++-- backend/Api/DBAccess/DBAccess.cs | 78 ++++++++++---------- backend/Api/Models/Devices/GetDeviceDTO.cs | 12 +++ frontend/scripts/devices.js | 59 +++++++++------ frontend/scripts/services/devices.service.js | 14 ++-- 7 files changed, 111 insertions(+), 89 deletions(-) create mode 100644 backend/Api/Models/Devices/GetDeviceDTO.cs diff --git a/backend/Api/Api.sln b/backend/Api/Api.sln index ebc8b3a..409cce6 100644 --- a/backend/Api/Api.sln +++ b/backend/Api/Api.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 17.9.34607.119 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Api", "Api.csproj", "{9CCF78E1-969C-420F-BE31-F8AFCE0C6827}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "..\test\test.csproj", "{5ACD3275-AE0C-458C-AACD-12FE1E165621}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -17,10 +15,6 @@ Global {9CCF78E1-969C-420F-BE31-F8AFCE0C6827}.Debug|Any CPU.Build.0 = Debug|Any CPU {9CCF78E1-969C-420F-BE31-F8AFCE0C6827}.Release|Any CPU.ActiveCfg = Release|Any CPU {9CCF78E1-969C-420F-BE31-F8AFCE0C6827}.Release|Any CPU.Build.0 = Release|Any CPU - {5ACD3275-AE0C-458C-AACD-12FE1E165621}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5ACD3275-AE0C-458C-AACD-12FE1E165621}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5ACD3275-AE0C-458C-AACD-12FE1E165621}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5ACD3275-AE0C-458C-AACD-12FE1E165621}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/backend/Api/BusinessLogic/DeviceLogic.cs b/backend/Api/BusinessLogic/DeviceLogic.cs index 7df4190..3af9e81 100644 --- a/backend/Api/BusinessLogic/DeviceLogic.cs +++ b/backend/Api/BusinessLogic/DeviceLogic.cs @@ -31,7 +31,7 @@ namespace Api.BusinessLogic var devices = await _dbAccess.ReadDevices(userId); - if (devices.Count == 0) { return new ConflictObjectResult(new { message = "Could not find any devices connected to the user" }); } + if (devices.Count == 0) { return new OkObjectResult(new { message = "Could not find any devices connected to the user" }); } return new OkObjectResult(devices); } @@ -46,6 +46,9 @@ namespace Api.BusinessLogic public async Task AddDevice(string referenceId, int userId) { var profile = await _dbAccess.ReadUser(userId); + var possibleDevice = _dbAccess.ReadDevice(referenceId); + if (possibleDevice != null) { return new ConflictObjectResult(new { message = "Device with given referenceId already exists" }); } + if (profile == null) { return new ConflictObjectResult(new { message = "Could not find user" }); } @@ -97,13 +100,9 @@ namespace Api.BusinessLogic /// The updated info /// The device to be edited /// returns the updated device in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason - public async Task EditDevice(Device device, int deviceId) + public async Task EditDevice(EditDeviceRequest device, int deviceId) { - var device1 = _dbAccess.ReadDevice(deviceId); - - if (device1 == null) { return new ConflictObjectResult(new { message = "Could not find device" }); } - - return await _dbAccess.UpdateDevice(device, deviceId); + return await _dbAccess.EditDevice(device, deviceId); } /// @@ -112,9 +111,9 @@ namespace Api.BusinessLogic /// the id used to delete /// Used for deleting device from devices list in user /// returns OK - public async Task DeleteDevice(string referenceId, int userId) + public async Task DeleteDevice(int deviceId, int userId) { - return await _dbAccess.DeleteDevice(referenceId, userId); + return await _dbAccess.DeleteDevice(deviceId, userId); } } } diff --git a/backend/Api/Controllers/DeviceController.cs b/backend/Api/Controllers/DeviceController.cs index aa88c32..ada5466 100644 --- a/backend/Api/Controllers/DeviceController.cs +++ b/backend/Api/Controllers/DeviceController.cs @@ -34,8 +34,8 @@ namespace Api.Controllers // Sends the device and userId to deviceLogic [Authorize] - [HttpPost("adddevice")] - public async Task AddDevice([FromBody] string referenceId) + [HttpPost("adddevice/{referenceId}")] + public async Task AddDevice(string referenceId) { var claims = HttpContext.User.Claims; string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value; @@ -64,21 +64,21 @@ namespace Api.Controllers // Sends the deviceId to deviceLogic [Authorize] - [HttpPut("Edit/{deviceId}")] - public async Task EditDevice([FromBody] Device device, int deviceId) + [HttpPut("update/{deviceId}")] + public async Task EditDevice([FromBody] EditDeviceRequest device, int deviceId) { return await _deviceLogic.EditDevice(device, deviceId); } // Sends the userId to userLogic [Authorize] - [HttpDelete("Delete/{referenceId}")] - public async Task DeleteUser(string referenceId) + [HttpDelete("Delete/{deviceId}")] + public async Task DeleteDevice(int deviceId) { var claims = HttpContext.User.Claims; string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value; int userId = Convert.ToInt32(userIdString); - return await _deviceLogic.DeleteDevice(referenceId, userId); + return await _deviceLogic.DeleteDevice(deviceId, userId); } } } diff --git a/backend/Api/DBAccess/DBAccess.cs b/backend/Api/DBAccess/DBAccess.cs index 6885970..08cab71 100644 --- a/backend/Api/DBAccess/DBAccess.cs +++ b/backend/Api/DBAccess/DBAccess.cs @@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Mvc; using static System.Runtime.InteropServices.JavaScript.JSType; using Api.Models.Devices; using Api.Models.Users; +using Microsoft.AspNetCore.Http.HttpResults; +using System.Collections.Generic; namespace Api.DBAccess @@ -182,13 +184,29 @@ namespace Api.DBAccess } // Returns devices according to userID - public async Task> ReadDevices(int userId) + public async Task> ReadDevices(int userId) { - var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId); + var user = await _context.Users.Include(u => u.Devices).ThenInclude(u => u.Logs).FirstOrDefaultAsync(u => u.Id == userId); - if (user == null || user.Devices == null) { return new List(); } + if (user == null || user.Devices == null) { return new List(); } - var devices = user.Devices; + List devices = new List(); + + foreach (var item in user.Devices) + { + var latestLog = item.Logs?.OrderByDescending(log => log.Date).FirstOrDefault(); // Get the latest log + GetDeviceDTO device = new GetDeviceDTO + { + Id = item.Id, + Name = item.Name, + TempHigh = item.TempHigh, + TempLow = item.TempLow, + ReferenceId = item.ReferenceId, + LatestLog = latestLog + }; + + devices.Add(device); + } return devices; } @@ -226,9 +244,16 @@ namespace Api.DBAccess return _context.Devices.FirstOrDefault(d => d.ReferenceId == referenceId); } - public async Task EditDevice(EditDeviceRequest request, string referenceId) + + /// + /// Updates a device in the database + /// + /// Contains the updated device info + /// Has the id for the device that is to be updated + /// returns the updated device in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason + public async Task EditDevice(EditDeviceRequest request, int deviceId) { - var device = await _context.Devices.FirstOrDefaultAsync(d => d.ReferenceId == referenceId); + var device = await _context.Devices.FirstOrDefaultAsync(d => d.Id == deviceId); if (device != null) { if (device.Name == "" || device.Name == null) @@ -247,7 +272,7 @@ namespace Api.DBAccess return new ConflictObjectResult(new { message = "Invalid device. May already be deleted" }); } - public async Task DeleteDevice(string referenceId, int userId) + public async Task DeleteDevice(int deviceId, int userId) { var user = await _context.Users .Include(u => u.Devices) // Ensure devices are loaded @@ -258,15 +283,19 @@ namespace Api.DBAccess return new NotFoundObjectResult(new { message = "User not found" }); } - var device = user.Devices?.FirstOrDefault(d => d.ReferenceId == referenceId); + var device = user.Devices?.FirstOrDefault(d => d.Id == deviceId); if (device != null || user.Devices != null) { user.Devices.Remove(device); - _context.Devices.Remove(device); - bool saved = await _context.SaveChangesAsync() > 0; + bool userDeviceDeleted = await _context.SaveChangesAsync() > 0; + if (userDeviceDeleted) + { + _context.Devices.Remove(device); + bool saved = await _context.SaveChangesAsync() > 0; - if (saved) return new OkObjectResult(new { message = "Device deleted successfully" }); + if (saved) return new OkObjectResult(new { message = "Device deleted successfully" }); + } return new ConflictObjectResult(new { message = "Could not save to database" }); } @@ -280,33 +309,6 @@ namespace Api.DBAccess return _context.Devices.ToList(); } - /// - /// Updates a device in the database - /// - /// Contains the updated device info - /// Has the id for the device that is to be updated - /// returns the updated device in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason - public async Task UpdateDevice(Device device, int deviceId) - { - var device1 = await _context.Devices.FirstOrDefaultAsync(u => u.Id == deviceId); - - if (device1 == null) { return new ConflictObjectResult(new { message = "Device does not exist" }); } - - device1.TempLow = device.TempLow; - - device1.TempHigh = device.TempHigh; - - device1.ReferenceId = device.ReferenceId; - - device1.Name = device.Name; - - bool saved = await _context.SaveChangesAsync() == 1; - - if (saved) { return new OkObjectResult(device1); } - - return new ConflictObjectResult(new { message = "Could not save to database" }); - } - /// /// Returns the logs from the device /// diff --git a/backend/Api/Models/Devices/GetDeviceDTO.cs b/backend/Api/Models/Devices/GetDeviceDTO.cs new file mode 100644 index 0000000..9449f73 --- /dev/null +++ b/backend/Api/Models/Devices/GetDeviceDTO.cs @@ -0,0 +1,12 @@ +namespace Api.Models.Devices +{ + public class GetDeviceDTO + { + public int Id { get; set; } + public string Name { get; set; } + public double TempHigh { get; set; } + public double TempLow { get; set; } + public string? ReferenceId { get; set; } + public TemperatureLogs LatestLog { get; set; } + } +} diff --git a/frontend/scripts/devices.js b/frontend/scripts/devices.js index f5e56d4..b76d1e3 100644 --- a/frontend/scripts/devices.js +++ b/frontend/scripts/devices.js @@ -1,14 +1,17 @@ -import { add } from "./services/devices.service.js"; +import { add, getDevices, update, deleteDevice } from "./services/devices.service.js"; import { devices } from "../mockdata/devices.mockdata.js"; import { logout } from "../shared/utils.js"; -// getDevices().then(res => { -// buildTable(res) -// }) +getDevices().then(res => { + if(!res.message){ + buildTable(res) + } +}) -buildTable(devices); - -let selectedReferenceId = null; // Store the selected referenceId +let selectedId = null; // Store the selected referenceId +const nameInput = document.getElementById("name"); +const tempHighInput = document.getElementById("tempHigh"); +const tempLowInput = document.getElementById("tempLow"); function buildTable(data) { var table = document.getElementById("deviceTable"); @@ -21,25 +24,25 @@ function buildTable(data) { ${device.name} ${device.tempHigh} ${device.tempLow} - Temperature: ${device.latestLog.temperature}°C, Date: ${device.latestLog.date} + Temperature: ${device.latestLog}°C, Date: ${device.latestLog} - - + + `; table.appendChild(row); }); + document.getElementById("addDevice").onclick = () => { document.getElementById("addModal").style.display = "block"; - } // Attach click event to all trash buttons document.querySelectorAll(".trashBtn").forEach((btn) => { btn.onclick = function () { - selectedReferenceId = this.getAttribute("data-referenceid"); // Store referenceId - document.getElementById("deleteDeviceHeader").innerHTML = `Delete Device ${selectedReferenceId}`; + selectedId = this.getAttribute("data-id"); // Store referenceId + // document.getElementById("deleteDeviceHeader").innerHTML = `Delete Device ${this.getAttribute("data-referenceId")}`; document.getElementById("deleteModal").style.display = "block"; }; }); @@ -47,13 +50,17 @@ function buildTable(data) { // Attach click event to all trash buttons document.querySelectorAll(".editIconbtn").forEach((btn) => { btn.onclick = function () { - selectedReferenceId = this.getAttribute("data-referenceid"); // Store referenceId - document.getElementById("editDeviceHeader").innerHTML = `Edit Device ${selectedReferenceId}`; + selectedId = this.getAttribute("data-id"); // Store referenceId + // document.getElementById("editDeviceHeader").innerHTML = `Edit Device ${this.getAttribute("data-referenceId")}`; + nameInput.value = this.getAttribute("data-name"); + tempHighInput.value = this.getAttribute("data-tempHigh"); + tempLowInput.value = this.getAttribute("data-tempLow"); document.getElementById("editModal").style.display = "block"; }; }); } + document.querySelectorAll(".cancelbtn").forEach(button => { button.onclick = () => { document.getElementById("deleteModal").style.display = "none"; @@ -64,9 +71,8 @@ document.querySelectorAll(".cancelbtn").forEach(button => { }); // Delete button logic document.getElementById("deletebtn").onclick = () => { - if (selectedReferenceId) { - deleteDevice(selectedReferenceId); // Call delete function with referenceId - document.getElementById("deleteModal").style.display = "none"; + if (selectedId) { + deleteDevice(selectedId); // Call delete function with referenceId window.location.reload(); } }; @@ -74,19 +80,24 @@ document.getElementById("deletebtn").onclick = () => { document.getElementById("addbtn").onclick = () => { const referenceId = document.getElementById("referenceId").value; add(referenceId); // Call delete function with referenceId - document.getElementById("deleteModal").style.display = "none"; - window.location.reload(); + window.location.reload(); }; document.getElementById("editbtn").onclick = () => { - if (selectedReferenceId) { + if (selectedId) { const name = document.getElementById("name").value; const tempHigh = document.getElementById("tempHigh").value; const tempLow = document.getElementById("tempLow").value; - update(name, tempHigh, tempLow, selectedReferenceId); // Call delete function with referenceId - document.getElementById("editModal").style.display = "none"; - window.location.reload(); + + update(selectedId, name, tempHigh, tempLow).then((response) => { + if (response?.error) { + document.getElementById("form-error").innerText = response.error; + document.getElementById("form-error").style.display = "block"; + return; + } + location.href = "/devices"; + }); } }; diff --git a/frontend/scripts/services/devices.service.js b/frontend/scripts/services/devices.service.js index d767050..f5b93a3 100644 --- a/frontend/scripts/services/devices.service.js +++ b/frontend/scripts/services/devices.service.js @@ -5,15 +5,19 @@ export function getDevices() { } export function add(referenceId) { - return request("POST", "/device/adddevice", {referenceId: referenceId}); + return request("POST", `/device/adddevice/${referenceId}`); } -export function deleteDevice(referenceId) { - return request("DELETE", "/device", {referenceId: referenceId}); +export function deleteDevice(deviceId) { + return request("DELETE", `/device/delete/${deviceId}`); } -export function update(name, temphigh, tempLow, referenceId) { - return request("PUT", "/device/edit", {name: name, temphigh: temphigh, tempLow: tempLow, referenceId: referenceId}); +export function update(deviceId, name, temphigh, tempLow) { + return request("PUT", `/device/update/${deviceId}`,{ + name, + temphigh, + tempLow + }); } export function getLogsOnDeviceId(id) {