Paginate all ticket list request, avoid returting too much data

This commit is contained in:
Ivan Diaz 2018-11-15 20:33:08 -03:00
parent 5f0996f243
commit e8848d898e
12 changed files with 135 additions and 50 deletions

View File

@ -12,22 +12,22 @@ export default {
};
},
retrieveMyTickets(closed = 0) {
retrieveMyTickets(page, closed = 0) {
return {
type: 'MY_TICKETS',
payload: API.call({
path: '/staff/get-tickets',
data: {closed}
data: {page, closed}
})
};
},
retrieveNewTickets() {
retrieveNewTickets(page = 1) {
return {
type: 'NEW_TICKETS',
payload: API.call({
path: '/staff/get-new-tickets',
data: {}
data: {page}
})
};
},

View File

@ -21,7 +21,7 @@ class AdminPanelAllTickets extends React.Component {
state = {
page: 1,
query: '',
closedTicketsShown: false
closedTicketsShown: 0
};
componentDidMount() {
@ -46,7 +46,7 @@ class AdminPanelAllTickets extends React.Component {
this.props.dispatch(AdminDataAction.retrieveAllTickets(
this.state.page,
this.state.query,
this.state.closedTicketsShown*1
this.state.closedTicketsShown * 1
));
}

View File

@ -18,15 +18,17 @@ class AdminPanelMyTickets extends React.Component {
static defaultProps = {
userId: 0,
departments: [],
tickets: []
tickets: [],
page: 1,
pages: 0,
};
state = {
closedTicketsShown: false
closedTicketsShown: false,
};
componentDidMount() {
this.props.dispatch(AdminDataAction.retrieveMyTickets());
this.retrieveMyTickets()
}
render() {
@ -52,7 +54,10 @@ class AdminPanelMyTickets extends React.Component {
loading: this.props.loading,
ticketPath: '/admin/panel/tickets/view-ticket/',
closedTicketsShown: this.state.closedTicketsShown,
onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this)
onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this),
pages: this.props.pages,
page: this.props.page,
onPageChange: event => this.retrieveMyTickets(event.target.value)
};
}
@ -61,9 +66,7 @@ class AdminPanelMyTickets extends React.Component {
return {
closedTicketsShown: !state.closedTicketsShown
};
}, () => {
this.props.dispatch(AdminDataAction.retrieveMyTickets(this.state.closedTicketsShown * 1));
});
}, () => this.retrieveMyTickets());
}
onCreateTicket() {
@ -79,7 +82,11 @@ class AdminPanelMyTickets extends React.Component {
onCreateTicketSuccess() {
ModalContainer.closeModal();
this.props.dispatch(AdminDataAction.retrieveMyTickets());
this.retrieveMyTickets();
}
retrieveMyTickets(page = this.props.page, closed = this.state.closedTicketsShown) {
this.props.dispatch(AdminDataAction.retrieveMyTickets(page, closed * 1));
}
}
@ -88,6 +95,8 @@ export default connect((store) => {
userId: store.session.userId,
departments: store.session.userDepartments,
tickets: store.adminData.myTickets,
page: store.adminData.myTicketsPage,
pages: store.adminData.myTicketsPages,
loading: !store.adminData.myTicketsLoaded,
error: store.adminData.myTicketsError
};

View File

@ -18,7 +18,7 @@ class AdminPanelNewTickets extends React.Component {
};
componentDidMount() {
this.props.dispatch(AdminDataAction.retrieveNewTickets());
this.retrieveNewTickets()
}
render() {
@ -39,9 +39,16 @@ class AdminPanelNewTickets 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/',
page: this.props.page,
pages: this.props.pages,
onPageChange: event => this.retrieveNewTickets(event.target.value)
};
}
retrieveNewTickets(page = this.props.page) {
this.props.dispatch(AdminDataAction.retrieveNewTickets(page));
}
}
export default connect((store) => {
@ -49,6 +56,8 @@ export default connect((store) => {
userId: store.session.userId,
departments: store.session.userDepartments,
tickets: store.adminData.newTickets,
page: store.adminData.newTicketsPage,
pages: store.adminData.newTicketsPages,
loading: !store.adminData.newTicketsLoaded,
error: store.adminData.newTicketsError
};

View File

@ -11,14 +11,20 @@ class AdminDataReducer extends Reducer {
customResponsesLoaded: false,
myTickets: [],
myTicketsPage: 1,
myTicketsPages: 1,
myTicketsLoaded: false,
myTicketsError: false,
newTickets: [],
newTicketsPage: 1,
newTicketsPages: 1,
newTicketsLoaded: false,
newTicketsError: false,
allTickets: [],
allTicketsPage: 1,
allTicketsPages: 1,
allTicketsLoaded: false,
allTicketsError: false,
@ -61,7 +67,9 @@ class AdminDataReducer extends Reducer {
onMyTicketsRetrieved(state, payload) {
return _.extend({}, state, {
myTickets: payload.data,
myTickets: payload.data.tickets,
myTicketsPage: payload.data.page * 1,
myTicketsPages: payload.data.pages * 1,
myTicketsLoaded: true
});
}
@ -82,7 +90,9 @@ class AdminDataReducer extends Reducer {
onNewTicketsRetrieved(state, payload) {
return _.extend({}, state, {
newTickets: payload.data,
newTickets: payload.data.tickets,
newTicketsPage: payload.data.page * 1,
newTicketsPages: payload.data.pages * 1,
newTicketsLoaded: true
});
}
@ -104,7 +114,8 @@ class AdminDataReducer extends Reducer {
onAllTicketsRetrieved(state, payload) {
return _.extend({}, state, {
allTickets: payload.data.tickets,
allTicketsPages: payload.data.pages,
allTicketsPage: payload.data.page * 1,
allTicketsPages: payload.data.pages * 1,
allTicketsLoaded: true
});
}

View File

@ -52,7 +52,7 @@ class GetAllTicketsStaffController extends Controller {
}
Response::respondSuccess([
'tickets' => $this->getTicketList()->toArray(),
'tickets' => $this->getTicketList()->toArray(true),
'pages' => $this->getTotalPages()
]);
}
@ -81,9 +81,14 @@ class GetAllTicketsStaffController extends Controller {
}
private function getTotalPages() {
$query = $this->getStaffDepartmentsQueryFilter();
$query = $this->getSearchQuery();
$query .= $this->getStaffDepartmentsQueryFilter();
$query .= $this->getClosedFilter();
return ceil(Ticket::count($query) / 10);
return ceil(Ticket::count($query, [
Controller::request('query') . '%',
'%' . Controller::request('query') . '%'
]) / 10);
}
private function getStaffDepartmentsQueryFilter() {

View File

@ -14,9 +14,15 @@ use Respect\Validation\Validator as DataValidator;
*
* @apiPermission staff1
*
* @apiUse NO_PERMISSION
* @apiParam {Number} page The page number.
*
* @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data Array of new tickets.
* @apiUse NO_PERMISSION
* @apiUse INVALID_PAGE
*
* @apiSuccess {Object} data Information about a tickets and quantity of pages.
* @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data.tickets Array of new tickets of the current page.
* @apiSuccess {Number} data.page Number of current page.
* @apiSuccess {Number} data.pages Quantity of pages.
*
*/
@ -27,7 +33,12 @@ class GetNewTicketsStaffController extends Controller {
public function validations() {
return[
'permission' => 'staff_1',
'requestData' => []
'requestData' => [
'page' => [
'validation' => DataValidator::numeric(),
'error' => ERRORS::INVALID_PAGE
]
]
];
}
public function handler() {
@ -37,6 +48,8 @@ class GetNewTicketsStaffController extends Controller {
}
$user = Controller::getLoggedUser();
$page = Controller::request('page');
$query = ' (';
foreach ($user->sharedDepartmentList as $department) {
$query .= 'department_id=' . $department->id . ' OR ';
@ -45,13 +58,22 @@ class GetNewTicketsStaffController extends Controller {
$ownerExists = RedBean::exec('SHOW COLUMNS FROM ticket LIKE \'owner_id\'');
if($ownerExists != 0) {
$query .= 'FALSE) AND owner_id IS NULL';
$query .= 'FALSE) AND closed = 0 AND owner_id IS NULL';
} else {
$query .= 'FALSE)';
$query .= 'FALSE) AND closed = 0';
}
$countTotal = Ticket::count($query);
$query .= ' ORDER BY unread_staff DESC';
$query .= ' LIMIT 10 OFFSET ' . ($page-1)*10;
$ticketList = Ticket::find($query);
Response::respondSuccess($ticketList->toArray());
Response::respondSuccess([
'tickets' => $ticketList->toArray(true),
'page' => $page,
'pages' => ceil($countTotal / 10)
]);
}
}

View File

@ -13,11 +13,16 @@ use Respect\Validation\Validator as DataValidator;
*
* @apiPermission staff1
*
* @apiParam {Number} page The page number.
* @apiParam {bool} closed Include closed tickets in the response.
*
* @apiUse NO_PERMISSION
* @apiUse INVALID_PAGE
*
* @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data Array of tickets assigned to the staff
* @apiSuccess {Object} data Information about a tickets and quantity of pages.
* @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data.tickets Array of tickets assigned to the staff of the current page.
* @apiSuccess {Number} data.page Number of current page.
* @apiSuccess {Number} data.pages Quantity of pages.
*
*/
@ -28,17 +33,33 @@ class GetTicketStaffController extends Controller {
public function validations() {
return [
'permission' => 'staff_1',
'requestData' => []
'requestData' => [
'page' => [
'validation' => DataValidator::numeric(),
'error' => ERRORS::INVALID_PAGE
]
]
];
}
public function handler() {
$user = Controller::getLoggedUser();
$closed = Controller::request('closed');
$page = Controller::request('page');
$offset = ($page-1)*10;
if ($closed) {
Response::respondSuccess($user->sharedTicketList->toArray());
$tickets = $user->withCondition(' TRUE LIMIT 10 OFFSET ?', [$offset])->sharedTicketList->toArray(true);
$countTotal = $user->countShared('ticket');
} else {
Response::respondSuccess($user->withCondition('closed = ?', ['0'])->sharedTicketList->toArray());
$tickets = $user->withCondition(' closed = ? LIMIT 10 OFFSET ?', ['0', $offset])->sharedTicketList->toArray(true);
$countTotal = $user->withCondition(' closed = ?', ['0'])->countShared('ticket');
}
Response::respondSuccess([
'tickets' => $tickets,
'page' => $page,
'pages' => ceil($countTotal / 10)
]);
}
}

View File

@ -60,12 +60,12 @@ class DataStoreList implements IteratorAggregate {
return $beanList;
}
public function toArray() {
public function toArray($minimized = false) {
$array = [];
foreach($this->list as $item) {
$item->updateBeanProperties();
$array[] = $item->toArray();
$array[] = $item->toArray($minimized);
}
return $array;

View File

@ -154,6 +154,10 @@ abstract class DataStore {
return new static($this->_bean->withCondition($condition, $values));
}
public function countShared($shared) {
return $this->_bean->countShared($shared);
}
private function updateBeanProp($key, $value) {
if ($value instanceof DataStoreList) {
$this->_bean[$key] = $value->toBeanList();

View File

@ -2,13 +2,14 @@ describe '/staff/get-new-tickets' do
request('/user/logout')
Scripts.login($staff[:email], $staff[:password], true)
it 'should get news tickets' do
it 'should get new tickets' do
result = request('/staff/get-new-tickets', {
page: 1,
csrf_userid: $csrf_userid,
csrf_token: $csrf_token
})
(result['status']).should.equal('success')
(result['data'].size).should.equal(9)
(result['data']['tickets'].size).should.equal(8)
end
end

View File

@ -7,21 +7,24 @@ describe '/staff/get-tickets' do
ticket = $database.getRow('ticket', 1 , 'id')
request('/staff/assign-ticket', {
ticketNumber: ticket['ticket_number'],
page: 1,
csrf_userid: $csrf_userid,
csrf_token: $csrf_token
})
ticket = $database.getRow('ticket', 2 , 'id')
request('/staff/assign-ticket', {
ticketNumber: ticket['ticket_number'],
page: 1,
csrf_userid: $csrf_userid,
csrf_token: $csrf_token
})
result = request('/staff/get-tickets', {
page: 1,
csrf_userid: $csrf_userid,
csrf_token: $csrf_token
})
(result['status']).should.equal('success')
(result['data'].size).should.equal(5)
(result['data']['tickets'].size).should.equal(5)
end
end