"Mark as Done" Button
Tutorial: Creating a "Mark as Done" Button
Learn how to create a button that allows users to update a record's status to "Done" directly from a table row with a single click.
Introduction
This guide will walk you through creating a "Mark as Done" button for each row in a table view. When a user clicks this button, the record's status field will be updated in the database, and the page will refresh to show the change. This is incredibly useful for task lists, ticket systems, or any workflow where records have a status.
We will achieve this by creating a small PHP script that handles the database update and then configuring a "Custom Button" in the application settings to call this script.
Step 1: Create the Server-Side PHP Script
This PHP script is the engine of our button. It receives the record ID, performs security checks, updates the database, and sends a success or failure response back to the browser.
Create a new file named set_status_done.php inside the /custom_buttons/ directory.
File: /custom_buttons/set_status_done.php
<?php
require_once '../init.php'; // Path to init.php, one level up
/**
* Sets the status of a record to "Done".
* This script is called by a Custom Button.
* It performs security and permission checks,
* updates the record, and returns a JSON response.
*/
// --- Access Control & Security Checks ---
if (!isset($_SESSION['user'])) {
api_error_response(403, 'AUTH_REQUIRED', 'Authentication required.');
}
$table_id = (int)($_GET['table_id'] ?? 0);
$record_id = (int)($_GET['id'] ?? 0);
$sig_from_url = trim($_GET['sig'] ?? '');
if ($table_id === 0 || $record_id === 0) {
api_error_response(400, 'INVALID_INPUT', 'Table or Record ID is missing.');
}
// Validate signature to prevent URL tampering
$expected_sig = hash_hmac('sha256', "{$table_id}-{$record_id}", INVITE_SECRET_KEY);
if (!hash_equals($expected_sig, $sig_from_url)) {
api_error_response(403, 'INVALID_SIGNATURE', 'Invalid signature.');
}
try {
// --- Permission Check ---
$table_def = DBGet('custom_tables', $table_id);
if (!$table_def) {
api_error_response(404, 'NOT_FOUND', 'Table definition not found.');
}
if (!check_user_permission($table_def['table_name'], 'can_edit')) {
api_error_response(403, 'PERMISSION_DENIED', 'Permission denied to edit this record.');
}
// --- Update Record ---
// Note: Replace 'bearbeitungsstatus' with the actual technical name of your status field.
$status_field_name = 'bearbeitungsstatus';
$physical_table_name = "data_team_{$table_def['team']}_{$table_id}";
$record = DBGet($physical_table_name, $record_id, ['version']); // Fetch only the version for optimistic locking
if (!$record) {
api_error_response(404, 'NOT_FOUND', 'Record not found.');
}
// Note: Replace 'Erledigt' with the actual value for "Done" in your system.
$affected_rows = DBUpdate($physical_table_name, [$status_field_name], ['Erledigt'], $record_id, $record['version']);
if ($affected_rows > 0) {
// Minimalist success response, as the page will reload anyway.
echo json_encode(['success' => true]);
} elseif ($affected_rows === 0) {
api_error_response(409, 'CONFLICT', lang('error_concurrent_update'));
} else {
api_error_response(500, 'UPDATE_FAILED', 'Database update failed.');
}
} catch (Exception $e) {
api_error_response(500, 'INTERNAL_SERVER_ERROR', $e->getMessage());
}
exit();
bearbeitungsstatus to the technical name of your status field and Erledigt to the value you use for "Done".
Step 2: Configure the Custom Button
Now, let's create the button in the user interface that will trigger our script.
- Navigate to Settings → Custom Buttons.
- Click on New Button.
- Fill in the form with the following details:
| Field | Value | Description |
|---|---|---|
| Button Display Name | Mark as Done |
The text displayed on the button. |
| Icon | fa-check-circle |
A visual icon for the button. |
| Color | Success (Green) |
The button's color. |
| URL / JavaScript | custom_buttons/set_status_done.php |
The path to our PHP script. The system will automatically add the record and table IDs. |
| Display Context | List View (per row) |
This makes the button appear on every row in the table view. |
| Conditional Display | bearbeitungsstatus != Erledigt |
(Recommended) This condition hides the button if the status is already "Done", preventing redundant clicks. |
Save the button. It should now appear in the actions column of your table.
Step 3: How It Works
The magic happens through a combination of your new PHP script and a global JavaScript handler already present in the application (in custom_table_view.php).
- When you click the "Mark as Done" button, the browser doesn't navigate away. Instead, the global JavaScript handler intercepts the click.
- It takes the URL from the button's
hrefattribute (custom_buttons/set_status_done.php) and adds the correct `id`, `table_id`, and a security `sig`nature. - It then makes an asynchronous request (a `fetch` call) to this complete URL.
- Your PHP script runs on the server, updates the database, and returns a simple JSON response:
{"success": true}. - The JavaScript handler receives this response. Seeing that
successistrue, it executeswindow.location.reload(). - The page reloads, showing the updated data. If you have a filter active (e.g., showing only "Open" items), the newly "Done" item will correctly disappear from the view.