Skip to content

Commit

Permalink
First commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
engren committed Oct 4, 2024
1 parent 2d103da commit 61c8250
Show file tree
Hide file tree
Showing 14 changed files with 1,083 additions and 2 deletions.
136 changes: 134 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,134 @@
# filamentmanager
Simply web based tool for managing your 3D printer spool inventory
# Filament Manager

## Overview

**Filament Manager** is a web-based tool for organizing 3D printer filaments. It allows users to catalog filaments by brand, type, color, ideal print temperatures, and spool size. Users can also track their filament inventory and store temperature tower images for easy reference.

This application is built with PHP 8.3 and MySQL, and it uses Bootstrap for its user interface.

## Features

- Add, edit, and delete filaments with brand, material, color, and ideal print temperatures.
- Track filament inventory with multiple spool sizes (250g, 500g, 750g, 1000g, 2000g).
- Manage users with different access levels (admin and regular users).
- Profile page for users to change their password.
- Admin control panel to add or remove users.
- Secure login system with password hashing.
- Fully responsive UI with Bootstrap.

## Setup Instructions

### 1. Clone the Repository

```bash
git clone https://github.com/engren/filamentmanager.git
cd filamentmanager
```

### 2. Install Dependencies

Make sure you have **composer** installed on your system. Run the following command to install dependencies:

```bash
composer install
```

### 3. Configure the `.env` File

Create a `.env` file in the root directory of the project and add your database credentials. This file stores sensitive configuration data like database connection details.

#### Example `.env` file:

```ini
DB_HOST=localhost
DB_USER=root
DB_PASS=your_password
DB_NAME=filament_manager
```

- **DB_HOST**: The database host, usually `localhost` if it's running locally.
- **DB_USER**: The MySQL username.
- **DB_PASS**: The MySQL password.
- **DB_NAME**: The name of your database.

### 4. Create the Database and Tables

You need to create a MySQL database and set up the necessary tables for this application. Below is the SQL script to create the required tables.

#### SQL Script:

```sql
CREATE DATABASE IF NOT EXISTS filament_manager;

USE filament_manager;

CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL
);

CREATE TABLE filaments (
id INT AUTO_INCREMENT PRIMARY KEY,
brand VARCHAR(100) NOT NULL,
material VARCHAR(100) NOT NULL,
color VARCHAR(50) NOT NULL,
unique_id VARCHAR(50) NOT NULL UNIQUE,
ideal_nozzle_temp INT NOT NULL,
ideal_bed_temp INT NOT NULL,
rolls_250g INT DEFAULT 0,
rolls_500g INT DEFAULT 0,
rolls_750g INT DEFAULT 0,
rolls_1000g INT DEFAULT 0,
rolls_2000g INT DEFAULT 0,
purchase_url VARCHAR(255),
notes TEXT,
image_url VARCHAR(255)
);
```

- The **`users`** table stores user login information, including hashed passwords.
- The **`filaments`** table stores detailed information about each filament, including brand, material, color, spool size, and more.

### 5. Upload the Filament Manager Logo

Make sure to upload the **Filament Manager** logo in `.webp` format to the `/images/` directory:

- Place the logo as `filament-manager-logo.png` (or `webp`) in the `/images/` folder.

### 6. Run the Application

Once the database and `.env` file are configured, you can serve the application using your web server (Apache, Nginx, etc.). Ensure that PHP 8.3 and MySQL are properly installed and configured.

Visit the application in your browser:

```bash
http://localhost/filamentmanager
```

### 7. Default Admin User

To log in as an admin, you can manually insert an admin user into the **users** table:

```sql
INSERT INTO users (username, password) VALUES ('admin', 'hashed_password');
```

Make sure to hash the password before inserting. You can use tools like PHP's `password_hash()` to generate a hashed password:

```php
<?php
echo password_hash('your_password', PASSWORD_DEFAULT);
?>
```

## Usage

- **Admin Users**: Admin users have access to the **Manage Users** section and can add, edit, or delete users.
- **Regular Users**: Regular users can update their profile and manage filaments but cannot manage users.
- **Profile Page**: Users can change their password on the profile page.

## Support

Provided as is, but happy to assist with any questions using issues.

207 changes: 207 additions & 0 deletions add.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
<?php
session_start();
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
header("Location: login.php");
exit();
}

require_once 'vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$servername = $_ENV['DB_HOST'];
$username = $_ENV['DB_USER'];
$password = $_ENV['DB_PASS'];
$dbname = $_ENV['DB_NAME'];

$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}

$isEditing = false;
$filament = null;
$error = '';
$success = '';

if (isset($_GET['id'])) {
$id = $_GET['id'];
$isEditing = true;

$sql = "SELECT * FROM filaments WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$filament = $result->fetch_assoc();
}
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
$brand = trim($_POST['brand']);
$material = trim($_POST['material']);
$color = trim($_POST['color']);
$ideal_nozzle_temp = (int) $_POST['ideal_nozzle_temp'];
$ideal_bed_temp = (int) $_POST['ideal_bed_temp'];
$rolls_250g = (int) $_POST['rolls_250g'];
$rolls_500g = (int) $_POST['rolls_500g'];
$rolls_750g = (int) $_POST['rolls_750g'];
$rolls_1000g = (int) $_POST['rolls_1000g'];
$rolls_2000g = (int) $_POST['rolls_2000g'];
$purchase_url = trim($_POST['purchase_url']);
$notes = trim($_POST['notes']);
$image_url = '';

if (empty($brand) || empty($material) || empty($color)) {
$error = "Brand, Material, and Color are required fields.";
} elseif (!filter_var($purchase_url, FILTER_VALIDATE_URL) && !empty($purchase_url)) {
$error = "Purchase URL is invalid.";
} else {
if (isset($_FILES['image']) && $_FILES['image']['error'] == 0) {
$image_url = 'uploads/' . basename($_FILES['image']['name']);
move_uploaded_file($_FILES['image']['tmp_name'], $image_url);
}

if ($isEditing) {
$sql = "UPDATE filaments SET brand=?, material=?, color=?, ideal_nozzle_temp=?, ideal_bed_temp=?, rolls_250g=?, rolls_500g=?, rolls_750g=?, rolls_1000g=?, rolls_2000g=?, purchase_url=?, notes=?, image_url=? WHERE id=?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('ssssiissssissi', $brand, $material, $color, $ideal_nozzle_temp, $ideal_bed_temp, $rolls_250g, $rolls_500g, $rolls_750g, $rolls_1000g, $rolls_2000g, $purchase_url, $notes, $image_url, $id);
} else {
$unique_id = uniqid();
$sql = "INSERT INTO filaments (brand, material, color, unique_id, ideal_nozzle_temp, ideal_bed_temp, rolls_250g, rolls_500g, rolls_750g, rolls_1000g, rolls_2000g, purchase_url, notes, image_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param('sssssiissssiss', $brand, $material, $color, $unique_id, $ideal_nozzle_temp, $ideal_bed_temp, $rolls_250g, $rolls_500g, $rolls_750g, $rolls_1000g, $rolls_2000g, $purchase_url, $notes, $image_url);
}

if ($stmt->execute()) {
$success = $isEditing ? "Filament updated successfully!" : "Filament added successfully!";
header("Location: index.php?success=" . urlencode($success));
exit();
} else {
$error = "Error: " . $stmt->error;
}
}
}

$conn->close();
?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $isEditing ? 'Edit Filament' : 'Add Filament'; ?></title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
margin-top: 70px;
}
td, th {
vertical-align: middle;
text-align: center;
}
.nowrap {
white-space: nowrap;
}
.narrow {
width: 60px;
}
</style>
</head>
<body>

<?php include('navigation.php'); ?>

<div class="container">
<h1 class="mb-4"><?php echo $isEditing ? 'Edit Filament' : 'Add Filament'; ?></h1>

<?php if ($error): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>

<?php if ($success): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($success); ?></div>
<?php endif; ?>

<form method="POST" enctype="multipart/form-data" class="row g-3">
<div class="col-md-6">
<label for="brand" class="form-label">Brand</label>
<input type="text" class="form-control" id="brand" name="brand" value="<?php echo htmlspecialchars($filament['brand'] ?? ''); ?>" required>
</div>

<div class="col-md-6">
<label for="material" class="form-label">Material</label>
<input type="text" class="form-control" id="material" name="material" value="<?php echo htmlspecialchars($filament['material'] ?? ''); ?>" required>
</div>

<div class="col-md-6">
<label for="color" class="form-label">Color</label>
<input type="text" class="form-control" id="color" name="color" value="<?php echo htmlspecialchars($filament['color'] ?? ''); ?>" required>
</div>

<div class="col-md-6">
<label for="nozzle_temp" class="form-label">Ideal Nozzle Temperature (°C)</label>
<input type="number" class="form-control" id="nozzle_temp" name="ideal_nozzle_temp" value="<?php echo htmlspecialchars($filament['ideal_nozzle_temp'] ?? ''); ?>" required>
</div>

<div class="col-md-6">
<label for="bed_temp" class="form-label">Ideal Bed Temperature (°C)</label>
<input type="number" class="form-control" id="bed_temp" name="ideal_bed_temp" value="<?php echo htmlspecialchars($filament['ideal_bed_temp'] ?? ''); ?>" required>
</div>

<div class="col-md-6">
<label for="rolls_250g" class="form-label">250g Rolls</label>
<input type="number" class="form-control" id="rolls_250g" name="rolls_250g" value="<?php echo htmlspecialchars($filament['rolls_250g'] ?? 0); ?>">
</div>

<div class="col-md-6">
<label for="rolls_500g" class="form-label">500g Rolls</label>
<input type="number" class="form-control" id="rolls_500g" name="rolls_500g" value="<?php echo htmlspecialchars($filament['rolls_500g'] ?? 0); ?>">
</div>

<div class="col-md-6">
<label for="rolls_750g" class="form-label">750g Rolls</label>
<input type="number" class="form-control" id="rolls_750g" name="rolls_750g" value="<?php echo htmlspecialchars($filament['rolls_750g'] ?? 0); ?>">
</div>

<div class="col-md-6">
<label for="rolls_1000g" class="form-label">1000g Rolls</label>
<input type="number" class="form-control" id="rolls_1000g" name="rolls_1000g" value="<?php echo htmlspecialchars($filament['rolls_1000g'] ?? 0); ?>">
</div>

<div class="col-md-6">
<label for="rolls_2000g" class="form-label">2000g Rolls</label>
<input type="number" class="form-control" id="rolls_2000g" name="rolls_2000g" value="<?php echo htmlspecialchars($filament['rolls_2000g'] ?? 0); ?>">
</div>

<div class="col-md-12">
<label for="purchase_url" class="form-label">Purchase Location (URL)</label>
<input type="url" class="form-control" id="purchase_url" name="purchase_url" value="<?php echo htmlspecialchars($filament['purchase_url'] ?? ''); ?>">
</div>

<div class="col-md-12">
<label for="notes" class="form-label">Notes</label>
<textarea class="form-control" id="notes" name="notes" rows="3"><?php echo htmlspecialchars($filament['notes'] ?? ''); ?></textarea>
</div>

<div class="col-md-12">
<label for="image" class="form-label">Upload Image</label>
<input type="file" class="form-control" id="image" name="image">
</div>

<div class="col-md-12">
<button type="submit" class="btn btn-primary w-100"><?php echo $isEditing ? 'Update Filament' : 'Add Filament'; ?></button>
</div>
</form>
</div>
<br><br><br><br>

<?php include('footer.php'); ?>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

</body>
</html>

5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"require": {
"vlucas/phpdotenv": "^5.6"
}
}
42 changes: 42 additions & 0 deletions delete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
// Connect to MySQL
require_once __DIR__ . '/vendor/autoload.php';

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

// Access environment variables
$servername = $_ENV['DB_HOST'];
$username = $_ENV['DB_USER'];
$password = $_ENV['DB_PASS'];
$dbname = $_ENV['DB_NAME'];

$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}

// Check if the 'id' parameter is set
if (isset($_GET['id'])) {
$id = (int)$_GET['id'];

// Prepare and execute the SQL query to delete the filament
$sql = "DELETE FROM filaments WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $id);

if ($stmt->execute()) {
// Redirect back to the index.php page after deletion
header("Location: index.php?deleted=true");
exit();
} else {
echo "Error deleting record: " . $conn->error;
}

$stmt->close();
}

$conn->close();
?>

Binary file added edit-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 61c8250

Please sign in to comment.