Compare commits
5 Commits
bd9ddfb0d2
...
7083a55e03
| Author | SHA1 | Date | |
|---|---|---|---|
| 7083a55e03 | |||
| c14a7948a5 | |||
| 633664d035 | |||
| e25af0dca3 | |||
| a32d12f4de |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
composer.lock
|
||||
package-lock.json
|
||||
lib/
|
||||
downloads/
|
||||
public/tmp/
|
||||
@ -6,3 +7,5 @@ storage/
|
||||
public/test.php
|
||||
app/config/.env.cfg
|
||||
app/.env.cfg
|
||||
app/config/tp_servicedesk.sql
|
||||
node_modules
|
||||
|
||||
@ -61,3 +61,22 @@ POST /project/@id/update=ProjectController->update
|
||||
GET /users=UserController->index
|
||||
GET /user/@id/edit=UserController->editForm
|
||||
POST /user/@id/update=UserController->update
|
||||
|
||||
|
||||
|
||||
; admin
|
||||
GET /admin=Admin\HomeController->index
|
||||
; admin/priority
|
||||
GET /admin/priority=Admin\TicketOptionsController->listPriorities
|
||||
GET /admin/priority/create=Admin\TicketOptionsController->createPriorityForm
|
||||
POST /admin/priority/create=Admin\TicketOptionsController->createPriority
|
||||
GET /admin/priority/@id/edit=Admin\TicketController->editPriorityForm
|
||||
POST /admin/priority/@id/update=Admin\TicketController->updatePriority
|
||||
GET /admin/priority/@id/delete=Admin\TicketController->deletePriority
|
||||
; admin/status
|
||||
GET /admin/status=Admin\TicketOptionsController->listStatuses
|
||||
GET /admin/status/create=Admin\TicketOptionsController->createStatusForm
|
||||
POST /admin/status/create=Admin\TicketOptionsController->createStatus
|
||||
GET /admin/status/@id/edit=Admin\TicketController->editStatusForm
|
||||
POST /admin/status/@id/update=Admin\TicketController->updateStatus
|
||||
GET /admin/status/@id/delete=Admin\TicketController->deleteStatus
|
||||
11
app/controllers/Admin/HomeController.php
Normal file
11
app/controllers/Admin/HomeController.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Admin;
|
||||
|
||||
class HomeController extends \BaseController
|
||||
{
|
||||
public function index($f3)
|
||||
{
|
||||
$this->renderView('/ui/views/admin/index.html');
|
||||
}
|
||||
}
|
||||
36
app/controllers/Admin/TicketOptionsController.php
Normal file
36
app/controllers/Admin/TicketOptionsController.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Admin;
|
||||
|
||||
class TicketOptionsController extends \BaseController
|
||||
{
|
||||
public function listPriorities()
|
||||
{
|
||||
$this->requireLogin();
|
||||
// TODO: check admin
|
||||
|
||||
$model = new \TicketPriority($this->getDB());
|
||||
$priorities = $model->findAll();
|
||||
|
||||
$this->renderView('/ui/views/admin/priorities/index.html', [
|
||||
'priorities' => $priorities
|
||||
]);
|
||||
}
|
||||
|
||||
public function createPriorityForm()
|
||||
{
|
||||
$this->requireLogin();
|
||||
$this->renderView('/ui/views/admin/priorities/create.html');
|
||||
}
|
||||
|
||||
public function createPriority()
|
||||
{
|
||||
$this->requireLogin();
|
||||
$p = new \TicketPriority($this->getDB());
|
||||
$p->name = $this->f3->get('POST.name');
|
||||
$p->sort_order = $this->f3->get('POST.sort_order');
|
||||
$p->save();
|
||||
}
|
||||
|
||||
// TODO: editPriorityForm(), updatePriorityForm(), deletePriorityForm()
|
||||
}
|
||||
@ -3,16 +3,23 @@
|
||||
class IconsHelper extends \Prefab {
|
||||
|
||||
static public $status_icons = [
|
||||
'New' => ['fas fa-plus-circle has-text-warning', "🆕"],
|
||||
'In Progress' => ['fas fa-repeat has-text-link', "🔄"],
|
||||
'On Hold' => ['fas fa-pause-circle has-text-danger',"⏸️"],
|
||||
'Completed' => ['fas fa-check-circle has-text-success', "✅"]
|
||||
'New' => ['fas fa-circle-dot has-text-success', "🆕"],
|
||||
'In Progress' => ['fas fa-circle-play has-text-link', "🔄"],
|
||||
'On Hold' => ['fas fa-pause-circle has-text-warning',"⏸️"],
|
||||
'Completed' => ['fas fa-check-circle has-text-danger', "✅"]
|
||||
];
|
||||
|
||||
static public $priority_icons = [
|
||||
'Low' => ['fas fa-arrow-down',"🟢"],
|
||||
'Medium' => ['fas fa-minus', "🟡"],
|
||||
'High' => ['fas fa-arrow-up', "🔴"]
|
||||
'Low' => ['fas fa-circle-down',"🟢"],
|
||||
'Medium' => ['fas fa-circle-dot', "🟡"],
|
||||
'High' => ['fas fa-circle-up', "🔴"]
|
||||
];
|
||||
|
||||
static public $priority_colors = [
|
||||
'Low' => 'success',
|
||||
'Medium' => 'warning',
|
||||
'High' => 'danger',
|
||||
'' => 'info'
|
||||
];
|
||||
|
||||
static public function icons($node){
|
||||
@ -38,13 +45,21 @@ class IconsHelper extends \Prefab {
|
||||
break;
|
||||
case 'priority':
|
||||
$icon_class = IconsHelper::$priority_icons[$value] ?? ['fas fa-question-circle', "🔲"];
|
||||
$icon_color = IconsHelper::$priority_colors[$value] ?? 'info';
|
||||
break;
|
||||
default:
|
||||
$icon_class = 'fas fa-question-circle';
|
||||
}
|
||||
|
||||
if($type == 'priority'){
|
||||
// return '<p class="button"><span class="icon is-small">'
|
||||
return '<span class="icon is-medium">
|
||||
<i class="'.$icon_class[0].' fa-lg has-text-'.$icon_color.'"></i>
|
||||
</span>';
|
||||
} else {
|
||||
return '<span class="icon is-medium"><i class="'.$icon_class[0].' fa-lg"></i></span>';
|
||||
}
|
||||
return '<span class="is-size-5">'.$icon_class[1].'</span>';
|
||||
return '<i class="'.$icon_class[0].' is-size-4"></i>';
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -11,10 +11,11 @@ class Ticket extends \DB\SQL\Mapper {
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->db->exec(
|
||||
'SELECT t.* , tp.name AS priority_name, ts.name AS status_name
|
||||
'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
|
||||
ORDER BY t.created_at DESC'
|
||||
);
|
||||
|
||||
10
package.json
Normal file
10
package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"bulma": "^1.0.3"
|
||||
},
|
||||
"scripts": {
|
||||
"sass": "sass scss/main.scss public/css/main.css",
|
||||
"sass:min": "sass scss/main.scss public/css/main.min.css --style compressed",
|
||||
"sass:watch": "sass --watch scss/main.scss:public/css/main.css"
|
||||
}
|
||||
}
|
||||
21605
public/css/main.css
Normal file
21605
public/css/main.css
Normal file
File diff suppressed because it is too large
Load Diff
1
public/css/main.css.map
Normal file
1
public/css/main.css.map
Normal file
File diff suppressed because one or more lines are too long
1
public/css/main.min.css
vendored
Normal file
1
public/css/main.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/main.min.css.map
Normal file
1
public/css/main.min.css.map
Normal file
File diff suppressed because one or more lines are too long
@ -8,6 +8,8 @@ i.fa { font-weight: 100 !important ; }
|
||||
|
||||
.table th.th-icon { width: 2rem; }
|
||||
|
||||
#ticket_list .g-flex-item { border-bottom: 1px solid var(--bulma-text-soft); }
|
||||
|
||||
/* List Component */
|
||||
.list{
|
||||
--be-list-color:var(--bulma-text);
|
||||
|
||||
59
scss/components/_ticket-item.scss
Normal file
59
scss/components/_ticket-item.scss
Normal file
@ -0,0 +1,59 @@
|
||||
@use "../vendor/bulma";
|
||||
|
||||
.ticket-item {
|
||||
@extend .is-flex;
|
||||
@extend .mb-1;
|
||||
@extend .pt-1;
|
||||
@extend .pb-2;
|
||||
@extend .is-align-items-flex-start;
|
||||
border-bottom: 1px solid var(--bulma-text-90);
|
||||
|
||||
.ticket-icon {
|
||||
@extend .mr-2;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
.checkbox {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.ticket-content {
|
||||
@extend .is-flex;
|
||||
@extend .is-flex-direction-column;
|
||||
@extend .is-flex-grow-1;
|
||||
align-self: baseline;
|
||||
|
||||
.ticket-header {
|
||||
@extend .is-flex;
|
||||
@extend .is-justify-content-flex-start;
|
||||
@extend .is-flex-wrap-wrap;
|
||||
align-items: center;
|
||||
|
||||
.ticket-title {
|
||||
@extend .title;
|
||||
@extend .is-5;
|
||||
@extend .mb-1;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.tags {
|
||||
@extend .ml-2;
|
||||
}
|
||||
}
|
||||
|
||||
.ticket-meta {
|
||||
@extend .is-flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25rem;
|
||||
|
||||
p {
|
||||
@extend .subtitle;
|
||||
@extend .is-6;
|
||||
font-weight: 300;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
scss/main.scss
Normal file
5
scss/main.scss
Normal file
@ -0,0 +1,5 @@
|
||||
// import bulma
|
||||
@use "vendor/bulma";
|
||||
|
||||
// import custom components
|
||||
@use "components/ticket-item";
|
||||
3
scss/vendor/_bulma-tools.scss
vendored
Normal file
3
scss/vendor/_bulma-tools.scss
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
@use "../../node_modules/bulma/sass/utilities/" as bulma-utils;
|
||||
@use "../../node_modules/bulma/sass/helpers/" as bulma-helpers;
|
||||
@use "../../node_modules/bulma/sass/elements/" as bulma-elements;
|
||||
1
scss/vendor/_bulma.scss
vendored
Normal file
1
scss/vendor/_bulma.scss
vendored
Normal file
@ -0,0 +1 @@
|
||||
@forward "../../node_modules/bulma/bulma";
|
||||
34
ui/partials/ticket_item.html
Normal file
34
ui/partials/ticket_item.html
Normal file
@ -0,0 +1,34 @@
|
||||
<div class="ticket-item">
|
||||
<div class="ticket-icon">
|
||||
<div class="field">
|
||||
<label class="b-checkbox checkbox">
|
||||
<input type="checkbox" value="false" />
|
||||
<span class="check"></span>
|
||||
<span class="control-label"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<span class="icon is-medium"><icons type="status">{{@ticket.status_name}}</icons></span>
|
||||
</div>
|
||||
<div class="ticket-content">
|
||||
<div class="ticket-header">
|
||||
<span class="ticket-title">
|
||||
<a href="/ticket/{{ @ticket.id }}">{{ @ticket.title }}</a>
|
||||
</span>
|
||||
<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 }}">
|
||||
<span class="tag is-link">{{ @tag }}</span>
|
||||
</repeat>
|
||||
*/ ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ticket-meta">
|
||||
<p>#{{ @ticket.id }} opened {{ @ticket.created_at }} by {{ @ticket.display_name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -5,14 +5,16 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>TP ServiceDesk</title>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="/css/main.min.css">
|
||||
<!-- bulma.io-->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.2/css/bulma.min.css">
|
||||
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.2/css/bulma.min.css"> -->
|
||||
<!-- bulma helpers -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma-helpers/0.4.3/css/bulma-helpers.min.css"
|
||||
integrity="sha512-U6ELnUi7oqVEjkLmFw5r5UR5LEtvpImS/jUykBKneVhD0lxZxfJZ3k3pe003ktrtNZYungd9u3Urp2X09wKwXg=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma-checkradio@2.1/dist/css/bulma-checkradio.min.css">
|
||||
<!-- bulma-checkbox -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma-checkbox@1.2.1/css/main.min.css" integrity="sha256-wvxLpriInkhouxrLZ5oo74cJpCtZJkR9bRJwFDvdd4w=" crossorigin="anonymous">
|
||||
<!-- font awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
|
||||
integrity="sha512-Evv84Mr4kqVGRNSgIGL/F/aIDqQb7xQ2vcrdIwxfjThSH8CSR7PBEakCr51Ck+w+/U6swU2Im1vVX0SVk9ABhg=="
|
||||
|
||||
8
ui/views/admin/index.html
Normal file
8
ui/views/admin/index.html
Normal file
@ -0,0 +1,8 @@
|
||||
<h1 class="title">Admin</h1>
|
||||
<include href="/ui/session/error.html">
|
||||
<hr>
|
||||
|
||||
<section>
|
||||
<p><a href="/admin/priority">Ticket > Priorities</a></p>
|
||||
<p><a href="/admin/status">Ticket > Statuses</a></p>
|
||||
</section>
|
||||
2
ui/views/admin/priorities/create.html
Normal file
2
ui/views/admin/priorities/create.html
Normal file
@ -0,0 +1,2 @@
|
||||
<h1 class="title">Create Ticket Priority</h1>
|
||||
<p>TODO:</p>
|
||||
33
ui/views/admin/priorities/index.html
Normal file
33
ui/views/admin/priorities/index.html
Normal file
@ -0,0 +1,33 @@
|
||||
<h1 class="title">Admin: Ticket Priorities</h1>
|
||||
<include href="/ui/session/error.html">
|
||||
<p><a class="button" href="/admin/priority/create">create priority</a></p>
|
||||
<hr>
|
||||
|
||||
<table class="table is-fullwidth is-bordered">
|
||||
<thead>
|
||||
<tr class="has-background-grey">
|
||||
<th class="has-text-light">id</th>
|
||||
<th class="has-text-light">name</th>
|
||||
<th class="has-text-light">sort_order</th>
|
||||
<th class="has-text-light"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<repeat group="{{@priorities}}" value="{{@priority}}">
|
||||
<tr>
|
||||
<td>{{@priority.id}}</td>
|
||||
<td><a href="/admin/priority/{{@priority.id}}">{{@priority.name}}</a></td>
|
||||
<td>{{@priority.sort_order}}</td>
|
||||
<td>
|
||||
<a class="button is-link is-small" href="/admin/priority/{{@priority.id}}/edit">
|
||||
<i class="fa fa-edit"></i></a>
|
||||
<a class="button is-danger is-small"
|
||||
href="/admin/priority/{{@priority.id}}/delete"
|
||||
onclick="return confirm('Are you sure you want to delete this ticket?');">
|
||||
<i class="fa fa-trash-can"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</repeat>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -1,34 +1,38 @@
|
||||
<h1 class="title">Tickets</h1>
|
||||
<include href="/ui/session/error.html">
|
||||
<p><a class="button" href="/ticket/create">create ticket</a></p>
|
||||
<include href="/ui/session/error.html"></include>
|
||||
</include>
|
||||
<!-- updated design -- inspiration gitea -->
|
||||
<div class="field is-grouped">
|
||||
<div class="control is-expanded">
|
||||
<div class="field has-addons is-expanded">
|
||||
<div class="control is-expanded">
|
||||
<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 class="field">
|
||||
<div class="control">
|
||||
<p><a class="button is-primary" href="/ticket/create">create ticket</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<table class="table is-fullwidth is-bordered">
|
||||
<thead>
|
||||
<tr class="has-background-warning">
|
||||
<th>id</th><th>title</th>
|
||||
<th>status</th><th>priority</th><th>created_at</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<div id="ticket_list">
|
||||
<repeat group="{{@tickets}}" value="{{@ticket}}">
|
||||
<include href="/ui/partials/ticket_item.html"></include>
|
||||
</repeat>
|
||||
</div>
|
||||
|
||||
<tbody>
|
||||
<repeat group="{{@tickets}}" value="{{@ticket}}">
|
||||
<tr>
|
||||
<td>{{@ticket.id}}</td>
|
||||
<td><a href="/ticket/{{@ticket.id}}">{{@ticket.title}}</a></td>
|
||||
<td><icons type="status">{{@ticket.status_name}}</icons></td>
|
||||
<td><icons type="priority">{{@ticket.priority_name}}</icons></td>
|
||||
<td>{{@ticket.created_at}}</td>
|
||||
<td>
|
||||
<a class="button is-link is-small" href="/ticket/{{@ticket.id}}/edit">
|
||||
<i class="fa fa-edit"></i></a>
|
||||
<a class="button is-danger is-small"
|
||||
href="/ticket/{{@ticket.id}}/delete"
|
||||
onclick="return confirm('Are you sure you want to delete this ticket?');">
|
||||
<i class="fa fa-trash-can"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</repeat>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
/*
|
||||
<div id="ticket_list">
|
||||
<repeat group="{{@tickets}}" value="{{@ticket}}">
|
||||
<include href="/ui/views/ticket/index_row.html"></include>
|
||||
</repeat>
|
||||
</div>
|
||||
*/
|
||||
?>
|
||||
20
ui/views/ticket/index_row.html
Normal file
20
ui/views/ticket/index_row.html
Normal file
@ -0,0 +1,20 @@
|
||||
<div class="g-flex-item is-flex is-align-items-flex-start mb-1 pt-1 pb-2">
|
||||
<div class="g-flex-item-icon is-align-self-baseline mr-2">
|
||||
<label class="checkbox mr-2"><input type="checkbox"></label>
|
||||
<span class="icon is-medium"><icons type="status">{{@ticket.status_name}}</icons></span>
|
||||
</div>
|
||||
<div class="g-flex-item-main is-flex is-flex-direction-column is-flex-grow-1 is-align-self-baseline">
|
||||
<div class="g-flex-item-header is-flex is-justify-content-flex-start is-flex-wrap-wrap">
|
||||
<div class="">
|
||||
<span class="title is-5 has-text-weight-normal"><a href="/ticket/{{@ticket.id}}">{{@ticket.title}}</a></span>
|
||||
</div>
|
||||
<div class="tags ml-2">
|
||||
<!-- TODO: get tags -->
|
||||
<span class="tag is-link">tag</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-flex-item-body is-flex is-align-items-centre flex-wrap gap ">
|
||||
<p class="subtitle is-6 has-text-weight-light">#{{@ticket.id}} opened 2025-03-25 by {{@ticket.display_name}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,6 +1,12 @@
|
||||
<!-- Ticket - View -->
|
||||
<h1 class="title">{{ @ticket.title }}</h1>
|
||||
<p><a href="/ticket/{{ @ticket.id}}/edit">edit ticket</a></p>
|
||||
<div class="is-flex">
|
||||
<h1 class="title is-flex-grow-1">{{ @ticket.title }}</h1>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="content">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user