+ +
-
- -
-renderAssetsLate(); ?> \ No newline at end of file + diff --git a/Admin/Install/Application/Shop/info.json b/Admin/Install/Application/Shop/info.json new file mode 100755 index 0000000..83cd964 --- /dev/null +++ b/Admin/Install/Application/Shop/info.json @@ -0,0 +1,20 @@ +{ + "name": { + "id": 1007700001, + "internal": "{APPNAME}", + "external": "{APPNAME}" + }, + "category": "Web", + "version": "1.0.0", + "requirements": { + "phpOMS": "1.0.0", + "phpOMS-db": "1.0.0" + }, + "creator": { + "name": "Orange Management", + "website": "www.spl1nes.com" + }, + "description": "The shop application.", + "directory": "Shop", + "dependencies": {} +} diff --git a/Admin/Install/Application/Shop/js/shop.js b/Admin/Install/Application/Shop/js/shop.js new file mode 100755 index 0000000..3abfb75 --- /dev/null +++ b/Admin/Install/Application/Shop/js/shop.js @@ -0,0 +1,5 @@ +jsOMS.ready(function () +{ + "use strict"; + +}); diff --git a/Admin/Install/Application/Shop/lang/en.lang.php b/Admin/Install/Application/Shop/lang/en.lang.php new file mode 100755 index 0000000..7b4fc53 --- /dev/null +++ b/Admin/Install/Application/Shop/lang/en.lang.php @@ -0,0 +1,19 @@ + 'Demo Shop.', +]]; diff --git a/Admin/Install/Application/Shop/manifest.json b/Admin/Install/Application/Shop/manifest.json new file mode 100755 index 0000000..90b0321 --- /dev/null +++ b/Admin/Install/Application/Shop/manifest.json @@ -0,0 +1,75 @@ +{ + "lang": "en", + "dir": "ltr", + "start_url": "../../{APPNAME}", + "type": "privileged", + "name": "Orange Management Shop", + "description": "OMS shop application.", + "short_name": "OMS Shop", + "icons": [ + { + "src": "img/maskable_icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-384x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ], + "scope": "/", + "display": "standalone", + "orientation": "any", + "theme_color": "#343a40", + "background_color": "white", + "permissions": { + "audio-capture" : { + "description" : "Audio capture" + }, + "video-capture": { + "description": "Video capture" + }, + "speech-recognition" : { + "description" : "Speech recognition" + } + } +} \ No newline at end of file diff --git a/Admin/Install/Application/Shop/manifest.webmanifest b/Admin/Install/Application/Shop/manifest.webmanifest new file mode 100755 index 0000000..90b0321 --- /dev/null +++ b/Admin/Install/Application/Shop/manifest.webmanifest @@ -0,0 +1,75 @@ +{ + "lang": "en", + "dir": "ltr", + "start_url": "../../{APPNAME}", + "type": "privileged", + "name": "Orange Management Shop", + "description": "OMS shop application.", + "short_name": "OMS Shop", + "icons": [ + { + "src": "img/maskable_icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-384x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "img/maskable_icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ], + "scope": "/", + "display": "standalone", + "orientation": "any", + "theme_color": "#343a40", + "background_color": "white", + "permissions": { + "audio-capture" : { + "description" : "Audio capture" + }, + "video-capture": { + "description": "Video capture" + }, + "speech-recognition" : { + "description" : "Speech recognition" + } + } +} \ No newline at end of file diff --git a/Admin/Install/CMS.install.json b/Admin/Install/CMS.install.json new file mode 100755 index 0000000..82df26b --- /dev/null +++ b/Admin/Install/CMS.install.json @@ -0,0 +1,7 @@ +[ + { + "src": "Modules/Shop/Admin/Install/Application/Shop", + "dest": "Web/Shop", + "name": "Shop" + } +] \ No newline at end of file diff --git a/Admin/Install/CMS.php b/Admin/Install/CMS.php new file mode 100755 index 0000000..ca5df1b --- /dev/null +++ b/Admin/Install/CMS.php @@ -0,0 +1,45 @@ + __DIR__ . '/CMS.install.json']); + } +} diff --git a/Admin/Install/Navigation.install.json b/Admin/Install/Navigation.install.json index 3d7e42f..9a61df4 100755 --- a/Admin/Install/Navigation.install.json +++ b/Admin/Install/Navigation.install.json @@ -18,7 +18,7 @@ "pid": "/", "type": 2, "subtype": 1, - "name": "Ticket", + "name": "Tickets", "uri": "{/prefix}support/list", "target": "self", "icon": null, diff --git a/Admin/Install/db.json b/Admin/Install/db.json index 5ab6d94..6f0fa8f 100755 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -1,4 +1,21 @@ { + "support_app": { + "name": "support_app", + "fields": { + "support_app_id": { + "name": "support_app_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "support_app_name": { + "name": "support_app_name", + "type": "VARCHAR(255)", + "default": null + } + } + }, "support_ticket": { "name": "support_ticket", "fields": { @@ -15,6 +32,244 @@ "null": false, "foreignTable": "task", "foreignKey": "task_id" + }, + "support_ticket_for": { + "name": "support_ticket_for", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "account", + "foreignKey": "account_id" + }, + "support_ticket_app": { + "name": "support_ticket_app", + "type": "INT", + "null": false, + "foreignTable": "support_app", + "foreignKey": "support_app_id" + } + } + }, + "support_ticket_element": { + "name": "support_ticket_element", + "fields": { + "support_ticket_element_id": { + "name": "support_ticket_element_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "support_ticket_element_time": { + "name": "support_ticket_element_time", + "type": "INT", + "null": false + }, + "support_ticket_element_task_element": { + "name": "support_ticket_element_task_element", + "type": "INT", + "null": false, + "foreignTable": "task_element", + "foreignKey": "task_element_id" + }, + "support_ticket_element_ticket": { + "name": "support_ticket_element_ticket", + "type": "INT", + "null": false, + "foreignTable": "support_ticket", + "foreignKey": "support_ticket_id" + } + } + }, + "support_attr_type": { + "name": "support_attr_type", + "fields": { + "support_attr_type_id": { + "name": "support_attr_type_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "support_attr_type_name": { + "name": "support_attr_type_name", + "type": "VARCHAR(255)", + "null": false + }, + "support_attr_type_fields": { + "name": "support_attr_type_fields", + "type": "INT(11)", + "null": false + }, + "support_attr_type_custom": { + "name": "support_attr_type_custom", + "type": "TINYINT(1)", + "null": false + }, + "support_attr_type_required": { + "description": "Every ticket must have this attribute type if set to true.", + "name": "support_attr_type_required", + "type": "TINYINT(1)", + "null": false + }, + "support_attr_type_pattern": { + "description": "This is a regex validation pattern.", + "name": "support_attr_type_pattern", + "type": "VARCHAR(255)", + "null": false + } + } + }, + "support_attr_type_l11n": { + "name": "support_attr_type_l11n", + "fields": { + "support_attr_type_l11n_id": { + "name": "support_attr_type_l11n_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "support_attr_type_l11n_title": { + "name": "support_attr_type_l11n_title", + "type": "VARCHAR(255)", + "null": false + }, + "support_attr_type_l11n_type": { + "name": "support_attr_type_l11n_type", + "type": "INT(11)", + "null": false, + "foreignTable": "support_attr_type", + "foreignKey": "support_attr_type_id" + }, + "support_attr_type_l11n_lang": { + "name": "support_attr_type_l11n_lang", + "type": "VARCHAR(2)", + "null": false, + "foreignTable": "language", + "foreignKey": "language_639_1" + } + } + }, + "support_attr_value": { + "name": "support_attr_value", + "fields": { + "support_attr_value_id": { + "name": "support_attr_value_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "support_attr_value_default": { + "name": "support_attr_value_default", + "type": "TINYINT(1)", + "null": false + }, + "support_attr_value_type": { + "name": "support_attr_value_type", + "type": "INT(11)", + "null": false + }, + "support_attr_value_valueStr": { + "name": "support_attr_value_valueStr", + "type": "VARCHAR(255)", + "null": true, + "default": null + }, + "support_attr_value_valueInt": { + "name": "support_attr_value_valueInt", + "type": "INT(11)", + "null": true, + "default": null + }, + "support_attr_value_valueDec": { + "name": "support_attr_value_valueDec", + "type": "DECIMAL(19,5)", + "null": true, + "default": null + }, + "support_attr_value_valueDat": { + "name": "support_attr_value_valueDat", + "type": "DATETIME", + "null": true, + "default": null + }, + "support_attr_value_lang": { + "name": "support_attr_value_lang", + "type": "VARCHAR(2)", + "null": true, + "default": null, + "foreignTable": "language", + "foreignKey": "language_639_1" + }, + "support_attr_value_country": { + "name": "support_attr_value_country", + "type": "VARCHAR(2)", + "null": true, + "default": null, + "foreignTable": "country", + "foreignKey": "country_code2" + } + } + }, + "support_ticket_attr_default": { + "name": "support_ticket_attr_default", + "fields": { + "support_ticket_attr_default_id": { + "name": "support_ticket_attr_default_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "support_ticket_attr_default_type": { + "name": "support_ticket_attr_default_type", + "type": "INT(11)", + "null": false, + "foreignTable": "support_attr_type", + "foreignKey": "support_attr_type_id" + }, + "support_ticket_attr_default_value": { + "name": "support_ticket_attr_default_value", + "type": "INT(11)", + "null": false, + "foreignTable": "support_attr_value", + "foreignKey": "support_attr_value_id" + } + } + }, + "support_ticket_attr": { + "name": "support_ticket_attr", + "fields": { + "support_ticket_attr_id": { + "name": "support_ticket_attr_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "support_ticket_attr_ticket": { + "name": "support_ticket_attr_ticket", + "type": "INT(11)", + "null": false, + "foreignTable": "support_ticket", + "foreignKey": "support_ticket_id" + }, + "support_ticket_attr_type": { + "name": "support_ticket_attr_type", + "type": "INT(11)", + "null": false, + "foreignTable": "support_attr_type", + "foreignKey": "support_attr_type_id" + }, + "support_ticket_attr_value": { + "name": "support_ticket_attr_value", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "support_attr_value", + "foreignKey": "support_attr_value_id" } } } diff --git a/Admin/Routes/Web/Backend.php b/Admin/Routes/Web/Backend.php index f382848..f97599b 100755 --- a/Admin/Routes/Web/Backend.php +++ b/Admin/Routes/Web/Backend.php @@ -17,7 +17,7 @@ return [ ], ], ], - '^.*/support/single.*$' => [ + '^.*/support/ticket.*$' => [ [ 'dest' => '\Modules\Support\Controller\BackendController:viewSupportTicket', 'verb' => RouteVerb::GET, diff --git a/Application/Ticket/Timerecording/Error/403_inline.tpl.php b/Application/Ticket/Timerecording/Error/403_inline.tpl.php deleted file mode 100755 index e76b530..0000000 --- a/Application/Ticket/Timerecording/Error/403_inline.tpl.php +++ /dev/null @@ -1 +0,0 @@ -Inline \ No newline at end of file diff --git a/Application/Ticket/Timerecording/Routes.php b/Application/Ticket/Timerecording/Routes.php deleted file mode 100755 index 9012cb5..0000000 --- a/Application/Ticket/Timerecording/Routes.php +++ /dev/null @@ -1,25 +0,0 @@ - [ - 0 => [ - 'dest' => '\Modules\HumanResourceTimeRecording\Controller\TimerecordingController:viewDashboard', - 'verb' => 1, - 'permission' => [ - 'module' => 'HumanResourceTimeRecording', - 'type' => 2, - 'state' => 1, - ], - ], - ], - '^.*/timerecording/dashboard.*$' => [ - 0 => [ - 'dest' => '\Modules\HumanResourceTimeRecording\Controller\TimerecordingController:viewDashboard', - 'verb' => 1, - 'permission' => [ - 'module' => 'HumanResourceTimeRecording', - 'type' => 2, - 'state' => 1, - ], - ], - ], -]; diff --git a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording-small.css b/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording-small.css deleted file mode 100755 index 7562f51..0000000 --- a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording-small.css +++ /dev/null @@ -1,190 +0,0 @@ -:root { - --main-background: rgb(46, 26, 90); - --main-background-highlight: rgb(158, 81, 197); - --input-border: rgba(166, 135, 232, .4); - --input-border-active: rgba(166, 135, 232, .7); - --input-color: rgb(116, 67, 161); - --input-color-active: rgb(94, 52, 133); - --input-background: rgba(255, 255, 255); - --input-background-active: rgba(255, 255, 255); - --input-icon-color: rgba(166, 135, 232, .6); - --input-icon-color-active: rgba(166, 135, 232, 1); - --button-main-background: rgba(166, 135, 232, .6); - --button-main-background-active: rgba(166, 135, 232, .8); - --button-main-color: rgba(255, 255, 255, .9); - --text-on-background-color: rgba(255, 255, 255, 0.7); - --text-on-background-color-2: rgba(255, 255, 255, 0.85); - --nav-category-background: rgb(43, 58, 101); - --nav-category-background-highlight: rgb(113, 43, 145); - --nav-category-background-hover: rgb(120, 50, 153); - --nav-sub-background: rgb(72, 39, 102); - --nav-sub-background-highlight: rgb(94, 52, 133); - --nav-sub-background-hover: rgb(116, 67, 161); - --nav-header-background: rgb(72, 39, 102); - --nav-header-background-highlight: rgb(94, 52, 133); - --nav-header-background-hover: rgb(116, 67, 161); - --nav-content-hover: rgb(177, 97, 218); - --font-family: 'Roboto', sans-serif; - --button-colored-background: rgb(158, 81, 197); - --button-colored-background-hover: rgb(177, 97, 218); - --table-caption-background: rgb(255, 255, 255); - --table-head-background: rgb(236, 232, 255); - --table-row-background: rgb(255, 255, 255); - --table-row-background-alt: rgb(255, 255, 255); - --table-row-background-hover: rgb(220, 211, 255); - --link-color: rgb(72, 39, 102); - --link-hover: rgb(158, 81, 197); - --badge-size: .55rem; - --badge-color: rgb(255, 255, 255); - --badge-background: rgb(158, 81, 197); - --box-border: rgb(218, 218, 218); } - - html, body { - width: 100%; - height: 100%; - min-width: 100%; - max-width: 100%; - overflow: hidden; - font-family: var(--font-family); - color: #000; } - - body { - display: flex; flex-direction: column;} - -header { - background: #f8f8f8; - border-bottom: 1px solid var(--box-border); - padding: 1rem; - box-sizing: border-box; - display: flex; - align-items: center; - flex-flow: row; - flex: 0; } - header > form { - display: flex; - flex: 1; - padding: 0 5px 0 5px; - max-width: 800px; } - header .inputWrapper { - flex: 1; } - header input[type=text] { - width: 100%; - background: white; - border: 1px solid var(--input-border); - text-shadow: none; - box-shadow: none; - transition: border 500ms ease-out; - outline: none; - box-sizing: border-box; - padding-left: 2rem; } - - #logo { - flex: 1; - text-align: right; } - #logo select { - background: none; - color: rgba(255, 255, 255, 0.8); - font-size: .8rem; } - - .ham-trigger { - display: flex; - color: #000; - align-items: center; - flex: 0; - margin-right: 5px; } - .ham-trigger i { - font-size: 1.5rem; } - - nav .ham-trigger { - color: var(--text-on-background-color-2); - margin: 0 0 0 5px; - display: none; } - - #t-nav-container { - margin-left: auto; } - - #content { - flex: 1; - padding-left: 1rem; - overflow-y: auto; } - - #t-nav { - font-size: .8rem; - color: #000; - font-weight: bold; } - #t-nav a { - padding: 0 5px 0 5px; - line-height: 25px; } - #t-nav i { - margin-right: 5px; } - #t-nav li { - display: inline; } - #t-nav li:hover { - color: var(--link-hover); } - - main { - display: flex; - flex-direction: column; - height: 100%; - background: #f1f1f1; - flex: 1; - box-sizing: border-box; } - - #dim { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: #000; - opacity: 0.5; - z-index: 5; } - - #u-box { - display: flex; - align-items: center; - padding: 0 1rem 0 1rem; - height: 60px; - border-bottom: 1px solid var(--input-border); - box-sizing: border-box; } - #u-box img { - width: 40px; - height: 40px; - border-radius: 50%; } - #u-box a { - display: inline-block; } - - #app-message-container { - position: absolute; - margin: 0 auto; - right: 0; - top: 0; - padding: 85px 10px 0 0; - } - - .log-msg { - z-index: 11; - position: relative; - margin: 0 auto; - right: 0; - top: 0; - margin-bottom: 10px; - } - - @media only screen and (max-width: 500px) { - nav .ham-trigger { - display: flex; } } - @media only screen and (max-width: 600px) { -header { - flex-flow: column; - height: auto; - padding: 1rem; } - header form { - width: 100%; } - - #t-nav-container { - order: -1; - margin-bottom: .5rem; } } - @media only screen and (max-width: 1000px) { - #t-nav .link { - display: none; } } diff --git a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording-small.scss b/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording-small.scss deleted file mode 100755 index 7252f9d..0000000 --- a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording-small.scss +++ /dev/null @@ -1,153 +0,0 @@ -@import "backend_vars"; - -html, body { - width: 100%; - height: 100%; - min-width: 100%; - max-width: 100%; - overflow: hidden; - font-family: var(--font-family); - color: #000; -} - -body { - display: flex; - flex-direction: column; -} - -header { - background: rgb(248, 248, 248); - border-bottom: 1px solid var(--box-border); - padding: 1rem; - box-sizing: border-box; - display: flex; - align-items: center; - flex-flow: row; - flex: 0; - - > form { - display: flex; - flex: 1; - padding: 0 5px 0 5px; - max-width: 800px; - } - - .inputWrapper { - flex: 1; - } - - input[type=text] { - width: 100%; - background: rgba(255, 255, 255, 1); - border: 1px solid var(--input-border); - text-shadow: none; - box-shadow: none; - transition : border 500ms ease-out; - outline: none; - box-sizing: border-box; - padding-left: 2rem; - } -} - -#logo { - flex: 1; - text-align: right; - - select { - background: none; - color: rgba(255, 255, 255, 0.8); - font-size: .8rem; - } -} - -#t-nav-container { - margin-left: auto; -} - -#content { - flex: 1; - padding-left: 1rem; - overflow-y: auto; -} - -#t-nav { - font-size: .8rem; - color: #000; - font-weight: bold; - - a { - padding: 0 5px 0 5px; - line-height: 25px; - } - - i { - margin-right: 5px; - } - - li { - display: inline; - - &:hover { - color: var(--link-hover); - } - } -} - -main { - display: flex; - flex-direction: column; - height: 100%; - background: #f1f1f1; - - flex: 1; - box-sizing: border-box; -} - -#dim { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: #000; - opacity: 0.5; - z-index: 5; -} - -#u-box { - display: flex; - align-items: center; - padding: 0 1rem 0 1rem; - height: 60px; - border-bottom: 1px solid var(--input-border); - box-sizing: border-box; - - img { - width: 40px; - height: 40px; - border-radius: 50%; - } - - a { - display: inline-block; - } -} - -#app-message-container { - position: absolute; - margin: 0 auto; - right: 0; - top: 0; - padding: 85px 10px 0 0; - - .log-msg { - z-index: 11; - position: relative; - margin: 0 auto; - right: 0; - top: 0; - margin-bottom: 10px; - } -} - -@import "timerecording_media"; \ No newline at end of file diff --git a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_media.css b/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_media.css deleted file mode 100755 index cc491bf..0000000 --- a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_media.css +++ /dev/null @@ -1,39 +0,0 @@ -@media only screen and (min-width: 1101px) { - .b-1 { - width: 31.5%; - width: calc(33.3% - 10px); } - - .b-2 { - width: 48.5%; - width: calc(50% - 10px); } - - .b-3 { - width: 63%; - width: calc(66.6% - 10px); } } -@media only screen and (min-width: 801px) and (max-width: 1100px) { - .b-1 { - width: 48.5%; - width: calc(50% - 10px); } } -@media only screen and (max-width: 1100px) { - .b-2, .b-3 { - width: 100%; - width: calc(100% - 10px); } } -@media only screen and (min-width: 801px) { - .b-4 { - width: 48.5%; - width: calc(50% - 10px); } } -@media only screen and (max-width: 800px) { - .b-1, .b-3 { - width: 100%; - width: calc(100% - 10px); } - - #logo { - display: none; } - - #s-nav { - width: 100%; } - - #s-bar input[type=text] { - margin-left: 35px; - width: 80%; - width: calc(100% - 90px); } } diff --git a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_media.scss b/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_media.scss deleted file mode 100755 index 089e346..0000000 --- a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_media.scss +++ /dev/null @@ -1,22 +0,0 @@ -@media only screen and (max-width: 600px) { - header { - flex-flow: column; - height: auto; - padding: 1rem; - - form { - width: 100%; - } - } - - nav { - order: -1; - margin-bottom: .5rem; - } -} - -@media only screen and (max-width: 1000px) { - nav .link { - display: none; - } -} \ No newline at end of file diff --git a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_vars.css b/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_vars.css deleted file mode 100755 index 1f5ee22..0000000 --- a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_vars.css +++ /dev/null @@ -1,24 +0,0 @@ -:root { - --main-background: rgb(46, 26, 90); - --main-background-highlight: rgb(158, 81, 197); - --input-border: rgba(166, 135, 232, .4); - --input-border-active: rgba(166, 135, 232, .7); - --input-color: rgba(166, 135, 232, .6); - --input-color-active: rgba(166, 135, 232, .8); - --input-icon-color: rgba(166, 135, 232, .6); - --input-icon-color-active: rgba(166, 135, 232, 1); - --button-main-background: rgba(166, 135, 232, .6); - --button-main-background-active: rgba(166, 135, 232, .8); - --button-main-color: rgba(255, 255, 255, .9); - --text-on-background-color: rgba(255, 255, 255, 0.7); - --nav-category-background: rgb(43, 58, 101); - --nav-category-background-highlight: rgb(113, 43, 145); - --nav-category-background-hover: rgb(120, 50, 153); - --nav-sub-background: rgb(72, 39, 102); - --nav-sub-background-highlight: rgb(94, 52, 133); - --nav-sub-background-hover: rgb(116, 67, 161); - --nav-header-background: rgb(72, 39, 102); - --nav-header-background-highlight: rgb(94, 52, 133); - --nav-header-background-hover: rgb(116, 67, 161); - --font-family: 'Roboto', sans-serif; - --box-border-color: rgb(202, 202, 202); } diff --git a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_vars.scss b/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_vars.scss deleted file mode 100755 index d13715e..0000000 --- a/Application/Ticket/Timerecording/Themes/Akebi/css/timerecording_vars.scss +++ /dev/null @@ -1,55 +0,0 @@ -:root { - --main-background: rgb(46, 26, 90); - --main-background-highlight: rgb(158, 81, 197); - - --input-border: rgba(166, 135, 232, .4); - --input-border-active: rgba(166, 135, 232, .7); - --input-color: rgb(116, 67, 161); - --input-color-active: rgb(94, 52, 133); - --input-background: rgba(255, 255, 255); - --input-background-active: rgba(255, 255, 255); - - --input-icon-color: rgba(166, 135, 232, .6); - --input-icon-color-active: rgba(166, 135, 232, 1); - - --button-main-background: rgba(166, 135, 232, .6); - --button-main-background-active: rgba(166, 135, 232, .8); - --button-main-color: rgba(255, 255, 255, .9); - - --text-on-background-color: rgba(255, 255, 255, 0.7); - --text-on-background-color-2: rgba(255, 255, 255, 0.85); - - --nav-category-background: rgb(43, 58, 101); - --nav-category-background-highlight: rgb(113, 43, 145); - --nav-category-background-hover: rgb(120, 50, 153); - - --nav-sub-background: rgb(72, 39, 102); - --nav-sub-background-highlight: rgb(94, 52, 133); - --nav-sub-background-hover: rgb(116, 67, 161); - - --nav-header-background: rgb(72, 39, 102); - --nav-header-background-highlight: rgb(94, 52, 133); - --nav-header-background-hover: rgb(116, 67, 161); - - --nav-content-hover: rgb(177, 97, 218); - - --font-family: 'Roboto', sans-serif; - - --button-colored-background: rgb(158, 81, 197); - --button-colored-background-hover: rgb(177, 97, 218); - - --table-caption-background: rgb(255, 255, 255); - --table-head-background: rgb(236, 232, 255); - --table-row-background: rgb(255, 255, 255); - --table-row-background-alt: rgb(255, 255, 255); - --table-row-background-hover: rgb(220, 211, 255); - - --link-color: rgb(72, 39, 102); - --link-hover: rgb(158, 81, 197); - - --badge-size: .55rem; - --badge-color: rgb(255, 255, 255); - --badge-background: rgb(158, 81, 197); - - --box-border: rgb(218, 218, 218); -} diff --git a/Application/Ticket/Timerecording/TimerecordingView.php b/Application/Ticket/Timerecording/TimerecordingView.php deleted file mode 100755 index 8805237..0000000 --- a/Application/Ticket/Timerecording/TimerecordingView.php +++ /dev/null @@ -1,116 +0,0 @@ -nav = $nav; - } - - /** - * Set user profile. - * - * @param Profile $profile user account - * - * @return void - * - * @since 1.0.0 - * @codeCoverageIgnore - */ - public function setProfile(Profile $profile) : void - { - $this->profile = $profile; - } - - /** - * Get profile image - * - * @return string Profile image link - * - * @since 1.0.0 - */ - public function getProfileImage() : string - { - if ($this->profile === null || $this->profile->image->getPath() === '') { - return UriFactory::build('Web/Timerecording/img/user_default_' . \mt_rand(1, 6) . '.png'); - } - - return UriFactory::build($this->profile->image->getPath()); - } - - /** - * Set organizations - * - * @param Unit[] $organizations Organizations - * - * @return void - * - * @since 1.0.0 - * @codeCoverageIgnore - */ - public function setOrganizations(array $organizations) : void - { - $this->organizations = $organizations; - } -} diff --git a/Application/Ticket/Timerecording/img/favicon.ico b/Application/Ticket/Timerecording/img/favicon.ico deleted file mode 100755 index ec514e2..0000000 Binary files a/Application/Ticket/Timerecording/img/favicon.ico and /dev/null differ diff --git a/Application/Ticket/Timerecording/img/logo.png b/Application/Ticket/Timerecording/img/logo.png deleted file mode 100755 index 27d7f3c..0000000 Binary files a/Application/Ticket/Timerecording/img/logo.png and /dev/null differ diff --git a/Application/Ticket/Timerecording/js/global/ActionEvents.js b/Application/Ticket/Timerecording/js/global/ActionEvents.js deleted file mode 100755 index 54e6334..0000000 --- a/Application/Ticket/Timerecording/js/global/ActionEvents.js +++ /dev/null @@ -1,5 +0,0 @@ -import { redirectMessage } from '../../../../jsOMS/Model/Message/Redirect.js'; - -export const ACTION_EVENTS = { - 'redirect': redirectMessage, /** global: redirectMessage */ -}; \ No newline at end of file diff --git a/Application/Ticket/Timerecording/js/global/KeyboardEvents.js b/Application/Ticket/Timerecording/js/global/KeyboardEvents.js deleted file mode 100755 index 4dc44d1..0000000 --- a/Application/Ticket/Timerecording/js/global/KeyboardEvents.js +++ /dev/null @@ -1,3 +0,0 @@ -/** global: jsOMS */ -export const KEYBOARD_EVENTS = [ -]; \ No newline at end of file diff --git a/Application/Ticket/Timerecording/js/global/MouseEvents.js b/Application/Ticket/Timerecording/js/global/MouseEvents.js deleted file mode 100755 index 1fb6b1e..0000000 --- a/Application/Ticket/Timerecording/js/global/MouseEvents.js +++ /dev/null @@ -1,3 +0,0 @@ -/** global: jsOMS */ -export const MOUSE_EVENTS = [ -]; \ No newline at end of file diff --git a/Application/Ticket/Timerecording/js/global/ResponseEvents.js b/Application/Ticket/Timerecording/js/global/ResponseEvents.js deleted file mode 100755 index 6a3eed5..0000000 --- a/Application/Ticket/Timerecording/js/global/ResponseEvents.js +++ /dev/null @@ -1,12 +0,0 @@ -import { notifyMessage } from '../../../../jsOMS/Model/Message/Notify.js'; -import { formValidationMessage } from '../../../../jsOMS/Model/Message/FormValidation.js'; -import { redirectMessage } from '../../../../jsOMS/Model/Message/Redirect.js'; -import { reloadMessage } from '../../../../jsOMS/Model/Message/Reload.js'; - -/** global: jsOMS */ -export const RESPONSE_EVENTS = { - 'notify': notifyMessage, /** global: notifyMessage */ - 'validation': formValidationMessage, /** global: formValidationMessage */ - 'redirect': redirectMessage, /** global: redirectMessage */ - 'reload': reloadMessage /** global: reloadMessage */ -}; \ No newline at end of file diff --git a/Application/Ticket/Timerecording/js/global/TouchEvents.js b/Application/Ticket/Timerecording/js/global/TouchEvents.js deleted file mode 100755 index 72a2598..0000000 --- a/Application/Ticket/Timerecording/js/global/TouchEvents.js +++ /dev/null @@ -1,2 +0,0 @@ -/** global: jsOMS */ -export const TOUCH_EVENTS = {}; \ No newline at end of file diff --git a/Application/Ticket/Timerecording/js/global/VoiceEvents.js b/Application/Ticket/Timerecording/js/global/VoiceEvents.js deleted file mode 100755 index 31905de..0000000 --- a/Application/Ticket/Timerecording/js/global/VoiceEvents.js +++ /dev/null @@ -1,6 +0,0 @@ -import { Logger } from '../../../../jsOMS/Log/Logger.js'; - -/** global: jsOMS */ -export const VOICE_EVENTS = { - 'login': function() { document.getElementById('iCameraLoginButton').click(); }, -}; \ No newline at end of file diff --git a/Application/Ticket/Timerecording/js/login.js b/Application/Ticket/Timerecording/js/login.js deleted file mode 100755 index aa62637..0000000 --- a/Application/Ticket/Timerecording/js/login.js +++ /dev/null @@ -1,90 +0,0 @@ -jsOMS.ready(function () -{ - "use strict"; - - const logo = document.getElementById('login-logo'); - const cLogin = document.getElementById('iCameraLoginButton'); - const pLogin = document.getElementById('iPasswordLoginButton'); - const cancel = document.getElementsByClassName('cancelButton'); - const cancelLength = cancel.length; - let timer = 10000; - - cLogin.addEventListener('click', function() { - if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { - const clock = document.getElementById('iCameraCountdownClock'); - const countdown = document.getElementById('iCameraCountdown'); - const video = document.getElementById('iVideoCanvas'); - - navigator.mediaDevices.getUserMedia({ video: true, audio: false }).then(function(stream) { - video.srcObject = stream; - video.play(); - - jsOMS.addClass(logo, 'hidden'); - jsOMS.addClass(cLogin, 'hidden'); - jsOMS.addClass(pLogin, 'hidden'); - jsOMS.removeClass(document.getElementById('cameraLogin'), 'hidden'); - - timer = 10000; - clock.innerHTML = timer / 1000; - - jsOMS.removeClass(countdown, 'hidden'); - - const cameraTimer = setInterval(function() { - timer -= 100; - - if (timer % 1000 === 0) { - clock.innerHTML = timer / 1000; - } - - if (timer <= 0) { - jsOMS.addClass(document.getElementById('cameraLogin'), 'hidden'); - jsOMS.removeClass(cLogin, 'hidden'); - jsOMS.removeClass(pLogin, 'hidden'); - jsOMS.removeClass(logo, 'hidden'); - - video.pause(); - stream.getVideoTracks()[0].stop();; - - clearInterval(cameraTimer); - } - }, 100); - }); - } - }); - - pLogin.addEventListener('click', function() { - const clock = document.getElementById('iPasswordCountdownClock'); - const countdown = document.getElementById('iPasswordCountdown'); - - jsOMS.addClass(pLogin, 'hidden'); - jsOMS.addClass(cLogin, 'hidden'); - jsOMS.removeClass(document.getElementById('passwordLogin'), 'hidden'); - - timer = 10000; - clock.innerHTML = timer / 1000; - - jsOMS.removeClass(countdown, 'hidden'); - - const passwordTimer = setInterval(function() { - timer -= 100; - - if (timer % 1000 === 0) { - clock.innerHTML = timer / 1000; - } - - if (timer <= 0) { - jsOMS.addClass(document.getElementById('passwordLogin'), 'hidden'); - jsOMS.removeClass(pLogin, 'hidden'); - jsOMS.removeClass(cLogin, 'hidden'); - - clearInterval(passwordTimer); - } - }, 100); - }); - - for (let i = 0; i < cancelLength; ++i) { - cancel[i].addEventListener('click', function() { - timer = 0; - }); - } -}); diff --git a/Application/Ticket/Timerecording/js/timerecording.js b/Application/Ticket/Timerecording/js/timerecording.js deleted file mode 100755 index dfbf7bf..0000000 --- a/Application/Ticket/Timerecording/js/timerecording.js +++ /dev/null @@ -1,137 +0,0 @@ -import { AssetManager } from '../../../jsOMS/Asset/AssetManager.js'; -import { Logger } from '../../../jsOMS/Log/Logger.js'; -import { CacheManager } from '../../../jsOMS/DataStorage/CacheManager.js'; -import { StorageManager } from '../../../jsOMS/DataStorage/StorageManager.js'; -import { EventManager } from '../../../jsOMS/Event/EventManager.js'; -import { ResponseManager } from '../../../jsOMS/Message/Response/ResponseManager.js'; -import { Dispatcher } from '../../../jsOMS/Dispatcher/Dispatcher.js'; -import { AccountManager } from '../../../jsOMS/Account/AccountManager.js'; -import { UIManager } from '../../../jsOMS/UI/UIManager.js'; -import { InputManager } from '../../../jsOMS/UI/Input/InputManager.js'; -import { ModuleManager } from '../../../jsOMS/Module/ModuleManager.js'; -import { ReadManager } from '../../../jsOMS/UI/Input/Voice/ReadManager.js'; -import { VoiceManager } from '../../../jsOMS/UI/Input/Voice/VoiceManager.js'; -import { NotificationManager } from '../../../jsOMS/Message/Notification/NotificationManager.js'; -import { HttpUri } from '../../../jsOMS/Uri/HttpUri.js'; -import { UriFactory } from '../../../jsOMS/Uri/UriFactory.js'; - -import { ACTION_EVENTS } from './global/ActionEvents.js'; -import { KEYBOARD_EVENTS } from './global/KeyboardEvents.js'; -import { MOUSE_EVENTS } from './global/MouseEvents.js'; -import { RESPONSE_EVENTS } from './global/ResponseEvents.js'; -import { TOUCH_EVENTS } from './global/TouchEvents.js'; -import { VOICE_EVENTS } from './global/VoiceEvents.js'; - -export class Application { - constructor () - { - //jsOMS.Autoloader.initPreloaded(); - - this.logger = Logger.getInstance(); - window.logger = this.logger; - - this.cacheManager = new CacheManager(); - this.storageManager = new StorageManager(); - this.eventManager = new EventManager(); - this.responseManager = new ResponseManager(); - this.dispatcher = new Dispatcher(); - this.assetManager = new AssetManager(); - this.accountManager = new AccountManager(); - this.uiManager = new UIManager(this); - this.inputManager = new InputManager(this); - this.moduleManager = new ModuleManager(this); - this.readManager = new ReadManager(); - this.voiceManager = new VoiceManager(this); - this.notifyManager = new NotificationManager(); - this.request = new HttpUri(window.location.href); - - this.request.setRootPath( - HttpUri.parseUrl( - document.getElementsByTagName('base')[0].href - ).path - ); - - this.setResponseMessages(); - - this.setActions(); - this.setKeyboardActions(); - this.setMouseActions(); - this.setVoiceActions(); - - UriFactory.setupUriBuilder(this.request); - UriFactory.setQuery('/lang', window.location.href.substr(this.request.getBase().length).split('/')[0]); - - this.uiManager.bind(); - }; - - setResponseMessages () - { - /** global: RESPONSE_EVENTS */ - for (const key in RESPONSE_EVENTS) { - if (RESPONSE_EVENTS.hasOwnProperty(key)) { - this.responseManager.add(key, RESPONSE_EVENTS[key]); - } - } - }; - - setActions () - { - /** global: ACTION_EVENTS */ - for (const key in ACTION_EVENTS) { - if (ACTION_EVENTS.hasOwnProperty(key)) { - this.uiManager.getActionManager().add(key, ACTION_EVENTS[key]); - } - } - }; - - setKeyboardActions () - { - /** global: KEYBOARD_EVENTS */ - let length = KEYBOARD_EVENTS.length; - - for (let i = 0; i < length; i++) { - this.inputManager.getKeyboardManager().add( - KEYBOARD_EVENTS[i]['element'], - KEYBOARD_EVENTS[i]['keys'], - KEYBOARD_EVENTS[i]['callback'] - ); - } - }; - - setMouseActions () - { - /** global: MOUSE_EVENTS */ - let length = MOUSE_EVENTS.length; - - for (let i = 0; i < length; i++) { - this.inputManager.getMouseManager().add( - MOUSE_EVENTS[i]['element'], - MOUSE_EVENTS[i]['type'], - MOUSE_EVENTS[i]['button'], - MOUSE_EVENTS[i]['callback'], - MOUSE_EVENTS[i]['exact'] - ); - } - }; - - setVoiceActions () - { - /** global: VOICE_EVENTS */ - for (const key in VOICE_EVENTS) { - if (VOICE_EVENTS.hasOwnProperty(key)) { - this.voiceManager.add(key, VOICE_EVENTS[key]); - } - } - - this.voiceManager.setup(); - this.voiceManager.start(); - }; -}; - -jsOMS.ready(function () -{ - "use strict"; - - /** global: jsOMS */ - window.omsApp = new Application(); -}); diff --git a/Application/Ticket/Timerecording/lang/en.lang.php b/Application/Ticket/Timerecording/lang/en.lang.php deleted file mode 100755 index 2e62356..0000000 --- a/Application/Ticket/Timerecording/lang/en.lang.php +++ /dev/null @@ -1,27 +0,0 @@ - 'Camera Login', - 'Cancel' => 'Cancel', - 'IDCard' => 'ID Card', - 'Login' => 'Login', - 'Logo' => 'Logo', - 'Password' => 'Password', - 'PasswordLogin' => 'Password Login', - 'TimerCamera' => 'Camera turns off in: %s (s)', - 'TimerLogin' => 'Login turns off in: %s (s)', - 'Username' => 'Username', - ':meta' => 'Time recording application', -]]; diff --git a/Application/Ticket/Timerecording/login.tpl.php b/Application/Ticket/Timerecording/login.tpl.php deleted file mode 100755 index eebdd6e..0000000 --- a/Application/Ticket/Timerecording/login.tpl.php +++ /dev/null @@ -1,267 +0,0 @@ -getData('head'); -?> - - - - - - - - - - - - - meta->render(); ?> - <?= $this->printHtml($head->title); ?> - - - renderAssets(); ?> - - - -
- -
-
- - - - -
-
-
-renderAssetsLate(); ?> diff --git a/Application/Ticket/Timerecording/manifest.json b/Application/Ticket/Timerecording/manifest.json deleted file mode 100755 index b84f605..0000000 --- a/Application/Ticket/Timerecording/manifest.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "lang": "en", - "dir": "ltr", - "start_url": "../../en/timerecording", - "type": "privileged", - "name": "Orange Management Time Recording", - "description": "OMS timerecording application.", - "short_name": "OMS Backend", - "icons": [ - { - "src": "/Web/Timerecording/img/logo.png", - "sizes": "64x64 128x128 256x256 512x512", - "type": "image/png", - "purpose": "any maskable" - } - ], - "scope": "/", - "display": "standalone", - "orientation": "any", - "theme_color": "#712b91", - "background_color": "white", - "permissions": { - "audio-capture" : { - "description" : "Audio capture" - }, - "video-capture": { - "description": "Video capture" - }, - "speech-recognition" : { - "description" : "Speech recognition" - } - } -} \ No newline at end of file diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 4556493..0ad2bfa 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -16,10 +16,13 @@ namespace Modules\Support\Controller; use Modules\Admin\Models\NullAccount; use Modules\Tag\Models\NullTag; -use Modules\Tasks\Models\Task; -use Modules\Tasks\Models\TaskElement; -use Modules\Tasks\Models\TaskElementMapper; -use Modules\Tasks\Models\TaskMapper; +use Modules\Support\Models\Ticket; +use Modules\Support\Models\TicketElement; +use Modules\Support\Models\TicketElementMapper; +use Modules\Support\Models\TicketMapper; +use Modules\Support\Models\SupportApp; +use Modules\Support\Models\NullSupportApp; +use Modules\Support\Models\SupportAppMapper; use Modules\Tasks\Models\TaskStatus; use Modules\Tasks\Models\TaskType; use phpOMS\Message\Http\HttpResponse; @@ -31,22 +34,17 @@ use phpOMS\Model\Message\FormValidation; use phpOMS\Utils\Parser\Markdown\Markdown; /** - * Api controller for the tasks module. + * Api controller for the tickets module. * * @package Modules\Support * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 - * - * @todo Orange-Management/Modules#33 - * Repeating tasks should be implemented. - * At the same time this means a fix to the due date needs to be implemented. - * Maybe simple calculate the time difference between first start and first due? */ final class ApiController extends Controller { /** - * Validate task create request + * Validate ticket create request * * @param RequestAbstract $request Request * @@ -67,7 +65,7 @@ final class ApiController extends Controller } /** - * Api method to create a task + * Api method to create a ticket * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -88,67 +86,38 @@ final class ApiController extends Controller return; } - $task = $this->createTicketFromRequest($request); - $this->createModel($request->header->account, $task, TaskMapper::class, 'task', $request->getOrigin()); - $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Task', 'Task successfully created.', $task); + $ticket = $this->createTicketFromRequest($request); + + $this->createModel($request->header->account, $ticket, TicketMapper::class, 'ticket', $request->getOrigin()); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Ticket', 'Ticket successfully created.', $ticket); } /** - * Method to create task from request. + * Method to create ticket from request. * * @param RequestAbstract $request Request * - * @return Task Returns the created task from the request + * @return Ticket Returns the created ticket from the request * * @since 1.0.0 */ - private function createTicketFromRequest(RequestAbstract $request) : Task + private function createTicketFromRequest(RequestAbstract $request) : Ticket { - $task = new Task(); - $task->title = (string) ($request->getData('title') ?? ''); - $task->description = Markdown::parse((string) ($request->getData('plain') ?? '')); - $task->descriptionRaw = (string) ($request->getData('plain') ?? ''); - $task->setCreatedBy(new NullAccount($request->header->account)); - $task->setStatus(TaskStatus::OPEN); - $task->setType(TaskType::SINGLE); + $task = $this->app->moduleManager->get('Tasks')->createTaskFromRequest($request); + $task->setType(TaskType::HIDDEN); - if (empty($request->getData('priority'))) { - $task->due = empty($request->getData('due')) ? null : new \DateTime($request->getData('due')); - } else { - $task->setPriority((int) $request->getData('priority')); + $ticket = new Ticket($task); + $ticket->app = new NullSupportApp((int) ($request->getData('app') ?? 1)); + + if ($request->getData('for') !== null) { + $ticket->for = new NullAccount((int) $request->getData('for')); } - if (!empty($tags = $request->getDataJson('tags'))) { - foreach ($tags as $tag) { - if (!isset($tag['id'])) { - $request->setData('title', $tag['title'], true); - $request->setData('color', $tag['color'], true); - $request->setData('icon', $tag['icon'] ?? null, true); - $request->setData('language', $tag['language'], true); - - $internalResponse = new HttpResponse(); - $this->app->moduleManager->get('Tag')->apiTagCreate($request, $internalResponse, null); - $task->addTag($internalResponse->get($request->uri->__toString())['response']); - } else { - $task->addTag(new NullTag((int) $tag['id'])); - } - } - } - - $element = new TaskElement(); - $element->addTo(new NullAccount((int) ($request->getData('forward') ?? $request->header->account))); - $element->createdBy = $task->getCreatedBy(); - $element->due = $task->due; - $element->setPriority($task->getPriority()); - $element->setStatus(TaskStatus::OPEN); - - $task->addElement($element); - - return $task; + return $ticket; } /** - * Api method to get a task + * Api method to get a ticket * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -162,12 +131,12 @@ final class ApiController extends Controller */ public function apiTicketGet(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { - $task = TaskMapper::get((int) $request->getData('id')); - $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Task', 'Task successfully returned.', $task); + $ticket = TicketMapper::get((int) $request->getData('id')); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Ticket', 'Ticket successfully returned.', $ticket); } /** - * Api method to update a task + * Api method to update a ticket * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -181,37 +150,30 @@ final class ApiController extends Controller */ public function apiTicketSet(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { - $old = clone TaskMapper::get((int) $request->getData('id')); + $old = clone TicketMapper::get((int) $request->getData('id')); $new = $this->updateTicketFromRequest($request); - $this->updateModel($request->header->account, $old, $new, TaskMapper::class, 'task', $request->getOrigin()); - $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Task', 'Task successfully updated.', $new); + $this->updateModel($request->header->account, $old, $new, TicketMapper::class, 'ticket', $request->getOrigin()); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Ticket', 'Ticket successfully updated.', $new); } /** - * Method to update an task from a request + * Method to update an ticket from a request * * @param RequestAbstract $request Request * - * @return Task Returns the updated task from the request + * @return Ticket Returns the updated ticket from the request * * @since 1.0.0 */ - private function updateTicketFromRequest(RequestAbstract $request) : Task + private function updateTicketFromRequest(RequestAbstract $request) : Ticket { - $task = TaskMapper::get((int) ($request->getData('id'))); - $task->title = (string) ($request->getData('title') ?? $task->getTitle()); - $task->description = Markdown::parse((string) ($request->getData('plain') ?? $task->descriptionRaw)); - $task->descriptionRaw = (string) ($request->getData('plain') ?? $task->descriptionRaw); - $task->due = new \DateTime((string) ($request->getData('due') ?? $task->getDue()->format('Y-m-d H:i:s'))); - $task->setStatus((int) ($request->getData('status') ?? $task->getStatus())); - $task->setType((int) ($request->getData('type') ?? $task->getType())); - $task->setPriority((int) ($request->getData('priority') ?? $task->getPriority())); + $ticket = TicketMapper::get((int) ($request->getData('id'))); - return $task; + return $ticket; } /** - * Validate task element create request + * Validate ticket element create request * * @param RequestAbstract $request Request * @@ -224,7 +186,7 @@ final class ApiController extends Controller $val = []; if (($val['status'] = !TaskStatus::isValidValue((int) $request->getData('status'))) || ($val['due'] = !((bool) \strtotime((string) $request->getData('due')))) - || ($val['task'] = !(\is_numeric($request->getData('task')))) + || ($val['ticket'] = !(\is_numeric($request->getData('ticket')))) || ($val['forward'] = !(\is_numeric(empty($request->getData('forward')) ? $request->header->account : $request->getData('forward')))) ) { return $val; @@ -234,7 +196,7 @@ final class ApiController extends Controller } /** - * Api method to create a task element + * Api method to create a ticket element * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -249,72 +211,46 @@ final class ApiController extends Controller public function apiTicketElementCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { if (!empty($val = $this->validateTicketElementCreate($request))) { - $response->set('task_element_create', new FormValidation($val)); + $response->set('ticket_element_create', new FormValidation($val)); $response->header->status = RequestStatusCode::R_400; return; } - /** - * @todo Orange-Management/oms-Tasks#3 - * Validate that the user is allowed to create a task element for a specific task - */ + $ticket = TicketMapper::get((int) ($request->getData('ticket'))); + $element = $this->createTicketElementFromRequest($request, $ticket); + $ticket->task->setStatus($element->taskElement->getStatus()); + $ticket->task->setPriority($element->taskElement->getPriority()); + $ticket->task->setDue($element->taskElement->due); - $task = TaskMapper::get((int) ($request->getData('task'))); - $element = $this->createTicketElementFromRequest($request, $task); - $task->setStatus($element->getStatus()); - $task->setPriority($element->getPriority()); - $task->setDue($element->due); - - $this->createModel($request->header->account, $element, TaskElementMapper::class, 'taskelement', $request->getOrigin()); - $this->updateModel($request->header->account, $task, $task, TaskMapper::class, 'task', $request->getOrigin()); - $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Task element', 'Task element successfully created.', $element); + $this->createModel($request->header->account, $element, TicketElementMapper::class, 'ticketelement', $request->getOrigin()); + $this->updateModel($request->header->account, $ticket, $ticket, TicketMapper::class, 'ticket', $request->getOrigin()); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Ticket element', 'Ticket element successfully created.', $element); } /** - * Method to create task element from request. + * Method to create ticket element from request. * * @param RequestAbstract $request Request - * @param Task $task Task + * @param Ticket $ticket Ticket * - * @return TaskElement Returns the task created from the request + * @return TicketElement Returns the ticket created from the request * * @since 1.0.0 */ - private function createTicketElementFromRequest(RequestAbstract $request, Task $task) : TaskElement + private function createTicketElementFromRequest(RequestAbstract $request, Ticket $ticket) : TicketElement { - $element = new TaskElement(); - $element->createdBy = new NullAccount($request->header->account); - $element->due = !empty($request->getData('due')) ? new \DateTime((string) ($request->getData('due'))) : $task->due; - $element->setPriority((int) ($request->getData('priority') ?? $task->getPriority())); - $element->setStatus((int) ($request->getData('status'))); - $element->task = $task->getId(); - $element->description = Markdown::parse((string) ($request->getData('plain') ?? '')); - $element->descriptionRaw = (string) ($request->getData('plain') ?? ''); + $taskElement = $this->app->moduleManager->get('Tasks')->createTaskElementFromRequest($request); - $tos = $request->getData('to') ?? $request->header->account; - if (!\is_array($tos)) { - $tos = [$tos]; - } + $ticketElement = new TicketElement($taskElement); + $ticketElement->time = (int) $request->getData('time') ?? 0; + $ticketElement->ticket = $ticket->getId(); - $ccs = $request->getData('cc') ?? []; - if (!\is_array($ccs)) { - $ccs = [$ccs]; - } - - foreach ($tos as $to) { - $element->addTo(new NullAccount((int) $to)); - } - - foreach ($ccs as $cc) { - $element->addCC(new NullAccount((int) $cc)); - } - - return $element; + return $ticketElement; } /** - * Api method to get a task + * Api method to get a ticket * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -328,12 +264,12 @@ final class ApiController extends Controller */ public function apiTicketElementGet(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { - $task = TaskElementMapper::get((int) $request->getData('id')); - $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Task element', 'Task element successfully returned.', $task); + $ticket = TicketElementMapper::get((int) $request->getData('id')); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Ticket element', 'Ticket element successfully returned.', $ticket); } /** - * Api method to update a task + * Api method to update a ticket * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -347,32 +283,26 @@ final class ApiController extends Controller */ public function apiTicketElementSet(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { - $old = clone TaskElementMapper::get((int) $request->getData('id')); + $old = clone TicketElementMapper::get((int) $request->getData('id')); $new = $this->updateTicketElementFromRequest($request); - $this->updateModel($request->header->account, $old, $new, TaskElementMapper::class, 'taskelement', $request->getOrigin()); + $this->updateModel($request->header->account, $old, $new, TicketElementMapper::class, 'ticketelement', $request->getOrigin()); - /** - * @todo Orange-Management/oms-Tasks#2 - * Update task status depending on the new task element or updated task element - * The task status is not normalized and relates to the last task element. - * Depending on the task status of the last task element also the task status should change. - */ - //$this->updateModel($request->header->account, $task, $task, TaskMapper::class, 'task', $request->getOrigin()); - $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Task element', 'Task element successfully updated.', $new); + //$this->updateModel($request->header->account, $ticket, $ticket, TicketMapper::class, 'ticket', $request->getOrigin()); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Ticket element', 'Ticket element successfully updated.', $new); } /** - * Method to update an task element from a request + * Method to update an ticket element from a request * * @param RequestAbstract $request Request * - * @return TaskElement Returns the updated task element from the request + * @return TaskElement Returns the updated ticket element from the request * * @since 1.0.0 */ private function updateTicketElementFromRequest(RequestAbstract $request) : TaskElement { - $element = TaskElementMapper::get((int) ($request->getData('id'))); + $element = TicketElementMapper::get((int) ($request->getData('id'))); $element->setDue(new \DateTime((string) ($request->getData('due') ?? $element->getDue()->format('Y-m-d H:i:s')))); $element->setStatus((int) ($request->getData('status') ?? $element->getStatus())); $element->description = Markdown::parse((string) ($request->getData('plain') ?? $element->descriptionRaw)); @@ -398,4 +328,68 @@ final class ApiController extends Controller return $element; } + + /** + * Api method to create a category + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiSupportAppCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void + { + if (!empty($val = $this->validateSupportAppCreate($request))) { + $response->set('qa_app_create', new FormValidation($val)); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $app = $this->createSupportAppFromRequest($request); + $this->createModel($request->header->account, $app, SupportAppMapper::class, 'app', $request->getOrigin()); + + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'App', 'App successfully created.', $app); + } + + /** + * Method to create app from request. + * + * @param RequestAbstract $request Request + * + * @return SupportApp Returns the created app from the request + * + * @since 1.0.0 + */ + public function createSupportAppFromRequest(RequestAbstract $request) : SupportApp + { + $app = new SupportApp(); + $app->name = $request->getData('name') ?? ''; + + return $app; + } + + /** + * Validate app create request + * + * @param RequestAbstract $request Request + * + * @return array Returns the validation array of the request + * + * @since 1.0.0 + */ + private function validateSupportAppCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['name'] = empty($request->getData('name')))) { + return $val; + } + + return []; + } } diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 9afe6be..2f022d4 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -15,10 +15,12 @@ declare(strict_types=1); namespace Modules\Support\Controller; use Modules\Support\Models\TicketMapper; +use Modules\Support\Views\TicketView; use phpOMS\Contract\RenderableInterface; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; use phpOMS\Views\View; +use phpOMS\Asset\AssetType; /** * Support controller class. @@ -44,12 +46,32 @@ final class BackendController extends Controller */ public function viewSupportList(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface { + $head = $response->get('Content')->getData('head'); + $head->addAsset(AssetType::CSS, 'Modules/Tasks/Theme/Backend/css/styles.css'); + $view = new View($this->app->l11nManager, $request, $response); $view->setTemplate('/Modules/Support/Theme/Backend/support-list'); $view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1002901101, $request, $response)); - $tickets = TicketMapper::getAll(); - $view->setData('tickets', $tickets); + if ($request->getData('ptype') === 'p') { + $view->setData('tickets', + TicketMapper::with('language', $response->getLanguage()) + ::with('ticketElements', models: null) + ::getBeforePivot((int) ($request->getData('id') ?? 0), limit: 25) + ); + } elseif ($request->getData('ptype') === 'n') { + $view->setData('tickets', + TicketMapper::with('language', $response->getLanguage()) + ::with('ticketElements', models: null) + ::getAfterPivot((int) ($request->getData('id') ?? 0), limit: 25) + ); + } else { + $view->setData('tickets', + TicketMapper::with('language', $response->getLanguage()) + ::with('ticketElements', models: null) + ::getAfterPivot(0, limit: 25) + ); + } return $view; } @@ -68,13 +90,20 @@ final class BackendController extends Controller */ public function viewSupportTicket(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface { - $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Modules/Support/Theme/Backend/ticket-single'); + $view = new TicketView($this->app->l11nManager, $request, $response); + + $view->setTemplate('/Modules/Support/Theme/Backend/support-ticket'); $view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1002901101, $request, $response)); $ticket = TicketMapper::get((int) $request->getData('id')); $view->addData('ticket', $ticket); + $accGrpSelector = new \Modules\Profile\Theme\Backend\Components\AccountGroupSelector\BaseView($this->app->l11nManager, $request, $response); + $view->addData('accGrpSelector', $accGrpSelector); + + $editor = new \Modules\Editor\Theme\Backend\Components\Editor\BaseView($this->app->l11nManager, $request, $response); + $view->addData('editor', $editor); + return $view; } diff --git a/Models/Issue.php b/Models/Issue.php deleted file mode 100755 index 7544acf..0000000 --- a/Models/Issue.php +++ /dev/null @@ -1,140 +0,0 @@ -created = new \DateTime('now'); - } - - /** - * Creator. - * - * @var int - * @since 1.0.0 - */ - private ?int $creator = null; - - /** - * Get id. - * - * @return int - * - * @since 1.0.0 - */ - public function getId() : int - { - return $this->id; - } - - /** - * Get created. - * - * @return \DateTime - * - * @since 1.0.0 - */ - public function getCreated() : \DateTime - { - return $this->created; - } - - /** - * Set created. - * - * @param \DateTime $created Date of when the article got created - * - * @return void - * - * @since 1.0.0 - */ - public function setCreated($created) : void - { - $this->created = $created; - } - - /** - * Get creator. - * - * @return mixed - * - * @since 1.0.0 - */ - public function getCreator() - { - return $this->creator; - } - - /** - * Set creator. - * - * @param mixed $creator Creator - * - * @return void - * - * @since 1.0.0 - */ - public function setCreator($creator) : void - { - $this->creator = $creator; - } -} diff --git a/Models/Message.php b/Models/Message.php deleted file mode 100755 index d82d050..0000000 --- a/Models/Message.php +++ /dev/null @@ -1,138 +0,0 @@ -created = new \DateTime('now'); - } - - /** - * Get id. - * - * @return int - * - * @since 1.0.0 - */ - public function getId() : int - { - return $this->id; - } - - /** - * Get created. - * - * @return \DateTime - * - * @since 1.0.0 - */ - public function getCreated() : \DateTime - { - return $this->created; - } - - /** - * Set created. - * - * @return void - * - * @since 1.0.0 - */ - public function setCreated($created) : void - { - $this->created = $created; - } - - /** - * Get creator. - * - * @return mixed - * - * @since 1.0.0 - */ - public function getCreator() - { - return $this->creator; - } - - /** - * Set creator. - * - * @param mixed $creator Creator - * - * @return void - * - * @since 1.0.0 - */ - public function setCreator($creator) : void - { - $this->creator = $creator; - } -} diff --git a/Models/NullSupportApp.php b/Models/NullSupportApp.php new file mode 100644 index 0000000..94ba7ea --- /dev/null +++ b/Models/NullSupportApp.php @@ -0,0 +1,38 @@ +id = $id; + } +} diff --git a/Models/NullTicketElement.php b/Models/NullTicketElement.php new file mode 100644 index 0000000..7061d6b --- /dev/null +++ b/Models/NullTicketElement.php @@ -0,0 +1,39 @@ +id = $id; + parent::__construct(); + } +} diff --git a/Models/SupportApp.php b/Models/SupportApp.php new file mode 100644 index 0000000..2786adb --- /dev/null +++ b/Models/SupportApp.php @@ -0,0 +1,73 @@ +id; + } + + /** + * {@inheritdoc} + */ + public function toArray() : array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + ]; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() + { + return $this->toArray(); + } +} diff --git a/Models/SupportAppMapper.php b/Models/SupportAppMapper.php new file mode 100644 index 0000000..2ef2863 --- /dev/null +++ b/Models/SupportAppMapper.php @@ -0,0 +1,55 @@ + + * @since 1.0.0 + */ + protected static array $columns = [ + 'support_app_id' => ['name' => 'support_app_id', 'type' => 'int', 'internal' => 'id'], + 'support_app_name' => ['name' => 'support_app_name', 'type' => 'string', 'internal' => 'name'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + protected static string $table = 'support_app'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + protected static string $primaryField = 'support_app_id'; +} diff --git a/Models/Ticket.php b/Models/Ticket.php index d5b2dc0..6e67121 100755 --- a/Models/Ticket.php +++ b/Models/Ticket.php @@ -14,11 +14,12 @@ declare(strict_types=1); namespace Modules\Support\Models; +use Modules\Admin\Models\Account; use Modules\Tasks\Models\Task; use Modules\Tasks\Models\TaskType; /** - * Issue class. + * Ticket class. * * @package Modules\Support\Models * @license OMS License 1.0 @@ -35,17 +36,24 @@ class Ticket */ protected int $id = 0; - private $task = null; + public Task $task; + + public SupportApp $app; + + private array $ticketElements = []; + + public ?Account $for = null; /** * Constructor. * * @since 1.0.0 */ - public function __construct() + public function __construct(Task $task = null) { - $this->task = new Task(); + $this->task = $task ?? new Task(); $this->task->setType(TaskType::HIDDEN); + $this->app = new SupportApp(); } /** @@ -61,28 +69,80 @@ class Ticket } /** - * Get task. + * Adding new task element. * - * @return Task + * @param TicketElement $element Ticket element + * + * @return int * * @since 1.0.0 */ - public function getTask() : Task + public function addElement(TicketElement $element) : int { - return $this->task; + $this->ticketElements[] = $element; + + \end($this->ticketElements); + $key = (int) \key($this->ticketElements); + \reset($this->ticketElements); + + return $key; } /** - * Set task. + * Remove Element from list. * - * @param Task $task Task + * @param int $id Ticket element * - * @return void + * @return bool * * @since 1.0.0 */ - public function setTask(Task $task) : void + public function removeElement($id) : bool { - $this->task = $task; + if (isset($this->ticketElements[$id])) { + unset($this->ticketElements[$id]); + + return true; + } + + return false; + } + + /** + * Get ticket elements. + * + * @return TicketElement[] + * + * @since 1.0.0 + */ + public function getTicketElements() : array + { + return $this->ticketElements; + } + + /** + * Get ticket elements in inverted order. + * + * @return TicketElement[] + * + * @since 1.0.0 + */ + public function invertTicketElements() : array + { + return \array_reverse($this->ticketElements); + } + + /** + * Get ticket elements. + * + * @param int $id Element id + * + * @return TicketElement + * + * @since 1.0.0 + */ + public function getTicketElement(int $id) : TicketElement + { + return $this->ticketElements[$id] ?? new NullTicketElement(); } } diff --git a/Models/TicketElement.php b/Models/TicketElement.php new file mode 100644 index 0000000..bd87f89 --- /dev/null +++ b/Models/TicketElement.php @@ -0,0 +1,80 @@ +taskElement = $taskElement ?? new TaskElement(); + } + + /** + * Get id + * + * @return int + * + * @since 1.0.0 + */ + public function getId() : int + { + return $this->id; + } +} \ No newline at end of file diff --git a/Models/TicketElementMapper.php b/Models/TicketElementMapper.php new file mode 100644 index 0000000..4955d8f --- /dev/null +++ b/Models/TicketElementMapper.php @@ -0,0 +1,71 @@ + + * @since 1.0.0 + */ + protected static array $columns = [ + 'support_ticket_element_id' => ['name' => 'support_ticket_element_id', 'type' => 'int', 'internal' => 'id'], + 'support_ticket_element_task_element' => ['name' => 'support_ticket_element_task_element', 'type' => 'int', 'internal' => 'task'], + 'support_ticket_element_time' => ['name' => 'support_ticket_element_time', 'type' => 'int', 'internal' => 'time'], + 'support_ticket_element_ticket' => ['name' => 'support_ticket_element_ticket', 'type' => 'int', 'internal' => 'ticket'], + ]; + + /** + * Has one relation. + * + * @var array + * @since 1.0.0 + */ + protected static array $ownsOne = [ + 'taskElement' => [ + 'mapper' => TaskElementMapper::class, + 'external' => 'support_ticket_element_task_element', + ], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + protected static string $table = 'support_ticket_element'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + protected static string $primaryField = 'support_ticket_element_id'; +} diff --git a/Models/TicketMapper.php b/Models/TicketMapper.php index c222d0b..3fc13a3 100755 --- a/Models/TicketMapper.php +++ b/Models/TicketMapper.php @@ -14,6 +14,7 @@ declare(strict_types=1); namespace Modules\Support\Models; +use Modules\Admin\Models\AccountMapper; use Modules\Tasks\Models\TaskMapper; use phpOMS\DataStorage\Database\DataMapperAbstract; @@ -36,6 +37,8 @@ final class TicketMapper extends DataMapperAbstract protected static array $columns = [ 'support_ticket_id' => ['name' => 'support_ticket_id', 'type' => 'int', 'internal' => 'id'], 'support_ticket_task' => ['name' => 'support_ticket_task', 'type' => 'int', 'internal' => 'task'], + 'support_ticket_for' => ['name' => 'support_ticket_for', 'type' => 'int', 'internal' => 'for'], + 'support_ticket_app' => ['name' => 'support_ticket_app', 'type' => 'int', 'internal' => 'app'], ]; /** @@ -51,6 +54,38 @@ final class TicketMapper extends DataMapperAbstract ], ]; + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + protected static array $hasMany = [ + 'ticketElements' => [ + 'mapper' => TicketElementMapper::class, + 'table' => 'support_ticket_element', + 'self' => 'support_ticket_element_ticket', + 'external' => null, + ], + ]; + + /** + * Belongs to. + * + * @var array + * @since 1.0.0 + */ + protected static array $belongsTo = [ + 'app' => [ + 'mapper' => SupportAppMapper::class, + 'external' => 'support_ticket_app', + ], + 'for' => [ + 'mapper' => AccountMapper::class, + 'external' => 'support_ticket_for', + ], + ]; + /** * Primary table. * diff --git a/Theme/Backend/Lang/Navigation.en.lang.php b/Theme/Backend/Lang/Navigation.en.lang.php index d9a365e..4336434 100755 --- a/Theme/Backend/Lang/Navigation.en.lang.php +++ b/Theme/Backend/Lang/Navigation.en.lang.php @@ -15,4 +15,5 @@ declare(strict_types=1); return ['Navigation' => [ 'Support' => 'Support', 'Ticket' => 'Ticket', + 'Tickets' => 'Tickets', ]]; diff --git a/Theme/Backend/support-list.tpl.php b/Theme/Backend/support-list.tpl.php index 0241252..72f93e7 100755 --- a/Theme/Backend/support-list.tpl.php +++ b/Theme/Backend/support-list.tpl.php @@ -12,11 +12,14 @@ */ declare(strict_types=1); +use phpOMS\Uri\UriFactory; + /** * @var \phpOMS\Views\View $this - * @var \Modules\Tasks\Models\Task[] $tickets + * @var \Modules\Support\Models\Ticket[] $tickets */ $tickets = $this->getData('tickets'); + echo $this->getData('nav')->render(); ?>
@@ -26,26 +29,27 @@ echo $this->getData('nav')->render(); ?> - $ticket) : ++$c; - $url = \phpOMS\Uri\UriFactory::build('{/prefix}support/single?{?}&id=' . $ticket->getId()); - $color = 'darkred'; - if ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::DONE) { $color = 'green'; } - elseif ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::OPEN) { $color = 'darkblue'; } - elseif ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::WORKING) { $color = 'purple'; } - elseif ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::CANCELED) { $color = 'red'; } - elseif ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::SUSPENDED) { $color = 'yellow'; } ?> + $ticket) : ++$c; + $url = UriFactory::build('{/prefix}support/ticket?{?}&id=' . $ticket->getId()); + ?> -
getHtml('Status'); ?> - getHtml('Due'); ?> + getHtml('Priority'); ?> getHtml('Title'); ?> getHtml('Creator'); ?> + getHtml('Assigned'); ?> + getHtml('For'); ?> getHtml('Created'); ?>
getHtml('S' . $ticket->getTask()->getStatus(), 'Tasks'); ?> - printHtml($ticket->getTask()->getDue()->format('Y-m-d H:i')); ?> - printHtml($ticket->getTask()->getTitle()); ?> - printHtml($ticket->getTask()->createdBy->name1); ?> - printHtml($ticket->getTask()->createdAt->format('Y-m-d H:i')); ?> + getHtml('S' . $ticket->task->getStatus(), 'Tasks'); ?> + getHtml('P' . $ticket->task->getPriority(), 'Tasks'); ?> + printHtml($ticket->task->title); ?> + printHtml($ticket->task->createdBy->name1); ?> printHtml($ticket->task->createdBy->name2); ?> + printHtml($ticket->task->createdBy->name1); ?> printHtml($ticket->task->createdBy->name2); ?> + printHtml($ticket->for->name1); ?> printHtml($ticket->for->name2); ?> + printHtml($ticket->task->createdAt->format('Y-m-d H:i')); ?>
getHtml('Empty', '0', '0'); ?> @@ -76,11 +80,11 @@ echo $this->getData('nav')->render(); ?>
getHtml('Settings'); ?>
-
getHtml('Received'); ?>0 -
getHtml('Created'); ?>0 -
getHtml('Forwarded'); ?>0 -
getHtml('AverageAmount'); ?>0 -
getHtml('AverageProcessTime'); ?>0 +
getHtml('All'); ?>0 +
getHtml('Unassigned'); ?>0 +
getHtml('Open'); ?>0 +
getHtml('Unsolved'); ?>0 +
getHtml('Closed'); ?>0
getHtml('InTime'); ?>0
diff --git a/Theme/Backend/support-ticket.tpl.php b/Theme/Backend/support-ticket.tpl.php new file mode 100755 index 0000000..4d98718 --- /dev/null +++ b/Theme/Backend/support-ticket.tpl.php @@ -0,0 +1,404 @@ +getData('ticket'); +$task = $ticket->task; +$taskMedia = $task->getMedia(); +$elements = $task->invertTaskElements(); +$cElements = \count($elements); +$color = 'red'; //$this->getStatus($task->getStatus()); + +echo $this->getData('nav')->render(); ?> + +
+
+
+ isEditable) : ?> + + + +
+
+ + <?= $this->getHtml('User', '0', '0'); ?> + + + printHtml($task->createdBy->name1); ?> - printHtml($task->createdAt->format('Y/m/d H:i')); ?> + + + + getHtml('S' . $task->getStatus(), 'Tasks'); ?> + + +
+
+
+ printHtml($task->title); ?> +
description; ?>
+
+
+
+
+ +
+ + name; ?> + +
+ + +
+ getPriority() === TaskPriority::NONE) : ?> + getHtml('Due'); ?>: printHtml($task->due->format('Y/m/d H:i')); ?> + + getHtml('Priority'); ?>: getHtml('P' . $task->getPriority()); ?> + + + getTags(); foreach ($tags as $tag) : ?> + icon !== null ? '' : ''; ?>printHtml($tag->getL11n()); ?> + +
+
+
+ isEditable && $this->request->header->account === $task->createdBy->getId()) : ?> +
+ + + +
+ +
+
+
+
+ +
+ + isEditable) : ?> + + + $element) : ++$c; ?> + getStatus() !== TaskStatus::OPEN) + || ($previous !== null && $element->getStatus() !== $previous->getStatus()) + ) : ?> +
+
+ getHtml('status_change'), + '' . $this->printHtml($element->createdBy->name1) . '', + $element->createdAt->format('Y-m-d H:i') + ); ?> + + getHtml('S' . $element->getStatus(), 'Tasks'); ?> + +
+
+ + + getPriority() !== $task->getPriority()) + || ($previous !== null && $element->getPriority() !== $previous->getPriority()) + ) : ?> +
+
+ getHtml('priority_change'), + '' . $this->printHtml($element->createdBy->name1) . '', + $element->createdAt->format('Y-m-d H:i') + ); ?> + + getHtml('P' . $element->getPriority()); ?> + +
+
+ + + description !== '') : ?> +
+
+
+ + <?= $this->getHtml('User', '0', '0'); ?> + + + printHtml($element->createdBy->name1); ?> - printHtml($element->createdAt->format('Y-m-d H:i')); ?> + +
+
+ + description !== '') : ?> +
+
description; ?>
+
+ + + + getMedia(); + if (!empty($elementMedia) + || ($task->isEditable + && $this->request->header->account === $element->createdBy->getId()) + ) : ?> +
+ +
+ + name; ?> + +
+ + + getStatus() !== TaskStatus::CANCELED + || $element->getStatus() !== TaskStatus::DONE + || $element->getStatus() !== TaskStatus::SUSPENDED + || $c != $cElements + ) : ?> +
+ getPriority() === TaskPriority::NONE + && ($previous !== null + && $previous->due->format('Y/m/d H:i') !== $element->due->format('Y/m/d H:i') + ) + ) : ?> + getHtml('Due'); ?>: printHtml($element->due->format('Y/m/d H:i')); ?> + getPriority() !== $element->getPriority()) : ?> + getHtml('Priority'); ?>: getHtml('P' . $element->getPriority()); ?> + +
+ + + isEditable + && $this->request->header->account === $element->createdBy->getId() + ) : ?> +
+ + + + +
+ +
+ +
+ + + getTo(); + if (\count($tos) > 1 + || (!empty($tos) && $tos[0]->getRelation()->getId() !== $element->createdBy->getId()) + ) : ?> +
+
+ printHtml($element->createdBy->name1); ?> getHtml('forwarded_to'); ?> + + + printHtml($to->getRelation()->name1); ?> + + printHtml($to->getRelation()->name); ?> + + +
+
+ + +
+
+ +
+
+
+
getHtml('Message'); ?>
+
+
+ getData('editor')->render('task-editor'); ?> +
+ +
+ getData('editor')->getData('text')->render( + 'task-editor', + 'plain', + 'taskElementCreate', + '', '', + '/content', '{/api}task?id={?id}' + ); ?> +
+ +
+ + +
+ +
+ + getData('accGrpSelector')->render('iReceiver', 'to', true); ?> +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ +
+ + +
+
+ +
+ +
+
+
+
+
+ +
+ + +
+
+
+ + +
+
+
+
+
diff --git a/Theme/Backend/ticket-single.tpl.php b/Theme/Backend/ticket-single.tpl.php deleted file mode 100755 index 93d9073..0000000 --- a/Theme/Backend/ticket-single.tpl.php +++ /dev/null @@ -1,113 +0,0 @@ -getData('ticket'); -$elements = $ticket->getTask()->getTaskElements(); -$cElements = \count($elements); - -if ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::OPEN) { $color = 'darkblue'; } -elseif ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::WORKING) { $color = 'purple'; } -elseif ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::CANCELED) { $color = 'red'; } -elseif ($ticket->getTask()->getStatus() === \Modules\Tasks\Models\TaskStatus::SUSPENDED) { $color = 'yellow'; } - -echo $this->getData('nav')->render(); ?> - -
-
-
-

printHtml($ticket->getTask()->getTitle()); ?>

-
-
Due printHtml($ticket->getTask()->getDue()->format('Y-m-d H:i')); ?>
-
Created printHtml($ticket->getTask()->createdAt->format('Y-m-d H:i')); ?>
-
-
-
- printHtml($ticket->getTask()->description); ?> -
-
-
-
-
Created printHtml($ticket->getTask()->createdBy->name1); ?>
- getHtml('S' . $ticket->getTask()->getStatus()); ?> -
-
-
- - $element) : ++$c; - if ($element->getStatus() === \Modules\Tasks\Models\TaskStatus::DONE) { $color = 'green'; } - elseif ($element->getStatus() === \Modules\Tasks\Models\TaskStatus::OPEN) { $color = 'darkblue'; } - elseif ($element->getStatus() === \Modules\Tasks\Models\TaskStatus::WORKING) { $color = 'purple'; } - elseif ($element->getStatus() === \Modules\Tasks\Models\TaskStatus::CANCELED) { $color = 'red'; } - elseif ($element->getStatus() === \Modules\Tasks\Models\TaskStatus::SUSPENDED) { $color = 'yellow'; } ?> -
-
-
printHtml($element->createdBy->name1); ?> - printHtml($element->createdAt->format('Y-m-d H:i')); ?>
- getHtml('S' . $element->getStatus()); ?> -
- - description !== '') : ?> -
-
- printHtml($element->description); ?> -
-
- - -
- getForwarded() !== 0) : ?> -
Forwarded printHtml($element->getForwarded()->getName1()); ?>
- - getStatus() !== \Modules\Tasks\Models\TaskStatus::CANCELED || - $element->getStatus() !== \Modules\Tasks\Models\TaskStatus::DONE || - $element->getStatus() !== \Modules\Tasks\Models\TaskStatus::SUSPENDED || $c != $cElements - ) : ?> -
Due printHtml($element->getDue()->format('Y-m-d H:i')); ?>
- -
- - -
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Views/TicketView.php b/Views/TicketView.php new file mode 100644 index 0000000..21fdecd --- /dev/null +++ b/Views/TicketView.php @@ -0,0 +1,79 @@ +image->getPath() === '') { + return UriFactory::build('Web/Backend/img/user_default_' . \mt_rand(1, 6) . '.png'); + } + + return UriFactory::build($profile->image->getPath()); + } + + /** + * Get task status color. + * + * @param int $status Status + * + * @return string + * + * @since 1.0.0 + */ + public function getStatus(int $status) : string + { + if ($status === TaskStatus::OPEN) { + return 'darkblue'; + } elseif ($status === TaskStatus::DONE) { + return 'green'; + } elseif ($status === TaskStatus::WORKING) { + return 'purple'; + } elseif ($status === TaskStatus::CANCELED) { + return 'red'; + } elseif ($status === TaskStatus::SUSPENDED) { + return 'yellow'; + } + + return 'black'; + } +}