diff --git a/client/src/actions/admin-data-actions.js b/client/src/actions/admin-data-actions.js
index f9ac73f7..aea9550e 100644
--- a/client/src/actions/admin-data-actions.js
+++ b/client/src/actions/admin-data-actions.js
@@ -32,12 +32,22 @@ export default {
};
},
- retrieveAllTickets() {
+ retrieveAllTickets(page) {
return {
type: 'ALL_TICKETS',
payload: API.call({
path: '/staff/get-all-tickets',
- data: {}
+ data: {page}
+ })
+ };
+ },
+
+ searchTickets(query, page) {
+ return {
+ type: 'ALL_TICKETS',
+ payload: API.call({
+ path: '/staff/search-tickets',
+ data: {query, page}
})
};
}
diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js
index 3f9b2e61..fa6f8aac 100644
--- a/client/src/app-components/ticket-list.js
+++ b/client/src/app-components/ticket-list.js
@@ -15,6 +15,7 @@ class TicketList extends React.Component {
departments: React.PropTypes.array,
loading: React.PropTypes.bool,
ticketPath: React.PropTypes.string,
+ showDepartmentDropdown: React.PropTypes.bool,
tickets: React.PropTypes.arrayOf(React.PropTypes.object),
type: React.PropTypes.oneOf([
'primary',
@@ -23,6 +24,7 @@ class TicketList extends React.Component {
};
static defaultProps = {
+ showDepartmentDropdown: true,
loading: false,
tickets: [],
departments: [],
@@ -37,8 +39,8 @@ class TicketList extends React.Component {
render() {
return (
- {(this.props.type === 'secondary') ? this.renderDepartmentsDropDown() : null}
-
+ {(this.props.type === 'secondary' && this.props.showDepartmentDropdown) ? this.renderDepartmentsDropDown() : null}
+
);
}
@@ -62,6 +64,19 @@ class TicketList extends React.Component {
size: 'medium'
};
}
+
+ getTableProps() {
+ return {
+ loading: this.props.loading,
+ headers: this.getTableHeaders(),
+ rows: this.getTableRows(),
+ pageSize: 10,
+ comp: this.compareFunction,
+ page: this.props.page,
+ pages: this.props.pages,
+ onPageChange: this.props.onPageChange
+ };
+ }
getDepartments() {
let departments = this.props.departments.map((department) => {
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 490a15cf..00dbc3a4 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
@@ -6,6 +6,7 @@ import i18n from 'lib-app/i18n';
import AdminDataAction from 'actions/admin-data-actions';
import Header from 'core-components/header';
import TicketList from 'app-components/ticket-list';
+import SearchBox from 'core-components/search-box';
class AdminPanelAllTickets extends React.Component {
@@ -14,6 +15,11 @@ class AdminPanelAllTickets extends React.Component {
tickets: []
};
+ state = {
+ page: 1,
+ query: ''
+ };
+
componentDidMount() {
this.props.dispatch(AdminDataAction.retrieveAllTickets());
}
@@ -22,26 +28,51 @@ class AdminPanelAllTickets extends React.Component {
return (
);
}
- getProps() {
+ getTicketListProps() {
return {
+ showDepartmentDropdown: false,
departments: this.props.departments,
tickets: this.props.tickets,
type: 'secondary',
loading: this.props.loading,
- ticketPath: '/admin/panel/tickets/view-ticket/'
+ ticketPath: '/admin/panel/tickets/view-ticket/',
+ onPageChange: this.onPageChange.bind(this),
+ page: this.state.page,
+ pages: this.props.pages
};
}
+
+ onSearch(query) {
+ this.setState({query, page: 1});
+ this.props.dispatch(AdminDataAction.searchTickets(query));
+ }
+
+ 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));
+ }
+ }
}
export default connect((store) => {
return {
departments: store.session.userDepartments,
tickets: store.adminData.allTickets,
+ pages: store.adminData.allTicketsPages,
loading: !store.adminData.allTicketsLoaded
};
})(AdminPanelAllTickets);
diff --git a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.scss b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.scss
new file mode 100644
index 00000000..d09f84bc
--- /dev/null
+++ b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.scss
@@ -0,0 +1,6 @@
+.admin-panel-my-tickets {
+ &__search-box {
+ padding: 0 50px;
+ margin-bottom: 30px;
+ }
+}
\ No newline at end of file
diff --git a/client/src/core-components/search-box.js b/client/src/core-components/search-box.js
new file mode 100644
index 00000000..13489a75
--- /dev/null
+++ b/client/src/core-components/search-box.js
@@ -0,0 +1,41 @@
+import React from 'react';
+
+import Input from 'core-components/input';
+import Icon from 'core-components/icon';
+import keyCode from 'keycode';
+
+class SearchBox extends React.Component {
+
+ static propTypes = {
+ onSearch: React.PropTypes.func
+ };
+
+ state = {
+ value: ''
+ };
+
+ render() {
+ return (
+
+
+
+
+
+
+ );
+ }
+
+ onChange(event) {
+ this.setState({
+ value: event.target.value
+ });
+ }
+
+ onKeyDown(event) {
+ if(keyCode(event) === 'enter' && this.props.onSearch) {
+ this.props.onSearch(this.state.value);
+ }
+ }
+}
+
+export default SearchBox;
\ No newline at end of file
diff --git a/client/src/core-components/search-box.scss b/client/src/core-components/search-box.scss
new file mode 100644
index 00000000..3a09ac49
--- /dev/null
+++ b/client/src/core-components/search-box.scss
@@ -0,0 +1,21 @@
+@import "../scss/vars";
+
+.search-box {
+ position: relative;
+ color: $dark-grey;
+
+ &__text {
+ width: 100%;
+ font-size: $font-size--lg;
+
+ .input__text {
+ padding-left: 50px;
+ }
+ }
+
+ &__icon {
+ position: absolute;
+ top: 15px;
+ left: 20px;
+ }
+}
\ No newline at end of file
diff --git a/client/src/core-components/table.js b/client/src/core-components/table.js
index b145e1c1..58494e05 100644
--- a/client/src/core-components/table.js
+++ b/client/src/core-components/table.js
@@ -13,9 +13,12 @@ class Table extends React.Component {
className: React.PropTypes.string
})),
rows: React.PropTypes.arrayOf(React.PropTypes.object),
- pageSize: React.PropTypes.number,
loading: React.PropTypes.bool,
type: React.PropTypes.oneOf(['default']),
+ page: React.PropTypes.number,
+ pages: React.PropTypes.number,
+ pageSize: React.PropTypes.number,
+ onPageChange: React.PropTypes.func,
comp: React.PropTypes.func
};
@@ -41,7 +44,7 @@ class Table extends React.Component {
{(this.props.loading) ? this.renderLoading() : null}
- {(this.props.pageSize && this.props.rows.length > this.props.pageSize) ? this.renderNavigation() : null}
+ {this.renderPagination()}
);
}
@@ -59,8 +62,8 @@ class Table extends React.Component {
renderRow(row, index) {
const headersKeys = this.props.headers.map(header => header.key);
- const minIndex = this.props.pageSize * (this.state.page - 1);
- const maxIndex = this.props.pageSize * this.state.page;
+ const minIndex = this.props.pageSize * ((this.props.page) ? 0 : this.state.page - 1);
+ const maxIndex = this.props.pageSize * ((this.props.page) ? 1 : this.state.page);
const shouldRenderRow = !this.props.pageSize || (index >= minIndex && index < maxIndex);
return (shouldRenderRow) ? (
@@ -81,12 +84,15 @@ class Table extends React.Component {
);
}
+ renderPagination() {
+ return (this.props.pages || (this.props.pageSize && this.props.rows.length > this.props.pageSize)) ? this.renderNavigation() : null
+ }
+
renderNavigation() {
- const pages = Math.ceil(this.props.rows.length / this.props.pageSize) + 1;
- const items = _.range(1, pages).map((index) => {return {content: index};});
+ const items = _.range(1, this.getPages()).map((index) => {return {content: index};});
return (
-