enabled uploading images from clipboard on ticket edit.
This commit is contained in:
parent
2a3465fff8
commit
8c8de5ec34
@ -145,4 +145,41 @@ class AttachmentController {
|
||||
// remove DB row
|
||||
$db->exec('DELETE FROM attachments WHERE id =?', [$attachment_id]);
|
||||
}
|
||||
|
||||
// view attachment
|
||||
public function view($f3){
|
||||
$this->check_access($f3);
|
||||
|
||||
$attachment_id = (int) $f3->get('PARAMS.id');
|
||||
$db = $f3->get('DB');
|
||||
|
||||
$rows = $db->exec('SELECt * FROM attachments WHERE id = ?', [$attachment_id]);
|
||||
|
||||
if(!$rows){
|
||||
$f3->error(404, "File not found");
|
||||
return;
|
||||
}
|
||||
|
||||
$attachment = $rows[0];
|
||||
$file_path = $attachment['path'];
|
||||
$file_name = $attachment['file_name'];
|
||||
|
||||
if(!file_exists($file_path)){
|
||||
$f3->error(404, "File not found");
|
||||
return;
|
||||
}
|
||||
|
||||
// detect mime type
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime_type = finfo_file($finfo, $file_path);
|
||||
finfo_close($finfo);
|
||||
|
||||
header('Content-Type: ' . $mime_type);
|
||||
header('Content-Disposition: inline; filename="' . basename($file_name) . '"');
|
||||
header('Content-Length: ' . filesize($file_path));
|
||||
|
||||
flush();
|
||||
readfile($file_path);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
89
ui/parts/clipboard.html
Normal file
89
ui/parts/clipboard.html
Normal file
@ -0,0 +1,89 @@
|
||||
<div class="block">
|
||||
<style>
|
||||
#upload-area {
|
||||
height: 250px;
|
||||
border: 2px dashed #aaa;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
color: #555;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#upload-area.hover {
|
||||
background-color: #f0f0f0;
|
||||
border-color: #444;
|
||||
}
|
||||
|
||||
#preview {
|
||||
max-width:100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="upload-area" contenteditable="true">
|
||||
Paste or drag an image here
|
||||
</div>
|
||||
<img id="preview" alt="image preview" hidden>
|
||||
<p id="status"></p>
|
||||
|
||||
<script>
|
||||
const area = document.getElementById('upload-area');
|
||||
const preview = document.getElementById('preview');
|
||||
const status = document.getElementById('status');
|
||||
|
||||
async function uploadImage(file){
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
preview.src = reader.result;
|
||||
preview.hidden = false;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('attachment', file);
|
||||
|
||||
try {
|
||||
const res = await fetch('/ticket/{{@ticket->id}}/attachments/upload', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
const text = await res.text();
|
||||
status.textContent = text;
|
||||
} catch (e) {
|
||||
status.textContent = 'upload failed.'
|
||||
}
|
||||
}
|
||||
|
||||
// paste
|
||||
area.addEventListener('paste', (e) => {
|
||||
for(let item of e.clipboardData.items){
|
||||
if(item.type.startsWith('image/')){
|
||||
uploadImage(item.getAsFile());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// drag and drop
|
||||
area.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
area.classList.add('hover');
|
||||
});
|
||||
|
||||
area.addEventListener('dragLeave', ()=> {
|
||||
area.classList.remove('hover');
|
||||
});
|
||||
|
||||
area.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
area.classList.remove('hover');
|
||||
const files = e.dataTransfer.files;
|
||||
for(let file of files){
|
||||
if(file.type.startsWith('image/')){
|
||||
uploadImage(file);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
@ -28,6 +28,12 @@
|
||||
</repeat>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<div>
|
||||
<repeat group="{{ @attachments }}" value="{{ @attach }}">
|
||||
<img src="/attachment/{{@attach.id}}/view">
|
||||
</repeat>
|
||||
</div>
|
||||
</check>
|
||||
</check>
|
||||
<div class="block">
|
||||
|
||||
@ -4,9 +4,10 @@
|
||||
<form action="/ticket/create" method="POST">
|
||||
|
||||
<bulma type="H_FIELD_INPUT" label="Title:" name="title" value=""></bulma>
|
||||
<bulma type="H_FIELD_INPUT" label="Created At:" name="created_at" value=""></bulma>
|
||||
<bulma type="H_FIELD_TEXTAREA" label="Description:" name="description" value=""></bulma>
|
||||
|
||||
|
||||
<!-- TODO implement priority and status -->
|
||||
<bulma type="H_FIELD_SELECT" label="Priority:" name="priority" options="['Low', 'Medium', 'High']" selected="Medium"></bulma>
|
||||
<bulma type="H_FIELD_SELECT" label="Status:" name="status" options="['New', 'In Progress', 'On Hold', 'Completed']" selected="New"></bulma>
|
||||
|
||||
|
||||
@ -3,12 +3,14 @@
|
||||
<form action="/ticket/{{ @PARAMS.id }}/update" method="POST">
|
||||
|
||||
<bulma type="H_FIELD_INPUT" label="Title:" name="title" value="{{@ticket.title}}"></bulma>
|
||||
<bulma type="H_FIELD_INPUT" label="Created At:" name="created_at" value="{{@ticket.created_at}}"></bulma>
|
||||
<bulma type="H_FIELD_TEXTAREA" label="Description:" name="description" value="{{@ticket.description}}"></bulma>
|
||||
|
||||
|
||||
<bulma type="H_FIELD_SELECT" label="Priority:" name="priority" options="['Low', 'Medium', 'High']" selected="{{@ticket.priority}}"></bulma>
|
||||
<bulma type="H_FIELD_SELECT" label="Status:" name="status" options="['New', 'In Progress', 'On Hold', 'Completed']" selected="{{@ticket.status}}"></bulma>
|
||||
|
||||
<include href="/ui/parts/clipboard.html"></include>
|
||||
|
||||
<div class="block">
|
||||
<h3 class="title is-5">Custom Fields</h3>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user