2020-10-19 14:48:21 +02:00
2020-11-01 23:23:36 +01:00
import ListColumn from './list-column.ts' ;
import ListAction from './list-action.ts' ;
2020-10-19 14:48:21 +02:00
class List
{
2021-05-08 15:20:23 +02:00
_alias ;
_fetch ;
_filterOptions ;
2020-10-19 14:48:21 +02:00
/**
2020-10-21 11:26:16 +02:00
* Set the default query options which are passed to the fetch function.
2020-10-19 14:48:21 +02:00
* You can extend it to your needs
*/
2020-10-21 11:26:16 +02:00
query = {
2020-10-19 14:48:21 +02:00
// default order by
orderBy : 'createdDate' ,
// order is descending
isDescending : true ,
// current page index
page : 1 ,
// default items per page
pageSize : 25 ,
// search term
search : null ,
// custom filter
filter : null
};
/**
* Overrides the string generation for the label
*/
templateLabel = field => field ;
/**
* Build a link for a row (returns options passed to <router-link /> or a route name where id-param is automatically inserted)
*/
link = null ;
2021-03-03 15:55:14 +01:00
/**
* Convert a row into a button where the callback is this function
*/
onClick = null ;
2020-10-19 14:48:21 +02:00
columns = [];
2020-10-21 11:48:21 +02:00
actions = [];
2020-11-19 18:09:59 +01:00
/**
* Converts the list parameters (like page, search, filter, ...) to a vue router query
*/
paramsToQuery = params =>
{
let values : any = {};
if ( params . page !== this . query . page )
{
values . page = params . page ;
}
if ( params . isDescending !== this . query . isDescending || params . orderBy !== this . query . orderBy )
{
values . by = params . orderBy || this . query . orderBy ;
values . desc = params . isDescending || this . query . isDescending ;
}
if ( !! params . search )
{
values . search = params . search ;
}
if ( params . filter && params . filter . id )
{
values . filter = params . filter . id ;
}
return values ;
};
/**
* Converts an URL query string to list parameters
*/
queryToParams = query =>
{
if ( ! query )
{
return {};
}
let values = JSON . parse ( JSON . stringify ( this . query ));
if ( query . page )
{
values . page = + query . page || this . query . page ;
}
if ( query . by )
{
values . orderBy = query . by ;
}
if ( query . desc )
{
values . isDescending = query . desc === "true" || query . desc === true ;
}
if ( query . search )
{
values . search = query . search ;
}
if ( query . filter )
{
values . filter = values . filter || {};
values . filter . id = query . filter ;
}
return values ;
};
2020-10-19 14:48:21 +02:00
constructor ( alias )
{
2021-05-08 15:20:23 +02:00
this . _alias = alias ;
2020-10-19 14:48:21 +02:00
}
get alias ()
{
2021-05-08 15:20:23 +02:00
return this . _alias ;
2020-10-19 14:48:21 +02:00
}
get filterOptions ()
{
2021-05-08 15:20:23 +02:00
return this . _filterOptions ;
2020-10-19 14:48:21 +02:00
}
/**
* Specify a list column
* @param {string} path - Model path
* @param {object} [options] - Custom options
* @param {string} [options.label] - A custom label for this column (otherwise it's generated via `templateLabel`)
* @param {boolean} [options.hideLabel=false] - Hide the column label
* @param {number} [options.width] - Custom width of the column in px
* @param {boolean} [options.canSort=true] - Disable/enable sorting within this column
* @param {string} [options.class] - Append HTML class to the generated cells
* @returns {ListColumn}
*/
column ( path , options )
{
2020-11-19 14:57:00 +01:00
let column = this . columns . find ( x => x . path === path );
if ( ! column )
{
column = new ListColumn ( path , options );
this . columns . push ( column );
}
else
{
column . options = { ... column . options , ...( options || {}) };
}
2020-10-19 14:48:21 +02:00
return column ;
}
2020-10-21 11:48:21 +02:00
/**
* Add an action to the list header (only used when it is attached to <ui-table-filter />)
* @param {string} key - Alias to refer to
* @param {string} label - Dropdown-item label
* @param {string} icon - Displayed dropdown-item icon
* @param {function} callback - Called when the action button is clicked (including dropdown options as parameter)
* @param {boolean} [autoclose=true] - Autoclose the actions overlay when this action is clicked
* @returns {ListAction}
*/
action ( key , label , icon , callback , autoclose )
{
const action = new ListAction ( key , label , icon , callback );
action . autoclose = typeof autoclose === 'undefined' ? true : autoclose ;
this . actions . push ( action );
return action ;
}
/**
* Shortcut for an "export" action with predefined key, label and icon
* @param {Promise} callback - A promise which is called when the action button is clicked (including dropdown options as parameter)
* @returns {ListColumn}
*/
export ( callback )
{
return this . action ( 'export' , '@ui.export.action' , 'fth-share' , opts =>
{
opts . loading ( true );
callback (). then ( _ => opts . hide ());
}, false );
}
2020-10-19 14:48:21 +02:00
/**
* Get list items with this function
* @param {function} callback - This function is called when the list is requested (parameter is the filter object). You should either return a Promise or an Array here.
*/
onFetch ( callback )
{
2021-05-08 15:20:23 +02:00
this . _fetch = callback ;
2020-10-19 14:48:21 +02:00
}
/**
* Fetch items with the specified filter
*/
fetch ( filter )
{
2021-05-08 15:20:23 +02:00
return this . _fetch ( filter );
2020-10-19 14:48:21 +02:00
}
/**
* Filter a list by providing an editor renderer and a default template.
* This activates the Filter button and overlay in the <ui-table-filter /> component.
* @param {Editor} editor - An editor renderer which opens in an overlay
* @param {object} template - The default template to use when creating a new filter
*/
useFilter ( editor , template )
{
2021-05-08 15:20:23 +02:00
this . _filterOptions = { editor , template };
2020-10-19 14:48:21 +02:00
}
};
export default List ;