diff --git a/client/src/actions/admin-data-actions.js b/client/src/actions/admin-data-actions.js index 94c9cde5..8926b1f4 100644 --- a/client/src/actions/admin-data-actions.js +++ b/client/src/actions/admin-data-actions.js @@ -12,12 +12,12 @@ export default { }; }, - retrieveMyTickets() { + retrieveMyTickets(closed = 0) { return { type: 'MY_TICKETS', payload: API.call({ path: '/staff/get-tickets', - data: {} + data: {closed} }) }; }, @@ -32,12 +32,12 @@ export default { }; }, - retrieveAllTickets(page = 1) { + retrieveAllTickets(page = 1, query = '', closed = 0) { return { type: 'ALL_TICKETS', payload: API.call({ path: '/staff/get-all-tickets', - data: {page} + data: {page, query, closed} }) }; }, diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js index c3d95be4..86ee0403 100644 --- a/client/src/app-components/ticket-list.js +++ b/client/src/app-components/ticket-list.js @@ -9,6 +9,7 @@ import Table from 'core-components/table'; import Button from 'core-components/button'; import Tooltip from 'core-components/tooltip'; import DropDown from 'core-components/drop-down'; +import Checkbox from 'core-components/checkbox'; class TicketList extends React.Component { static propTypes = { @@ -21,7 +22,9 @@ class TicketList extends React.Component { type: React.PropTypes.oneOf([ 'primary', 'secondary' - ]) + ]), + closedTicketsShown: React.PropTypes.bool, + onClosedTicketsShownChange: React.PropTypes.func }; static defaultProps = { @@ -30,7 +33,8 @@ class TicketList extends React.Component { tickets: [], departments: [], ticketPath: '/dashboard/ticket/', - type: 'primary' + type: 'primary', + closedTicketsShown: false }; state = { @@ -40,12 +44,20 @@ class TicketList extends React.Component { render() { return (
- {(this.props.type === 'secondary' && this.props.showDepartmentDropdown) ? this.renderDepartmentsDropDown() : null} +
+ {(this.props.type === 'secondary' && this.props.showDepartmentDropdown) ? this.renderDepartmentsDropDown() : null} + {this.props.onClosedTicketsShownChange ? this.renderFilterCheckbox() : null} +
); } + + renderFilterCheckbox() { + return + } + renderDepartmentsDropDown() { return (
diff --git a/client/src/app-components/ticket-list.scss b/client/src/app-components/ticket-list.scss index e0cb9ceb..33783043 100644 --- a/client/src/app-components/ticket-list.scss +++ b/client/src/app-components/ticket-list.scss @@ -2,8 +2,19 @@ .ticket-list { - &__department-selector { + &__filters { margin-bottom: 25px; + text-align: left; + } + + &__department-selector { + display: inline-block; + margin-right: 25px; + text-align: center; + } + + &__checkbox { + display: inline-block; } &__number { @@ -52,4 +63,4 @@ &__priority-high { background-color: $primary-red; } -} \ No newline at end of file +} diff --git a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js index ec6be25d..bbc7ef70 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js @@ -20,11 +20,12 @@ class AdminPanelAllTickets extends React.Component { state = { page: 1, - query: '' + query: '', + closedTicketsShown: false }; componentDidMount() { - this.props.dispatch(AdminDataAction.retrieveAllTickets()); + this.updateTicketList(); } render() { @@ -41,6 +42,14 @@ class AdminPanelAllTickets extends React.Component { ); } + updateTicketList() { + this.props.dispatch(AdminDataAction.retrieveAllTickets( + this.state.page, + this.state.query, + this.state.closedTicketsShown*1 + )); + } + getTicketListProps() { return { userId: this.props.userId, @@ -52,28 +61,32 @@ class AdminPanelAllTickets extends React.Component { ticketPath: '/admin/panel/tickets/view-ticket/', onPageChange: this.onPageChange.bind(this), page: this.state.page, - pages: this.props.pages + pages: this.props.pages, + closedTicketsShown: this.state.closedTicketsShown, + onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this) }; } - onSearch(query) { - this.setState({query, page: 1}); + onClosedTicketsShownChange() { + this.setState(function(state) { + return { + closedTicketsShown: !state.closedTicketsShown + }; + }, () => { + this.updateTicketList(); + }); + } - if(query) { - this.props.dispatch(AdminDataAction.searchTickets(query)); - } else { - this.props.dispatch(AdminDataAction.retrieveAllTickets()); - } + onSearch(query) { + this.setState({query, page: 1}, () => { + this.updateTicketList(); + }); } onPageChange(event) { - this.setState({page: event.target.value}); - - if(this.state.query) { - this.props.dispatch(AdminDataAction.searchTickets(this.state.query, event.target.value)); - } else { - this.props.dispatch(AdminDataAction.retrieveAllTickets(event.target.value)); - } + this.setState({page: event.target.value}, () => { + this.updateTicketList(); + }); } } diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js index 2b85418b..a5f827ac 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js @@ -21,6 +21,10 @@ class AdminPanelMyTickets extends React.Component { tickets: [] }; + state = { + closedTicketsShown: false + }; + componentDidMount() { this.props.dispatch(AdminDataAction.retrieveMyTickets()); } @@ -46,10 +50,22 @@ class AdminPanelMyTickets extends React.Component { tickets: this.props.tickets, type: 'secondary', loading: this.props.loading, - ticketPath: '/admin/panel/tickets/view-ticket/' + ticketPath: '/admin/panel/tickets/view-ticket/', + closedTicketsShown: this.state.closedTicketsShown, + onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this) }; } + onClosedTicketsShownChange() { + this.setState(function(state) { + return { + closedTicketsShown: !state.closedTicketsShown + }; + }, () => { + this.props.dispatch(AdminDataAction.retrieveMyTickets(this.state.closedTicketsShown * 1)); + }); + } + onCreateTicket() { ModalContainer.openModal(
diff --git a/client/src/data/languages/br.js b/client/src/data/languages/br.js index d8702d58..952c475b 100644 --- a/client/src/data/languages/br.js +++ b/client/src/data/languages/br.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'privado', 'ENABLE_USER': 'Ativar usuário', 'DISABLE_USER': 'Desativar usuário', + 'SHOW_CLOSED_TICKETS': 'Mostrar ingressos fechados', 'CHART_CREATE_TICKET': 'Chamados criados', 'CHART_CLOSE': 'Chamados fechados', diff --git a/client/src/data/languages/cn.js b/client/src/data/languages/cn.js index 1e419142..290a5512 100644 --- a/client/src/data/languages/cn.js +++ b/client/src/data/languages/cn.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': '私人的', 'ENABLE_USER': '启用用户', 'DISABLE_USER': '禁用用户', + 'SHOW_CLOSED_TICKETS': '显示已关闭的门票', 'CHART_CREATE_TICKET': '已創建門票', 'CHART_CLOSE': '門票已關閉', diff --git a/client/src/data/languages/de.js b/client/src/data/languages/de.js index f82747c4..f2c0c8e6 100644 --- a/client/src/data/languages/de.js +++ b/client/src/data/languages/de.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'Privatgelände', 'ENABLE_USER': 'Benutzer aktivieren', 'DISABLE_USER': 'Benutzer deaktivieren', + 'SHOW_CLOSED_TICKETS': 'Geschlossene Tickets anzeigen', 'CHART_CREATE_TICKET': 'Tickets erstellt', 'CHART_CLOSE': 'Tickets geschlossen', diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 58df9540..85e0f24d 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'Private', 'ENABLE_USER': 'Enable User', 'DISABLE_USER': 'Disable User', + 'SHOW_CLOSED_TICKETS': 'Show Closed Tickets', 'CHART_CREATE_TICKET': 'Tickets created', 'CHART_CLOSE': 'Tickets closed', diff --git a/client/src/data/languages/es.js b/client/src/data/languages/es.js index 59addec6..eedde904 100644 --- a/client/src/data/languages/es.js +++ b/client/src/data/languages/es.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'privado', 'ENABLE_USER': 'Habilitar usuario', 'DISABLE_USER': 'Deshabilitar usuario', + 'SHOW_CLOSED_TICKETS': 'Mostrar Tickets Cerrados', 'CHART_CREATE_TICKET': 'Tickets creados', 'CHART_CLOSE': 'Tickets cerrados', diff --git a/client/src/data/languages/fr.js b/client/src/data/languages/fr.js index 4b5a7d39..92ddcc8f 100644 --- a/client/src/data/languages/fr.js +++ b/client/src/data/languages/fr.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'privé', 'ENABLE_USER': 'Activer l\'utilisateur', 'DISABLE_USER': 'Désactiver l\'utilisateur', + 'SHOW_CLOSED_TICKETS': 'Afficher les billets fermés', 'CHART_CREATE_TICKET': 'Tickets créés', 'CHART_CLOSE': 'Tickets fermés', diff --git a/client/src/data/languages/gr.js b/client/src/data/languages/gr.js index 94b2db28..23742ce0 100644 --- a/client/src/data/languages/gr.js +++ b/client/src/data/languages/gr.js @@ -188,6 +188,7 @@ 'PRIVATE': 'ιδιωτικός', 'ENABLE_USER': 'Ενεργοποίηση χρήστη', 'DISABLE_USER': 'Απενεργοποίηση χρήστη', + 'SHOW_CLOSED_TICKETS': 'Εμφάνιση κλειστών εισιτηρίων', 'CHART_CREATE_TICKET': 'Τα εισιτήρια δημιουργήθηκαν', 'CHART_CLOSE': 'Τα εισιτήρια κλείσανε', diff --git a/client/src/data/languages/in.js b/client/src/data/languages/in.js index 7f81cfb1..7e1e34cd 100644 --- a/client/src/data/languages/in.js +++ b/client/src/data/languages/in.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'निजी', 'ENABLE_USER': 'उपयोगकर्ता सक्षम करें', 'DISABLE_USER': 'उपयोगकर्ता को अक्षम करें', + 'SHOW_CLOSED_TICKETS': 'बंद टिकट दिखाएं', 'CHART_CREATE_TICKET': 'टिकट बनाया', 'CHART_CLOSE': 'टिकट बंद कर दिया', diff --git a/client/src/data/languages/it.js b/client/src/data/languages/it.js index caa00841..494a938a 100644 --- a/client/src/data/languages/it.js +++ b/client/src/data/languages/it.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'privato', 'ENABLE_USER': 'Abilita utente', 'DISABLE_USER': 'Disabilita utente', + 'SHOW_CLOSED_TICKETS': 'Mostra biglietti chiusi', 'CHART_CREATE_TICKET': 'Tickets creato', 'CHART_CLOSE': 'Tickets chiuso', diff --git a/client/src/data/languages/jp.js b/client/src/data/languages/jp.js index 1c52c9f1..1ccbb22f 100644 --- a/client/src/data/languages/jp.js +++ b/client/src/data/languages/jp.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'プライベート', 'ENABLE_USER': 'ユーザーを有効にする', 'DISABLE_USER': 'ユーザーを無効にする', + 'SHOW_CLOSED_TICKETS': 'クローズドチケットを表示する', 'CHART_CREATE_TICKET': '作成されたチケット', 'CHART_CLOSE': 'チケットが閉じられました', diff --git a/client/src/data/languages/nl.js b/client/src/data/languages/nl.js index e47ab33f..616d7028 100644 --- a/client/src/data/languages/nl.js +++ b/client/src/data/languages/nl.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'privaat', 'ENABLE_USER': 'Schakel gebruiker in', 'DISABLE_USER': 'Gebruiker uitschakelen', + 'SHOW_CLOSED_TICKETS': 'Toon gesloten tickets', 'CHART_CREATE_TICKET': 'Aangemaakte incidenten', 'CHART_CLOSE': 'Gesloten incidenten', diff --git a/client/src/data/languages/pt.js b/client/src/data/languages/pt.js index d1db214f..6bc0bdc0 100644 --- a/client/src/data/languages/pt.js +++ b/client/src/data/languages/pt.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'privado', 'ENABLE_USER': 'Ativar usuário', 'DISABLE_USER': 'Desativar usuário', + 'SHOW_CLOSED_TICKETS': 'Mostrar ingressos fechados', 'CHART_CREATE_TICKET': 'Ingressos criados', 'CHART_CLOSE': 'Ingressos fechados', diff --git a/client/src/data/languages/ru.js b/client/src/data/languages/ru.js index c967a393..073315a2 100644 --- a/client/src/data/languages/ru.js +++ b/client/src/data/languages/ru.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'частный', 'ENABLE_USER': 'Включить пользователя', 'DISABLE_USER': 'Отключить пользователя', + 'SHOW_CLOSED_TICKETS': 'Показать закрытые билеты', 'CHART_CREATE_TICKET': 'Билеты создано', 'CHART_CLOSE': ' Билеты закрыты', diff --git a/client/src/data/languages/tr.js b/client/src/data/languages/tr.js index 0a00bf76..984116e5 100644 --- a/client/src/data/languages/tr.js +++ b/client/src/data/languages/tr.js @@ -188,6 +188,7 @@ export default { 'PRIVATE': 'gizli', 'ENABLE_USER': 'Kullanıcıyı Etkinleştir', 'DISABLE_USER': 'Kullanıcıyı Devre Dışı Bırak', + 'SHOW_CLOSED_TICKETS': 'Kapalı Biletleri Göster', 'CHART_CREATE_TICKET': 'Biletler oluşturuldu', 'CHART_CLOSE': 'Biletler kapandı', diff --git a/server/controllers/staff/get-all-tickets.php b/server/controllers/staff/get-all-tickets.php index 03d2c8bf..7c38a489 100755 --- a/server/controllers/staff/get-all-tickets.php +++ b/server/controllers/staff/get-all-tickets.php @@ -2,18 +2,20 @@ use Respect\Validation\Validator as DataValidator; /** - * @api {post} /staff/get-all-tickets Get all tickets + * @api {post} /staff/get-all-tickets Get all tickets according to search * @apiVersion 4.3.0 * * @apiName Get all tickets * * @apiGroup Staff * - * @apiDescription This path retrieves all tickets. + * @apiDescription This path retrieves all tickets according to search and opened/closed filters. * * @apiPermission staff1 * * @apiParam {Number} page The page number. + * @apiParam {String} query Query string to search. + * @apiParam {Boolean} closed Include closed tickets. * * @apiUse NO_PERMISSION * @apiUse INVALID_PAGE @@ -58,10 +60,24 @@ class GetAllTicketsStaffController extends Controller { private function getTicketList() { $page = Controller::request('page'); - $query = $this->getStaffDepartmentsQueryFilter(); - $query .= 'ORDER BY id DESC LIMIT 10 OFFSET ' . (($page-1)*10); + $query = $this->getSearchQuery(); + $query .= $this->getStaffDepartmentsQueryFilter(); + $query .= $this->getClosedFilter(); + $query .= "ORDER BY CASE WHEN (title LIKE ?) THEN 1 ELSE 2 END ASC, id DESC LIMIT 10 OFFSET " . (($page-1)*10); - return Ticket::find($query); + return Ticket::find($query, [ + Controller::request('query') . '%', + '%' . Controller::request('query') . '%', + Controller::request('query') . '%' + ]); + } + + private function getSearchQuery() { + $page = Controller::request('page'); + + $query = " (title LIKE ? OR title LIKE ?) AND "; + + return $query; } private function getTotalPages() { @@ -81,4 +97,13 @@ class GetAllTicketsStaffController extends Controller { return $query; } + + private function getClosedFilter() { + $closed = Controller::request('closed')*1; + if ($closed) { + return ''; + } else { + return " AND (closed = '0')"; + } + } } diff --git a/server/controllers/staff/get-tickets.php b/server/controllers/staff/get-tickets.php index 1f768042..137cb7eb 100755 --- a/server/controllers/staff/get-tickets.php +++ b/server/controllers/staff/get-tickets.php @@ -13,6 +13,8 @@ use Respect\Validation\Validator as DataValidator; * * @apiPermission staff1 * + * @apiParam {bool} closed Include closed tickets in the response. + * * @apiUse NO_PERMISSION * * @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data Array of tickets assigned to the staff @@ -32,6 +34,11 @@ class GetTicketStaffController extends Controller { public function handler() { $user = Controller::getLoggedUser(); - Response::respondSuccess($user->sharedTicketList->toArray()); + $closed = Controller::request('closed'); + if ($closed) { + Response::respondSuccess($user->sharedTicketList->toArray()); + } else { + Response::respondSuccess($user->withCondition('closed = ?', ['0'])->sharedTicketList->toArray()); + } } -} \ No newline at end of file +} diff --git a/server/models/DataStore.php b/server/models/DataStore.php index 43ec9d22..d4310fdc 100755 --- a/server/models/DataStore.php +++ b/server/models/DataStore.php @@ -150,6 +150,10 @@ abstract class DataStore { } } + public function withCondition($condition, $values) { + return new static($this->_bean->withCondition($condition, $values)); + } + private function updateBeanProp($key, $value) { if ($value instanceof DataStoreList) { $this->_bean[$key] = $value->toBeanList();