mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 01:51:40 -05:00
Add support for sortable property (bool/string) on datatable columns to make them sortable
This commit is contained in:
parent
4ec9c08500
commit
4da86c44a3
2 changed files with 65 additions and 9 deletions
|
@ -28,10 +28,23 @@ class Datatable extends PureComponent {
|
||||||
this.updateQuery = this.updateQuery.bind(this);
|
this.updateQuery = this.updateQuery.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
value: '',
|
value: '',
|
||||||
query: ''
|
query: '',
|
||||||
|
currentSort: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleSort = column => {
|
||||||
|
let currentSort;
|
||||||
|
if (!this.state.currentSort[column]) {
|
||||||
|
currentSort = { [column] : 1 };
|
||||||
|
} else if (this.state.currentSort[column] === 1) {
|
||||||
|
currentSort = { [column] : -1 };
|
||||||
|
} else {
|
||||||
|
currentSort = {};
|
||||||
|
}
|
||||||
|
this.setState({ currentSort });
|
||||||
|
}
|
||||||
|
|
||||||
updateQuery(e) {
|
updateQuery(e) {
|
||||||
e.persist()
|
e.persist()
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -66,7 +79,7 @@ class Datatable extends PureComponent {
|
||||||
return (
|
return (
|
||||||
<div className={`datatable datatable-${collection.options.collectionName}`}>
|
<div className={`datatable datatable-${collection.options.collectionName}`}>
|
||||||
<Components.DatatableAbove {...this.props} collection={collection} canInsert={canInsert} value={this.state.value} updateQuery={this.updateQuery} />
|
<Components.DatatableAbove {...this.props} collection={collection} canInsert={canInsert} value={this.state.value} updateQuery={this.updateQuery} />
|
||||||
<DatatableWithList {...this.props} collection={collection} terms={{query: this.state.query}} currentUser={this.props.currentUser}/>
|
<DatatableWithList {...this.props} collection={collection} terms={{query: this.state.query, orderBy: this.state.currentSort }} currentUser={this.props.currentUser} toggleSort={this.toggleSort} currentSort={this.state.currentSort}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +129,7 @@ registerComponent('DatatableAbove', DatatableAbove);
|
||||||
DatatableHeader Component
|
DatatableHeader Component
|
||||||
|
|
||||||
*/
|
*/
|
||||||
const DatatableHeader = ({ collection, column }, { intl }) => {
|
const DatatableHeader = ({ collection, column, toggleSort, currentSort }, { intl }) => {
|
||||||
|
|
||||||
const columnName = typeof column === 'string' ? column : column.label || column.name;
|
const columnName = typeof column === 'string' ? column : column.label || column.name;
|
||||||
|
|
||||||
|
@ -135,7 +148,9 @@ const DatatableHeader = ({ collection, column }, { intl }) => {
|
||||||
const defaultMessage = schema[columnName] ? schema[columnName].label : Utils.camelToSpaces(columnName);
|
const defaultMessage = schema[columnName] ? schema[columnName].label : Utils.camelToSpaces(columnName);
|
||||||
const formattedLabel = intl.formatMessage({ id: `${collection._name}.${columnName}`, defaultMessage });
|
const formattedLabel = intl.formatMessage({ id: `${collection._name}.${columnName}`, defaultMessage });
|
||||||
|
|
||||||
return <th>{formattedLabel}</th>;
|
// if sortable is a string, use it as the name of the property to sort by. If it's just `true`, use column.name
|
||||||
|
const sortPropertyName = typeof column.sortable === 'string' ? column.sortable : column.name;
|
||||||
|
return column.sortable ? <Components.DatatableSorter name={sortPropertyName} label={formattedLabel} toggleSort={toggleSort} currentSort={currentSort} sortable={column.sortable}/> : <th>{formattedLabel}</th>;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -151,6 +166,43 @@ DatatableHeader.contextTypes = {
|
||||||
|
|
||||||
registerComponent('DatatableHeader', DatatableHeader);
|
registerComponent('DatatableHeader', DatatableHeader);
|
||||||
|
|
||||||
|
const SortNone = () =>
|
||||||
|
<svg width='16' height='16' viewBox='0 0 438 438' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||||
|
<path d='M25.7368 247.243H280.263C303.149 247.243 314.592 274.958 298.444 291.116L171.18 418.456C161.128 428.515 144.872 428.515 134.926 418.456L7.55631 291.116C-8.59221 274.958 2.85078 247.243 25.7368 247.243ZM298.444 134.884L171.18 7.54408C161.128 -2.51469 144.872 -2.51469 134.926 7.54408L7.55631 134.884C-8.59221 151.042 2.85078 178.757 25.7368 178.757H280.263C303.149 178.757 314.592 151.042 298.444 134.884Z' transform='translate(66 6)' fill='#000' fillOpacity='0.2' />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
const SortDesc = () =>
|
||||||
|
<svg width="16" height="16" viewBox="0 0 438 438" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M25.7368 0H280.263C303.149 0 314.592 27.7151 298.444 43.8734L171.18 171.213C161.128 181.272 144.872 181.272 134.926 171.213L7.55631 43.8734C-8.59221 27.7151 2.85078 0 25.7368 0Z" transform="translate(66 253.243)" fill="black" fillOpacity="0.7"/>
|
||||||
|
<path d="M171.18 7.54408L298.444 134.884C314.592 151.042 303.149 178.757 280.263 178.757H25.7368C2.85078 178.757 -8.59221 151.042 7.55631 134.884L134.926 7.54408C144.872 -2.51469 161.128 -2.51469 171.18 7.54408Z" transform="translate(66 6)" fill="black" fillOpacity="0.2"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
const SortAsc = () =>
|
||||||
|
<svg width="16" height="16" viewBox="0 0 438 438" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M298.444 134.884L171.18 7.54408C161.128 -2.51469 144.872 -2.51469 134.926 7.54408L7.55631 134.884C-8.59221 151.042 2.85078 178.757 25.7368 178.757H280.263C303.149 178.757 314.592 151.042 298.444 134.884Z" transform="translate(66 6)" fill="black" fillOpacity="0.7"/>
|
||||||
|
<path d="M280.263 0H25.7368C2.85078 0 -8.59221 27.7151 7.55631 43.8734L134.926 171.213C144.872 181.272 161.128 181.272 171.18 171.213L298.444 43.8734C314.592 27.7151 303.149 0 280.263 0Z" transform="translate(66 253.243)" fill="black" fillOpacity="0.2"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
const DatatableSorter = ({ name, label, toggleSort, currentSort }) =>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<div className="datatable-sorter" onClick={() => {toggleSort(name)}}>
|
||||||
|
<span className="datatable-sorter-label">{label}</span>
|
||||||
|
<span className="sort-icon">
|
||||||
|
{!currentSort[name] ? (
|
||||||
|
<SortNone/>
|
||||||
|
) : currentSort[name] === 1 ? (
|
||||||
|
<SortDesc/>
|
||||||
|
) : (
|
||||||
|
<SortAsc/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
registerComponent('DatatableSorter', DatatableSorter);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
DatatableContents Component
|
DatatableContents Component
|
||||||
|
@ -159,11 +211,11 @@ DatatableContents Component
|
||||||
|
|
||||||
const DatatableContents = (props) => {
|
const DatatableContents = (props) => {
|
||||||
|
|
||||||
const {collection, columns, results, loading, loadMore, count, totalCount, networkStatus, showEdit, currentUser, emptyState} = props;
|
const {collection, columns, results, loading, loadMore, count, totalCount, networkStatus, showEdit, currentUser, emptyState, toggleSort, currentSort } = props;
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <div className="datatable-list datatable-list-loading"><Components.Loading /></div>;
|
return <div className="datatable-list datatable-list-loading"><Components.Loading /></div>;
|
||||||
} else if (!results.length) {
|
} else if (!results || !results.length) {
|
||||||
return emptyState || null;
|
return emptyState || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +227,7 @@ const DatatableContents = (props) => {
|
||||||
<table className="table">
|
<table className="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{_.sortBy(columns, column => column.order).map((column, index) => <Components.DatatableHeader key={index} collection={collection} column={column}/>)}
|
{_.sortBy(columns, column => column.order).map((column, index) => <Components.DatatableHeader key={index} collection={collection} column={column} toggleSort={toggleSort} currentSort={currentSort} />)}
|
||||||
{showEdit ? <th><FormattedMessage id="datatable.edit"/></th> : null}
|
{showEdit ? <th><FormattedMessage id="datatable.edit"/></th> : null}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
|
@ -6,7 +6,6 @@ import { runCallbacks } from './callbacks.js';
|
||||||
import { getSetting, registerSetting } from './settings.js';
|
import { getSetting, registerSetting } from './settings.js';
|
||||||
import { registerFragment, getDefaultFragmentText } from './fragments.js';
|
import { registerFragment, getDefaultFragmentText } from './fragments.js';
|
||||||
import escapeStringRegexp from 'escape-string-regexp';
|
import escapeStringRegexp from 'escape-string-regexp';
|
||||||
import { isIntlField } from './intl.js';
|
|
||||||
const wrapAsync = (Meteor.wrapAsync)? Meteor.wrapAsync : Meteor._wrapAsync;
|
const wrapAsync = (Meteor.wrapAsync)? Meteor.wrapAsync : Meteor._wrapAsync;
|
||||||
// import { debug } from './debug.js';
|
// import { debug } from './debug.js';
|
||||||
|
|
||||||
|
@ -297,6 +296,11 @@ export const createCollection = options => {
|
||||||
parameters = runCallbacks(`${collectionName.toLowerCase()}.parameters.server`, parameters, _.clone(terms), context);
|
parameters = runCallbacks(`${collectionName.toLowerCase()}.parameters.server`, parameters, _.clone(terms), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort using terms.orderBy (overwrite defaultView's sort)
|
||||||
|
if (terms.orderBy && !_.isEmpty(terms.orderBy)) {
|
||||||
|
parameters.options.sort = terms.orderBy
|
||||||
|
}
|
||||||
|
|
||||||
// if there is no sort, default to sorting by createdAt descending
|
// if there is no sort, default to sorting by createdAt descending
|
||||||
if (!parameters.options.sort) {
|
if (!parameters.options.sort) {
|
||||||
parameters.options.sort = { createdAt: -1 };
|
parameters.options.sort = { createdAt: -1 };
|
||||||
|
@ -318,7 +322,7 @@ export const createCollection = options => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(terms.query) {
|
if (terms.query) {
|
||||||
|
|
||||||
const query = escapeStringRegexp(terms.query);
|
const query = escapeStringRegexp(terms.query);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue