Merge pull request #342 from mredigonda/closed-tickets-filter
Adds a button to filter opened/closed tickets
This commit is contained in:
commit
4d2d0eac31
|
@ -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}
|
||||
})
|
||||
};
|
||||
},
|
||||
|
|
|
@ -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 (
|
||||
<div className="ticket-list">
|
||||
{(this.props.type === 'secondary' && this.props.showDepartmentDropdown) ? this.renderDepartmentsDropDown() : null}
|
||||
<div className="ticket-list__filters">
|
||||
{(this.props.type === 'secondary' && this.props.showDepartmentDropdown) ? this.renderDepartmentsDropDown() : null}
|
||||
{this.props.onClosedTicketsShownChange ? this.renderFilterCheckbox() : null}
|
||||
</div>
|
||||
<Table {...this.getTableProps()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
renderFilterCheckbox() {
|
||||
return <Checkbox className="ticket-list__checkbox" label={i18n("SHOW_CLOSED_TICKETS")} value={this.props.closedTicketsShown} onChange={this.props.onClosedTicketsShownChange} wrapInLabel/>
|
||||
}
|
||||
|
||||
renderDepartmentsDropDown() {
|
||||
return (
|
||||
<div className="ticket-list__department-selector">
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
<div>
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -188,6 +188,7 @@ export default {
|
|||
'PRIVATE': '私人的',
|
||||
'ENABLE_USER': '启用用户',
|
||||
'DISABLE_USER': '禁用用户',
|
||||
'SHOW_CLOSED_TICKETS': '显示已关闭的门票',
|
||||
|
||||
'CHART_CREATE_TICKET': '已創建門票',
|
||||
'CHART_CLOSE': '門票已關閉',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -188,6 +188,7 @@
|
|||
'PRIVATE': 'ιδιωτικός',
|
||||
'ENABLE_USER': 'Ενεργοποίηση χρήστη',
|
||||
'DISABLE_USER': 'Απενεργοποίηση χρήστη',
|
||||
'SHOW_CLOSED_TICKETS': 'Εμφάνιση κλειστών εισιτηρίων',
|
||||
|
||||
'CHART_CREATE_TICKET': 'Τα εισιτήρια δημιουργήθηκαν',
|
||||
'CHART_CLOSE': 'Τα εισιτήρια κλείσανε',
|
||||
|
|
|
@ -188,6 +188,7 @@ export default {
|
|||
'PRIVATE': 'निजी',
|
||||
'ENABLE_USER': 'उपयोगकर्ता सक्षम करें',
|
||||
'DISABLE_USER': 'उपयोगकर्ता को अक्षम करें',
|
||||
'SHOW_CLOSED_TICKETS': 'बंद टिकट दिखाएं',
|
||||
|
||||
'CHART_CREATE_TICKET': 'टिकट बनाया',
|
||||
'CHART_CLOSE': 'टिकट बंद कर दिया',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -188,6 +188,7 @@ export default {
|
|||
'PRIVATE': 'プライベート',
|
||||
'ENABLE_USER': 'ユーザーを有効にする',
|
||||
'DISABLE_USER': 'ユーザーを無効にする',
|
||||
'SHOW_CLOSED_TICKETS': 'クローズドチケットを表示する',
|
||||
|
||||
'CHART_CREATE_TICKET': '作成されたチケット',
|
||||
'CHART_CLOSE': 'チケットが閉じられました',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -188,6 +188,7 @@ export default {
|
|||
'PRIVATE': 'частный',
|
||||
'ENABLE_USER': 'Включить пользователя',
|
||||
'DISABLE_USER': 'Отключить пользователя',
|
||||
'SHOW_CLOSED_TICKETS': 'Показать закрытые билеты',
|
||||
|
||||
'CHART_CREATE_TICKET': 'Билеты создано',
|
||||
'CHART_CLOSE': ' Билеты закрыты',
|
||||
|
|
|
@ -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ı',
|
||||
|
|
|
@ -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')";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue