Fix filter show bug in ticket search when ordering (#829)

* Fix bug in admin panel search tickets page first part.

* fix show filters in search ticket

* fix a ternary in admin panel search ticket.

* fix a ternary in admin panel search ticket second part.

* Add loading in ticket query filters buttons.

* fix bug in search ticket when ordering.

* Fix error with retrieve staff members in admin panel search tickets.

* get all staff members after staff login.

* Move history listen to index.js and add staff members in local storage.

* Rename className in ticket query filters

* Rename currentSearchObject to currentSearchParams.

* Fix change show tickets in reducer and admin panel search tickets.

* fix get filters for url function in search utils.

* add some tabulations in search tickets utils.

* fix error with initial url in ticket search

* Add empty line at the end of ticket-query-filters.js
This commit is contained in:
LautaroCesso 2020-07-21 23:07:05 -03:00 committed by GitHub
parent 2e37c35b41
commit 302a29db41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 143 additions and 77 deletions

View File

@ -47,15 +47,34 @@ export default {
payload: showFilters
}
},
changePage(listConfigWithPage) {
const filtersForAPI = searchTicketsUtils.prepareFiltersForAPI(listConfigWithPage.filters);
changePage(filtersWithPage) {
const filtersForAPI = searchTicketsUtils.prepareFiltersForAPI(filtersWithPage);
const currentPath = window.location.pathname;
const urlQuery = searchTicketsUtils.getFiltersForURL(filtersForAPI, false);
const urlQuery = searchTicketsUtils.getFiltersForURL({
filters: filtersForAPI,
shouldRemoveCustomParam: false,
shouldRemoveUseInitialValuesParam: true
});
urlQuery && history.push(`${currentPath}${urlQuery}`);
return {
type: 'SEARCH_FILTERS_CHANGE_PAGE',
payload: {...listConfigWithPage, filtersForAPI}
payload: {...filtersWithPage, ...filtersForAPI}
}
},
changeOrderBy(filtersWithOrderBy) {
const filtersForAPI = searchTicketsUtils.prepareFiltersForAPI(filtersWithOrderBy);
const currentPath = window.location.pathname;
const urlQuery = searchTicketsUtils.getFiltersForURL({
filters: filtersForAPI,
shouldRemoveCustomParam: false,
shouldRemoveUseInitialValuesParam: true
});
urlQuery && history.push(`${currentPath}${urlQuery}`);
return {
type: 'SEARCH_FILTERS_CHANGE_ORDER_BY',
payload: {...filtersWithOrderBy, ...filtersForAPI}
}
},
};

View File

@ -22,6 +22,7 @@ export default {
.then(() => {
if(result.data.staff) {
store.dispatch(AdminDataActions.retrieveCustomResponses());
store.dispatch(AdminDataActions.retrieveStaffMembers());
}
});

View File

@ -5,17 +5,18 @@ import {connect} from 'react-redux';
import SearchFiltersActions from 'actions/search-filters-actions';
import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import DateTransformer from 'lib-core/date-transformer';
import history from 'lib-app/history';
import searchTicketsUtils from 'lib-app/search-tickets-utils';
import DateTransformer from 'lib-core/date-transformer';
import Form from 'core-components/form';
import SubmitButton from 'core-components/submit-button';
import FormField from 'core-components/form-field';
import Icon from 'core-components/icon';
import Button from 'core-components/button';
import searchTicketsUtils from '../lib-app/search-tickets-utils';
import Loading from 'core-components/loading';
const INITIAL_PAGE = 1;
@ -38,40 +39,42 @@ class TicketQueryFilters extends React.Component {
const {
formState,
filters,
showFilters
showFilters,
ticketQueryListState
} = this.props;
return (
<div className={"ticket-query-filters" + (showFilters ? "__open" : "") }>
<Form
loading={ticketQueryListState.loading}
values={this.getFormValue(formState)}
onChange={this.onChangeForm.bind(this)}
onSubmit={this.onSubmitListConfig.bind(this)}>
<div className="ticket-query-filters__search-box">
<FormField name="query" field="search-box" fieldProps={{onSearch: this.onSubmitListConfig.bind(this)}} />
</div>
<div className="ticket-query-filters__group">
<div className="ticket-query-filters__group__container">
<div className="ticket-query-filters__row">
<div className="ticket-query-filters__row__filter">
<span>{i18n('DATE')}</span>
<FormField
name="dateRange"
field="date-range"
fieldProps={{defaultValue: this.dateRangeToFormValue(filters.dateRange)}} />
</div>
<div className="ticket-query-filters__group__container">
<div className="ticket-query-filters__row__filter">
<span>{i18n('STATUS')}</span>
<FormField name="closed" field="select" fieldProps={{items: this.getStatusItems()}} />
</div>
</div>
<div className="ticket-query-filters__group">
<div className="ticket-query-filters__group__container">
<div className="ticket-query-filters__row">
<div className="ticket-query-filters__row__filter">
<span className="ticket-query-filters__title">{i18n('DEPARTMENTS')}</span>
<FormField
name="departments"
field="autocomplete"
fieldProps={{items: this.getDepartmentsItems()}} />
</div>
<div className="ticket-query-filters__group__container">
<div className="ticket-query-filters__row__filter">
<span className="ticket-query-filters__title">{i18n('OWNER')}</span>
<FormField
name="owners"
@ -79,8 +82,8 @@ class TicketQueryFilters extends React.Component {
fieldProps={{items: this.getStaffList()}} />
</div>
</div>
<div className="ticket-query-filters__group">
<div className="ticket-query-filters__group__container">
<div className="ticket-query-filters__row">
<div className="ticket-query-filters__row__filter">
<span className="ticket-query-filters__title">{i18n('TAGS')}</span>
<FormField
name="tags"
@ -91,7 +94,7 @@ class TicketQueryFilters extends React.Component {
onTagSelected: this.addTag.bind(this)
}} />
</div>
<div className="ticket-query-filters__group__container">
<div className="ticket-query-filters__row__filter">
<span className="ticket-query-filters__title">{i18n('AUTHORS')}</span>
<FormField
name="authors"
@ -106,13 +109,16 @@ class TicketQueryFilters extends React.Component {
<Button
className="ticket-query-filters__container__button ticket-query-filters__container__clear-button"
size= "medium"
disabled={ticketQueryListState.loading}
onClick={this.clearFormValues.bind(this)}>
{i18n('CLEAR')}
{ticketQueryListState.loading ?
<Loading />
: i18n('CLEAR')}
</Button>
<SubmitButton
className="ticket-query-filters__container__button ticket-query-filters__container__search-button"
type="secondary"
size= "medium"
className="ticket-query-filters__container__button ticket-query-filters__container__search-button">
size= "medium">
{i18n('SEARCH')}
</SubmitButton>
</div>
@ -316,7 +322,11 @@ class TicketQueryFilters extends React.Component {
if(formEdited) {
const filtersForAPI = searchTicketsUtils.prepareFiltersForAPI(listConfigWithCompleteAuthorsList.filters);
const currentPath = window.location.pathname;
const urlQuery = searchTicketsUtils.getFiltersForURL(filtersForAPI, true);
const urlQuery = searchTicketsUtils.getFiltersForURL({
filters: filtersForAPI,
shouldRemoveCustomParam: true,
shouldRemoveUseInitialValuesParam: true
});
urlQuery && history.push(`${currentPath}${urlQuery}`);
}
}
@ -393,5 +403,6 @@ export default connect((store) => {
filters: store.searchFilters.listConfig.filters,
showFilters: store.searchFilters.showFilters,
formEdited: store.searchFilters.formEdited,
ticketQueryListState: store.searchFilters.ticketQueryListState,
};
})(TicketQueryFilters);

View File

@ -41,13 +41,13 @@
}
}
&__group {
&__row {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: flex-start;
&__container {
&__filter {
display: flex;
flex-direction: column;
align-items: start;

View File

@ -38,10 +38,8 @@ class TicketQueryList extends React.Component {
} = this.props;
dispatch(searchFiltersActions.changePage({
filters: {
...filters,
page: event.target.value
}
}));
}

View File

@ -116,7 +116,7 @@ class AdminPanelMenu extends React.Component {
return window.customTicketList.map((item, index) => {
return {
name: item.title,
path: `/admin/panel/tickets/search-tickets?custom=${index}&page=${INITIAL_PAGE}`,
path: `/admin/panel/tickets/search-tickets?custom=${index}&page=${INITIAL_PAGE}&useInitialValues=true`,
level: 1,
}
})
@ -165,7 +165,7 @@ class AdminPanelMenu extends React.Component {
},
{
name: i18n('SEARCH_TICKETS'),
path: `/admin/panel/tickets/search-tickets?dateRange=${searchTicketsUtils.getDefaultDateRangeForFilters()}&page=${INITIAL_PAGE}`,
path: `/admin/panel/tickets/search-tickets?page=${INITIAL_PAGE}&useInitialValues=true`,
level: 1,
},
{

View File

@ -1,53 +1,50 @@
import React from 'react';
import {connect} from 'react-redux';
import queryString from 'query-string';
import store from 'app/store';
import i18n from 'lib-app/i18n';
import searchTicketsUtils from 'lib-app/search-tickets-utils';
import searchFiltersActions from 'actions/search-filters-actions';
import TicketQueryList from 'app-components/ticket-query-list';
import AdminDataActions from 'actions/admin-data-actions';
import searchTicketsUtils from '../../../../lib-app/search-tickets-utils';
import searchFiltersActions from '../../../../actions/search-filters-actions';
import history from 'lib-app/history';
import TicketQueryFilters from 'app-components/ticket-query-filters';
import Header from 'core-components/header';
import Message from 'core-components/message';
import TicketQueryFilters from 'app-components/ticket-query-filters';
import Icon from 'core-components/icon';
import Button from 'core-components/button';
import store from 'app/store';
const INITIAL_PAGE = 1;
const SEARCH_TICKETS_PATH = '/search-tickets';
const SEARCH_TICKETS_INITIAL_QUERY = `?page=${INITIAL_PAGE}&useInitialValues=true`;
function retrieveStaffMembers() {
store.dispatch(AdminDataActions.retrieveStaffMembers());
}
function updateSearchTicketsFromURL() {
export function updateSearchTicketsFromURL() {
const currentPathName = window.location.pathname;
const currentSearch = window.location.search;
const currentPath = `${currentPathName}${currentSearch}`;
if(currentPath.includes(SEARCH_TICKETS_PATH)) {
searchTicketsUtils.getFiltersFromParams().then((listConfig) => {
const currentSearchParams = queryString.parse(currentSearch);
const showFilters = (currentSearch !== SEARCH_TICKETS_INITIAL_QUERY) && currentSearchParams.custom;
if((showFilters !== undefined) && currentSearchParams.useInitialValues) store.dispatch(searchFiltersActions.changeShowFilters(!showFilters));
store.dispatch(searchFiltersActions.changeFilters(listConfig));
store.dispatch(searchFiltersActions.retrieveSearchTickets(
{
...store.getState().searchFilters.ticketQueryListState,
page: (queryString.parse(currentSearch).page || INITIAL_PAGE)*1
page: (currentSearchParams.page || INITIAL_PAGE)*1
},
searchTicketsUtils.prepareFiltersForAPI(listConfig.filters)
));
});
retrieveStaffMembers();
}
}
history.listen(() => {
store.dispatch(searchFiltersActions.setLoadingInTrue());
updateSearchTicketsFromURL();
});
updateSearchTicketsFromURL();
class AdminPanelSearchTickets extends React.Component {
@ -83,27 +80,19 @@ class AdminPanelSearchTickets extends React.Component {
onChangeOrderBy(value) {
const {
listConfig,
ticketQueryListState,
dispatch
} = this.props;
let orderBy = listConfig.filters.orderBy ? JSON.parse(listConfig.filters.orderBy) : {value: ""};
const orderBy = listConfig.filters.orderBy ? JSON.parse(listConfig.filters.orderBy) : {value: ""};
const newValue = value;
let newOrderBy = {};
let newAsc = 0;
let newValue = value;
if(value === orderBy.value) {
newAsc = orderBy.asc === 0 ? 1 : 0;
}
newOrderBy = JSON.stringify({"value": newValue, "asc": newAsc});
dispatch(searchFiltersActions.changeFilters({
...listConfig,
filters: {
...listConfig.filters,
orderBy: newOrderBy
},
hasAllAuthorsInfo: true
}));
dispatch(searchFiltersActions.retrieveSearchTickets(ticketQueryListState, {...listConfig.filters, orderBy: newOrderBy}));
dispatch(searchFiltersActions.changeOrderBy({...listConfig.filters, orderBy: newOrderBy}));
}
onChangeShowFilters() {
@ -111,7 +100,7 @@ class AdminPanelSearchTickets extends React.Component {
showFilters,
dispatch
} = this.props;
dispatch(searchFiltersActions.changeShowFilters(showFilters));
dispatch(searchFiltersActions.changeShowFilters(!showFilters));
}
}

View File

@ -2,11 +2,17 @@ import React from 'react';
import {render} from 'react-dom'
import { Provider } from 'react-redux';
import history from 'lib-app/history';
import SessionActions from 'actions/session-actions';
import ConfigActions from 'actions/config-actions';
import searchFiltersActions from 'actions/search-filters-actions';
import routes from 'app/Routes';
import store from 'app/store';
import { updateSearchTicketsFromURL } from './app/admin/panel/tickets/admin-panel-search-tickets';
import './main.scss';
Array.prototype.swap = function (x,y) {
@ -39,6 +45,11 @@ let unsubscribe = store.subscribe(() => {
}
});
history.listen(() => {
store.dispatch(searchFiltersActions.setLoadingInTrue());
updateSearchTicketsFromURL();
});
store.dispatch(ConfigActions.checkInstallation());
store.dispatch(ConfigActions.init());
store.dispatch(SessionActions.initSession());

View File

@ -99,14 +99,26 @@ export default {
getDefaultDateRangeForFilters() {
return JSON.stringify(DateTransformer.formDateRangeToFilters([20170101, DateTransformer.getDateToday()]));
},
getFiltersForURL(filters, shouldRemoveCustomParam = false) {
getFiltersForURL(filtersWithShouldRemoveParams) {
const shouldRemoveCustomParam = filtersWithShouldRemoveParams.shouldRemoveCustomParam ? filtersWithShouldRemoveParams.shouldRemoveCustomParam : false;
const shouldRemoveUseInitialValuesParam = filtersWithShouldRemoveParams.shouldRemoveUseInitialValuesParam ? filtersWithShouldRemoveParams.shouldRemoveUseInitialValuesParam : false;
let filters = filtersWithShouldRemoveParams.filters;
filters = {
...queryString.parse(window.location.search),
...filters,
};
if(shouldRemoveCustomParam) delete filters.custom;
filters = (filters.custom !== undefined) ? {custom: filters.custom, page: (filters.page !== undefined) ? filters.page : undefined} : filters;
if(shouldRemoveUseInitialValuesParam) delete filters.useInitialValues;
filters = (filters.custom !== undefined) ?
{
custom: filters.custom,
orderBy: filters.orderBy,
page: (filters.page !== undefined) ? filters.page : undefined
} :
filters;
const query = Object.keys(filters).reduce(function (query, filter) {
const value = filters[filter];

View File

@ -28,7 +28,7 @@ class AdminDataReducer extends Reducer {
allTicketsLoaded: false,
allTicketsError: false,
staffMembers: [],
staffMembers: JSON.parse(sessionStore.getItem('staffMembers')) || [],
staffMembersLoaded: false,
staffMembersError: false,
};
@ -135,6 +135,8 @@ class AdminDataReducer extends Reducer {
}
onStaffMembersRetrieved(state, payload) {
sessionStore.setItem('staffMembers', JSON.stringify(payload.data));
return _.extend({}, state, {
staffMembers: payload.data,
staffMembersLoaded: true

View File

@ -24,7 +24,7 @@ class searchFiltersReducer extends Reducer {
getInitialState() {
return {
showFilters: true,
showFilters: !this.getListConfig().title,
listConfig: this.getListConfig(),
form: {
query: '',
@ -48,16 +48,20 @@ class searchFiltersReducer extends Reducer {
getTypeHandlers() {
return {
'SEARCH_TICKETS_FULFILLED': this.onSearchTicketsRetrieved.bind(this),
'SEARCH_TICKETS_REJECTED': this.onSearchTicketsRejected.bind(this),
'SEARCH_TICKETS_PENDING': this.onSearchTicketsPending.bind(this),
'SEARCH_TICKETS_FULFILLED': this.onSearchTicketsRetrieved,
'SEARCH_TICKETS_REJECTED': this.onSearchTicketsRejected,
'SEARCH_TICKETS_PENDING': this.onSearchTicketsPending,
'SEARCH_FILTERS_CHANGE_PAGE': this.onPageChange.bind(this),
'SEARCH_FILTERS_CHANGE_FILTERS': this.onFiltersChange.bind(this),
'SEARCH_FILTERS_CHANGE_FORM': this.onFormChange,
'SEARCH_FILTERS_CHANGE_SHOW_FILTERS': this.onChangeShowFilters.bind(this),
'SEARCH_FILTERS_SET_DEFAULT_FORM_VALUES': this.onSetDefaultFormValues.bind(this),
'SEARCH_FILTERS_SET_LOADING_IN_TRUE': this.onSetLoadingInTrue.bind(this)
'SEARCH_FILTERS_SET_DEFAULT_FORM_VALUES': this.onSetDefaultFormValues,
'SEARCH_FILTERS_CHANGE_FILTERS': this.onFiltersChange,
'SEARCH_FILTERS_CHANGE_PAGE': this.onPageChange,
'SEARCH_FILTERS_CHANGE_ORDER_BY': this.onOrderByChange,
'SEARCH_FILTERS_CHANGE_SHOW_FILTERS': this.onChangeShowFilters,
'SEARCH_FILTERS_SET_LOADING_IN_TRUE': this.onSetLoadingInTrue,
};
}
@ -121,6 +125,25 @@ class searchFiltersReducer extends Reducer {
)
}
onOrderByChange(state, payload) {
return (
_.extend(
{},
state,
{
listConfig: {
...state.listConfig,
filters: {
...state.listConfig.filters,
orderBy: payload.orderBy,
}
},
formEdited: true,
}
)
);
}
onPageChange(state, payload) {
return (
_.extend(
@ -129,7 +152,7 @@ class searchFiltersReducer extends Reducer {
{
ticketQueryListState: {
...state.ticketQueryListState,
page: payload.filters.page
page: payload.page
},
formEdited: true,
}
@ -154,7 +177,7 @@ class searchFiltersReducer extends Reducer {
loading: true
},
formEdited: state.ticketQueryListState.page !== 1,
showFilters: !payload.title,
showFilters: state.showFilters,
form: payload.hasAllAuthorsInfo ?
state.form :
searchTicketsUtils.transformToFormValue({...DEFAULT_FILTERS, ...payload.filters})
@ -169,7 +192,7 @@ class searchFiltersReducer extends Reducer {
}
onChangeShowFilters(state, payload) {
return _.extend({}, state, {showFilters: !payload});
return _.extend({}, state, {showFilters: payload});
}
onSetDefaultFormValues(state) {