-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
1,083 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"require": { | ||
"vlucas/phpdotenv": "^5.6" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
?> | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.