- refactored TicketController into protected functions
- added custom fields to TicketController - attachment view
This commit is contained in:
parent
6bbfdd6017
commit
b2764a0f58
@ -2,13 +2,6 @@
|
|||||||
|
|
||||||
class TicketController {
|
class TicketController {
|
||||||
|
|
||||||
protected function check_access($f3){
|
|
||||||
if(!$f3->exists('SESSION.user')){
|
|
||||||
// $f3->set('SESSION.error', 'You don\'t have permission for this ticket.');
|
|
||||||
$f3->reroute('/login');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// list all tickts
|
// list all tickts
|
||||||
public function index($f3){
|
public function index($f3){
|
||||||
$this->check_access($f3);
|
$this->check_access($f3);
|
||||||
@ -35,24 +28,13 @@ class TicketController {
|
|||||||
$ticket_id = $f3->get('PARAMS.id');
|
$ticket_id = $f3->get('PARAMS.id');
|
||||||
$db = $f3->get('DB');
|
$db = $f3->get('DB');
|
||||||
|
|
||||||
$result = $db->exec(
|
$this->get_ticket($f3, $db, $ticket_id);
|
||||||
'SELECT t.*, u.username as created_by_name
|
$this->get_child_tickets($f3, $db, $ticket_id);
|
||||||
FROM tickets t
|
$this->get_parent_tickets($f3, $db, $ticket_id);
|
||||||
LEFT JOIN users u ON t.created_by = u.id
|
$this->get_custom_fields($f3, $db, $ticket_id);
|
||||||
WHERE t.id =? LIMIT 1',
|
|
||||||
[$ticket_id]
|
|
||||||
);
|
|
||||||
|
|
||||||
if(!$result){
|
|
||||||
// no record
|
|
||||||
$f3->set('SESSION.error', 'Ticket not found.');
|
|
||||||
$f3->reroute('/tickets');
|
|
||||||
}
|
|
||||||
|
|
||||||
$ticket = $result[0];
|
|
||||||
$f3->set('ticket', $ticket);
|
|
||||||
|
|
||||||
// render
|
// render
|
||||||
|
$f3->set('js', 'ticket_view.js');
|
||||||
$f3->set('content', '../ui/views/ticket/view.html');
|
$f3->set('content', '../ui/views/ticket/view.html');
|
||||||
echo \Template::instance()->render('../ui/templates/layout.html');
|
echo \Template::instance()->render('../ui/templates/layout.html');
|
||||||
|
|
||||||
@ -66,6 +48,7 @@ class TicketController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle POST
|
// handle POST
|
||||||
|
// including custom forms
|
||||||
public function create($f3){
|
public function create($f3){
|
||||||
$this->check_access($f3);
|
$this->check_access($f3);
|
||||||
|
|
||||||
@ -84,39 +67,31 @@ class TicketController {
|
|||||||
[$title, $description, $priority, $status, $created_by]
|
[$title, $description, $priority, $status, $created_by]
|
||||||
);
|
);
|
||||||
|
|
||||||
$f3->reroute('/tickets');
|
$ticket_id = $db->lastInserId();
|
||||||
}
|
|
||||||
|
|
||||||
protected function get_ticket_check_edit_permission($f3){
|
// custom fields
|
||||||
|
$meta_keys = $f3->get('POST.meta_key'); // eg ['department', 'category']
|
||||||
|
$meta_values = $f3->get('POST.meta_value');
|
||||||
|
|
||||||
$db = $f3->get('DB');
|
if(is_array($meta_keys) && is_array($meta_values)){
|
||||||
|
foreach($meta_keys as $index => $key){
|
||||||
$ticket_id = $f3->get('PARAMS.id');
|
$val = $meta_values[$index] ?? '';
|
||||||
$result = $db->exec('SELECT * FROM tickets WHERE id = ? LIMIT 1', [$ticket_id]);
|
if(!empty($key) && $val !== ''){
|
||||||
|
$db->exec(
|
||||||
if(!$result){
|
'INSERT INTO ticket_meta (ticket_id, meta_key, meta_value)
|
||||||
$f3->set('SESSION.error', 'Ticket not found.');
|
VALUES (?,?,?)',
|
||||||
$f3->reroute('/tickets');
|
[$ticket_id, $key, $val]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$ticket = $result[0];
|
// reroute to ticket
|
||||||
|
$f3->reroute('/ticket/'.$ticket_id);
|
||||||
// TODO: refine
|
|
||||||
$current_user = $f3->get('SESSION.user');
|
|
||||||
$is_admin = (isset($current_user['role']) && $current_user['role'] == 'admin');
|
|
||||||
$is_assigned = ($ticket['assigned_to'] == $current_user['id']);
|
|
||||||
|
|
||||||
if(!$is_admin && !$is_assigned){ // should this be ||
|
|
||||||
// if not assigned and not admin, disallow edit
|
|
||||||
$f3->set('SESSION.error', 'You do not have permission to edit this ticket.');
|
|
||||||
$f3->reroute('/tickets');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ticket;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show edit form
|
// show edit form
|
||||||
|
// including custom forms
|
||||||
public function editForm($f3){
|
public function editForm($f3){
|
||||||
$this->check_access($f3);
|
$this->check_access($f3);
|
||||||
|
|
||||||
@ -127,6 +102,15 @@ class TicketController {
|
|||||||
$ticket = $this->get_ticket_check_edit_permission($f3);
|
$ticket = $this->get_ticket_check_edit_permission($f3);
|
||||||
$f3->set('ticket', $ticket);
|
$f3->set('ticket', $ticket);
|
||||||
|
|
||||||
|
// fetch custom fields
|
||||||
|
$meta = $db->exec(
|
||||||
|
'SELECT id, meta_key, meta_value
|
||||||
|
FROM ticket_meta
|
||||||
|
WHERE ticket_id = ?',
|
||||||
|
[$ticket_id]
|
||||||
|
);
|
||||||
|
$f3->set('ticket_meta', $meta);
|
||||||
|
|
||||||
$f3->set('ticket', $ticket);
|
$f3->set('ticket', $ticket);
|
||||||
$f3->set('content', '../ui/views/ticket/edit.html');
|
$f3->set('content', '../ui/views/ticket/edit.html');
|
||||||
echo \Template::instance()->render('../ui/templates/layout.html');
|
echo \Template::instance()->render('../ui/templates/layout.html');
|
||||||
@ -155,7 +139,163 @@ class TicketController {
|
|||||||
[$title, $description, $priority, $status, $updated_by, 'NOW()', $ticket_id]
|
[$title, $description, $priority, $status, $updated_by, 'NOW()', $ticket_id]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// handle custom fields
|
||||||
|
// 1. update existing custom fields
|
||||||
|
$meta_ids = $f3->get('POST.meta_id');
|
||||||
|
$meta_keys = $f3->get('POST.meta_key');
|
||||||
|
$meta_values = $f3->get('POST.meta_value');
|
||||||
|
|
||||||
|
if(is_array($meta_ids) && is_array($meta_keys) && is_array($meta_values)){
|
||||||
|
foreach($meta_ids as $idx => $m_id){
|
||||||
|
$m_key = $meta_keys[$idx] ?? '';
|
||||||
|
$m_val = $meta_values[$idx] ?? '';
|
||||||
|
|
||||||
|
if(!empty($m_key) && $m_val !== ''){
|
||||||
|
$db->exec(
|
||||||
|
'UPDATE ticket_meta
|
||||||
|
SET meta_key = ?, meta_value=?
|
||||||
|
WHERE id = ? AND ticket_id = ?',
|
||||||
|
[$m_key, $m_val, $m_id, $ticket_id]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// delete if the user cleared it
|
||||||
|
$db->exec(
|
||||||
|
'DELETE FROM ticket_meta
|
||||||
|
WHERE id =? AND ticket_id = ?',
|
||||||
|
[$m_id, $ticket_id]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. insert new fields
|
||||||
|
$new_keys = $f3->get('POST.new_meta_key');
|
||||||
|
$new_values = $f3->get('POST.new_meta_value');
|
||||||
|
if(is_array($new_keys) && is_array($new_values)){
|
||||||
|
foreach($new_keys as $idx => $n_key){
|
||||||
|
$n_val = $new_values[$idx] ?? '';
|
||||||
|
if(!empty($n_key) && $n_val !== ''){
|
||||||
|
$db->exec(
|
||||||
|
'INSERT INTO ticket_meta (ticket_id, meta_key, meta_value)
|
||||||
|
VALUES (?,?,?)',
|
||||||
|
[$ticket_id, $n_key, $n_val]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$f3->reroute('/ticket/' . $ticket_id);
|
$f3->reroute('/ticket/' . $ticket_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// subtask
|
||||||
|
public function addSubtask($f3){
|
||||||
|
$this->check_access($f3);
|
||||||
|
|
||||||
|
$parent_id = (int) $f3->get('PARAMS.id');
|
||||||
|
$child_id = (int) $f3->get('POST.child_ticket_id');
|
||||||
|
$db = $f3->get('DB');
|
||||||
|
|
||||||
|
// TODO check that both parent and child tickets exist
|
||||||
|
// ensure you don't link a ticket to itself, etc.
|
||||||
|
|
||||||
|
// insert or ignore
|
||||||
|
$db->exec(
|
||||||
|
'INSERT IGNORE INTO ticket_relations (parent_ticket_id, child_ticket_id)
|
||||||
|
VALUES (?, ?)',
|
||||||
|
[$parent_id, $child_id]
|
||||||
|
);
|
||||||
|
$f3->reroute('/ticket/' . $parent_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function check_access($f3){
|
||||||
|
if(!$f3->exists('SESSION.user')){
|
||||||
|
// $f3->set('SESSION.error', 'You don\'t have permission for this ticket.');
|
||||||
|
$f3->reroute('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function get_ticket_check_edit_permission($f3){
|
||||||
|
|
||||||
|
$db = $f3->get('DB');
|
||||||
|
|
||||||
|
$ticket_id = $f3->get('PARAMS.id');
|
||||||
|
$result = $db->exec('SELECT * FROM tickets WHERE id = ? LIMIT 1', [$ticket_id]);
|
||||||
|
|
||||||
|
if(!$result){
|
||||||
|
$f3->set('SESSION.error', 'Ticket not found.');
|
||||||
|
$f3->reroute('/tickets');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ticket = $result[0];
|
||||||
|
|
||||||
|
// TODO: refine
|
||||||
|
$current_user = $f3->get('SESSION.user');
|
||||||
|
$is_admin = (isset($current_user['role_name']) && $current_user['role_name'] == 'admin');
|
||||||
|
$is_assigned = ($ticket['assigned_to'] == $current_user['id']);
|
||||||
|
|
||||||
|
if(!$is_admin && !$is_assigned){ // should this be ||
|
||||||
|
// if not assigned and not admin, disallow edit
|
||||||
|
$f3->set('SESSION.error', 'You do not have permission to edit this ticket.');
|
||||||
|
$f3->reroute('/tickets');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ticket;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function get_ticket($f3, $db, $ticket_id){
|
||||||
|
$result = $db->exec(
|
||||||
|
'SELECT t.*, u.username as created_by_name
|
||||||
|
FROM tickets t
|
||||||
|
LEFT JOIN users u ON t.created_by = u.id
|
||||||
|
WHERE t.id =? LIMIT 1',
|
||||||
|
[$ticket_id]
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!$result){
|
||||||
|
// no record
|
||||||
|
$f3->set('SESSION.error', 'Ticket not found.');
|
||||||
|
$f3->reroute('/tickets');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ticket = $result[0];
|
||||||
|
$f3->set('ticket', $ticket);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function get_child_tickets($f3, $db, $ticket_id){
|
||||||
|
$child_tickets = $db->exec(
|
||||||
|
'SELECT c.*
|
||||||
|
FROM ticket_relations r
|
||||||
|
INNER JOIN tickets c ON r.child_ticket_id = c.id
|
||||||
|
WHERE r.parent_ticket_id = ?',
|
||||||
|
[$ticket_id]);
|
||||||
|
$f3->set('child_tickets', $child_tickets);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function get_parent_tickets($f3, $db, $ticket_id){
|
||||||
|
$parent_tickets = $db->exec(
|
||||||
|
'SELECT p.*
|
||||||
|
FROM ticket_relations r
|
||||||
|
INNER JOIN tickets p ON r.parent_ticket_id = p.id
|
||||||
|
WHERE r.child_ticket_id = ?',
|
||||||
|
[$ticket_id]
|
||||||
|
);
|
||||||
|
$f3->set('parent_tickets', $parent_tickets);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function get_custom_fields($f3, $db, $ticket_id){
|
||||||
|
$meta = $db->exec(
|
||||||
|
'SELECT meta_key, meta_value
|
||||||
|
FROM ticket_meta
|
||||||
|
WHERE ticket_id = ?',
|
||||||
|
[$ticket_id]
|
||||||
|
);
|
||||||
|
// convert meta rows into assoc array
|
||||||
|
$meta_array = [];
|
||||||
|
foreach($meta as $m){
|
||||||
|
$meta_array[$m['meta_key']] = $m['meta_value'];
|
||||||
|
}
|
||||||
|
$f3->set('ticket_meta', $meta_array);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
48
ui/views/attachment/index.html
Normal file
48
ui/views/attachment/index.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<div class="box">
|
||||||
|
<div class="content">
|
||||||
|
<h2 class="title">Attachments</h2>
|
||||||
|
<div class="block">
|
||||||
|
<check if="isset( {{@attachments }})">
|
||||||
|
<table class="table is-fullwidth is-narrow is-striped is-hoverable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="th-icon"></th>
|
||||||
|
<th>File Name</th>
|
||||||
|
<th>Uploaded By</th>
|
||||||
|
<th>Created At</th>
|
||||||
|
<th>Version</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<repeat group="{{ @attachments }}" value="{{ @attach }}">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span class="icon"><i class="fas fa-file"></i></span>
|
||||||
|
</td>
|
||||||
|
<td><a href="/attachment/{{@attach.id}}/download">{{ @attach.file_name }}</a></td>
|
||||||
|
<td>{{ @attach.username }}</td>
|
||||||
|
<td>{{ @attach.created_at }}</td>
|
||||||
|
<td>{{ @attach.version_number }}</td>
|
||||||
|
</tr>
|
||||||
|
</repeat>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</check>
|
||||||
|
<div class="block">
|
||||||
|
<h3 class="title">Upload attachment</h3>
|
||||||
|
<form action="/ticket/{{@ticket_id}}/attachments/upload" method="POST" enctype="multipart/form-data">
|
||||||
|
<div class="field has-addons">
|
||||||
|
<div class="control has-icons-left"><!-- is-expanded -->
|
||||||
|
<input class="input" type="file" name="attachment" required>
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-file"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<button class="button" type="submit">Upload</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Loading…
x
Reference in New Issue
Block a user