| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- const datefns = require('date-fns');
- const ObjectId = require('mongoose').Types.ObjectId;
- /**
- * Get table header of the model
- * @param {Model} model
- */
- function getHeaders(model, full) {
- let headers = Object.keys(model.schema.paths).filter((key) => {
- //TODO
- return key.substring(0, 1) != '_';
- }).map((key) => {
- let options = model.schema.path(key).options || {};
- return {
- data: key,
- title: options.desc || key,
- orderable: !(options.orderable === false),
- searchable: options.searchable || false,
- listingOrder: options.listingOrder || 1000,
- listing: options.listing,
- unit: options.unit,
- type: getType(options.type),
- }
- })
- if (!full) {
- headers = headers.filter(function (obj) {
- if (obj.listing === false) {
- return false;
- } else return true;
- });
- }
- headers = headers.sort((a, b) => {
- return a.listingOrder - b.listingOrder;
- });
- //console.table(headers);
- return headers;
- }
- function getType(typeFunc) {
- let type;
- switch (typeFunc) {
- case Number:
- type = "number";
- break;
- case String:
- type = 'string';
- break;
- case Date:
- type = 'date';
- break;
- case Boolean:
- type = 'boolean';
- break;
- default:
- type = "other";
- }
- return type;
- }
- /**
- *
- * @param {Model} model
- * @returns
- */
- async function getListBuilder(params, model, populates) {
- let { page, length, search, filters } = params;
- //let paths = model.schema.paths;
- let schema = model.schema;
- let baseQuery = params.base || {};
- let query = Object.assign({}, baseQuery);
- //filters
- try {
- // filters = JSON.parse(filters);
- //console.log('filters: ', filters);
- Object.keys(filters)
- .filter(data => schema.paths[data]) //filter not in schema
- .filter(data => {
- let value = filters[data];
- if (value === undefined) return false; //undefined
- if (Array.isArray(value) && value.length <= 0) return false;
- return true;
- }).forEach(data => {
- //console.log('data', data);
- let options = schema.path(data).options;
- //console.log('options', options);
- let value = filters[data];
- if (Array.isArray(value) && options.type == Date) {
- query[data] = {};
- if (value[0]) {
- query[data].$gte = datefns.startOfDay(new Date(value[0]));
- }
- if (value[1]) {
- query[data].$lte = datefns.endOfDay(new Date(value[1]));
- }
- } else if (Array.isArray(value)) {
- if (query[data]) {
- query[data].$in = value;
- } else {
- query[data] = { $in: value };
- }
- } else {
- query[data] = value;
- }
- })
- } catch (e) {
- console.warn(e);
- }
- //search
- if (search) { search = search.trim(); }
- if (search) {
- search = escapeRegExp(search);
- let match = { $regex: new RegExp(search, 'i') };
- let searchable = getHeaders(model).filter(h => h.searchable);
- if (searchable.length > 0) {
- query.$or = searchable.map(header => {
- let field = {};
- field[header.data] = match;
- return field;
- });
- if (ObjectId.isValid(search)) {
- query.$or.push({ _id: search }); // add id search
- }
- }
- }
- //console.log('search: ', search);
- //console.log('query : ', JSON.stringify(query));
- //pagination
- page = parseInt(page) || 1;
- if (page <= 0) page = 1;
- length = parseInt(length) || 30;
- if (length <= 0) length = 30;
- else if (length > 500) length = 500;
- let start = (page - 1) * length
- let recordsTotal = await model.countDocuments(baseQuery);
- let recordsFiltered = await model.countDocuments(query);
- // console.log('baseQuery', baseQuery);
- // console.log('query', query);
- /** @type {Query} */
- let theQuery = model.find(query)
- .skip(start)
- .limit(length);
- //order
- let { orderBy, order } = params;
- if (orderBy) {
- if (order != 'asc' && order != 'desc') order = 'desc';
- let sort = {};
- sort[orderBy] = order;
- theQuery.sort(sort)
- }
- //populate
- if (populates) {
- populates.forEach(p => theQuery.populate(p))
- }
- let data = await theQuery.exec();
- data = data.map(item => item.toObject());
- return { page, length, recordsFiltered, recordsTotal, data, filters, query }
- }
- function escapeRegExp(str) {
- var len;
- var s;
- var i;
- var RE_CHARS = /[-\/\\^$*+?.()|[\]{}]/g; // eslint-disable-line no-useless-escape
- // Check if the string starts with a forward slash...
- if (str[0] === '/') {
- // Find the last forward slash...
- len = str.length;
- for (i = len - 1; i >= 0; i--) {
- if (str[i] === '/') {
- break;
- }
- }
- }
- // If we searched the string to no avail or if the first letter is not `/`, assume that the string is not of the form `/[...]/[guimy]`:
- if (i === void 0 || i <= 0) {
- return str.replace(RE_CHARS, '\\$&');
- }
- // We need to de-construct the string...
- s = str.substring(1, i);
- // Only escape the characters between the `/`:
- s = s.replace(RE_CHARS, '\\$&');
- // Reassemble:
- str = str[0] + s + str.substring(i);
- return str;
- }
- module.exports = { getHeaders, getListBuilder, escapeRegExp }
|