Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properties #57

Merged
merged 4 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions backend/Controllers/PropertiesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using Chemistry_Cafe_API.Models;
using Chemistry_Cafe_API.Services;

namespace Chemistry_Cafe_API.Controllers
{
[ApiController]
[Route("api/properties")]
public class PropertiesController : ControllerBase
{
private readonly PropertyService _propertyService;

public PropertiesController(PropertyService propertyService)
{
_propertyService = propertyService;
}

// GET: api/Properties
[HttpGet]
public async Task<ActionResult<IEnumerable<Property>>> GetProperties()
{
var properties = await _propertyService.GetPropertiesAsync();
return Ok(properties);
}

// GET: api/Properties/id/{id}
[HttpGet("id/{id}")]
public async Task<ActionResult<Property>> GetPropertyById(Guid id)
{
var property = await _propertyService.GetPropertyByIdAsync(id);

if (property == null)
{
return NotFound();
}

return Ok(property);
}

// POST: api/Properties
[HttpPost]
public async Task<ActionResult<Property>> CreateProperty(Property property)
{
var createdProperty = await _propertyService.CreatePropertyAsync(property);
return CreatedAtAction(nameof(GetPropertyById), new { id = createdProperty.Id }, createdProperty);
}

// PUT: api/Properties/{id}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateProperty(Guid id, Property property)
{
if (id != property.Id)
{
return BadRequest();
}

await _propertyService.UpdatePropertyAsync(property);

return NoContent();
}

// DELETE: api/Properties/{id}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProperty(Guid id)
{
await _propertyService.DeletePropertyAsync(id);
return NoContent();
}
}
}
33 changes: 33 additions & 0 deletions backend/Models/Properties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;

namespace Chemistry_Cafe_API.Models;

[Table("properties")]
public partial class Property
{
[Key]
[Column("id")]
public Guid Id { get; set; }

[Column("species_id")]
public Guid SpeciesId { get; set; }

[Column("tolerance")]
public double Tolerance { get; set; }

[Column("weight")]
public double Weight { get; set; }

[Column("concentration")]
public double Concentration { get; set; }

[Column("diffusion")]
public double Diffusion { get; set; }

[ForeignKey(nameof(SpeciesId))]
[InverseProperty("Properties")] // Assuming you have a `Species` model with a collection of `Property`
public virtual Species Species { get; set; } = null!;
}
1 change: 1 addition & 0 deletions backend/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
builder.Services.AddScoped<InitialConditionSpeciesService>();
builder.Services.AddScoped<OpenAtmosService>();
builder.Services.AddScoped<UserService>();
builder.Services.AddScoped<PropertyService>();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
Expand Down
134 changes: 134 additions & 0 deletions backend/Services/PropertyService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using Chemistry_Cafe_API.Models;
using System.Data.Common;
using MySqlConnector;

namespace Chemistry_Cafe_API.Services
{
public class PropertyService
{
private readonly MySqlDataSource _database;

public PropertyService(MySqlDataSource database)
{
_database = database;
}

public async Task<IReadOnlyList<Property>> GetPropertiesAsync()
{
using var connection = await _database.OpenConnectionAsync();
using var command = connection.CreateCommand();

command.CommandText = "SELECT * FROM properties";
return await ReadAllAsync(await command.ExecuteReaderAsync());
}

public async Task<Property?> GetPropertyByIdAsync(Guid id)
{
using var connection = await _database.OpenConnectionAsync();
using var command = connection.CreateCommand();

command.CommandText = "SELECT * FROM properties WHERE id = @id";
command.Parameters.AddWithValue("@id", id);

var result = await ReadAllAsync(await command.ExecuteReaderAsync());
return result.FirstOrDefault();
}

public async Task<Property> CreatePropertyAsync(Property property)
{
using var connection = await _database.OpenConnectionAsync();
using var transaction = await connection.BeginTransactionAsync();

try
{
// Generate a new UUID for the property
property.Id = Guid.NewGuid();

// Insert the new property
using (var insertCommand = connection.CreateCommand())
{
insertCommand.Transaction = transaction;
insertCommand.CommandText = @"
INSERT INTO properties (id, species_id, tolerance, weight, concentration, diffusion)
VALUES (@id, @species_id, @tolerance, @weight, @concentration, @diffusion);";

insertCommand.Parameters.AddWithValue("@id", property.Id.ToString());
insertCommand.Parameters.AddWithValue("@species_id", property.SpeciesId.ToString());
insertCommand.Parameters.AddWithValue("@tolerance", property.Tolerance);
insertCommand.Parameters.AddWithValue("@weight", property.Weight);
insertCommand.Parameters.AddWithValue("@concentration", property.Concentration);
insertCommand.Parameters.AddWithValue("@diffusion", property.Diffusion);

await insertCommand.ExecuteNonQueryAsync();
}

await transaction.CommitAsync();
return property;
}
catch (Exception ex)
{
await transaction.RollbackAsync();
// Log the exception for debugging
Console.Error.WriteLine($"Error creating property: {ex}");
throw; // Re-throw the exception to propagate the error
}
}

public async Task UpdatePropertyAsync(Property property)
{
using var connection = await _database.OpenConnectionAsync();
using var command = connection.CreateCommand();

command.CommandText = @"
UPDATE properties
SET species_id = @species_id,
tolerance = @tolerance,
weight = @weight,
concentration = @concentration,
diffusion = @diffusion
WHERE id = @id;";

command.Parameters.AddWithValue("@id", property.Id.ToString());
command.Parameters.AddWithValue("@species_id", property.SpeciesId.ToString());
command.Parameters.AddWithValue("@tolerance", property.Tolerance);
command.Parameters.AddWithValue("@weight", property.Weight);
command.Parameters.AddWithValue("@concentration", property.Concentration);
command.Parameters.AddWithValue("@diffusion", property.Diffusion);

await command.ExecuteNonQueryAsync();
}

public async Task DeletePropertyAsync(Guid id)
{
using var connection = await _database.OpenConnectionAsync();
using var command = connection.CreateCommand();

command.CommandText = "DELETE FROM properties WHERE id = @id";
command.Parameters.AddWithValue("@id", id.ToString());

await command.ExecuteNonQueryAsync();
}

private async Task<IReadOnlyList<Property>> ReadAllAsync(DbDataReader reader)
{
var properties = new List<Property>();
using (reader)
{
while (await reader.ReadAsync())
{
var property = new Property
{
Id = reader.GetGuid(reader.GetOrdinal("id")),
SpeciesId = reader.GetGuid(reader.GetOrdinal("species_id")),
Tolerance = reader.GetDouble(reader.GetOrdinal("tolerance")),
Weight = reader.GetDouble(reader.GetOrdinal("weight")),
Concentration = reader.GetDouble(reader.GetOrdinal("concentration")),
Diffusion = reader.GetDouble(reader.GetOrdinal("diffusion"))
};
properties.Add(property);
}
}
return properties;
}
}
}
19 changes: 19 additions & 0 deletions frontend/src/API/API_CreateMethods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
MechanismSpecies,
User,
UserMechanism,
Property,
} from "./API_Interfaces";

export async function createFamily(familyData: Family) {
Expand Down Expand Up @@ -180,3 +181,21 @@ export async function addUserToMechanism(userMechanismData: UserMechanism) {
throw error;
}
}

export async function createProperty(propertyData: Property) {
try {
const response = await axios.post(
"http://localhost:8080/api/properties", // Adjust the URL to match your properties API endpoint
propertyData,
{
headers: {
"Content-Type": "application/json",
},
}
);
return response.data as Property;
} catch (error) {
console.error(error);
throw error;
}
}
17 changes: 17 additions & 0 deletions frontend/src/API/API_DeleteMethods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,20 @@ export async function deleteUser(id: string) {
throw error;
}
}

export async function deleteProperty(id: string) {
try {
const response = await axios.delete(
`http://localhost:8080/api/properties/${id}`,
{
headers: {
"Content-Type": "application/json",
},
}
);
return response.data;
} catch (error) {
console.error(error);
throw error;
}
}
15 changes: 14 additions & 1 deletion frontend/src/API/API_GetMethods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
Reaction,
User,
ReactionSpeciesDto,
InitialConditionSpecies
InitialConditionSpecies,
Property
} from "./API_Interfaces";

// Get all families
Expand Down Expand Up @@ -257,6 +258,18 @@ export async function getUserById(id: string): Promise<User> {
}
}

export async function getPropertyById(id: string): Promise<Property> {
try {
const response = await axios.get<Property>(
`http://localhost:8080/api/properties/id/${id}`
);
return response.data;
} catch (error) {
console.error(error);
throw error;
}
}

// Download OpenAtmos JSON for a mechanism
export async function downloadOAJSON(mechanismId?: string) {
if (!mechanismId) return "";
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/API/API_Interfaces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,13 @@ export interface UserMechanism {
mechanism_id: string;
role?: string;
}

export interface Property {
id: string; // UUID for the property entry
species_id: string; // Foreign key to the species table (UUID)
tolerance?: number; // Tolerance value (optional, as it might not be provided for every property)
weight?: number; // Weight value (optional)
concentration?: number; // Concentration value (optional)
diffusion?: number; // Diffusion value (optional)
}

21 changes: 20 additions & 1 deletion frontend/src/API/API_UpdateMethods.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// API_UpdateMethods.ts

import axios from "axios";
import { Family, Mechanism, Species, Reaction, User } from "./API_Interfaces";
import { Family, Mechanism, Species, Reaction, User, Property } from "./API_Interfaces";

// Update a family
export async function updateFamily(family: Family) {
Expand Down Expand Up @@ -96,3 +96,22 @@ export async function updateUser(id: string, user: User) {
throw error;
}
}

export async function updateProperty(property: Property) {
try {
const response = await axios.put(
`http://localhost:8080/api/properties/${property.id}`,
property,
{
headers: {
"Content-Type": "application/json",
},
}
);
return response.data as Property;
} catch (error) {
console.error(error);
throw error;
}
}

Loading
Loading