import { get } from 'object-path';
/**
* A class responsible for handling a full column with its header.
*/
class Column {
/**
* Defines a new column.
*
* @param {object} props - A configuration object for the column.
* @param {'left'|'center'|'right'} [props.align = 'left'] - The alignment direction of the cells in this column.
* @param {'left'|'center'|'right'} [props.headerAlign = 'center'] - The alignment direction of the cells in this column.
* @param {string} [props.label = ''] - The label displayed in the header.
* @param {string} [props.field = ''] - The name of the field in the row object.
* @param {function} [props.representedAs] - A transformation function that returns the string to display
* @param {*} [props.component] - .... Yeah I don't know what it is.
* @param {boolean} [props.interpolate = false] - Set to true to convert the return value of `props.representedAs` to HTML.
* @param {VueDatatableHeader} [props.headerComponent] - The header cell component of the column.
* @param {boolean} [props.sortable = true] - Controls whetever this column can be sorted.
* @param {boolean} [props.filterable = true] - Controls whetever this column can be filtered.
* @param {string} [props.headerClass = ''] - The base CSS class to apply to the header component.
*/
constructor( props ){
/** @member {string} - The alignment direction of the cells in this column. */
this.align = Column.normalizeAlignment( props.align, 'left' );
/** @member {* | null} - .... Yeah I don't know what it is. */
this.component = props.component || null;
/** @member {string} - The name of the field in the row object. */
this.field = props.field || null;
/** @member {function | null} - A transformation function that returns the string to display */
this.representedAs = props.representedAs || null;
/** @member {boolean} - Set to true to convert the return value of `props.representedAs` to HTML. */
this.interpolate = props.interpolate || false;
/** @member {string} - The alignment direction of the header of this column. */
this.headerAlign = Column.normalizeAlignment( props.headerAlign, 'center' );
/** @member {VueDatatableHeader | null} - The header cell component of the column. */
this.headerComponent = props.headerComponent || null;
/** @member {string} - The base CSS class to apply to the header component. */
this.headerClass = props.headerClass || '';
/** @member {string} - The label displayed in the header. */
this.label = props.label || '';
/** @member {boolean} - Controls whetever this column can be sorted. */
this.sortable = Column.isSortable( props );
/** @member {boolean} - Controls whetever this column can be filtered. */
this.filterable = Column.isFilterable( props );
}
/**
* Normalize the alignment, using the requested default value.
*
* @param {*} align - The raw desired alignment
* @param {'left'|'center'|'right'} defaultAlign - The default alignment to use, if the 1st parameter isn't recognized
* @returns {'left'|'center'|'right'} The normalized alignment
*/
static normalizeAlignment( align, defaultAlign = 'left' ){
if ( typeof align === 'string' ){
const lowerAlign = ( align || defaultAlign ).toLowerCase();
if ( [ 'left', 'center', 'right' ].includes( lowerAlign ) ){
return lowerAlign;
}
}
return defaultAlign.toLowerCase();
}
/**
* Check if the column use plain text value (eg `representedAs` or `field`, but not `component`)
* If multiple representation props are provided, it is considered as plain text if there are alternatives to `component`
*
* @param {object} props - The column definition object
* @returns {boolean} - `true` if the column can be represented by plain text, `false` otherwise
*/
static isPlainTextField( props ){
return !!( props.field || props.representedAs );
}
/**
* Check if the column can be filtered.
*
* @param {object} props - The column definition object
* @returns {boolean} - `true` if the column can be filtered, `false` otherwise
*/
static isFilterable( props ){
// If the option is explicitly disabled, use it
if ( props.filterable === false ){
return false;
}
return this.isPlainTextField( props );
}
/**
* Check if the column can be sorted.
*
* @param {object} props - The column definition object
* @returns {boolean} - `true` if the column can be sorted, `false` otherwise
*/
static isSortable( props ){
// If the option is explicitly disabled, use it
if ( props.sortable === false ){
return false;
}
return this.isPlainTextField( props );
}
/**
* Converts a row to its string representation for the current column.
*
* @param {object} row - The row to convert
* @returns {string} - The string representation of this row in the current column.
*/
getRepresentation( row ) {
if ( this.representedAs && typeof this.representedAs === 'function' ){
return this.representedAs( row );
}
return get( row, this.field );
}
/**
* Check if the provided row's representation matches a certain filter string.
*
* @param {object} row - The row to check.
* @param {string} filterString - The filter string to test.
* @returns {boolean} - `true` if the row matches the filter, `false` otherwise.
*/
matches( row, filterString ) {
const colRepresentation = ( `${ this.getRepresentation( row ) }` ).toLowerCase();
return colRepresentation.indexOf( filterString.toLowerCase() ) > -1;
}
}
export default Column;