Compare commits
No commits in common. "23cad42bc1451b2b1ce678628c67d821f6d21714" and "7083a55e0333d717f0e25f79b740e79753a00105" have entirely different histories.
23cad42bc1
...
7083a55e03
@ -46,9 +46,6 @@ POST /tag/create=TagController->create
|
|||||||
; parsedown preview
|
; parsedown preview
|
||||||
POST /parsedown/preview=ParsedownPreview->view
|
POST /parsedown/preview=ParsedownPreview->view
|
||||||
|
|
||||||
; toggle-theme
|
|
||||||
POST /toggle-theme = ThemeController->toggle
|
|
||||||
|
|
||||||
; dashboard
|
; dashboard
|
||||||
GET /dashboard=DashboardController->index
|
GET /dashboard=DashboardController->index
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
class ThemeController
|
|
||||||
{
|
|
||||||
function toggle($f3)
|
|
||||||
{
|
|
||||||
$current = $f3->get('SESSION.theme') ?: 'light';
|
|
||||||
$new_theme = ($current === 'light') ? 'dark' : 'light';
|
|
||||||
$f3->set('SESSION.theme', $new_theme);
|
|
||||||
|
|
||||||
$f3->reroute($f3->get('HEADERS.Referer') ?: '/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -9,16 +9,9 @@ class TicketController extends BaseController implements CRUD {
|
|||||||
|
|
||||||
$this->requireLogin();
|
$this->requireLogin();
|
||||||
|
|
||||||
$filter = $f3->get('GET.status');
|
|
||||||
|
|
||||||
// retrieve tickets
|
// retrieve tickets
|
||||||
$ticket_mapper = new Ticket($this->getDB());
|
$ticket_mapper = new Ticket($this->getDB());
|
||||||
|
$tickets = $ticket_mapper->findAll();
|
||||||
if($filter){
|
|
||||||
$tickets = $ticket_mapper->findFiltered($filter);
|
|
||||||
} else {
|
|
||||||
$tickets = $ticket_mapper->findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
// render
|
// render
|
||||||
$this->renderView('../ui/views/ticket/index.html',
|
$this->renderView('../ui/views/ticket/index.html',
|
||||||
@ -106,9 +99,6 @@ class TicketController extends BaseController implements CRUD {
|
|||||||
$this->f3->reroute('/tickets');
|
$this->f3->reroute('/tickets');
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
$f3->set('js', 'markdown_preview.js');
|
|
||||||
|
|
||||||
// dropdowns
|
// dropdowns
|
||||||
$priorities = (new TicketPriority($this->getDB()))->findAll();
|
$priorities = (new TicketPriority($this->getDB()))->findAll();
|
||||||
$statuses = (new TicketStatus($this->getDB()))->findAll();
|
$statuses = (new TicketStatus($this->getDB()))->findAll();
|
||||||
|
|||||||
@ -7,30 +7,24 @@ class BulmaFormHelper extends \Prefab {
|
|||||||
const H_FIELD_SELECT = 3;
|
const H_FIELD_SELECT = 3;
|
||||||
const H_FIELD_SELECT_NEW = 4;
|
const H_FIELD_SELECT_NEW = 4;
|
||||||
|
|
||||||
const FIELD_INPUT = 10;
|
|
||||||
const FIELD_TEXTAREA = 11;
|
|
||||||
const FIELD_SELECT = 13;
|
|
||||||
|
|
||||||
static public function render($node) {
|
static public function render($node) {
|
||||||
|
|
||||||
$attr = $node['@attrib'] ?? [];
|
$attr = $node['@attrib'] ?? [];
|
||||||
$type = strtoupper($attr['type']) ?? null;
|
$type = strtoupper($attr['type']) ?? null;
|
||||||
|
|
||||||
// all *
|
// all *
|
||||||
$label = $attr['label'] ?? '';
|
$label = $attr['label'];
|
||||||
$name = $attr['name'] ?? '';
|
$name = $attr['name'];
|
||||||
$value = $attr['value'] ?? '';
|
$value = isset($attr['value']) ? $attr['value'] : '';
|
||||||
$class = $attr['class'] ?? '';
|
|
||||||
// select
|
// select
|
||||||
$options = $attr['options'] ?? [];
|
$options = isset($attr['options']) ? $attr['options'] : '';
|
||||||
$selected = $attr['selected'] ?? [];
|
$selected = isset($attr['selected']) ? $attr['selected'] : '';
|
||||||
// textarea
|
//
|
||||||
$rows = $attr['rows'] ?? '';
|
|
||||||
|
|
||||||
$label = \Template::instance()->build($label);
|
$label = \Template::instance()->build($label);
|
||||||
$name = \Template::instance()->build($name);
|
$name = \Template::instance()->build($name);
|
||||||
$value = \Template::instance()->build($value);
|
$value = \Template::instance()->build($value);
|
||||||
$selected = \Template::instance()->build($selected);
|
$options_array = \Template::instance()->token($options);
|
||||||
|
|
||||||
if(defined("BulmaFormHelper::$type")){
|
if(defined("BulmaFormHelper::$type")){
|
||||||
|
|
||||||
@ -49,15 +43,6 @@ class BulmaFormHelper extends \Prefab {
|
|||||||
case BulmaFormHelper::H_FIELD_SELECT_NEW:
|
case BulmaFormHelper::H_FIELD_SELECT_NEW:
|
||||||
return BulmaFormHelper::build_h_field_select_new($attr);
|
return BulmaFormHelper::build_h_field_select_new($attr);
|
||||||
break;
|
break;
|
||||||
case BulmaFormHelper::FIELD_INPUT:
|
|
||||||
return BulmaFormHelper::build_field_input($label, $name, $value, $class);
|
|
||||||
break;
|
|
||||||
case BulmaFormHelper::FIELD_TEXTAREA:
|
|
||||||
return BulmaFormHelper::build_field_textarea($label, $name, $value, $class, $rows);
|
|
||||||
break;
|
|
||||||
case BulmaFormHelper::FIELD_SELECT:
|
|
||||||
return BulmaFormHelper::build_field_select($attr);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return '<div class="notification is-danger">Error: Bulma CSS Form TYPE ('.$type.') not defined.</div>';
|
return '<div class="notification is-danger">Error: Bulma CSS Form TYPE ('.$type.') not defined.</div>';
|
||||||
break;
|
break;
|
||||||
@ -69,132 +54,6 @@ class BulmaFormHelper extends \Prefab {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function build_field_input($label, $name, $value, $class, $rows=10){
|
|
||||||
|
|
||||||
$string_label = $label !== '' ? sprintf('<label class="label">%1$s</label>', $label) : '';
|
|
||||||
$string = '
|
|
||||||
<div class="field %4$s">
|
|
||||||
%1$s
|
|
||||||
<div class="control">
|
|
||||||
<input class="input" id="%2$s" name="%2$s" type="text" placeholder="" value="%3$s">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
';
|
|
||||||
return sprintf($string, $string_label, $name, $value, $class, $rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function build_field_textarea($label, $name, $value, $class, $rows=10)
|
|
||||||
{
|
|
||||||
$string_label = $label !== '' ? sprintf('<label class="label">%1$s</label>', $label) : '';
|
|
||||||
$string = '
|
|
||||||
<div class="field %4$s">
|
|
||||||
%1$s
|
|
||||||
<div class="control">
|
|
||||||
<textarea class="textarea" id="%2$s" name="%2$s" rows="%5$s">%3$s</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
';
|
|
||||||
return sprintf($string, $string_label, $name, $value, $class,$rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function build_h_field_textarea($label, $name, $value){
|
|
||||||
$string = '
|
|
||||||
<div class="field is-horizontal">
|
|
||||||
<div class="field-label is-normal">
|
|
||||||
<label class="label">'.$label.'</label>
|
|
||||||
</div>
|
|
||||||
<div class="field-body">
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<textarea class="textarea" id="'.$name.'" name="'.
|
|
||||||
$name.'">'.$value.'</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
';
|
|
||||||
return $string;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function build_h_field_input($label, $name, $value){
|
|
||||||
$string = '
|
|
||||||
<div class="field is-horizontal">
|
|
||||||
<div class="field-label is-normal">
|
|
||||||
<label class="label">'.$label.'</label>
|
|
||||||
</div>
|
|
||||||
<div class="field-body">
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input class="input" type="text" id="'.$name.'" name="'.
|
|
||||||
$name.'" value="'.
|
|
||||||
$value.'">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
';
|
|
||||||
return $string;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* build_field_select_new
|
|
||||||
*
|
|
||||||
* `<bulma type="H_FIELD_SELECT" label="Priority:" name="priority_id"
|
|
||||||
* options="priorities" option_value="id" option_name="name"
|
|
||||||
* selected="{{@ticket.priority_id}}"></bulma>`
|
|
||||||
*
|
|
||||||
* @param mixed $attr
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
static function build_field_select($attr)
|
|
||||||
{
|
|
||||||
$f3 = \Base::instance();
|
|
||||||
|
|
||||||
$class = $attr['class'] ?? '';
|
|
||||||
$label = $attr['label'] ?? '';
|
|
||||||
$name = $attr['name'] ?? '';
|
|
||||||
// $options_arr = $attr['options'] ?? [];
|
|
||||||
$option_value = $attr['option_value'] ?? 'id';
|
|
||||||
$option_name = $attr['option_name'] ?? 'name';
|
|
||||||
|
|
||||||
$options = \Template::instance()->token($attr['options']);
|
|
||||||
$selected = \Template::instance()->token($attr['selected']);
|
|
||||||
|
|
||||||
// TODO: label - this could be moved into a seperate function
|
|
||||||
$html_label = $label !== '' ? sprintf('<label class="label">%1$s</label>', $label) : '';
|
|
||||||
|
|
||||||
$tmp_options = '<?php echo \BulmaFormHelper::instance()->field_select('.
|
|
||||||
$options.', '.$selected.', "'.$option_value.'", "'.$option_name.'"); ?>';
|
|
||||||
|
|
||||||
$html = '
|
|
||||||
<div class="field %4$s">
|
|
||||||
%1$s
|
|
||||||
<div class="control">
|
|
||||||
<div class="select">
|
|
||||||
<select name="%3$s" id="%3$s">
|
|
||||||
%2$s
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
';
|
|
||||||
|
|
||||||
return sprintf($html, $html_label, $tmp_options, $name, $class);
|
|
||||||
}
|
|
||||||
|
|
||||||
function field_select($options, $selected, $option_value, $option_name){
|
|
||||||
$html_options = '';
|
|
||||||
foreach ($options as $option) {
|
|
||||||
$value = $option[$option_value] ?? '';
|
|
||||||
$text = $option[$option_name] ?? '';
|
|
||||||
$html_selected = ((string)$value === (string)$selected) ? ' selected="selected"' : '';
|
|
||||||
$html_option = '<option value="%s"%s>%s</option>';
|
|
||||||
$html_options .= sprintf($html_option, $value, $html_selected, $text);
|
|
||||||
}
|
|
||||||
echo $html_options;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function build_h_field_select_new($attr)
|
static function build_h_field_select_new($attr)
|
||||||
{
|
{
|
||||||
$f3 = \Base::instance();
|
$f3 = \Base::instance();
|
||||||
@ -229,7 +88,25 @@ class BulmaFormHelper extends \Prefab {
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function build_h_field_input($label, $name, $value){
|
||||||
|
$string = '
|
||||||
|
<div class="field is-horizontal">
|
||||||
|
<div class="field-label is-normal">
|
||||||
|
<label class="label">'.$label.'</label>
|
||||||
|
</div>
|
||||||
|
<div class="field-body">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="text" id="'.$name.'" name="'.
|
||||||
|
$name.'" value="'.
|
||||||
|
$value.'">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
';
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
static function build_h_field_select($label, $name, $options, $selected){
|
static function build_h_field_select($label, $name, $options, $selected){
|
||||||
$opts = json_decode(str_replace("'", '"', $options));
|
$opts = json_decode(str_replace("'", '"', $options));
|
||||||
@ -262,6 +139,25 @@ class BulmaFormHelper extends \Prefab {
|
|||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function build_h_field_textarea($label, $name, $value){
|
||||||
|
$string = '
|
||||||
|
<div class="field is-horizontal">
|
||||||
|
<div class="field-label is-normal">
|
||||||
|
<label class="label">'.$label.'</label>
|
||||||
|
</div>
|
||||||
|
<div class="field-body">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<textarea class="textarea" id="'.$name.'" name="'.
|
||||||
|
$name.'">'.$value.'</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
';
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
\Template::instance()->extend('bulma', 'BulmaFormHelper::render');
|
\Template::instance()->extend('bulma', 'BulmaFormHelper::render');
|
||||||
@ -3,17 +3,10 @@
|
|||||||
class IconsHelper extends \Prefab {
|
class IconsHelper extends \Prefab {
|
||||||
|
|
||||||
static public $status_icons = [
|
static public $status_icons = [
|
||||||
'open' => ['fas fa-circle-dot has-text-success', "🆕"],
|
'New' => ['fas fa-circle-dot has-text-success', "🆕"],
|
||||||
'in_progress' => ['fas fa-circle-play has-text-link', "🔄"],
|
'In Progress' => ['fas fa-circle-play has-text-link', "🔄"],
|
||||||
'on_hold' => ['fas fa-pause-circle has-text-warning',"⏸️"],
|
'On Hold' => ['fas fa-pause-circle has-text-warning',"⏸️"],
|
||||||
'completed' => ['fas fa-check has-text-danger', "✅"]
|
'Completed' => ['fas fa-check-circle has-text-danger', "✅"]
|
||||||
];
|
|
||||||
|
|
||||||
static public $status_names = [
|
|
||||||
'open' => 'Open',
|
|
||||||
'in_progress' => 'In Progress',
|
|
||||||
'on_hold' => 'On Hold',
|
|
||||||
'completed' => 'Completed'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
static public $priority_icons = [
|
static public $priority_icons = [
|
||||||
@ -39,15 +32,12 @@ class IconsHelper extends \Prefab {
|
|||||||
$context = $f3->hive();
|
$context = $f3->hive();
|
||||||
$inner = $tpl->token($node[0], $context);
|
$inner = $tpl->token($node[0], $context);
|
||||||
|
|
||||||
return '<?php echo IconsHelper::do_the_switch("' . $attr['type'] . '", ' . $inner . '); ?>';
|
return '<?php echo IconsHelper::do_the_switch("' . $attr['type'] . '", ' . $inner . '); ?>';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function do_the_switch($type, $value){
|
static function do_the_switch($type, $value){
|
||||||
|
|
||||||
if($value !== null) {
|
|
||||||
$value = str_replace(' ', '_', strtolower($value));
|
|
||||||
}
|
|
||||||
$icon_class = '';
|
$icon_class = '';
|
||||||
switch(strtolower($type)){
|
switch(strtolower($type)){
|
||||||
case 'status':
|
case 'status':
|
||||||
|
|||||||
@ -2,65 +2,27 @@
|
|||||||
|
|
||||||
class ParsedownTableExtension extends Parsedown
|
class ParsedownTableExtension extends Parsedown
|
||||||
{
|
{
|
||||||
protected function blockTable($Line, array $Block = null)
|
protected function blockTable($Line, ?array $Block = null)
|
||||||
{
|
{
|
||||||
// Let Parsedown do its normal 'start-of-table' parsing.
|
|
||||||
$Block = parent::blockTable($Line, $Block);
|
$Block = parent::blockTable($Line, $Block);
|
||||||
|
if(!isset($Block)){
|
||||||
// If this line didn't create or start a table, do nothing.
|
|
||||||
if (!isset($Block)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flag it so we know in blockTableComplete that this is a table block.
|
// add classes to the table element
|
||||||
$Block['isMyTable'] = true;
|
$Block['element']['attributes'] = [
|
||||||
|
'class' => 'table is-bordered',
|
||||||
return $Block;
|
];
|
||||||
}
|
|
||||||
|
|
||||||
protected function blockTableContinue($Line, array $Block)
|
|
||||||
{
|
|
||||||
// Continue letting Parsedown do its normal table parsing.
|
|
||||||
$Block = parent::blockTableContinue($Line, $Block);
|
|
||||||
return $Block;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function blockTableComplete(array $Block)
|
|
||||||
{
|
|
||||||
// Let Parsedown finalize the table structure.
|
|
||||||
// $Block = parent::blockTableComplete($Block);
|
|
||||||
// If we flagged this as our table block, wrap it now.
|
|
||||||
if (!empty($Block['isMyTable'])) {
|
|
||||||
// $Block['element'] should now be fully formed, e.g.:
|
|
||||||
// [
|
|
||||||
// 'name' => 'table',
|
|
||||||
// 'handler' => 'elements',
|
|
||||||
// 'text' => [ ... ],
|
|
||||||
// 'attributes' => [...],
|
|
||||||
// ]
|
|
||||||
|
|
||||||
// Add your custom class to the <table> itself:
|
|
||||||
if (!isset($Block['element']['attributes'])) {
|
|
||||||
$Block['element']['attributes'] = [];
|
|
||||||
}
|
|
||||||
$Block['element']['attributes']['class'] = 'table is-bordered';
|
|
||||||
|
|
||||||
// Wrap the <table> in a <div class="table-container">:
|
|
||||||
$wrapped = [
|
|
||||||
'name' => 'div',
|
|
||||||
'attributes' => [
|
|
||||||
'class' => 'table-container',
|
|
||||||
],
|
|
||||||
'handler' => 'elements',
|
|
||||||
'text' => [
|
|
||||||
$Block['element'], // the <table> itself
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
// Replace the original element with our wrapped version:
|
|
||||||
$Block['element'] = $wrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// wrap the table in a bulma div
|
||||||
|
$Block['element'] = [
|
||||||
|
'name' => 'div',
|
||||||
|
'attributes' => [
|
||||||
|
'class' => 'table-container'
|
||||||
|
],
|
||||||
|
'handler' => 'element',
|
||||||
|
'text' => $Block['element'],
|
||||||
|
];
|
||||||
return $Block;
|
return $Block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,79 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
class Tag extends \DB\SQL\Mapper
|
|
||||||
{
|
|
||||||
|
|
||||||
protected $tag_table, $tag_table_id;
|
|
||||||
|
|
||||||
function __construct($db, $type = null)
|
|
||||||
{
|
|
||||||
if($type == null){
|
|
||||||
// do tag mapping
|
|
||||||
parent::__construct($db, 'tags');
|
|
||||||
} else {
|
|
||||||
$this->tag_table = $type . '_tags';
|
|
||||||
$this->tag_table_id = $type . '_id';
|
|
||||||
parent::__construct($db, $this->tag_table);
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// VERIFY: possible issue with this?
|
|
||||||
public function getTagsFor($objects, $id_key = 'id')
|
|
||||||
{
|
|
||||||
// echo $this->get('_type_id'); exit;
|
|
||||||
// printf('<pre>%s</pre>', print_r($this,1)); exit;
|
|
||||||
if(empty($objects)) return [];
|
|
||||||
$ids = array_column($objects, $id_key);
|
|
||||||
$placeholders = implode(',', array_fill(0, count($ids), '?'));
|
|
||||||
$sql =
|
|
||||||
'SELECT tt.%1$s, t.id, t.name, t.color
|
|
||||||
FROM %2$s tt
|
|
||||||
INNER JOIN tags t ON tt.tag_id = t.id
|
|
||||||
WHERE tt.%1$s IN (%3$s)';
|
|
||||||
$sql_sprintf = sprintf($sql, $this->tag_table_id, $this->tag_table, $placeholders);
|
|
||||||
$rows = $this->db->exec($sql_sprintf, $ids);
|
|
||||||
|
|
||||||
$tags_map = [];
|
|
||||||
foreach($rows as $row)
|
|
||||||
{
|
|
||||||
$tags_map[$row[$this->tag_table_id]][] = $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($objects as &$object)
|
|
||||||
{
|
|
||||||
$object['tags'] = $tags_map[$object[$id_key]] ?? [];
|
|
||||||
}
|
|
||||||
return $objects;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTagsForID($id, $id_key = 'id')
|
|
||||||
{
|
|
||||||
$sql = 'SELECT tt.%1$s, t.id, t.name, t.color
|
|
||||||
FROM %2$s tt
|
|
||||||
INNER JOIN tags t ON tt.tag_id = t.id
|
|
||||||
WHERE tt.%1$s = ?';
|
|
||||||
$sql_sprintf = sprintf($sql, $this->tag_table_id, $this->tag_table);
|
|
||||||
$rows = $this->db->exec($sql_sprintf, $id);
|
|
||||||
return $rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findLinkedTags($id = '')
|
|
||||||
{
|
|
||||||
$sql = '
|
|
||||||
SELECT t.name, t.color
|
|
||||||
FROM `?` tt
|
|
||||||
LEFT JOIN `tags` t ON t.id = tt.id
|
|
||||||
WHERE tt.`?` = ?
|
|
||||||
';
|
|
||||||
$params = [
|
|
||||||
$this->_type,
|
|
||||||
$this->_type_id,
|
|
||||||
$id
|
|
||||||
];
|
|
||||||
return $this->db->exec($sql, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -3,7 +3,6 @@
|
|||||||
class Ticket extends \DB\SQL\Mapper {
|
class Ticket extends \DB\SQL\Mapper {
|
||||||
function __construct($db){
|
function __construct($db){
|
||||||
parent::__construct($db, 'tickets');
|
parent::__construct($db, 'tickets');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,9 +10,8 @@ class Ticket extends \DB\SQL\Mapper {
|
|||||||
*/
|
*/
|
||||||
public function findAll(): array
|
public function findAll(): array
|
||||||
{
|
{
|
||||||
$tickets = $this->db->exec(
|
return $this->db->exec(
|
||||||
'SELECT t.id, t.title, t.created_at,
|
'SELECT t.* , tp.name AS priority_name, ts.name AS status_name, u.display_name
|
||||||
tp.name AS priority_name, ts.name AS status_name, u.display_name
|
|
||||||
FROM tickets t
|
FROM tickets t
|
||||||
LEFT JOIN ticket_priorities tp ON t.priority_id = tp.id
|
LEFT JOIN ticket_priorities tp ON t.priority_id = tp.id
|
||||||
LEFT JOIN ticket_statuses ts ON t.status_id = ts.id
|
LEFT JOIN ticket_statuses ts ON t.status_id = ts.id
|
||||||
@ -21,60 +19,11 @@ class Ticket extends \DB\SQL\Mapper {
|
|||||||
WHERE t.recycled = 0
|
WHERE t.recycled = 0
|
||||||
ORDER BY t.created_at DESC'
|
ORDER BY t.created_at DESC'
|
||||||
);
|
);
|
||||||
$result = $this->getTagsForTickets($tickets);
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findFiltered(string $filter): array
|
|
||||||
{
|
|
||||||
$sql = '
|
|
||||||
SELECT t.*, tp.name AS priority_name, ts.name AS status_name, u.display_name
|
|
||||||
FROM tickets t
|
|
||||||
LEFT JOIN ticket_priorities tp ON t.priority_id = tp.id
|
|
||||||
LEFT JOIN ticket_statuses ts ON t.status_id = ts.id
|
|
||||||
LEFT JOIN users u ON t.created_by = u.id
|
|
||||||
WHERE t.recycled = 0
|
|
||||||
';
|
|
||||||
$params = [];
|
|
||||||
switch($filter){
|
|
||||||
case 'open':
|
|
||||||
$sql .= ' AND status_id = ?';
|
|
||||||
$params[] = 1;
|
|
||||||
break;
|
|
||||||
case 'in_progress':
|
|
||||||
$sql .= ' AND status_id = ?';
|
|
||||||
$params[] = 2;
|
|
||||||
break;
|
|
||||||
case 'on_hold':
|
|
||||||
$sql .= ' AND status_id = ?';
|
|
||||||
$params[] = 3;
|
|
||||||
break;
|
|
||||||
case 'completed':
|
|
||||||
$sql .= ' AND status_id = ?';
|
|
||||||
$params[] = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql .= ' ORDER BY t.created_at DESC';
|
|
||||||
$tickets = $this->db->exec($sql, $params);
|
|
||||||
$result = $this->getTagsForTickets($tickets);
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTagsForTickets(array $tickets)
|
|
||||||
{
|
|
||||||
$tag_mapper = new Tag($this->db, 'ticket');
|
|
||||||
$tickets = $tag_mapper->getTagsFor($tickets);
|
|
||||||
|
|
||||||
return $tickets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findById($id): ?Ticket
|
public function findById($id): ?Ticket
|
||||||
{
|
{
|
||||||
$this->status_name = 'SELECT name FROM ticket_statuses WHERE tickets.status_id = ticket_statuses.id';
|
|
||||||
$this->priority_name = 'SELECT name FROM ticket_priorities WHERE tickets.priority_id = ticket_priorities.id';
|
|
||||||
$this->load(['id = ?', $id]);
|
$this->load(['id = ?', $id]);
|
||||||
$this->tags = (new Tag($this->db,'ticket'))->getTagsForID($id, 'ticket_id');
|
|
||||||
return $this->dry() ? null : $this;
|
return $this->dry() ? null : $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +35,7 @@ class Ticket extends \DB\SQL\Mapper {
|
|||||||
$this->description = $data['description'] ?? '';
|
$this->description = $data['description'] ?? '';
|
||||||
//
|
//
|
||||||
$this->priority_id = $data['priority_id'] ?? null;
|
$this->priority_id = $data['priority_id'] ?? null;
|
||||||
$this->status_id = $data['status_id'] ?? null;
|
$this->status = $data['status_id'] ?? null;
|
||||||
//
|
//
|
||||||
$this->created_by = $data['created_by'] ?? null;
|
$this->created_by = $data['created_by'] ?? null;
|
||||||
$this->created_at = ($data['created_at'] == '' ? date('Y-m-d H:i:s') : $data['created_at']) ?? date('Y-m-d H:i:s');
|
$this->created_at = ($data['created_at'] == '' ? date('Y-m-d H:i:s') : $data['created_at']) ?? date('Y-m-d H:i:s');
|
||||||
|
|||||||
2
public/css/main.min.css
vendored
2
public/css/main.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,73 +0,0 @@
|
|||||||
class TabSwitcherController {
|
|
||||||
constructor({ tabSelector, contentPrefix, textareaSelector, previewUrl }) {
|
|
||||||
this.tabSelector = tabSelector;
|
|
||||||
this.contentPrefix = contentPrefix;
|
|
||||||
this.textareaSelector = textareaSelector;
|
|
||||||
this.previewUrl = previewUrl;
|
|
||||||
|
|
||||||
this.tabParent = document.querySelector(tabSelector);
|
|
||||||
this.tabLinks = this.tabParent.querySelectorAll('a');
|
|
||||||
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
|
||||||
this.tabLinks.forEach(link => {
|
|
||||||
link.addEventListener('click', (e) => this.handleTabClick(e, link));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async handleTabClick(e, link) {
|
|
||||||
e.preventDefault();
|
|
||||||
const selectedTab = link.getAttribute('data-tab');
|
|
||||||
|
|
||||||
// Update active tab
|
|
||||||
this.tabParent.querySelectorAll('li').forEach(li => li.classList.remove('is-active'));
|
|
||||||
link.parentElement.classList.add('is-active');
|
|
||||||
|
|
||||||
// Show active content
|
|
||||||
document.querySelectorAll('.tab-content').forEach(el => el.style.display = 'none');
|
|
||||||
const activeContent = document.getElementById(`${this.contentPrefix}-${selectedTab}`);
|
|
||||||
if (activeContent) activeContent.style.display = '';
|
|
||||||
|
|
||||||
if (selectedTab === 'preview') {
|
|
||||||
await this.loadPreview();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadPreview() {
|
|
||||||
const previewTarget = document.getElementById('preview-output');
|
|
||||||
if (!previewTarget) return;
|
|
||||||
|
|
||||||
previewTarget.innerHTML = `
|
|
||||||
<div class="skeleton-lines">
|
|
||||||
<div></div><div></div><div></div><div></div><div></div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
|
||||||
|
|
||||||
const textarea = document.querySelector(this.textareaSelector);
|
|
||||||
const markdown = textarea ? textarea.value : '';
|
|
||||||
|
|
||||||
const res = await fetch(this.previewUrl, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
||||||
body: `content=${encodeURIComponent(markdown)}`
|
|
||||||
});
|
|
||||||
|
|
||||||
const html = await res.text();
|
|
||||||
previewTarget.innerHTML = html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usage
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
new TabSwitcherController({
|
|
||||||
tabSelector: '.tabs',
|
|
||||||
contentPrefix: 'tab',
|
|
||||||
textareaSelector: '#description',
|
|
||||||
previewUrl: '/parsedown/preview'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
@ -28,13 +28,12 @@
|
|||||||
@extend .is-flex;
|
@extend .is-flex;
|
||||||
@extend .is-justify-content-flex-start;
|
@extend .is-justify-content-flex-start;
|
||||||
@extend .is-flex-wrap-wrap;
|
@extend .is-flex-wrap-wrap;
|
||||||
@extend .mb-1;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.ticket-title {
|
.ticket-title {
|
||||||
@extend .title;
|
@extend .title;
|
||||||
@extend .mb-0;
|
|
||||||
@extend .is-5;
|
@extend .is-5;
|
||||||
|
@extend .mb-1;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,10 +15,16 @@
|
|||||||
<span class="ticket-title">
|
<span class="ticket-title">
|
||||||
<a href="/ticket/{{ @ticket.id }}">{{ @ticket.title }}</a>
|
<a href="/ticket/{{ @ticket.id }}">{{ @ticket.title }}</a>
|
||||||
</span>
|
</span>
|
||||||
<div class="tags ml-2">
|
<div class="tags">
|
||||||
|
<div class="tags ml-2">
|
||||||
|
<!-- TODO: get tags -->
|
||||||
|
<span class="tag is-link">tag</span>
|
||||||
|
</div>
|
||||||
|
<?php /*
|
||||||
<repeat group="{{ @ticket.tags }}" value="{{ @tag }}">
|
<repeat group="{{ @ticket.tags }}" value="{{ @tag }}">
|
||||||
<span class="tag is-{{@tag.color}}">{{ @tag.name }}</span>
|
<span class="tag is-link">{{ @tag }}</span>
|
||||||
</repeat>
|
</repeat>
|
||||||
|
*/ ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ticket-meta">
|
<div class="ticket-meta">
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html data-theme="{{ @SESSION.theme ?? 'light' }}" lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
@ -52,13 +52,6 @@
|
|||||||
<div class="navbar-end">
|
<div class="navbar-end">
|
||||||
<div class="navbar-item">
|
<div class="navbar-item">
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<form id="theme-toggle-form" method="post" action="/toggle-theme" style="display:inline">
|
|
||||||
<button type="submit" id="theme-toggle-button" class="button is-small" aria-label="Toggle Theme">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fas fa-circle-half-stroke" id="theme-icon"></i>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<check if="{{ isset(@SESSION.user) }}">
|
<check if="{{ isset(@SESSION.user) }}">
|
||||||
<true>
|
<true>
|
||||||
<a class="button is-primary" href="/logout">Log Out</a>
|
<a class="button is-primary" href="/logout">Log Out</a>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h4 class="title is-4">Attachments</h4>
|
<h2 class="title">Attachments</h2>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<check if="isset( {{@attachments }})">
|
<check if="isset( {{@attachments }})">
|
||||||
<check if="count({{@attachments}}) > 0">
|
<check if="count({{@attachments}}) > 0">
|
||||||
@ -37,6 +37,7 @@
|
|||||||
</check>
|
</check>
|
||||||
</check>
|
</check>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
|
<h3 class="title">Upload attachment</h3>
|
||||||
<form action="/ticket/{{@PARAMS.id}}/attachments/upload" method="POST" enctype="multipart/form-data">
|
<form action="/ticket/{{@PARAMS.id}}/attachments/upload" method="POST" enctype="multipart/form-data">
|
||||||
<div class="field has-addons">
|
<div class="field has-addons">
|
||||||
<div class="control has-icons-left"><!-- is-expanded -->
|
<div class="control has-icons-left"><!-- is-expanded -->
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<hr>
|
<hr>
|
||||||
<div class="box" id="comments">
|
<div class="box" id="comments">
|
||||||
<h3 class="title is-3">Comments</h3>
|
<h2 class="title">Comments</h2>
|
||||||
<check if="{{ !empty(@comments) }}">
|
<check if="{{ !empty(@comments) }}">
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<repeat group="{{ @comments }}" value="{{ @comment}}">
|
<repeat group="{{ @comments }}" value="{{ @comment}}">
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<bulma type="H_FIELD_INPUT" label="Created At:" name="created_at" 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>
|
<bulma type="H_FIELD_TEXTAREA" label="Description:" name="description" value=""></bulma>
|
||||||
|
|
||||||
<!-- priority and status -->
|
<!-- TODO implement priority and status -->
|
||||||
<bulma type="H_FIELD_SELECT_NEW" label="Priority:" name="priority_id"
|
<bulma type="H_FIELD_SELECT_NEW" label="Priority:" name="priority_id"
|
||||||
options="priorities" option_value="id" option_name="name"
|
options="priorities" option_value="id" option_name="name"
|
||||||
selected="2"></bulma>
|
selected="2"></bulma>
|
||||||
|
|||||||
@ -1,141 +1,60 @@
|
|||||||
<!-- Ticket - Edit -->
|
<h1 class="title">Edit Ticket Form</h1>
|
||||||
<!-- made to look more in line with view-->
|
|
||||||
<form action="/ticket/{{ @PARAMS.id }}/update" method="POST">
|
<form action="/ticket/{{ @PARAMS.id }}/update" method="POST">
|
||||||
<div class="is-flex">
|
|
||||||
<div class="is-flex-grow-1">
|
<bulma type="H_FIELD_INPUT" label="Title:" name="title" value="{{@ticket.title}}"></bulma>
|
||||||
<bulma type="FIELD_INPUT" name="title" value="{{@ticket.title}}" class="mr-3"></bulma>
|
<bulma type="H_FIELD_INPUT" label="Created At:" name="created_at" value="{{@ticket.created_at}}"></bulma>
|
||||||
</div>
|
<bulma type="H_FIELD_TEXTAREA" label="Description:" name="description" value="{{@ticket.description}}"></bulma>
|
||||||
<div class="field is-grouped">
|
|
||||||
<!-- <p class="control"><a class="button" href="/ticket/{{ @ticket.id}}/edit">edit ticket</a></p>
|
|
||||||
<p class="control"><a class="button is-primary" href="/ticket/create">new ticket</a></p>-->
|
<bulma type="H_FIELD_SELECT_NEW" label="Priority:" name="priority_id"
|
||||||
<div class="control">
|
options="priorities" option_value="id" option_name="name"
|
||||||
<a class="button is-secondary" href="/ticket/{{ @ticket.id }}">Cancel</a>
|
selected="{{@ticket.priority_id}}"></bulma>
|
||||||
|
|
||||||
|
<bulma type="H_FIELD_SELECT_NEW" label="Status:" name="status_id"
|
||||||
|
options="statuses" option_value="id" option_name="name"
|
||||||
|
selected="@ticket.status_id"></bulma>
|
||||||
|
|
||||||
|
<include href="/ui/parts/clipboard.html"></include>
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
<h3 class="title is-5">Custom Fields</h3>
|
||||||
|
<!-- existing fields-->
|
||||||
|
<div class="block">
|
||||||
|
<repeat group="{{ @ticket_meta }}" value="{{ @m }}">
|
||||||
|
<div class="field is-grouped is-grouped-right">
|
||||||
|
<input type="hidden" name="meta_id[]" value=" {{ @m.id }}">
|
||||||
|
<div class="control">
|
||||||
|
<label class="label">Key:</label>
|
||||||
|
<input class="input" type="text" name="meta_key[]" value="{{ @m.meta_key }}"
|
||||||
|
placeholder="eg. Department">
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<label class="label">Value:</label>
|
||||||
|
<input class="input" type="text" name="meta_value[]" value="{{ @m.meta_value }}"
|
||||||
|
placeholder="eg. Finance">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</repeat>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<hr>
|
||||||
<button class="button is-primary" type="submit">Save</button>
|
<!-- adding new custom meta -->
|
||||||
</div>
|
<div class="block">
|
||||||
</div>
|
<div class="field is-grouped is-grouped-right">
|
||||||
</div>
|
<div class="control">
|
||||||
|
<label class="label">Key:</label>
|
||||||
<hr>
|
<input class="input" type="text" name="meta_key[]"
|
||||||
<div class="block">
|
placeholder="eg. Department">
|
||||||
|
</div>
|
||||||
<div class="columns">
|
<div class="control">
|
||||||
<div class="column is-two-thirds">
|
<label class="label">Value:</label>
|
||||||
|
<input class="input" type="text" name="meta_value[]"
|
||||||
<div class="block">
|
placeholder="eg. Finance">
|
||||||
<bulma type="FIELD_INPUT" label="Created At:" name="created_at" value="{{@ticket.created_at}}"></bulma>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="tabs">
|
|
||||||
<ul>
|
|
||||||
<li class="is-active">
|
|
||||||
<a data-tab="write"><span class="icon is-small">
|
|
||||||
<i class="fas fa-pen" aria-hidden="true"></i></span><span>Write</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a data-tab="preview"><span class="icon is-small">
|
|
||||||
<i class="fas fa-magnifying-glass" aria-hidden="true"></i></span><span>Preview</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="tab-write" class="tab-content block">
|
|
||||||
<bulma type="FIELD_TEXTAREA" name="description" value="{{@ticket.description}}" rows="20"></bulma>
|
|
||||||
</div>
|
|
||||||
<div id="tab-preview" class="tab-content content">
|
|
||||||
<div id="preview-output"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="column">
|
|
||||||
<div class="block">
|
|
||||||
<!-- priority and status -->
|
|
||||||
<bulma type="FIELD_SELECT" label="Priority:" name="priority_id"
|
|
||||||
options="{{@priorities}}" option_value="id" option_name="name"
|
|
||||||
selected="{{@ticket.priority_id}}"></bulma>
|
|
||||||
|
|
||||||
<bulma type="FIELD_SELECT" label="Status:" name="status_id"
|
|
||||||
options="{{@statuses}}" option_value="id" option_name="name"
|
|
||||||
selected="{{@ticket.status_id}}"></bulma>
|
|
||||||
</div>
|
|
||||||
<!-- meta data -->
|
|
||||||
<div class="block">
|
|
||||||
<table class="table is-bordered is-fullwidth">
|
|
||||||
<thead>
|
|
||||||
<tr><th class="has-width-100">Property</th><th>Value</th></tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<repeat group="{{ @ticket }}" key="{{ @key }}" value="{{ @value }}">
|
|
||||||
<check if="{{ @key !== 'description'}}">
|
|
||||||
<tr><td>{{@key}}</td> <td>{{@value}}</td></tr>
|
|
||||||
</check>
|
|
||||||
</repeat>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<!-- form to add child ticket relationships -->
|
|
||||||
<div class="box">
|
|
||||||
<h4 class="title is-4">Linked Tickets</h4>
|
|
||||||
<!-- parent -->
|
|
||||||
<?php
|
|
||||||
/*
|
|
||||||
<check if="{{ @parent_tickets }}">
|
|
||||||
<div class="block">
|
|
||||||
<h4 class="title">Parent Tickets</h4>
|
|
||||||
<ul>
|
|
||||||
<repeat group="{{ @parent_tickets }}" value="{{ @p }}">
|
|
||||||
<li><a href="/ticket/{{ @p.id }}">{{ @p.title }}</a></li>
|
|
||||||
</repeat>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</check>
|
|
||||||
<!-- child tickets -->
|
|
||||||
<check if="{{ @child_tickets }}">
|
|
||||||
<div class="block">
|
|
||||||
<h4 class="title">Child Tickets</h4>
|
|
||||||
<ul>
|
|
||||||
<repeat group="{{ @child_tickets }}" value="{{ @c }}">
|
|
||||||
<li><a href="/ticket/{{ @c.id }}">{{ @c.title }}</a></li>
|
|
||||||
</repeat>
|
|
||||||
</div>
|
|
||||||
</check>
|
|
||||||
|
|
||||||
<form action="/ticket/{{ @ticket.id }}/add-subtask" method="POST">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">Add existing ticket as child ticket (ID):</label>
|
|
||||||
<div class="control">
|
|
||||||
<input class="input" type="number" placeholder="Child Ticket ID" required
|
|
||||||
name="child_ticket_id">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<button class="button is-link" type="submit">Link</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
*/ ?>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button class="button is-primary" type="submit">Save Ticket</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<include href="../ui/views/attachment/index.html">
|
|
||||||
<include href="../ui/views/comments/view.html">
|
|
||||||
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<div class="block" id="attachments"></div>
|
|
||||||
<div class="block" id="comments"></div>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|||||||
@ -1,60 +0,0 @@
|
|||||||
<h1 class="title">Edit Ticket Form</h1>
|
|
||||||
|
|
||||||
<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_NEW" label="Priority:" name="priority_id"
|
|
||||||
options="priorities" option_value="id" option_name="name"
|
|
||||||
selected="{{@ticket.priority_id}}"></bulma>
|
|
||||||
|
|
||||||
<bulma type="H_FIELD_SELECT_NEW" label="Status:" name="status_id"
|
|
||||||
options="statuses" option_value="id" option_name="name"
|
|
||||||
selected="{{@ticket.status_id}}"></bulma>
|
|
||||||
|
|
||||||
<include href="/ui/parts/clipboard.html"></include>
|
|
||||||
|
|
||||||
<div class="block">
|
|
||||||
<h3 class="title is-5">Custom Fields</h3>
|
|
||||||
<!-- existing fields-->
|
|
||||||
<div class="block">
|
|
||||||
<repeat group="{{ @ticket_meta }}" value="{{ @m }}">
|
|
||||||
<div class="field is-grouped is-grouped-right">
|
|
||||||
<input type="hidden" name="meta_id[]" value=" {{ @m.id }}">
|
|
||||||
<div class="control">
|
|
||||||
<label class="label">Key:</label>
|
|
||||||
<input class="input" type="text" name="meta_key[]" value="{{ @m.meta_key }}"
|
|
||||||
placeholder="eg. Department">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<label class="label">Value:</label>
|
|
||||||
<input class="input" type="text" name="meta_value[]" value="{{ @m.meta_value }}"
|
|
||||||
placeholder="eg. Finance">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</repeat>
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
<!-- adding new custom meta -->
|
|
||||||
<div class="block">
|
|
||||||
<div class="field is-grouped is-grouped-right">
|
|
||||||
<div class="control">
|
|
||||||
<label class="label">Key:</label>
|
|
||||||
<input class="input" type="text" name="meta_key[]"
|
|
||||||
placeholder="eg. Department">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<label class="label">Value:</label>
|
|
||||||
<input class="input" type="text" name="meta_value[]"
|
|
||||||
placeholder="eg. Finance">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button class="button is-primary" type="submit">Save Ticket</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
@ -2,38 +2,22 @@
|
|||||||
<include href="/ui/session/error.html"></include>
|
<include href="/ui/session/error.html"></include>
|
||||||
</include>
|
</include>
|
||||||
<!-- updated design -- inspiration gitea -->
|
<!-- updated design -- inspiration gitea -->
|
||||||
<div class="block">
|
<div class="field is-grouped">
|
||||||
<div class="field is-grouped">
|
<div class="control is-expanded">
|
||||||
<div class="control is-expanded">
|
<div class="field has-addons is-expanded">
|
||||||
<div class="field has-addons is-expanded">
|
<div class="control is-expanded">
|
||||||
<div class="control is-expanded">
|
<input class="input" type="text" placeholder="Find a ticket">
|
||||||
<input class="input" type="text" placeholder="Find a ticket">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<button class="button is-info"><span class="icon"><i
|
|
||||||
class="fas fa-magnifying-glass"></i></span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<p><a class="button is-primary" href="/ticket/create">create ticket</a></p>
|
<button class="button is-info"><span class="icon"><i class="fas fa-magnifying-glass"></i></span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<p><a class="button is-primary" href="/ticket/create">create ticket</a></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="block">
|
|
||||||
<div class="field has-addons">
|
|
||||||
<!-- TODO: move this into a template -->
|
|
||||||
<repeat group="{{ IconsHelper::$status_icons}}" key="{{ @k }}" value="{{ @icon }}">
|
|
||||||
<p class="control">
|
|
||||||
<a href="{{ @PATH }}/?status={{ @k }}" class="button">
|
|
||||||
<span class="icon is-small"><i class="fas fa-{{ @icon[0] }}"></i></span>
|
|
||||||
<span>{{ IconsHelper::$status_names[@k] }}</span>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</repeat>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|||||||
@ -24,11 +24,6 @@
|
|||||||
<div class="column">
|
<div class="column">
|
||||||
<!-- meta data -->
|
<!-- meta data -->
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="tags">
|
|
||||||
<repeat group="{{ @ticket.tags }}" value="{{@tag}}">
|
|
||||||
<span class="tag is-{{@tag.color}}">{{@tag.name}}</span>
|
|
||||||
</repeat>
|
|
||||||
</div>
|
|
||||||
<table class="table is-bordered is-fullwidth">
|
<table class="table is-bordered is-fullwidth">
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th class="has-width-100">Property</th><th>Value</th></tr>
|
<tr><th class="has-width-100">Property</th><th>Value</th></tr>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user