Compare commits
15 Commits
830a950bf4
...
main
Author | SHA1 | Date | |
---|---|---|---|
acbe69e9c7 | |||
80a12a86ef | |||
15ee9b78a3 | |||
ab2c87ce3a | |||
77c8605b49 | |||
5d5265ef38 | |||
f3ac8a6965 | |||
5683c0bc8b | |||
4371fd0b2f | |||
3ac8671742 | |||
b347988937 | |||
55048bda33 | |||
17c2e36bb5 | |||
c6d4c3df10 | |||
95bf9250e7 |
@ -1,2 +1,68 @@
|
||||
$(document).ready ->
|
||||
console.log('Hello, world!')
|
||||
$('.ticket-queue').on('click', (e) ->
|
||||
handleQueueClick(e)
|
||||
)
|
||||
$('.ticket-severity').on('click', (e) ->
|
||||
handleAttributeClick(e, 'severity')
|
||||
)
|
||||
$('.ticket-status').on('click', (e) ->
|
||||
handleAttributeClick(e, 'status')
|
||||
)
|
||||
|
||||
validOptions =
|
||||
'severity': ['low', 'medium', 'high'],
|
||||
'status': ['open', 'closed', 'parked']
|
||||
|
||||
handleQueueClick = (e, fail = false) ->
|
||||
newQueueId = prompt('Set queue ID:', $('.ticket-queue').data('id'))
|
||||
|
||||
if (newQueueId != null) and (newQueueId != '')
|
||||
if (true)
|
||||
console.log('Setting queue ID to ' + newQueueId)
|
||||
editLink = $('#ticketEditLink').attr('href') + '/queue_id'
|
||||
console.log('Sending data to ' + editLink)
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: editLink,
|
||||
data:
|
||||
'queue_id': newQueueId,
|
||||
dataType: 'json',
|
||||
success: (result) ->
|
||||
$('.ticket-queue').data('id', newQueueId)
|
||||
$('.ticket-queue > span').text(result.queue_name)
|
||||
updateTicketModified(result.updated_at)
|
||||
console.log('Ticket updated successfully.')
|
||||
})
|
||||
else
|
||||
console.log('Invalid queue ID entered')
|
||||
handleQueueClick(e, 'Invalid queue ID entered; you must enter a number.')
|
||||
|
||||
handleAttributeClick = (e, attr, fail = false) ->
|
||||
newValue = prompt('Set ticket ' + attr + ':', $('.ticket-' + attr + ' > span').text())
|
||||
newValue = newValue.toLowerCase()
|
||||
|
||||
if (newValue != null) and (newValue != '')
|
||||
if (newValue in validOptions[attr])
|
||||
console.log('Setting ' + attr + ' to ' + newValue)
|
||||
editLink = $('#ticketEditLink').attr('href') + '/' + attr
|
||||
postData = {}
|
||||
postData[attr] = newValue
|
||||
console.log('Sending data to ' + editLink)
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: editLink,
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
success: (result) ->
|
||||
newValue = newValue.charAt(0).toUpperCase() + newValue.slice(1)
|
||||
$('.ticket-' + attr + ' > span').text(newValue)
|
||||
updateTicketModified(result.updated_at)
|
||||
console.log('Ticket updated successfully.')
|
||||
})
|
||||
else
|
||||
console.log('Invalid ' + attr + ' entered')
|
||||
handleAttributeClick(e, attr, 'Invalid ' + attr + '; valid values are ' + validOptions.toString() + '.')
|
||||
|
||||
updateTicketModified = (date) ->
|
||||
$('.ticket-updated > span').text(date)
|
||||
console.log('Ticket update time is ' + date)
|
||||
|
@ -1,29 +1,58 @@
|
||||
$primary-color: yellow
|
||||
$primary-color-highlight: darken($primary-color, 10%)
|
||||
$primary-color: #009688
|
||||
$primary-color-highlight: lighten($primary-color, 10%)
|
||||
$accent-color: #795548
|
||||
$accent-color-highlight: lighten($accent-color, 10%)
|
||||
|
||||
$box-shadow-1: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)
|
||||
$box-shadow-2: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)
|
||||
|
||||
$nav-height: 60px
|
||||
$nav-height: 75px
|
||||
|
||||
body
|
||||
padding-top: $nav-height
|
||||
padding-bottom: 50px
|
||||
background: lightgrey
|
||||
font-size: 16px
|
||||
|
||||
a
|
||||
color: $accent-color
|
||||
transition: all 230ms ease-in-out
|
||||
&:hover
|
||||
color: $accent-color-highlight
|
||||
|
||||
.button.button-primary,
|
||||
button.button-primary,
|
||||
input[type="button"].button-primary,
|
||||
input[type="reset"].button-primary,
|
||||
input[type="submit"].button-primary
|
||||
background-color: $primary-color
|
||||
border-color: $primary-color
|
||||
font-size: 1.5rem
|
||||
transition: all 230ms ease-in-out
|
||||
&:hover
|
||||
background-color: $primary-color-highlight
|
||||
border-color: $primary-color-highlight
|
||||
|
||||
.container
|
||||
max-width: 1100px
|
||||
padding: 20px 30px
|
||||
|
||||
.card
|
||||
background: white
|
||||
box-shadow: $box-shadow-2
|
||||
|
||||
#main-nav
|
||||
position: fixed
|
||||
top: 0
|
||||
left: 0
|
||||
width: 100%
|
||||
height: $nav-height
|
||||
background: #212121
|
||||
color: #eee
|
||||
font-size: 2.75rem
|
||||
background: $primary-color
|
||||
color: white
|
||||
font-size: 3rem
|
||||
font-weight: bold
|
||||
box-shadow: $box-shadow-1
|
||||
z-index: 100
|
||||
|
||||
.nav-left
|
||||
float: left
|
||||
@ -34,16 +63,107 @@ body
|
||||
|
||||
li
|
||||
display: inline-block
|
||||
margin-top: 6px
|
||||
margin-top: 12px
|
||||
margin-left: 15px
|
||||
|
||||
.nav-link a
|
||||
color: $primary-color
|
||||
transition: all 230ms ease-in-out
|
||||
|
||||
color: white
|
||||
&:hover
|
||||
color: $primary-color-highlight
|
||||
color: #eee
|
||||
|
||||
#main-wrapper
|
||||
margin-top: 25px
|
||||
background: white
|
||||
|
||||
#ticket-form,
|
||||
#comment-form
|
||||
textarea
|
||||
max-width: 100%
|
||||
height: 250px
|
||||
min-height: 100px
|
||||
|
||||
#queue-header,
|
||||
#ticket-header
|
||||
margin-bottom: 15px
|
||||
|
||||
.queue-title,
|
||||
.ticket-title
|
||||
margin-bottom: 5px
|
||||
|
||||
.queue-created,
|
||||
.queue-updated,
|
||||
.ticket-created,
|
||||
.ticket-updated
|
||||
margin-bottom: 3px
|
||||
color: #666
|
||||
font-size: 1.5rem
|
||||
font-style: italic
|
||||
|
||||
#queue-description,
|
||||
#ticket-body
|
||||
p:last-child
|
||||
margin-bottom: 5px
|
||||
|
||||
.ticket-attributes
|
||||
list-style: none
|
||||
margin: 0
|
||||
border: 1px solid #bbb
|
||||
border-bottom: none
|
||||
box-shadow: $box-shadow-1
|
||||
font-size: 1.75rem
|
||||
|
||||
> li
|
||||
margin: 0
|
||||
padding: 10px 12px
|
||||
border-bottom: 1px solid #999
|
||||
|
||||
.ticket-actions
|
||||
padding: 0
|
||||
|
||||
ul
|
||||
list-style: none
|
||||
margin: 0
|
||||
|
||||
li
|
||||
display: inline
|
||||
margin: 0
|
||||
padding: 0
|
||||
&:not(:first-child)
|
||||
a
|
||||
border-left: 1px solid #999
|
||||
|
||||
a
|
||||
position: relative
|
||||
display: inline-block
|
||||
box-sizing: border-box
|
||||
width: 50%
|
||||
height: 100%
|
||||
padding: 10px 12px
|
||||
text-align: center
|
||||
&:hover
|
||||
background: rgba(0, 0, 0, .1)
|
||||
|
||||
i
|
||||
margin-right: 5px
|
||||
font-size: 2rem
|
||||
|
||||
.ticket-queue,
|
||||
.ticket-severity,
|
||||
.ticket-status
|
||||
transition: all 230ms ease-in-out
|
||||
&:hover
|
||||
background: rgba(0, 0, 0, .1)
|
||||
cursor: pointer
|
||||
|
||||
#comment-form
|
||||
textarea
|
||||
height: 150px
|
||||
|
||||
.comments-list
|
||||
list-style: none
|
||||
margin: 0
|
||||
|
||||
.comment
|
||||
&:not(:last-child)
|
||||
border-bottom: 1px solid #666
|
||||
p:last-child
|
||||
margin-bottom: 5px
|
||||
|
@ -22,6 +22,7 @@
|
||||
"slim/twig-view": "^3.3",
|
||||
"hassankhan/config": "^3.0",
|
||||
"illuminate/database": "^9.40",
|
||||
"robmorgan/phinx": "^0.13.1"
|
||||
"robmorgan/phinx": "^0.13.1",
|
||||
"league/commonmark": "^2.3"
|
||||
}
|
||||
}
|
||||
|
462
composer.lock
generated
462
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c1bc6d458a5bde9f693cfe4ca5d4f820",
|
||||
"content-hash": "f97fc3dd5b9c0a911f5aa8037accb13f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "cakephp/core",
|
||||
@ -236,6 +236,81 @@
|
||||
},
|
||||
"time": "2022-10-10T18:01:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
"version": "v3.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dflydev/dflydev-dot-access-data.git",
|
||||
"reference": "f41715465d65213d644d3141a6a93081be5d3549"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549",
|
||||
"reference": "f41715465d65213d644d3141a6a93081be5d3549",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.42",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.3",
|
||||
"scrutinizer/ocular": "1.6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dflydev\\DotAccessData\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dragonfly Development Inc.",
|
||||
"email": "info@dflydev.com",
|
||||
"homepage": "http://dflydev.com"
|
||||
},
|
||||
{
|
||||
"name": "Beau Simensen",
|
||||
"email": "beau@dflydev.com",
|
||||
"homepage": "http://beausimensen.com"
|
||||
},
|
||||
{
|
||||
"name": "Carlos Frutos",
|
||||
"email": "carlos@kiwing.it",
|
||||
"homepage": "https://github.com/cfrutos"
|
||||
},
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com"
|
||||
}
|
||||
],
|
||||
"description": "Given a deep data structure, access data by dot notation.",
|
||||
"homepage": "https://github.com/dflydev/dflydev-dot-access-data",
|
||||
"keywords": [
|
||||
"access",
|
||||
"data",
|
||||
"dot",
|
||||
"notation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
|
||||
"source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2"
|
||||
},
|
||||
"time": "2022-10-27T11:44:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/inflector",
|
||||
"version": "2.0.6",
|
||||
@ -890,6 +965,194 @@
|
||||
},
|
||||
"time": "2022-09-08T13:45:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "2.3.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "a36bd2be4f5387c0f3a8792a0d76b7d68865abbf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/a36bd2be4f5387c0f3a8792a0d76b7d68865abbf",
|
||||
"reference": "a36bd2be4f5387c0f3a8792a0d76b7d68865abbf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"league/config": "^1.1.1",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"symfony/deprecation-contracts": "^2.1 || ^3.0",
|
||||
"symfony/polyfill-php80": "^1.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"cebe/markdown": "^1.0",
|
||||
"commonmark/cmark": "0.30.0",
|
||||
"commonmark/commonmark.js": "0.30.0",
|
||||
"composer/package-versions-deprecated": "^1.8",
|
||||
"embed/embed": "^4.4",
|
||||
"erusev/parsedown": "^1.0",
|
||||
"ext-json": "*",
|
||||
"github/gfm": "0.29.0",
|
||||
"michelf/php-markdown": "^1.4 || ^2.0",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"phpstan/phpstan": "^1.8.2",
|
||||
"phpunit/phpunit": "^9.5.21",
|
||||
"scrutinizer/ocular": "^1.8.1",
|
||||
"symfony/finder": "^5.3 | ^6.0",
|
||||
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0",
|
||||
"unleashedtech/php-coding-standard": "^3.1.1",
|
||||
"vimeo/psalm": "^4.24.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\CommonMark\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)",
|
||||
"homepage": "https://commonmark.thephpleague.com",
|
||||
"keywords": [
|
||||
"commonmark",
|
||||
"flavored",
|
||||
"gfm",
|
||||
"github",
|
||||
"github-flavored",
|
||||
"markdown",
|
||||
"md",
|
||||
"parser"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://commonmark.thephpleague.com/",
|
||||
"forum": "https://github.com/thephpleague/commonmark/discussions",
|
||||
"issues": "https://github.com/thephpleague/commonmark/issues",
|
||||
"rss": "https://github.com/thephpleague/commonmark/releases.atom",
|
||||
"source": "https://github.com/thephpleague/commonmark"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.colinodell.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.paypal.me/colinpodell/10.00",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/colinodell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/league/commonmark",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T17:29:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/config",
|
||||
"version": "v1.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/config.git",
|
||||
"reference": "a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/config/zipball/a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e",
|
||||
"reference": "a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dflydev/dot-access-data": "^3.0.1",
|
||||
"nette/schema": "^1.2",
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.90",
|
||||
"phpunit/phpunit": "^9.5.5",
|
||||
"scrutinizer/ocular": "^1.8.1",
|
||||
"unleashedtech/php-coding-standard": "^3.1",
|
||||
"vimeo/psalm": "^4.7.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Config\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "Define configuration arrays with strict schemas and access values with dot notation",
|
||||
"homepage": "https://config.thephpleague.com",
|
||||
"keywords": [
|
||||
"array",
|
||||
"config",
|
||||
"configuration",
|
||||
"dot",
|
||||
"dot-access",
|
||||
"nested",
|
||||
"schema"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://config.thephpleague.com/",
|
||||
"issues": "https://github.com/thephpleague/config/issues",
|
||||
"rss": "https://github.com/thephpleague/config/releases.atom",
|
||||
"source": "https://github.com/thephpleague/config"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.colinodell.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.paypal.me/colinpodell/10.00",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/colinodell",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-08-14T12:15:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "2.63.0",
|
||||
@ -992,6 +1255,153 @@
|
||||
],
|
||||
"time": "2022-10-30T18:34:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/schema",
|
||||
"version": "v1.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/schema.git",
|
||||
"reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/schema/zipball/abbdbb70e0245d5f3bf77874cea1dfb0c930d06f",
|
||||
"reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nette/utils": "^2.5.7 || ^3.1.5 || ^4.0",
|
||||
"php": ">=7.1 <8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.3 || ^2.4",
|
||||
"phpstan/phpstan-nette": "^1.0",
|
||||
"tracy/tracy": "^2.7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "📐 Nette Schema: validating data structures against a given Schema.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"config",
|
||||
"nette"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/schema/issues",
|
||||
"source": "https://github.com/nette/schema/tree/v1.2.3"
|
||||
},
|
||||
"time": "2022-10-13T01:24:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v3.2.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "02a54c4c872b99e4ec05c4aec54b5a06eb0f6368"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/02a54c4c872b99e4ec05c4aec54b5a06eb0f6368",
|
||||
"reference": "02a54c4c872b99e4ec05c4aec54b5a06eb0f6368",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2 <8.3"
|
||||
},
|
||||
"conflict": {
|
||||
"nette/di": "<3.0.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "~2.0",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"tracy/tracy": "^2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use Image",
|
||||
"ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()",
|
||||
"ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
|
||||
"ext-json": "to use Nette\\Utils\\Json",
|
||||
"ext-mbstring": "to use Strings::lower() etc...",
|
||||
"ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()",
|
||||
"ext-xml": "to use Strings::length() etc. when mbstring is not available"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"array",
|
||||
"core",
|
||||
"datetime",
|
||||
"images",
|
||||
"json",
|
||||
"nette",
|
||||
"paginator",
|
||||
"password",
|
||||
"slugify",
|
||||
"string",
|
||||
"unicode",
|
||||
"utf-8",
|
||||
"utility",
|
||||
"validation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/utils/issues",
|
||||
"source": "https://github.com/nette/utils/tree/v3.2.8"
|
||||
},
|
||||
"time": "2022-09-12T23:36:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"version": "v1.3.0",
|
||||
@ -1263,6 +1673,56 @@
|
||||
},
|
||||
"time": "2021-11-05T16:50:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/event-dispatcher",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/event-dispatcher.git",
|
||||
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
|
||||
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\EventDispatcher\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Standard interfaces for event handling.",
|
||||
"keywords": [
|
||||
"events",
|
||||
"psr",
|
||||
"psr-14"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/event-dispatcher/issues",
|
||||
"source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
|
||||
},
|
||||
"time": "2019-01-08T18:20:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-factory",
|
||||
"version": "1.0.1",
|
||||
|
25
db/migrations/20221121043856_add_status_to_tickets_table.php
Normal file
25
db/migrations/20221121043856_add_status_to_tickets_table.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class AddStatusToTicketsTable extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('tickets');
|
||||
$table->addColumn('status', 'string', ['null' => false, 'default' => 'open'])
|
||||
->update();
|
||||
}
|
||||
}
|
29
db/migrations/20221122032232_add_comments_table.php
Normal file
29
db/migrations/20221122032232_add_comments_table.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class AddCommentsTable extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('comments');
|
||||
$table->addColumn('body', 'text', ['null' => false])
|
||||
->addColumn('ticket_id', 'integer', ['null' => false])
|
||||
->addTimestamps()
|
||||
->addForeignKey('ticket_id', 'tickets', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
|
||||
->addIndex(['body'])
|
||||
->create();
|
||||
}
|
||||
}
|
35
db/migrations/20221204223428_add_queue_table.php
Normal file
35
db/migrations/20221204223428_add_queue_table.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class AddQueueTable extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
// Create table for Queue objects
|
||||
$table = $this->table('queues');
|
||||
$table->addColumn('title', 'string', ['null' => false])
|
||||
->addColumn('description', 'text', ['null' => false])
|
||||
->addTimestamps()
|
||||
->addIndex(['title'])
|
||||
->create();
|
||||
|
||||
// Update tickets table to have a Queue ID field
|
||||
$tickets = $this->table('tickets')
|
||||
->addColumn('queue_id', 'integer', ['null' => false])
|
||||
->addForeignKey('queue_id', 'queues', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
|
||||
->update();
|
||||
}
|
||||
}
|
29
src/Controllers/CommentController.php
Normal file
29
src/Controllers/CommentController.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace BitGoblin\Goliath\Controllers;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Routing\RouteContext;
|
||||
use BitGoblin\Goliath\Models\Comment;
|
||||
|
||||
class CommentController extends Controller {
|
||||
|
||||
public function postAdd(Request $request, Response $response): Response {
|
||||
$params = (array)$request->getParsedBody();
|
||||
|
||||
$comment = new Comment;
|
||||
$comment->body = $params['comment_body'];
|
||||
$comment->ticket_id = $params['ticket_id'];
|
||||
|
||||
$comment->save();
|
||||
|
||||
// redirect the user back to the home page
|
||||
$routeContext = RouteContext::fromRequest($request);
|
||||
$routeParser = $routeContext->getRouteParser();
|
||||
return $response
|
||||
->withHeader('Location', $routeParser->urlFor('ticket.view', ['ticket_id' => $comment->ticket->id]))
|
||||
->withStatus(302);
|
||||
}
|
||||
|
||||
}
|
44
src/Controllers/QueueController.php
Normal file
44
src/Controllers/QueueController.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace BitGoblin\Goliath\Controllers;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Routing\RouteContext;
|
||||
use Slim\Views\Twig;
|
||||
use BitGoblin\Goliath\Models\Queue;
|
||||
|
||||
class QueueController extends Controller {
|
||||
|
||||
public function getView(Request $request, Response $response, array $args): Response {
|
||||
$queue = Queue::where('id', $args['queue_id'])->first();
|
||||
|
||||
$view = Twig::fromRequest($request);
|
||||
return $view->render($response, 'queue/view.twig', [
|
||||
'queue' => $queue,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getCreate(Request $request, Response $response): Response {
|
||||
$view = Twig::fromRequest($request);
|
||||
return $view->render($response, 'queue/create.twig');
|
||||
}
|
||||
|
||||
public function postCreate(Request $request, Response $response): Response {
|
||||
$params = (array)$request->getParsedBody();
|
||||
|
||||
$queue = new Queue;
|
||||
$queue->title = $params['queue_title'];
|
||||
$queue->description = $params['queue_description'];
|
||||
|
||||
$queue->save();
|
||||
|
||||
// redirect the user back to the home page
|
||||
$routeContext = RouteContext::fromRequest($request);
|
||||
$routeParser = $routeContext->getRouteParser();
|
||||
return $response
|
||||
->withHeader('Location', $routeParser->urlFor('queue.view', ['queue_id' => $queue->id]))
|
||||
->withStatus(302);
|
||||
}
|
||||
|
||||
}
|
@ -4,14 +4,29 @@ namespace BitGoblin\Goliath\Controllers;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Routing\RouteContext;
|
||||
use Slim\Views\Twig;
|
||||
use BitGoblin\Goliath\Models\Queue;
|
||||
use BitGoblin\Goliath\Models\Ticket;
|
||||
|
||||
class TicketController extends Controller {
|
||||
|
||||
public function getCreate(Request $request, Response $response): Response {
|
||||
public function getView(Request $request, Response $response, array $args): Response {
|
||||
$ticket = Ticket::where('id', $args['ticket_id'])->first();
|
||||
|
||||
$view = Twig::fromRequest($request);
|
||||
return $view->render($response, 'ticket/create.twig');
|
||||
return $view->render($response, 'ticket/view.twig', [
|
||||
'ticket' => $ticket,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getCreate(Request $request, Response $response): Response {
|
||||
$queues = Queue::all();
|
||||
|
||||
$view = Twig::fromRequest($request);
|
||||
return $view->render($response, 'ticket/create.twig', [
|
||||
'queues' => $queues,
|
||||
]);
|
||||
}
|
||||
|
||||
public function postCreate(Request $request, Response $response): Response {
|
||||
@ -21,6 +36,7 @@ class TicketController extends Controller {
|
||||
$ticket->title = $params['ticket_title'];
|
||||
$ticket->body = $params['ticket_body'];
|
||||
$ticket->severity = $params['ticket_severity'];
|
||||
$ticket->queue_id = $params['ticket_queue'];
|
||||
$ticket->due_at = $params['ticket_due'];
|
||||
|
||||
$ticket->save();
|
||||
@ -31,4 +47,68 @@ class TicketController extends Controller {
|
||||
->withStatus(302);
|
||||
}
|
||||
|
||||
public function getEdit(Request $request, Response $response, array $args): Response {
|
||||
$ticket = Ticket::where('id', $args['ticket_id'])->get();
|
||||
|
||||
$view = Twig::fromRequest($request);
|
||||
return $view->render($response, 'ticket/edit.twig', [
|
||||
'ticket' => $ticket[0],
|
||||
]);
|
||||
}
|
||||
|
||||
public function postEdit(Request $request, Response $response, array $args): Response {
|
||||
$ticket = Ticket::where('id', $args['ticket_id'])->first();
|
||||
|
||||
$params = (array)$request->getParsedBody();
|
||||
$ticket->title = $params['ticket_title'];
|
||||
$ticket->body = $params['ticket_body'];
|
||||
$ticket->severity = $params['ticket_severity'];
|
||||
$ticket->due_at = $params['ticket_due'];
|
||||
|
||||
$ticket->save();
|
||||
|
||||
// redirect the user back to the home page
|
||||
$routeContext = RouteContext::fromRequest($request);
|
||||
$routeParser = $routeContext->getRouteParser();
|
||||
return $response
|
||||
->withHeader('Location', $routeParser->urlFor('ticket.view', ['ticket_id' => $ticket->id]))
|
||||
->withStatus(302);
|
||||
}
|
||||
|
||||
public function postEditAttr(Request $request, Response $response, array $args): Response {
|
||||
// grab ticket from database
|
||||
$ticket = Ticket::where('id', $args['ticket_id'])->first();
|
||||
|
||||
// edit the specified attribute
|
||||
$params = (array)$request->getParsedBody();
|
||||
$attr = $args['attr'];
|
||||
$ticket->$attr = $params[$attr];
|
||||
|
||||
// save updated ticket
|
||||
$ticket->save();
|
||||
|
||||
// build JSON response
|
||||
$jsonResponse = [
|
||||
'result' => 'success',
|
||||
'updated_at' => $ticket->formatUpdatedAt(),
|
||||
];
|
||||
if ($attr == 'queue_id') {
|
||||
$jsonResponse['queue_name'] = $ticket->queue->title;
|
||||
}
|
||||
|
||||
// return a response
|
||||
$response->getBody()->write(json_encode($jsonResponse));
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function getDelete(Request $request, Response $response, array $args): Response {
|
||||
$ticket = Ticket::where('id', $args['ticket_id'])->first();
|
||||
|
||||
$ticket->delete();
|
||||
|
||||
return $response
|
||||
->withHeader('Location', '/')
|
||||
->withStatus(302);
|
||||
}
|
||||
|
||||
}
|
||||
|
28
src/Models/Comment.php
Normal file
28
src/Models/Comment.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace BitGoblin\Goliath\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
class Comment extends Model {
|
||||
|
||||
protected $fillable = [
|
||||
'body',
|
||||
'ticket_id',
|
||||
];
|
||||
|
||||
public function render(): string {
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
return $converter->convert($this->body);
|
||||
}
|
||||
|
||||
public function ticket() {
|
||||
return $this->belongsTo(Ticket::class);
|
||||
}
|
||||
|
||||
}
|
36
src/Models/Queue.php
Normal file
36
src/Models/Queue.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace BitGoblin\Goliath\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
class Queue extends Model {
|
||||
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'description',
|
||||
];
|
||||
|
||||
public function tickets() {
|
||||
return $this->hasMany(Ticket::class);
|
||||
}
|
||||
|
||||
public function render(): string {
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
return $converter->convert($this->description);
|
||||
}
|
||||
|
||||
public function formatCreatedAt(): string {
|
||||
return date_format(date_create($this->created_at), "F jS\\, Y \\a\\t g:i:s a");
|
||||
}
|
||||
|
||||
public function formatUpdatedAt(): string {
|
||||
return date_format(date_create($this->updated_at), "F jS\\, Y \\a\\t g:i:s a");
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace BitGoblin\Goliath\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
class Ticket extends Model {
|
||||
|
||||
@ -13,4 +14,29 @@ class Ticket extends Model {
|
||||
'due_at',
|
||||
];
|
||||
|
||||
public function queue() {
|
||||
return $this->belongsTo(Queue::class);
|
||||
}
|
||||
|
||||
public function comments() {
|
||||
return $this->hasMany(Comment::class);
|
||||
}
|
||||
|
||||
public function render(): string {
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
return $converter->convert($this->body);
|
||||
}
|
||||
|
||||
public function formatCreatedAt(): string {
|
||||
return date_format(date_create($this->created_at), "F jS\\, Y \\a\\t g:i:s a");
|
||||
}
|
||||
|
||||
public function formatUpdatedAt(): string {
|
||||
return date_format(date_create($this->updated_at), "F jS\\, Y \\a\\t g:i:s a");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,27 @@ use Slim\Views\Twig;
|
||||
// index GET route - this page should welcome the user and direct them to the available actions
|
||||
$app->get('/', '\\BitGoblin\\Goliath\\Controllers\\HomeController:getIndex')->setName('index');
|
||||
|
||||
// /ticket/create GET route - allows a user to fill out a form to create a ticket
|
||||
// /queue/create routes - allows a user to fill out a form to create a new queue
|
||||
$app->get('/queue/create', '\\BitGoblin\\Goliath\\Controllers\\QueueController:getCreate')->setName('queue.create');
|
||||
$app->post('/queue/create', '\\BitGoblin\\Goliath\\Controllers\\QueueController:postCreate');
|
||||
|
||||
// /queue/id route - displays queue info to user
|
||||
$app->get('/queue/{queue_id}', '\\BitGoblin\\Goliath\\Controllers\QueueController:getView')->setName('queue.view');
|
||||
|
||||
// /ticket/create routes - allows a user to fill out a form to create a ticket
|
||||
$app->get('/ticket/create', '\\BitGoblin\\Goliath\\Controllers\\TicketController:getCreate')->setName('ticket.create');
|
||||
$app->post('/ticket/create', '\\BitGoblin\\Goliath\\Controllers\\TicketController:postCreate');
|
||||
|
||||
// /ticket/edit routes - update a ticket!
|
||||
$app->get('/ticket/{ticket_id}/edit', '\\BitGoblin\\Goliath\\Controllers\\TicketController:getEdit')->setName('ticket.edit');
|
||||
$app->post('/ticket/{ticket_id}/edit', '\\BitGoblin\\Goliath\\Controllers\\TicketController:postEdit')->setName('ticket.edit');
|
||||
$app->post('/ticket/{ticket_id}/edit/{attr}', '\\BitGoblin\\Goliath\\Controllers\\TicketController:postEditAttr')->setName('ticket.edit.attr');
|
||||
|
||||
// ticket deletion route
|
||||
$app->get('/ticket/{ticket_id}/delete', '\\BitGoblin\\Goliath\\Controllers\\TicketController:getDelete')->setName('ticket.delete');
|
||||
|
||||
// /ticket/id route - displays ticket info to user
|
||||
$app->get('/ticket/{ticket_id}', '\\BitGoblin\\Goliath\\Controllers\\TicketController:getView')->setName('ticket.view');
|
||||
|
||||
// add a comment to a ticket
|
||||
$app->post('/comment/add', '\\BitGoblin\\Goliath\\Controllers\\CommentController:postAdd')->setName('comment.add');
|
||||
|
@ -16,12 +16,19 @@
|
||||
<th>Title</th>
|
||||
<th>Severity</th>
|
||||
<th>Due date</th>
|
||||
<th>Actions</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ticket in tickets %}
|
||||
<td>{{ ticket.title }}</td>
|
||||
<td>{{ ticket.severity }}</td>
|
||||
<td>{{ ticket.due_at }}</td>
|
||||
<tr>
|
||||
<td><a href="{{ url_for('ticket.view', {ticket_id: ticket.id}) }}">{{ ticket.title }}</a></td>
|
||||
<td>{{ ticket.severity }}</td>
|
||||
<td>{{ ticket.due_at ? ticket.due_at : 'N/a' }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('ticket.edit', {ticket_id: ticket.id}) }}"><i class="fa-solid fa-pen-to-square"></i></a>
|
||||
<a href="{{ url_for('ticket.delete', {ticket_id: ticket.id}) }}"><i class="fa-solid fa-trash"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -16,13 +16,14 @@
|
||||
<ul class="nav-menu">
|
||||
<li>Goliath</li>
|
||||
<li class="nav-link"><a href="{{ url_for('index') }}">Home</a></li>
|
||||
<li class="nav-link"><a href="{{ url_for('ticket.create') }}">Create</a></li>
|
||||
<li class="nav-link"><a href="{{ url_for('queue.create') }}">New Queue</a></li>
|
||||
<li class="nav-link"><a href="{{ url_for('ticket.create') }}">New Ticket</a></li>
|
||||
<li class="nav-link"><a href="/search">Search</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="main-wrapper" class="container">
|
||||
<div id="main-wrapper" class="card container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
|
29
views/queue/create.twig
Normal file
29
views/queue/create.twig
Normal file
@ -0,0 +1,29 @@
|
||||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block title %}Create New Queue{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="columns twelve">
|
||||
<h1>Create new queue</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="columns twelve">
|
||||
<form id="queue-form" action="/queue/create" method="POST" class="u-full-width">
|
||||
<div class="row">
|
||||
<div class="twelve columns">
|
||||
<label for="queue_title">Title</label>
|
||||
<input id="queue_title" class="u-full-width" type="text" placeholder="My new queue" name="queue_title">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label for="queue_description">Description</label>
|
||||
<textarea id="queue_description" class="u-full-width" placeholder="Explain what this queue is about..." name="queue_description"></textarea>
|
||||
|
||||
<input class="button-primary u-full-width" type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
44
views/queue/view.twig
Normal file
44
views/queue/view.twig
Normal file
@ -0,0 +1,44 @@
|
||||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block title %}Ticket Queue: {{ queue.title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- queue content -->
|
||||
<div class="row">
|
||||
<div class="twelve columns">
|
||||
<div id="queue-header" class="row">
|
||||
<div class="columns twelve">
|
||||
<h1 class="queue-title">{{ queue.title }}</h1>
|
||||
<h4 class="queue-created">Created at: <span>{{ queue.formatCreatedAt() }}</span></h4>
|
||||
<h4 class="queue-updated">Last updated at: <span>{{ queue.formatUpdatedAt() }}</span></h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="queue-description" class="row">
|
||||
<div class="columns twelve">
|
||||
{{ queue.render() | raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<!-- queue tickets -->
|
||||
<div class="row">
|
||||
<div class="twelve columns">
|
||||
<ul id="queue-list" class="row">
|
||||
<h3>Tickets in this queue:</h3>
|
||||
{% if queue.tickets | length > 0 %}
|
||||
{% for ticket in queue.tickets %}
|
||||
<li>
|
||||
<a href="{{ url_for('ticket.view', { ticket_id: ticket.id }) }}">{{ ticket.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>There are no tickets in this queue.</p>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -11,17 +11,25 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="columns twelve">
|
||||
<form action="/ticket/create" method="POST" class="u-full-width">
|
||||
<form id="ticket-form" action="/ticket/create" method="POST" class="u-full-width">
|
||||
<div class="row">
|
||||
<div class="six columns">
|
||||
<label for="ticket_title">Title</label>
|
||||
<input id="ticket_title" class="u-full-width" type="text" placeholder="My new ticket" name="ticket_title">
|
||||
</div>
|
||||
<div class="columns three">
|
||||
<div class="two columns">
|
||||
<label for="ticket_queue">Queue</label>
|
||||
<select name="ticket_queue" id="ticket_queue" class="u-full-width">
|
||||
{% for q in queues %}
|
||||
<option value="{{ q.id }}">{{ q.title }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="two columns">
|
||||
<label for="ticket_due">Due at</label>
|
||||
<input id="ticket_due" class="u-full-width" type="datetime-local" name="ticket_due">
|
||||
</div>
|
||||
<div class="three columns">
|
||||
<div class="two columns">
|
||||
<label for="ticket_severity">Severity level</label>
|
||||
<select id="ticket_severity" class="u-full-width" name="ticket_severity">
|
||||
<option value="low">Low</option>
|
||||
@ -34,7 +42,7 @@
|
||||
<label for="ticket_body">Ticket body</label>
|
||||
<textarea id="ticket_body" class="u-full-width" placeholder="Explain what this ticket is about..." name="ticket_body"></textarea>
|
||||
|
||||
<input class="button-primary" type="submit" value="Submit">
|
||||
<input class="button-primary u-full-width" type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
41
views/ticket/edit.twig
Normal file
41
views/ticket/edit.twig
Normal file
@ -0,0 +1,41 @@
|
||||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block title %}Editing ticket{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="columns twelve">
|
||||
<h1>Editing "{{ ticket.title }}"</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="columns twelve">
|
||||
<form id="ticket-form" action="{{ url_for('ticket.edit', {ticket_id: ticket.id}) }}" method="POST" class="u-full-width">
|
||||
<div class="row">
|
||||
<div class="six columns">
|
||||
<label for="ticket_title">Title</label>
|
||||
<input id="ticket_title" class="u-full-width" type="text" placeholder="My new ticket" name="ticket_title" value="{{ ticket.title }}">
|
||||
</div>
|
||||
<div class="columns three">
|
||||
<label for="ticket_due">Due at</label>
|
||||
<input id="ticket_due" class="u-full-width" type="datetime-local" name="ticket_due" value="{{ ticket.due_at }}">
|
||||
</div>
|
||||
<div class="three columns">
|
||||
<label for="ticket_severity">Severity level</label>
|
||||
<select id="ticket_severity" class="u-full-width" name="ticket_severity" value="{{ ticket.severity }}">
|
||||
<option value="low">Low</option>
|
||||
<option value="medium">Medium</option>
|
||||
<option value="high">High</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label for="ticket_body">Ticket body</label>
|
||||
<textarea id="ticket_body" class="u-full-width" placeholder="Explain what this ticket is about..." name="ticket_body">{{ ticket.body }}</textarea>
|
||||
|
||||
<input class="button-primary u-full-width" type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
81
views/ticket/view.twig
Normal file
81
views/ticket/view.twig
Normal file
@ -0,0 +1,81 @@
|
||||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block title %}{{ ticket.title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<!-- ticket content -->
|
||||
<div class="nine columns">
|
||||
<div id="ticket-header" class="row">
|
||||
<div class="columns twelve">
|
||||
<h1 class="ticket-title">{{ ticket.title }}</h1>
|
||||
<h4 class="ticket-created">Created at: <span>{{ ticket.formatCreatedAt() }}</span></h4>
|
||||
<h4 class="ticket-updated">Last updated at: <span>{{ ticket.formatUpdatedAt() }}</span></h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ticket-body" class="row">
|
||||
<div class="columns twelve">
|
||||
{{ ticket.render() | raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ticket status column -->
|
||||
<div class="three columns">
|
||||
<ul class="ticket-attributes">
|
||||
<li class="ticket-actions">
|
||||
<ul>
|
||||
<li><a id="ticketEditLink" href="{{ url_for('ticket.edit', {ticket_id: ticket.id}) }}"><i class="fa-solid fa-pen-to-square"></i>Edit</a></li><li><a href="{{ url_for('ticket.delete', {ticket_id: ticket.id}) }}"><i class="fa-solid fa-trash"></i>Delete</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="ticket-queue" data-id="{{ ticket.queue.id }}">
|
||||
Queue: <span>{{ ticket.queue.title }}</span>
|
||||
</li>
|
||||
<li class="ticket-severity">
|
||||
Severity: <span>{{ ticket.severity | capitalize }}</span>
|
||||
</li>
|
||||
<li class="ticket-status">
|
||||
Status: <span>{{ ticket.status | capitalize }}</span>
|
||||
</li>
|
||||
<li>
|
||||
Assignee(s): N/a
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<!-- ticket updates -->
|
||||
<div class="row">
|
||||
<div class="twelve columns">
|
||||
<h3>Ticket comments/Updates</h3>
|
||||
{% if ticket.comments | length > 0 %}
|
||||
<ul class="comments-list">
|
||||
{% for comment in ticket.comments %}
|
||||
<li class="comment">{{ comment.render() | raw }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>There are no comments to display at this time.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<!-- add a comment form -->
|
||||
<div class="row">
|
||||
<div class="twelve columns">
|
||||
<form id="comment-form" action="{{ url_for('comment.add') }}" method="POST" class="u-full-width">
|
||||
<label for="comment_body">Add a comment:</label>
|
||||
<textarea id="comment_body" class="u-full-width" placeholder="Add a comment..." name="comment_body"></textarea>
|
||||
|
||||
<input type="hidden" name="ticket_id" value="{{ ticket.id }}">
|
||||
|
||||
<input class="button-primary u-full-width" type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
Reference in New Issue
Block a user