Compare commits

..

No commits in common. "423f6ae383996f70a34072a81da4542cf443478d" and "b2764a0f5840513fafa57a59abc3dbfb049e5252" have entirely different histories.

16 changed files with 41 additions and 342 deletions

11
.gitignore vendored
View File

@ -1,7 +1,6 @@
/lib/
/downloads/
/app/.env.cfg
/public/tmp/
composer.lock
lib/
downloads/
app/.env.cfg
public/tmp/
storage/
public/test.php
/storage/

View File

@ -2,7 +2,11 @@
class AttachmentController {
use RequiresAuth;
private function check_access($f3){
if(!$f3->exists('SESSION.user')){
$f3->reroute('/login');
}
}
// list attachments
public function index($f3){

View File

@ -40,12 +40,6 @@ class AuthController {
'role' => $user['role'],
'role_name' => $user['role_name']
]);
if($f3->exists('SESSION.redirect')){
$redirect = $f3->get('SESSION.redirect');
$f3->clear('SESSION.redirect');
$f3->reroute($redirect);
}
$f3->reroute('/dashboard');
} else {
@ -55,7 +49,6 @@ class AuthController {
// if here, login failed.
$f3->set('SESSION.login_error', 'Invalid username');
}
$f3->reroute('/login');
}

View File

@ -1,8 +1,13 @@
<?php
class KBController implements CRUD {
class KBController {
use RequiresAuth;
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');
}
}
public function index($f3){

View File

@ -1,29 +0,0 @@
<?php
class ProjectController implements CRUD {
use RequiresAuth;
// list all projects
public function index($f3){
$this->check_access($f3);
$f3->set('content', '../ui/views/project/index.html');
echo \Template::instance()->render('../ui/templates/layout.html');
}
// create a new project
public function createForm($f3){
}
public function create($f3){
}
// show project details including links, tickets, events, tasks
public function view($f3){}
// update project details
public function editForm($f3){}
public function update($f3){}
}

View File

@ -1,8 +1,12 @@
<?php
class TagController implements CRUD {
class TagController {
use RequiresAuth;
protected function check_access($f3){
if(!$f3->exists('SESSION.user')){
$f3->reroute('/login');
}
}
/**
* List all tags
@ -36,20 +40,5 @@ class TagController implements CRUD {
$db->exec('INSERT IGNORE INTO tags (name, color) VALUES (?, ?)', [$name, $color]);
$f3->reroute('/tags');
}
public function view($f3)
{
}
public function editForm($f3)
{
}
public function update($f3)
{
}
}

View File

@ -1,8 +1,6 @@
<?php
class TicketController implements CRUD {
use RequiresAuth;
class TicketController {
// list all tickts
public function index($f3){
@ -24,7 +22,6 @@ class TicketController implements CRUD {
}
// view a single ticket
// TODO_PROJECTS: show a link back to the related project
public function view($f3){
$this->check_access($f3);
@ -44,7 +41,6 @@ class TicketController implements CRUD {
}
// show create form
// TODO_PROJECTS: dropdown to associate ticket with project
public function createForm($f3){
$this->check_access($f3);
$f3->set('content', '../ui/views/ticket/create.html');
@ -96,7 +92,6 @@ class TicketController implements CRUD {
// show edit form
// including custom forms
// TODO_PROJECTS: allow reasssigning or removing a project association
public function editForm($f3){
$this->check_access($f3);
@ -212,7 +207,12 @@ class TicketController implements CRUD {
$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){

View File

@ -1,11 +1,16 @@
<?php
class UserController implements CRUD {
use RequiresAuth;
class UserController {
// list all users (admin only)
protected function check_access($f3){
$current_user = $f3->get('SESSION.user');
if(!$current_user || $current_user['role_name'] !== 'admin'){
$f3->reroute('/login');
}
}
public function index($f3){
$this->check_access($f3);
@ -54,20 +59,4 @@ class UserController implements CRUD {
[$new_username, $user_id]);
$f3->reroute('/users');
}
public function createForm($f3)
{
}
public function create($f3)
{
}
public function view($f3)
{
}
}

View File

@ -3,21 +3,6 @@
class ParsedownHelper extends \Prefab {
static public function render($args) {
if(isset($args['@attrib']) && $args['@attrib']['inline'] === 'true'){
$return = \Parsedown::instance()->text($args[0]);
return '
<div class="content">
<parsedown_rendered>'.$return.'</parsedown_rendered>
</div>
';
}
return '<pre>'.print_r($args,1).'<pre>';
$content = $args[0];
$content_token = \Template::instance()->token($content);

View File

@ -1,25 +0,0 @@
<?php
interface CRUD {
// list all
public function index($f3);
// show form
public function createForm($f3);
// handle POST
public function create($f3);
// show single
public function view($f3);
// show edit form
public function editForm($f3);
// handle post
public function update($f3);
}

View File

@ -1,13 +0,0 @@
<?php
trait RequiresAuth {
public function check_access($f3){
if(!$f3->exists('SESSION.user')){
// $f3->set('SESSION.error', 'You don\'t have permission for this ticket.');
$f3->set('SESSION.redirect', $f3->get('PATH'));
$f3->reroute('/login');
}
}
}

View File

@ -84,15 +84,8 @@ $f3->route('POST /parsedown/preview', 'ParsedownPreview->view');
// dashboard
$f3->route('GET /dashboard', 'DashboardController->index');
// projects
$f3->route('GET /projects', 'ProjectController->index');
$f3->route('GET /project/@id', 'ProjectController->view');
$f3->route('GET /project/create', 'ProjectController->createForm');
$f3->route('POST /project/create', 'ProjectController->create');
$f3->route('GET /project/@id/edit', 'ProjectController->editForm');
$f3->route('POST /project/@id/update', 'ProjectController->update');
// additional routes - user
// additional routes
$f3->route('GET /users', 'UserController->index');
$f3->route('GET /user/@id/edit', 'UserController->editForm');
$f3->route('POST /user/@id/update', 'UserController->update');

View File

@ -1,62 +1,6 @@
<?php
class TicketPhraseGen {
$password = "pass!local";
private $opinion = ['amazing', 'cool', 'wicked', 'lovely'];
private $size = ['little', 'tiny', 'small', 'medium', 'large', 'huge', 'gigantic'];
private $age = ['young', 'old', 'ancient', 'new'];
private $shape = ['round', 'square', 'oval', 'long', 'short'];
private $color = ['red', 'orange', 'pink', 'blue', 'green', 'yellow', 'purple'];
private $origin = ['American', 'English', 'French', 'German', 'Spanish', 'Scottish', 'Welsh', 'Irish'];
private $material = ['wooden', 'silver', 'gold', 'plastic', 'glass'];
private $purpose = ['working', 'funny', 'serious', 'whittling'];
private $noun = ['ticket', 'device', 'gadget', 'system', 'dragon'];
public function convert_id_to_phrase(int $id): string {
$list = ['opinion', 'size', 'age', 'shape', 'color', 'origin', 'material', 'purpose', 'noun'];
$bases = [
'opinion' => count($this->opinion),
'size' => count($this->size),
'age' => count($this->age),
'shape' => count($this->shape),
'color' => count($this->color),
'origin' => count($this->origin),
'material' => count($this->material),
'purpose' => count($this->purpose),
'noun' => count($this->noun),
];
// perform mixed-radix conversion
$order = ['noun', 'purpose', 'material', 'origin', 'color', 'shape', 'age', 'size', 'opinion'];
$digits = [];
foreach($order as $category){
$radix = $bases[$category];
$digits[$category] = $id % $radix;
$id = intdiv($id, $radix);
}
if($id > 0){
throw new Exception("ID too large");
}
foreach($list as $k){
$phrase[] = $this->$k[$digits[$k]];
}
return implode('-', $phrase);
}
}
function generate(){
$generator = new TicketPhraseGen();
$ticket_number = 2;
$phrase = $generator->convert_id_to_phrase($ticket_number);
echo "Ticket #{$ticket_number} is {$phrase}";
}
generate();
function password_test(){
$password = "pass!local";
echo password_hash($password, PASSWORD_DEFAULT);
}
echo password_hash($password, PASSWORD_DEFAULT);

View File

@ -42,7 +42,6 @@
<div id="mainNavbar" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/dashboard">Dashboard</a>
<a class="navbar-item" href="/projects">Projects</a>
<a class="navbar-item" href="/tickets">Tickets</a>
<a class="navbar-item" href="/kb">Knowledge Base</a>
<a class="navbar-item" href="/tags">Tags</a>

View File

@ -1,134 +0,0 @@
<h3 class="title">Projects</h3>
<table class="table is-fullwidth is-hoverable is-bordered">
<thead>
<tr class="is-primary">
<th>ID</th>
<th>Title</th>
<th>Requester</th>
<th>Created By</th>
<th>Created At</th>
<th>Start Date</th>
<th>End Date</th>
</tr>
</thead>
<tbody>
<tr>
<td>{id}</td>
<td>{title}</td>
<td>{requester}</td>
<td>{created_by}</td>
<td>{created_at}</td>
<td>{start_date}</td>
<td>{end_date}</td>
</tr>
</tbody>
</table>
<hr>
<h3 class="title">Project {NAME}</h3>
<div class="columns">
<div class="column is-two-thirds">
<h3 class="title subtitle">Overview</h3>
<div class="skeleton-lines">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="column">
<div class="block">
<h3 class="title subtitle">Links</h3>
<div class="skeleton-lines">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>
<hr>
<div class="columns">
<div class="column">
<h3 class="title subtitle">Tickets</h3>
<div class="skeleton-lines">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="column">
<h3 class="title subtitle">Tasks</h3>
<div class="skeleton-lines">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="column">
<h3 class="title subtitle">Events</h3>
<div class="skeleton-lines">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<hr>
<div class="columns">
<div class="column">
<h3 class="title">Timeline</h3>
<div class="skeleton-lines">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<parsedown inline="true">
---
## View project
A central place to see everything for this project:
- Overview: (title, description, links, start/end dates).
- related tickets (with status and priorities)
- events
- tasks
- timeline combining events, tickets, milestone dates
## Example Workflow
- create a project - `team manager overview`
-- attach relevant links
- add tickets - each new request or issue can be a ticket referencing this project
- add events - quick notes about management meetings, or verbal discussions that don't need ticket overhead
-- meeting on 01 jan to discuss layout
-- teams message on 28 jan clarifying data requirements
- project tasks - for smaller to do items that don't warrant a full ticket
-- identify location of required data, create initial pq connections, build a mockup layout
## Reporting Timelines
- timeline view - merge ticket data with project_events sorted by date - chronological Overview
- status summaries - how many tickets open, on hold, completed
- progress tracking - sumarries or gantt style charts
</parsedown>