message
This commit is contained in:
parent
1f4ad77acc
commit
4e377f5a72
BIN
He-Anlage 2024_1.Halbjahr.ods
Normal file
BIN
He-Anlage 2024_1.Halbjahr.ods
Normal file
Binary file not shown.
BIN
db.sqlite3
Normal file
BIN
db.sqlite3
Normal file
Binary file not shown.
@ -19,5 +19,5 @@ from django.urls import path, include
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls), # Admin site
|
path('admin/', admin.site.urls), # Admin site
|
||||||
path('', include('sheets.urls')), # Sheets app URLs
|
path('', include('Sheets.urls')), # Sheets app URLs
|
||||||
]
|
]
|
21
sheets/migrations/0006_client.py
Normal file
21
sheets/migrations/0006_client.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Generated by Django 5.1.5 on 2025-04-08 11:23
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sheets', '0005_secondtableentry'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Client',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=100)),
|
||||||
|
('address', models.TextField()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
@ -1,5 +1,12 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
class Client(models.Model):
|
||||||
|
name = models.CharField(max_length=100)
|
||||||
|
address = models.TextField()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
class ExcelEntry(models.Model):
|
class ExcelEntry(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
age = models.IntegerField()
|
age = models.IntegerField()
|
||||||
|
22
sheets/templates/base.html
Normal file
22
sheets/templates/base.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{% block title %}My App{% endblock %}</title>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" />
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f4f4f9;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
282
sheets/templates/clients_table.html
Normal file
282
sheets/templates/clients_table.html
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Clients Table</title>
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f4f4f9;
|
||||||
|
}
|
||||||
|
.add-row-btn, .btn-go-back {
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.add-row-btn:hover,
|
||||||
|
.btn-go-back:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: 12px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
tr:hover {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
.actions button {
|
||||||
|
margin: 2px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.edit-btn {
|
||||||
|
background-color: #28a745;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.delete-btn {
|
||||||
|
background-color: #dc3545;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.popup {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.popup input {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.popup button {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<a href="/" class="btn-go-back">← Back to Main</a>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h2>Clients Table</h2>
|
||||||
|
<button class="add-row-btn" id="add-client">Add Client</button>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th> <!-- This is your new sequential number column -->
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Address</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for client in clients %}
|
||||||
|
<tr data-id="{{ client.id }}">
|
||||||
|
<td>{{ forloop.counter }}</td> <!-- ← this gives you 1, 2, 3... -->
|
||||||
|
<td>{{ client.id }}</td>
|
||||||
|
<td>{{ client.name }}</td>
|
||||||
|
<td>{{ client.address }}</td>
|
||||||
|
<td class="actions">
|
||||||
|
<button class="edit-btn">Edit</button>
|
||||||
|
<button class="delete-btn">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Add Client Popup -->
|
||||||
|
<div id="add-popup" class="popup">
|
||||||
|
<span class="close-btn">×</span>
|
||||||
|
<h3>Add Client</h3>
|
||||||
|
<input type="text" id="add-name" placeholder="Name">
|
||||||
|
<input type="text" id="add-address" placeholder="Address">
|
||||||
|
<button id="save-add">Add</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Edit Client Popup -->
|
||||||
|
<div id="edit-popup" class="popup">
|
||||||
|
<span class="close-btn">×</span>
|
||||||
|
<h3>Edit Client</h3>
|
||||||
|
<input type="hidden" id="edit-id">
|
||||||
|
<input type="text" id="edit-name" placeholder="Name">
|
||||||
|
<input type="text" id="edit-address" placeholder="Address">
|
||||||
|
<button id="save-edit">Save</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 30px; text-align: center;">
|
||||||
|
<a href="{% url 'table_one' %}">
|
||||||
|
<button class="add-row-btn">Go to Table One</button>
|
||||||
|
</a>
|
||||||
|
<a href="{% url 'table_two' %}">
|
||||||
|
<button class="add-row-btn">Go to Table Two</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let currentModelName = "Client";
|
||||||
|
|
||||||
|
// Open Add Popup
|
||||||
|
$('#add-client').on('click', function () {
|
||||||
|
$('#add-popup').fadeIn();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close Popups
|
||||||
|
$('.close-btn').on('click', function () {
|
||||||
|
$('.popup').fadeOut();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save Add Client
|
||||||
|
$('#save-add').on('click', function () {
|
||||||
|
let name = $('#add-name').val();
|
||||||
|
let address = $('#add-address').val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/add-entry/${currentModelName}/`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
'name': name,
|
||||||
|
'address': address,
|
||||||
|
'age': 0,
|
||||||
|
'email': 'none@example.com',
|
||||||
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
let rowCount = $('tbody tr').length + 1;
|
||||||
|
let newRow = `
|
||||||
|
<tr data-id="${response.id}">
|
||||||
|
<td>${rowCount}</td> <!-- Serial number -->
|
||||||
|
<td>${response.id}</td>
|
||||||
|
<td>${response.name}</td>
|
||||||
|
<td>${response.address}</td>
|
||||||
|
<td class="actions">
|
||||||
|
<button class="edit-btn">Edit</button>
|
||||||
|
<button class="delete-btn">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
$('tbody').append(newRow);
|
||||||
|
$('#add-popup').fadeOut();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Open Edit Popup
|
||||||
|
$(document).on('click', '.edit-btn', function () {
|
||||||
|
let row = $(this).closest('tr');
|
||||||
|
$('#edit-id').val(row.data('id'));
|
||||||
|
$('#edit-name').val(row.find('td:eq(2)').text()); // Name
|
||||||
|
$('#edit-address').val(row.find('td:eq(3)').text()); // Address
|
||||||
|
$('#edit-popup').fadeIn();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save Edit Client
|
||||||
|
$('#save-edit').on('click', function () {
|
||||||
|
let id = $('#edit-id').val();
|
||||||
|
let name = $('#edit-name').val();
|
||||||
|
let address = $('#edit-address').val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/update-entry/${currentModelName}/`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
'id': id,
|
||||||
|
'name': name,
|
||||||
|
'address': address,
|
||||||
|
'age': 0,
|
||||||
|
'email': 'none@example.com',
|
||||||
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
if (response.status === 'success') {
|
||||||
|
let row = $(`tr[data-id="${id}"]`);
|
||||||
|
row.find('td:eq(2)').text(name); // Correct column for Name
|
||||||
|
row.find('td:eq(3)').text(address); // Correct column for Address
|
||||||
|
$('#edit-popup').fadeOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete Client
|
||||||
|
$(document).on('click', '.delete-btn', function () {
|
||||||
|
let row = $(this).closest('tr');
|
||||||
|
let id = row.data('id');
|
||||||
|
|
||||||
|
if (!confirm('Are you sure you want to delete this client?')) return;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/delete-entry/${currentModelName}/`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
'id': id,
|
||||||
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
if (response.status === 'success') {
|
||||||
|
row.fadeOut(300, function () { $(this).remove(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -115,8 +115,16 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-start mb-2">
|
||||||
|
<!-- "Go to Clients" button at top-left -->
|
||||||
|
<a href="{% url 'clients_list' %}" class="btn btn-outline-primary">
|
||||||
|
⇦ Go to Clients
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Excel-like Table</h2>
|
<h2>Excel-like Table</h2>
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- First Table -->
|
<!-- First Table -->
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
@ -124,6 +132,7 @@
|
|||||||
<table id="table-1">
|
<table id="table-1">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Age</th>
|
<th>Age</th>
|
||||||
@ -135,38 +144,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for entry in entries_table1 %}
|
{% for entry in entries_table1 %}
|
||||||
<tr data-id="{{ entry.id }}">
|
<tr data-id="{{ entry.id }}">
|
||||||
<td>{{ entry.id }}</td>
|
<td>{{ forloop.counter }}</td> <!-- ← sequential number -->
|
||||||
<td>{{ entry.name }}</td>
|
|
||||||
<td>{{ entry.age }}</td>
|
|
||||||
<td>{{ entry.email }}</td>
|
|
||||||
<td>{{ entry.date_joined }}</td>
|
|
||||||
<td class="actions">
|
|
||||||
<button class="edit-btn">Edit</button>
|
|
||||||
<button class="delete-btn">Delete</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Second Table -->
|
|
||||||
<div class="table-container">
|
|
||||||
<button class="add-row-btn" id="add-row-2">Add Row</button>
|
|
||||||
<table id="table-2">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Age</th>
|
|
||||||
<th>Email</th>
|
|
||||||
<th>Date Joined</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for entry in entries_table2 %}
|
|
||||||
<tr data-id="{{ entry.id }}">
|
|
||||||
<td>{{ entry.id }}</td>
|
<td>{{ entry.id }}</td>
|
||||||
<td>{{ entry.name }}</td>
|
<td>{{ entry.name }}</td>
|
||||||
<td>{{ entry.age }}</td>
|
<td>{{ entry.age }}</td>
|
||||||
@ -215,14 +193,6 @@
|
|||||||
currentModelName = 'ExcelEntry'; // Model name for Table 1
|
currentModelName = 'ExcelEntry'; // Model name for Table 1
|
||||||
$('#add-popup').fadeIn();
|
$('#add-popup').fadeIn();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Open Add Popup for Table 2
|
|
||||||
$('#add-row-2').on('click', function () {
|
|
||||||
currentTableId = 'table-2';
|
|
||||||
currentModelName = 'SecondTableEntry'; // Model name for Table 2
|
|
||||||
$('#add-popup').fadeIn();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Close Popups
|
// Close Popups
|
||||||
$('.close-btn').on('click', function () {
|
$('.close-btn').on('click', function () {
|
||||||
$('.popup').fadeOut();
|
$('.popup').fadeOut();
|
||||||
@ -244,8 +214,10 @@
|
|||||||
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
||||||
},
|
},
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
|
let rowCount = $(`#${currentTableId} tbody tr`).length + 1;
|
||||||
let newRow = `
|
let newRow = `
|
||||||
<tr data-id="${response.id}">
|
<tr data-id="${response.id}">
|
||||||
|
<td>${rowCount}</td> <!-- serial number -->
|
||||||
<td>${response.id}</td>
|
<td>${response.id}</td>
|
||||||
<td>${response.name}</td>
|
<td>${response.name}</td>
|
||||||
<td>${response.age}</td>
|
<td>${response.age}</td>
|
||||||
@ -269,9 +241,9 @@
|
|||||||
currentTableId = row.closest('table').attr('id'); // Set current table ID
|
currentTableId = row.closest('table').attr('id'); // Set current table ID
|
||||||
currentModelName = currentTableId === 'table-1' ? 'ExcelEntry' : 'SecondTableEntry'; // Set model name
|
currentModelName = currentTableId === 'table-1' ? 'ExcelEntry' : 'SecondTableEntry'; // Set model name
|
||||||
$('#edit-id').val(row.data('id'));
|
$('#edit-id').val(row.data('id'));
|
||||||
$('#edit-name').val(row.find('td:eq(1)').text());
|
$('#edit-name').val(row.find('td:eq(2)').text()); // Name is now in column 2
|
||||||
$('#edit-age').val(row.find('td:eq(2)').text());
|
$('#edit-age').val(row.find('td:eq(3)').text()); // Age is now in column 3
|
||||||
$('#edit-email').val(row.find('td:eq(3)').text());
|
$('#edit-email').val(row.find('td:eq(4)').text()); // Email is now in column 4
|
||||||
$('#edit-popup').fadeIn();
|
$('#edit-popup').fadeIn();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -294,10 +266,10 @@
|
|||||||
},
|
},
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
if (response.status === 'success') {
|
if (response.status === 'success') {
|
||||||
let row = $(`tr[data-id="${id}"]`);
|
let row = $(`tr[data-id="${response.id}"]`);
|
||||||
row.find('td:eq(1)').text(name);
|
row.find('td:eq(2)').text(response.name);
|
||||||
row.find('td:eq(2)').text(age);
|
row.find('td:eq(3)').text(response.age);
|
||||||
row.find('td:eq(3)').text(email);
|
row.find('td:eq(4)').text(response.email);
|
||||||
$('#edit-popup').fadeOut();
|
$('#edit-popup').fadeOut();
|
||||||
} else {
|
} else {
|
||||||
alert('Failed to update entry: ' + response.message);
|
alert('Failed to update entry: ' + response.message);
|
318
sheets/templates/table_two.html
Normal file
318
sheets/templates/table_two.html
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Excel-like Table</title>
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f4f4f9;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.table-container {
|
||||||
|
width: 48%;
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: 12px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
tr:hover {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
.actions button {
|
||||||
|
margin: 2px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.edit-btn {
|
||||||
|
background-color: #28a745;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.delete-btn {
|
||||||
|
background-color: #dc3545;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.popup {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.popup input {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.popup button {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.add-row-btn {
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.add-row-btn:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-start mb-2">
|
||||||
|
<!-- "Go to Clients" button at top-left -->
|
||||||
|
<a href="{% url 'clients_list' %}" class="btn btn-outline-primary">
|
||||||
|
⇦ Go to Clients
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Excel-like Table</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Second Table -->
|
||||||
|
<div class="table-container">
|
||||||
|
<button class="add-row-btn" id="add-row-2">Add Row</button>
|
||||||
|
<table id="table-2">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Age</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Date Joined</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for entry in entries_table2 %}
|
||||||
|
<tr data-id="{{ entry.id }}">
|
||||||
|
<td>{{ forloop.counter }}</td>
|
||||||
|
<td>{{ entry.id }}</td>
|
||||||
|
<td>{{ entry.name }}</td>
|
||||||
|
<td>{{ entry.age }}</td>
|
||||||
|
<td>{{ entry.email }}</td>
|
||||||
|
<td>{{ entry.date_joined }}</td>
|
||||||
|
<td class="actions">
|
||||||
|
<button class="edit-btn">Edit</button>
|
||||||
|
<button class="delete-btn">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Add Entry Popup -->
|
||||||
|
<div id="add-popup" class="popup">
|
||||||
|
<span class="close-btn">×</span>
|
||||||
|
<h3>Add Entry</h3>
|
||||||
|
<input type="text" id="add-name" placeholder="Name">
|
||||||
|
<input type="number" id="add-age" placeholder="Age">
|
||||||
|
<input type="email" id="add-email" placeholder="Email">
|
||||||
|
<button id="save-add">Add</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Edit Entry Popup -->
|
||||||
|
<div id="edit-popup" class="popup">
|
||||||
|
<span class="close-btn">×</span>
|
||||||
|
<h3>Edit Entry</h3>
|
||||||
|
<input type="hidden" id="edit-id">
|
||||||
|
<input type="text" id="edit-name" placeholder="Name">
|
||||||
|
<input type="number" id="edit-age" placeholder="Age">
|
||||||
|
<input type="email" id="edit-email" placeholder="Email">
|
||||||
|
<button id="save-edit">Save</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
let currentTableId = null; // To track which table is being edited
|
||||||
|
let currentModelName = null; // To track which model is being used
|
||||||
|
|
||||||
|
// Open Add Popup for Table 2
|
||||||
|
$('#add-row-2').on('click', function () {
|
||||||
|
currentTableId = 'table-2';
|
||||||
|
currentModelName = 'SecondTableEntry'; // Model name for Table 2
|
||||||
|
$('#add-popup').fadeIn();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close Popups
|
||||||
|
$('.close-btn').on('click', function () {
|
||||||
|
$('.popup').fadeOut();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save Add Entry
|
||||||
|
$('#save-add').on('click', function () {
|
||||||
|
let name = $('#add-name').val();
|
||||||
|
let age = $('#add-age').val();
|
||||||
|
let email = $('#add-email').val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/add-entry/${currentModelName}/`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
'name': name,
|
||||||
|
'age': age,
|
||||||
|
'email': email,
|
||||||
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
let rowCount = $('#table-2 tbody tr').length + 1;
|
||||||
|
let newRow = `
|
||||||
|
<tr data-id="${response.id}">
|
||||||
|
<td>${rowCount}</td> <!-- Serial # -->
|
||||||
|
<td>${response.id}</td> <!-- ID -->
|
||||||
|
<td>${response.name}</td> <!-- Name -->
|
||||||
|
<td>${response.age}</td> <!-- Age -->
|
||||||
|
<td>${response.email}</td> <!-- Email -->
|
||||||
|
<td>${response.date_joined}</td> <!-- Date Joined -->
|
||||||
|
<td class="actions"> <!-- Actions -->
|
||||||
|
<button class="edit-btn">Edit</button>
|
||||||
|
<button class="delete-btn">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
$('#table-2 tbody').append(newRow);
|
||||||
|
$('#add-popup').fadeOut();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Open Edit Popup
|
||||||
|
$(document).on('click', '.edit-btn', function () {
|
||||||
|
let row = $(this).closest('tr');
|
||||||
|
currentTableId = row.closest('table').attr('id'); // Set current table ID
|
||||||
|
currentModelName = currentTableId === 'table-1' ? 'ExcelEntry' : 'SecondTableEntry'; // Set model name
|
||||||
|
$('#edit-id').val(row.data('id'));
|
||||||
|
$('#edit-name').val(row.find('td:eq(2)').text()); // Name is now in column 2
|
||||||
|
$('#edit-age').val(row.find('td:eq(3)').text()); // Age is now in column 3
|
||||||
|
$('#edit-email').val(row.find('td:eq(4)').text()); // Email is now in column 4
|
||||||
|
$('#edit-popup').fadeIn();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save Edit Entry
|
||||||
|
$('#save-edit').on('click', function () {
|
||||||
|
let id = $('#edit-id').val();
|
||||||
|
let name = $('#edit-name').val();
|
||||||
|
let age = $('#edit-age').val();
|
||||||
|
let email = $('#edit-email').val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/update-entry/${currentModelName}/`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
'id': id,
|
||||||
|
'name': name,
|
||||||
|
'age': age,
|
||||||
|
'email': email,
|
||||||
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
if (response.status === 'success') {
|
||||||
|
let row = $(`tr[data-id="${response.id}"]`);
|
||||||
|
row.find('td:eq(2)').text(response.name);
|
||||||
|
row.find('td:eq(3)').text(response.age);
|
||||||
|
row.find('td:eq(4)').text(response.email);
|
||||||
|
$('#edit-popup').fadeOut();
|
||||||
|
} else {
|
||||||
|
alert('Failed to update entry: ' + response.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
alert('Failed to update entry. Please try again.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete Entry
|
||||||
|
$(document).on('click', '.delete-btn', function () {
|
||||||
|
let row = $(this).closest('tr');
|
||||||
|
let id = row.data('id');
|
||||||
|
currentTableId = row.closest('table').attr('id'); // Set current table ID
|
||||||
|
currentModelName = currentTableId === 'table-1' ? 'ExcelEntry' : 'SecondTableEntry'; // Set model name
|
||||||
|
|
||||||
|
if (!confirm('Are you sure you want to delete this entry?')) return;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/delete-entry/${currentModelName}/`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
'id': id,
|
||||||
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
if (response.status === 'success') {
|
||||||
|
row.fadeOut(300, function () { $(this).remove(); });
|
||||||
|
} else {
|
||||||
|
alert('Failed to delete entry: ' + response.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
alert('Failed to delete entry. Please try again.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -2,7 +2,9 @@ from django.urls import path
|
|||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.excel_table_view, name='excel_table'),
|
path('', views.clients_list, name='clients_list'), # Main page
|
||||||
|
path('table-one/', views.table_one_view, name='table_one'), # Table One
|
||||||
|
path('table-two/', views.table_two_view, name='table_two'), # Table Two
|
||||||
path('add-entry/<str:model_name>/', views.add_entry, name='add_entry'),
|
path('add-entry/<str:model_name>/', views.add_entry, name='add_entry'),
|
||||||
path('update-entry/<str:model_name>/', views.update_entry, name='update_entry'),
|
path('update-entry/<str:model_name>/', views.update_entry, name='update_entry'),
|
||||||
path('delete-entry/<str:model_name>/', views.delete_entry, name='delete_entry'),
|
path('delete-entry/<str:model_name>/', views.delete_entry, name='delete_entry'),
|
||||||
|
@ -2,30 +2,42 @@ from django.shortcuts import render
|
|||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
from .models import Client
|
||||||
|
|
||||||
# View to render the table page
|
# Clients Page (Now the homepage)
|
||||||
def excel_table_view(request):
|
def clients_list(request):
|
||||||
# Fetch existing entries from both tables
|
clients = Client.objects.all().order_by('id')
|
||||||
|
return render(request, 'clients_table.html', {'clients': clients})
|
||||||
|
|
||||||
|
# Table One View (ExcelEntry)
|
||||||
|
def table_one_view(request):
|
||||||
entries_table1 = apps.get_model('sheets', 'ExcelEntry').objects.all()
|
entries_table1 = apps.get_model('sheets', 'ExcelEntry').objects.all()
|
||||||
entries_table2 = apps.get_model('sheets', 'SecondTableEntry').objects.all()
|
return render(request, 'table_one.html', {'entries_table1': entries_table1})
|
||||||
return render(request, 'excel_table.html', {
|
|
||||||
'entries_table1': entries_table1,
|
|
||||||
'entries_table2': entries_table2,
|
|
||||||
})
|
|
||||||
|
|
||||||
# Generic view to add a new row to any table
|
# Table Two View (SecondTableEntry)
|
||||||
|
def table_two_view(request):
|
||||||
|
entries_table2 = apps.get_model('sheets', 'SecondTableEntry').objects.all()
|
||||||
|
return render(request, 'table_two.html', {'entries_table2': entries_table2})
|
||||||
|
|
||||||
|
# Add Entry (Generic for all models)
|
||||||
def add_entry(request, model_name):
|
def add_entry(request, model_name):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
# Dynamically get the model
|
|
||||||
model = apps.get_model('sheets', model_name)
|
model = apps.get_model('sheets', model_name)
|
||||||
|
|
||||||
# Get data from the request
|
|
||||||
name = request.POST.get('name', 'New Name')
|
name = request.POST.get('name', 'New Name')
|
||||||
|
|
||||||
|
if model_name.lower() == 'client':
|
||||||
|
address = request.POST.get('address', '')
|
||||||
|
entry = model.objects.create(name=name, address=address)
|
||||||
|
return JsonResponse({
|
||||||
|
'id': entry.id,
|
||||||
|
'name': entry.name,
|
||||||
|
'address': entry.address,
|
||||||
|
})
|
||||||
|
|
||||||
age = int(request.POST.get('age', 0))
|
age = int(request.POST.get('age', 0))
|
||||||
email = request.POST.get('email', 'example@email.com')
|
email = request.POST.get('email', 'example@email.com')
|
||||||
|
|
||||||
# Create a new entry
|
|
||||||
entry = model.objects.create(
|
entry = model.objects.create(
|
||||||
name=name,
|
name=name,
|
||||||
age=age,
|
age=age,
|
||||||
@ -33,7 +45,6 @@ def add_entry(request, model_name):
|
|||||||
date_joined=date.today()
|
date_joined=date.today()
|
||||||
)
|
)
|
||||||
|
|
||||||
# Return the new entry as JSON response
|
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
'id': entry.id,
|
'id': entry.id,
|
||||||
'name': entry.name,
|
'name': entry.name,
|
||||||
@ -47,29 +58,35 @@ def add_entry(request, model_name):
|
|||||||
|
|
||||||
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)
|
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)
|
||||||
|
|
||||||
# Generic view to update an entry in any table
|
# Update Entry (Generic for all models)
|
||||||
def update_entry(request, model_name):
|
def update_entry(request, model_name):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
# Dynamically get the model
|
|
||||||
model = apps.get_model('sheets', model_name)
|
model = apps.get_model('sheets', model_name)
|
||||||
|
|
||||||
# Get data from the request
|
|
||||||
entry_id = int(request.POST.get('id'))
|
entry_id = int(request.POST.get('id'))
|
||||||
|
entry = model.objects.get(id=entry_id)
|
||||||
name = request.POST.get('name')
|
name = request.POST.get('name')
|
||||||
|
|
||||||
|
if model_name.lower() == 'client':
|
||||||
|
address = request.POST.get('address', '')
|
||||||
|
entry.name = name
|
||||||
|
entry.address = address
|
||||||
|
entry.save()
|
||||||
|
return JsonResponse({
|
||||||
|
'status': 'success',
|
||||||
|
'id': entry.id,
|
||||||
|
'name': entry.name,
|
||||||
|
'address': entry.address,
|
||||||
|
})
|
||||||
|
|
||||||
age = int(request.POST.get('age'))
|
age = int(request.POST.get('age'))
|
||||||
email = request.POST.get('email')
|
email = request.POST.get('email')
|
||||||
|
|
||||||
# Fetch the entry to be updated
|
|
||||||
entry = model.objects.get(id=entry_id)
|
|
||||||
|
|
||||||
# Update the entry with new data
|
|
||||||
entry.name = name
|
entry.name = name
|
||||||
entry.age = age
|
entry.age = age
|
||||||
entry.email = email
|
entry.email = email
|
||||||
entry.save()
|
entry.save()
|
||||||
|
|
||||||
# Return the updated entry as a JSON response
|
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
'status': 'success',
|
'status': 'success',
|
||||||
'id': entry.id,
|
'id': entry.id,
|
||||||
@ -86,21 +103,14 @@ def update_entry(request, model_name):
|
|||||||
|
|
||||||
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)
|
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)
|
||||||
|
|
||||||
# Generic view to delete an entry from any table
|
# Delete Entry (Generic for all models)
|
||||||
def delete_entry(request, model_name):
|
def delete_entry(request, model_name):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
# Dynamically get the model
|
|
||||||
model = apps.get_model('sheets', model_name)
|
model = apps.get_model('sheets', model_name)
|
||||||
|
|
||||||
# Get the entry ID from the request
|
|
||||||
entry_id = request.POST.get('id')
|
entry_id = request.POST.get('id')
|
||||||
|
|
||||||
# Find the entry by its ID and delete it
|
|
||||||
entry = model.objects.get(id=entry_id)
|
entry = model.objects.get(id=entry_id)
|
||||||
entry.delete()
|
entry.delete()
|
||||||
|
|
||||||
# Return success response
|
|
||||||
return JsonResponse({'status': 'success', 'message': 'Entry deleted'})
|
return JsonResponse({'status': 'success', 'message': 'Entry deleted'})
|
||||||
|
|
||||||
except model.DoesNotExist:
|
except model.DoesNotExist:
|
||||||
|
BIN
temperature_data.db
Normal file
BIN
temperature_data.db
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user