import _ from 'lodash';
import axios from 'axios';
const CancelToken = axios.CancelToken;
import FluroContentListService from '../services/FluroContentListService';
import {
Cache,
} from 'axios-extensions';
///////////////////////////////////////////////////
/**
* Creates a new FluroContent instance.
* This module provides a number of helper functions for Creating, Reading, Updating and Deleting content via the Fluro API
* @alias content
* @constructor
* @hideconstructor
* @param {FluroCore} fluro A reference to the parent instance of the FluroCore module. This module is usually created by a FluroCore instance that passes itself in as the first argument.
*/
var FluroContent = function(fluro) {
if (!fluro.api) {
throw new Error(`Can't Instantiate FluroContent before FluroAPI exists`);
}
//Keep track of any refresh requests
var inflightRefreshRequest;
///////////////////////////////////////////////////
var service = {}
///////////////////////////////////////////////////
/**
* Runs a search from the Fluro server and returns the results
* @alias content.search
* @param {String} terms The keywords to search for
* @param {Object} options Extra Configuration and options for how to search the database and how to render the results
* @param {Object} options.limit How many results should be returned. Defaults to 10
* @param {Array} options.types Specify types or definition names for which items should be searched for
* @param {Boolean} options.showQuery If true will return the query used to search instead of the search results themselves
* @return {Array} An array of content items that match the search, if options.types is specified will be a nested array of results for each type
*
* @example
* fluro.content.search('Wonder', {limit:5, types:['song', 'album', 'tag']}).then(function(results) {
* //Will return a nested array with up to 5 results for each type
* //[{_type:'Song', results:[{title:"Wonder"...}]}, {_type:'Album', results:[{title:"Wonder"...}]}]
* })
*
* fluro.content.search('Wonder', {limit:5}).then(function(results) {
* //Will return an array of up to 5 items the user has access to view that match the search terms
* //[{title:"Wonder", _type:'article', definition:'song'...}, {title:"Wonder", _type:'article', definition:'album'...}]
* })
*/
/////////////////////////////////////////////////
var currentSearch;
/////////////////////////////////////////////////
service.search = function(terms, params, config) {
if (!params) {
params = {};
}
if (!params.limit) {
params.limit = 10;
}
/////////////////////////////////////////////////
if (currentSearch) {
// cancel the request (the message parameter is optional)
currentSearch.cancel('Operation canceled by the user.');
}
/////////////////////////////////////////////////
currentSearch = CancelToken.source();
/////////////////////////////////////////////////
return new Promise(function(resolve, reject) {
if (!terms || !terms.length) {
return resolve([]);
}
if (!config) {
config = {};
}
config.params = params;
config.cancelToken = currentSearch.token;
// var requestOptions = {
// params: options,
// cancelToken: currentSearch.token,
// }
/////////////////////////////////////////////
//Retrieve the query results
fluro.api.get(`/content/search/${terms}`, config).then(function(res) {
resolve(res.data);
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
// //console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
});
}
///////////////////////////////////////////////////
/**
* Retrieves a specific definition or data type
* @alias content.type
* @param {String} definitionName The defined type or definition name to retrieve
* @param {Object} options Extra Configuration and options for how to search the database and how to render the results
* @return {Promise} A promise that will resolve with the definition
*
* @example
* fluro.content.type('song', options, config).then(function(definition) {
* //Will return the definition
* })
*/
var typePromise = {};;
var typeCacheable = true;
/////////////////////////////////////////////////
service.type = function(definitionName, params) {
if (!params) {
params = {};
}
if (!definitionName) {
throw Error('No definition name was provided');
}
/////////////////////////////////////////////////
//If we are already requesting this definition
if (typePromise[definitionName] && params.cache !== false) {
return typePromise[definitionName];
}
//Create a new promise
typePromise[definitionName] = new Promise(function(resolve, reject) {
// if (!config) {
// config = {};
// }
// config.params = params;
// var requestOptions = {
// params: options,
// cancelToken: currentMentionSearch.token,
// }
/////////////////////////////////////////////
//Retrieve the definition from the server and send it back to
//the user
fluro.api.get(`/defined/${definitionName}`)
.then(function(res) {
// console.log('CONTENT GET', definitionName, res.data);
resolve(res.data);
typeCacheable = true;
}).catch(function(err) {
reject(err);
typeCacheable = false;
});
});
/////////////////////////////////////////////////
return typePromise[definitionName];
}
///////////////////////////////////////////////////
/**
* Runs a search from the Fluro server for a specific mentionable user
* @alias content.mention
* @param {String} mentionID the Name or Mention ID of the persona to search for
* @param {Object} options Extra Configuration and options for how to search the database and how to render the results
* @param {Object} config Optional HTTP Request Configuration
* @param {Integer} options.limit Extra Configuration and options for how to search the database and how to render the results
* @param {Integer} options.managed Search for managed personas instead of Global Fluro user personas
* @return {Array} An array of personas who can be mentioned
*
* @example
* fluro.content.mention('john.smith', {limit:5}, config).then(function(results) {
* //Will return a nested array with up to 5 personas
* })
*/
/////////////////////////////////////////////////
var currentMentionSearch;
/////////////////////////////////////////////////
service.mention = function(terms, params, config) {
if (!params) {
params = {};
}
if (!params.limit) {
params.limit = 5;
}
/////////////////////////////////////////////////
if (currentMentionSearch) {
// cancel the request (the message parameter is optional)
currentMentionSearch.cancel('Operation canceled by the user.');
}
/////////////////////////////////////////////////
currentMentionSearch = CancelToken.source();
/////////////////////////////////////////////////
return new Promise(function(resolve, reject) {
if (!terms || !terms.length) {
return resolve([]);
}
if (!config) {
config = {};
}
config.params = params;
config.cancelToken = currentMentionSearch.token;
// var requestOptions = {
// params: options,
// cancelToken: currentMentionSearch.token,
// }
/////////////////////////////////////////////
//Retrieve the query results
fluro.api.get(`/mention/${terms}`, config).then(function(res) {
resolve(res.data);
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
// //console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
});
}
///////////////////////////////////////////////////
/**
* A helper function for retrieving the results of a specified query
* @alias content.query
* @param {String} queryID The id of the query you want to run
* @param {Object} options The options for the query
* @param {Object} options.params The query string parameters for the query that will be mapped ?one=value&two=value
* @param {Object} options.variables Any query variables you wish to inject each key will be mapped ?variables[key]=value
* @return {Promise} A promise that will be resolved with the results or an error
*/
service.query = function(queryID, options, requestOptions) {
//Get as just a query
queryID = fluro.utils.getStringID(queryID);
if (!options) {
options = {}
}
if (!requestOptions) {
requestOptions = {
params: {},
}
}
return new Promise(function(resolve, reject) {
//If there are query string parameters
if (options.params) {
requestOptions.params = options.params;
}
/////////////////////////////////////////////
if (options.variables) {
var variableParams = _.reduce(options.variables, function(set, value, key) {
set[`variables[${key}]`] = value;
return set;
}, {})
//Add it to our parameters
_.assign(requestOptions.params, variableParams);
}
/////////////////////////////////////////////
//Retrieve the query results
fluro.api.get(`/content/_query/${queryID}`, requestOptions).then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function returns a single populated item by providing its _id
* @alias content.get
* @param {String} id The item's _id
* @param {Object} params Extra query string parameters for the request
* @return {Promise} A promise that will be resolved with the item or an error
* @example
*
* //Retrieve just the title for item '5be504eabf33991239599d63'
* fluro.content.get('5be504eabf33991239599d63', {select:'title'})
*/
service.get = function(id, params, requestOptions) {
if (!requestOptions) {
requestOptions = {};
}
/////////////////////////////////////
//Ensure it's a simple single ID
id = fluro.utils.getStringID(id);
/////////////////////////////////////
if (!params) {
params = {}
}
/////////////////////////////////////
return new Promise(function(resolve, reject) {
//If there are query string parameters
if (params) {
requestOptions.params = params;
}
/////////////////////////////////////////////
// //console.log('REQUEST OPTIONS', requestOptions);
//Retrieve the query results
fluro.api.get(`/content/get/${id}`, requestOptions)
.then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
///////////////////////////////////////////////////
/**
* This function returns a single populated item by providing its _external id
* @alias content.external
* @param {String} externalID The item's _external id property
* @param {Object} params Extra query string parameters for the request
* @return {Promise} A promise that will be resolved with the item or an error
* @example
*
* //Retrieve just the title for item with external id that matches '5be504-eabf33991-239599-d63'
* fluro.content.external('5be504-eabf33991-239599-d63', {select:'title'})
*/
service.external = function(id, params, requestOptions) {
if (!requestOptions) {
requestOptions = {};
}
/////////////////////////////////////
if (!params) {
params = {}
}
return new Promise(function(resolve, reject) {
//If there are query string parameters
if (params) {
requestOptions.params = params;
}
/////////////////////////////////////////////
//Retrieve the query results
fluro.api.get(`/content/external/${id}`, requestOptions).then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function returns a single populated item by providing its slug
* @alias content.slug
* @param {String} slug The item's slug value
* @param {Object} params Extra query string parameters for the request
* @return {Promise} A promise that will be resolved with the item or an error
* @example
*
* //Retrieve just the title for item with the slug 'my-article'
* fluro.content.slug('my-article', {select:'title'})
*/
service.slug = function(id, params, requestOptions) {
if (!requestOptions) {
requestOptions = {}
}
if (!params) {
params = {}
}
return new Promise(function(resolve, reject) {
//If there are query string parameters
if (params) {
requestOptions.params = params;
}
/////////////////////////////////////////////
//Retrieve the query results
fluro.api.get(`/content/slug/${id}`, requestOptions).then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* A helper function for retrieving the results of a dynamic query
* @alias content.retrieve
* @param {Object} criteria The query criteria
* @param {Object} options Extra options and parameters
* @return {Promise} A promise that will be resolved with the results or an error
* @example
*
* //Find all events that have a status of active or archived where the endDate is greater than or equal to now and return the titles
* fluro.content.retrieve({_type:'event', status:{$in:['active', 'archived']}, endDate:{$gte:"date('now')"}}}, {select:'title'})
*/
service.retrieve = function(criteria, params, requestOptions) {
if (!params) {
params = {}
}
if (!requestOptions) {
requestOptions = {}
}
return new Promise(function(resolve, reject) {
//If there are query string parameters
if (params) {
requestOptions.params = params;
}
/////////////////////////////////////////////
//Retrieve the query results
fluro.api.post(`/content/_query`, criteria, requestOptions).then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function returns a list of related items
* That either reference the specified item or are referenced by the provided item
* @alias content.related
* @param {String} id The item to find related content for
* @param {Object} params Extra query string parameters for the request
* @return {Promise} A promise that will be resolved with an array of related items
* @example
*
* //Retrieve some related items for '5be504eabf33991239599d63'
* fluro.content.related('5be504eabf33991239599d63', {select:'title'})
*/
service.related = function(id, params, requestOptions) {
id = fluro.utils.getStringID(id);
if (!id) {
throw Error(`No id specified ${id}`);
}
if (!requestOptions) {
requestOptions = {}
}
if (!params) {
params = {}
}
return new Promise(function(resolve, reject) {
//If there are query string parameters
if (params) {
requestOptions.params = params;
}
var criteria = {
_references: id,
}
// service.retrieve(criteria, requestOptions).then(resolve, reject);
// /////////////////////////////////////////////
//Retrieve the query results
fluro.api.get(`/content/related/${id}`, requestOptions).then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function returns an interaction definition via the public 'form' API endpoint
* This will only result successfully if the definition requested has the definition of 'form' and has the status of 'active'
* @alias content.form
* @param {String} id The id of the form to retrieve
* @param {Object} options Extra options for the request
* @param {Object} options.testing Whether to load the form in testing mode or not
* @return {Promise} A promise that will be resolved with the form or an error
* @example
*
* //Retrieve a form ('58dca23c21428d2d045a1cf7') in testing mode
* fluro.content.form('58dca23c21428d2d045a1cf7', {testing:true})
*/
service.form = function(id, options, requestOptions) {
id = fluro.utils.getStringID(id);
if (!id) {
throw Error(`No id specified ${id}`);
}
if (!requestOptions) {
requestOptions = {}
}
if (!options) {
options = {}
}
if (options.requestOptions) {
requestOptions = options.requestOptions;
}
return new Promise(function(resolve, reject) {
//If there are query string parameters
// if (params) {
// requestOptions.params = params;
// }
// service.retrieve(criteria, requestOptions).then(resolve, reject);
// /////////////////////////////////////////////
// //console.log('request form', id, requestOptions);
//Retrieve the query results
fluro.api.get(`/form/${id}`, requestOptions).then(function(res) {
// //console.log('resolve form', res.data);
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function makes it easy to submit form interactions via the Fluro API
* @alias content.submitInteraction
* @param {String} definitionName the definition of the form you want to submit eg. 'supportRequest' or 'contactUs'...
* @param {Object} data The interaction data to submit
* @param {Object} options Extra options for the request
* @param {Object} options.reply The id of the post to reply to (If threaded conversation)
* @return {Promise} A promise that will be resolved with an array of related items
* @example
*
* //Retrieve some related items for '5be504eabf33991239599d63'
* fluro.content.submitInteraction('5be504eabf33991239599d63', 'comment', {data:{customField:'My message'}}, {reply:'5be504eabf33991239599d63'})
*/
service.submitInteraction = function(type, submission, options) {
//console.log('SUBMIT INTERACTION')
if (!options) {
options = {}
}
return new Promise(function(resolve, reject) {
var requestOptions = options;
/////////////////////////////////////////////
//console.log('SUBMISSION ACTIONS', requestOptions);
//Retrieve the query results
fluro.api.post(`/interact/${type}`, submission, requestOptions)
.then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function makes it easy to create and attach a post to a specified piece of fluro content
* @alias content.submitPost
* @param {String} target The ID of the item to attach this post to
* @param {String} definitionName the definition type of the post you want to create eg. 'note' or 'comment'...
* @param {Object} data The post content to create
* @param {Object} options Extra options for the request
* @param {Object} options.reply The id of the post to reply to (If threaded conversation)
* @return {Promise} A promise that will be resolved with an array of related items
* @example
*
* //Retrieve some related items for '5be504eabf33991239599d63'
* fluro.content.submitPost('5be504eabf33991239599d63', 'comment', {data:{customField:'My message'}}, {reply:'5be504eabf33991239599d63'})
*/
service.submitPost = function(id, type, body, options) {
id = fluro.utils.getStringID(id);
if (!id) {
throw Error(`No target specified ${id}`);
}
if (!options) {
options = {}
}
return new Promise(function(resolve, reject) {
var requestOptions = options.requestOptions || {
// params: {}
}
// /////////////////////////////////////////////
//Retrieve the query results
fluro.api.post(`/post/${id}/${type}`, body, requestOptions)
.then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function makes it easy to retrieve the current thread of posts attached to a specific
* item
* @alias content.thread
* @param {String} target The ID of the item to attach this post to
* @param {String} definitionName the definition type of the post you want to create eg. 'note' or 'comment'...
* @param {Object} data The post content to create
* @param {Object} options Extra options for the request
* @param {Object} options.reply The id of the post to reply to (If threaded conversation)
* @return {Promise} A promise that will be resolved with an array of related items
* @example
*
* //Retrieve the current post thread of all 'comments' attached to a specific content
* fluro.content.thread('5be504eabf33991239599d63', 'comment', {data:{customField:'My message'}}, {reply:'5be504eabf33991239599d63'})
*/
service.thread = function(id, type, options) {
id = fluro.utils.getStringID(id);
if (!id) {
throw Error(`No target specified ${id}`);
}
if (!options) {
options = {}
}
return new Promise(function(resolve, reject) {
var requestOptions = {
// params: {}
}
// /////////////////////////////////////////////
//Retrieve the query results
fluro.api.get(`/post/${id}/${type}`, requestOptions)
.then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function makes it easy to retrieve all distinct values for a specified field key
* for a specified subset of items from the server, for instance if you wanted to retrieve all possible 'firstName' values from
* a selection of content ids
* @alias content.values
* @param {Array} ids The ids you want to retrieve values for
* @param {String} key the key of the field you want to retrieve the values for
* @return {Promise} A promise that will be resolved with an array of possible values
* @example
*
*
* fluro.content.values(['5be504eabf33991239599d63'], 'firstName').then(function(values) {
* //Would return ['Frank', 'Lucy', 'Marissa']
* })
*/
service.values = function(ids, key, options) {
ids = fluro.utils.arrayIDs(ids);
// if (!ids | !ids.length ) {
// throw Error(`No ids specified ${ids}`);
// }
if (!key | !key.length) {
throw Error(`No key specified `);
}
if (!options) {
options = {}
}
return new Promise(function(resolve, reject) {
var payload = {
ids,
key,
}
/////////////////////////////////////////////
var url = `/content/distinct/values`;
if (options.type) {
url = `/content/${options.type}/distinct/values`;
}
/////////////////////////////////////////////
//Retrieve the query results
return fluro.api.post(url, payload, options)
.then(function(res) {
resolve(_.orderBy(res.data, function(entry) {
return entry.title || entry;
}));
}, reject);
})
}
service.createDuplicate = function(populatedItem) {
var definedType = populatedItem.definition || populatedItem._type;
var newItem = JSON.parse(JSON.stringify(populatedItem));
////////////////////////////////////////////
delete newItem._id;
delete newItem.slug;
delete newItem.author;
delete newItem.managedAuthor;
delete newItem.__v;
delete newItem.created;
delete newItem.updated;
delete newItem.updatedBy;
delete newItem.stats;
delete newItem.privateDetails;
delete newItem._external;
delete newItem.apikey;
////////////////////////////////////////////
switch (newItem._type) {
case 'event':
//Clear out other bits
newItem.plans = [];
newItem.assignments = [];
break;
case 'mailout':
newItem.state = 'ready';
newItem.subject = newItem.title;
newItem.title = newItem.title + ' Copy';
delete newItem.publishDate;
break;
case 'plan':
newItem.startDate = null;
break;
case 'persona':
newItem.user = null;
newItem.collectionEmail = '';
newItem.username = '';
newItem.firstName = '';
newItem.lastName = '';
break;
}
newItem.status = 'active';
////////////////////////////////////////////
newItem.realms = [];
delete newItem.account;
return Promise.resolve(newItem);
}
///////////////////////////////////////////////////
/**
* This function creates an instance of a FluroContentListService
* this then becomes a service that can be used to retrieve filtered data from the server
* @alias content.list
* @param {String} typeName The type or definition name of the content you want to retrieve
* @param {Object} options Extra options for creating the service
* @param {Object} options.criteria The filter criteria for specifying which content items should be returned
* @param {Object} options.criteria.sort The sorting configuration for the results
* @param {Boolean} options.criteria.allDefinitions Whether to include all defined types if a basic type is used as the typeName
* @param {Object} options.criteria.filter the fluro filter configuration for filtering returned results
* @param {String} options.criteria.search A basic keyword search for filtering results
* @param {Date} options.criteria.startDate Used in conjunction with endDate to crop results to a relevant date period
* @param {Date} options.criteria.endDate Used in conjunction with startDate to crop results to a relevant date period
* @param {Object} options.perPage The number of items to retrieve per page
* @param {Object} options.pageIndex The starting page to load from the list
* @param {Object} options.cumulative Whether new page items should append to the results or replace the results
* @param {Object} options.cacheKey A cache id that can be used to refresh cached results
* @return {Object} A new instance of a FluroContentListService
* @example
*
* //How to sort the results
* var sort = {
* key:'title',
* direction:'asc',
* type:'string',
* }
*
* //If you want to filter by search keywords
* var search = 'Any keywords you want to search for'
*
* //If you want to crop results to within a certain timeframe
* var startDate;// = new Date();
* var endDate;// = new Date()
*
* //For more complex AND/OR filtering
* var filter = {
* operator:'and',
* filters:[
* {
* key:'status',
* comparator:'in',
* values:['active'],
* }
* ]
* }
*
* var criteria = {
* search,
* sort,
* startDate,
* endDate,
* filter,
* }
*
* var dataBucket = fluro.content.list('event', {
* perPage: 2,
* criteria,
* });
*
* var isLoading = dataBucket.loading;
* var allItems = dataBucket.items;
* var pageItems = dataBucket.page;
* var currentPage = dataBucket.pageIndex;
* dataBucket.nextPage();
* dataBucket.previousPage();
* dataBucket.reloadCurrentPage();
* dataBucket.addEventListener('items', function(results) {});
* dataBucket.addEventListener('error', function(err) { console.log('an error occurred')});
* dataBucket.addEventListener('totalPages', function() { console.log('the number of pages changed')});
* dataBucket.addEventListener('loadingFilter', function() { console.log('filter is reloading')});
* dataBucket.addEventListener('loadingPage', function() { console.log('the page is reloading')});
* dataBucket.addEventListener('page', function() { console.log('the current page was updated')});
*/
service.list = function(typeName, options) {
return new FluroContentListService(typeName, fluro, options);
}
///////////////////////////////////////////////////
/**
* This function makes it easy to retrieve a large filtered list of content matching certain criteria
* Only the relevant fields will be returned that allows you to paginate and populate content with the
* fluro.content.getMultiple() function
* for more information please see the REST API endpoint documentation here (https://developers.fluro.io/#filter-content)
* @alias content.filter
* @param {String} typeName The type or definition name of the content you want to retrieve
* @param {Object} criteria The criteria used to filter the results
* @return {Promise} A promise that will be resolved with an array of all results
* @example
*
* //How to sort the results
* var sort = {
* key:'title',
* direction:'asc',
* type:'string',
* }
*
* //If you want to filter by search keywords
* var search = 'Any keywords you want to search for'
*
* //If you want to crop results to within a certain timeframe
* var startDate;// = new Date();
* var endDate;// = new Date()
*
* //For more complex AND/OR filtering
* var filter = {
* operator:'and',
* filters:[
* {
* key:'status',
* comparator:'in',
* values:['active'],
* }
* ]
* }
*
* var criteria = {
* search,
* sort,
* startDate,
* endDate,
* filter,
* }
*
* fluro.content.filter('event', criteria)
* .then(function(results) {
* //Returns all results with the basic fields
* })
*/
service.filter = function(typeName, criteria) {
return new Promise(function(resolve, reject) {
return fluro.api.post(`/content/${typeName}/filter`, criteria)
.then(function(res) {
return resolve(res.data);
})
.catch(reject);
})
}
///////////////////////////////////////////////////
/**
* This function makes it easy to retrieve the full content items for a specified selection of ids
* @alias content.getMultiple
* @param {String} typeName The type or definition name of the content you want to retrieve
* @param {Array} ids The ids of the content you want to retrieve
* @param {Object} options extra options for the request
* @param {Array} options.select specify fields you want to retrieve for the items. If blank will return the full object
* @return {Promise} A promise that will be resolved with an array of possible keys
* @example
*
*
* fluro.content.getMultiple(['5be504eabf33991239599d63', '5be504eabf33721239599d83'])
.then(function(items) {
* //Returns the full content items
* })
*/
service.getMultiple = function(typeName, ids, options) {
if(!options) {
options = {};
}
//Ensure the ids are actually ids
ids = fluro.utils.arrayIDs(ids);
//console.log('posted', ids);
return new Promise(function(resolve, reject) {
fluro.api.post(`/content/${typeName}/multiple`, {
ids,
select: options.select ? _.uniq(options.select) : undefined,
//populateAll: true,
limit: ids.length,
//appendContactDetails,
//appendAssignments,
//appendFullFamily,
// cancelToken: currentPageItemsRequest.token,
})
.then(function(res) {
resolve(res.data);
})
.catch(reject);
})
}
///////////////////////////////////////////////////
/**
* This function makes it easy to retrieve all distinct keys for a specified selection of ids
* @alias content.keys
* @param {Array} ids The ids you want to retrieve keys for
* @param {Object} options extra options and query parameters for the http request
* @return {Promise} A promise that will be resolved with an array of possible keys
* @example
*
*
* fluro.content.keys(['5be504eabf33991239599d63']).then(function(values) {
* //Would return ['firstName', 'lastName', 'title', 'tags', 'realms']
* })
*/
service.keys = function(ids, options) {
ids = fluro.utils.arrayIDs(ids);
if (!ids | !ids.length) {
throw Error(`No ids specified ${ids}`);
}
if (!options) {
options = {}
}
return new Promise(function(resolve, reject) {
var payload = {
ids,
}
/////////////////////////////////////////////
var url = `/content/distinct/keys`;
if (options.type) {
url = `/content/${options.type}/distinct/keys`;
}
/////////////////////////////////////////////
//Retrieve the query results
return fluro.api.post(url, payload, options)
.then(function(res) {
resolve(res.data);
}, reject);
})
}
///////////////////////////////////////////////////
/**
* This function creates a clean copy of a specified content item
* @alias content.duplicate
* @param {Object} item The ID or object representing the item you want to duplicate
* @return {Promise} A promise that will be resolved with a cleaned duplicate of the original item
* @example
*
*
* fluro.content.duplicate({_id:'5be504eabf33991239599d63'})
* .then(function(freshItem) {
* //Fresh item is a cleaned duplicate of the original item
* })
*/
service.duplicate = function(item, options) {
if (!options) {
options = {};
}
///////////////////////////////////////
var itemID = fluro.utils.getStringID(item);
return new Promise(function(resolve, reject) {
//Load the proper thing
service.get(itemID)
.then(function(populatedItem) {
var definedType = populatedItem.definition || populatedItem._type;
var newItem = JSON.parse(JSON.stringify(populatedItem));
////////////////////////////////////////////
//Remove the bits and pieces
delete newItem._id;
delete newItem.slug;
delete newItem.author;
delete newItem.managedAuthor;
delete newItem.__v;
delete newItem.created;
delete newItem.updated;
delete newItem.updatedBy;
delete newItem.stats;
delete newItem.privateDetails;
delete newItem._external;
delete newItem.apikey;
////////////////////////////////////////////
if (options.customise) {
//Keep the definition name
} else {
delete newItem.definitionName;
//console.log('Dupliacate', newItem)
}
////////////////////////////////////////////
switch (newItem._type) {
case 'event':
//Clear out other bits
newItem.plans = [];
newItem.assignments = [];
break;
case 'mailout':
newItem.state = 'ready';
newItem.subject = newItem.title;
newItem.title = newItem.title + ' Copy';
delete newItem.publishDate;
break;
case 'plan':
newItem.startDate = null;
break;
case 'persona':
newItem.user = null;
newItem.collectionEmail = '';
newItem.username = '';
newItem.firstName = '';
newItem.lastName = '';
break;
}
//Set the new item as active
newItem.status = 'active';
////////////////////////////////////////////
var accountID = fluro.utils.getStringID(newItem.account);
var userAccountID = fluro.utils.getStringID(populatedItem.account);
if (userAccountID != accountID) {
newItem.realms = [];
}
delete newItem.account;
////////////////////////////////////////////
return resolve(newItem);
})
.catch(reject)
})
}
//////////////////////////////////////
return service;
}
export default FluroContent;