src/helpers/ProjectContent.js
import ProjectContentService from '../services/ProjectContentService';
import { validate, isRequired } from '../utilities/ValidationUtility';
/**
* The ProjectContent class wraps custom API endpoints in a simple and quick set of objects /
* methods. This object will contain many properties belonging to the type when returned from the
* server. A ProjectContent for a car, for example, may have `myCar.make` or `myCar.model` in
* addition to the listed properties.
*
* @property {Object} _options - Used for API calls
* @property {String} _options.owner - The owner of the object (id)
* @property {String} _options.ownerType - The ownerType of the object (type)
* @property {String} [_options.version=v2] - The version of the api being used
* @property {any} _meta - The combined list of meta data obtained through
* this instance's call
* @example
* let labs1 = new ProjectContent('site_start/labs'); // commonly used
* let labs2 = new ProjectContent('site_start/labs', { version: 'v2' });
* let labs3 = new ProjectContent('site_start/labs', { id: 23 }); // commonly used
* let labs4 = new ProjectContent('site_start/labs', {}, { make: 'corolla' });
*/
class ProjectContent {
/**
* This is used to manage the `_options` property
* - owner (unique identifier / id)
* - ownerType (content type)
* - version
* @type {Object}
*/
set options(options) { Object.assign(this._options, options); }
/**
* This is used to manage the `_options` property
* @type {Object}
*/
get options() { return this._options; }
/**
* Set _data to set information to the current object.
* @type {Object}
*/
set _data(data) { Object.assign(this, data); }
/**
* Get _data to quickly get the raw data without options.
* @type {Object}
*/
get _data() {
const clone = JSON.parse(JSON.stringify(this));
delete clone._options;
delete clone._meta;
return clone;
}
/**
* Return meta data for the project content. The data it consumes is required to come at the
* root of the API endpoint with the `meta` key containing keys pointing to arrays of data.
* For example `{"meta": { "certificate_types": [ {"value": ..., "label": ...} ] }}` could then
* be obtained through `myProjectContent.meta['certificate_types']`
*
* @readonly
*
* @type {Object}
*/
get meta() {
return this._meta;
}
/**
* Creates an instance of ProjectContent.
*
* @param {?String} [type=''] - Type of the ProjectContent ('site_start/labs')
* @param {?any} [options={}] - Options available to support the API. Version = 'v2'
* @param {?any} [data={}] - The data of the object
*/
constructor(type = '', options = {}, data = {}, meta = {}) {
/** @type {Object} */
this._options = {
version: 'v2',
ownerType: type,
};
if (options.id) {
this._options.owner = options.id;
}
if (options.type) {
this._options.ownerType = options.type;
}
// copy over data
this.options = options;
this._data = data;
/** @type {Object} */
this._meta = meta;
}
/**
* Add child of type belonging to the ProjectContent
*
* @param {String} type - The type of the child being inserted
* @param {Object} child - The child data being inserted
*
* @return {Promise<Object>} - Promise of the resulting API call
* @example
* let lab = new ProjectContent('site_start/labs', { id: 23 });
* let lab_director = { first_name: 'Joe', last_name: 'Waldron' };
* await lab.addChild('lab_directors', lab_director).then((data) => (lab_director = data));
*/
addChild(type, child) {
return (new ProjectContentService()).insertProject(this.options, type, child);
}
// /**
// * Add a comment for this project content
// *
// * @return {Promise<Comment>} - Promise with an array containing the new comment
// */
// addComment(text) {
// return (new DiscussService()).addComment(
// text,
// this._options.ownerType, // content type
// this._options.owner, // content id
// 'mobile_user'
// // this._options.ownerType, // owner type
// // this._options.owner // owner id
// );
// }
/**
* Gets all data belonging to the ProjectContent ownerType
*
* @return {Promise<ProjectContent[]>} - Promise of an Array of ProjectContent
* @example
* let labs = new ProjectContent('site_start/labs');
* labs.getAll().then((list) => {
* console.log(list);
* });
* // or alternatively in one line
* (new ProjectContent('site_start/labs')).getAll().then((list) => console.log(list));
*/
getAll() {
const { version, ownerType } = this.options;
return (new ProjectContentService()).getProject({ version, ownerType }).then((results) => {
// @TODO handle meta
this._meta = Object.assign({}, results.meta || {}, this._meta);
return results.data.map(obj => new ProjectContent(ownerType, { version, owner: obj.id }, obj));
});
}
/**
* Get one child with id and type belonging to the ProjectContent
*
* @param {String} type - The type of the child
* @param {Number} id - The id of the child
*
* @return {Promise<Object>} - Promise of the resulting API call
* @example
* let lab = new ProjectContent('site_start/labs', { id: 23 });
* let lab_director = await lab.getChild('lab_directors', 512);
*/
getChild(type, id) {
return (new ProjectContentService()).getProject(this.options, type, id).then((results) => {
// @TODO handle meta data
this._meta = Object.assign({}, results.meta || {}, this._meta);
return results.data;
});
}
/**
* Get all children with type belonging to the ProjectContent
*
* @param {String} type - The type of the children to be returned
* @return {Promise<Array>} - Promise of an array of children json
* @example
* let lab = new ProjectContent('site_start/labs', { id: 23 });
* let lab_directors = await lab.getChildren('lab_directors');
*/
getChildren(type) {
return (new ProjectContentService()).getProject(this.options, type).then((results) => {
// @TODO handle meta data
this._meta = Object.assign({}, results.meta || {}, this._meta);
return results.data;
});
}
/**
* Gets data belonging to this ProjectContent (ownerType and owner). Stores data in
* ProjectContent.
*
* @return {Promise<Object>} - Promise of the data
* @example
* let lab = new ProjectContent('site_start/labs');
* lab.getAll().then((list) => {
* list[0].getData().then(() => console.log(list[0])); // should have new properties
* });
* lab = new ProjectContent('site_start/labs', { id: 23 });
* lab.getData().then(() => console.log(lab)); // should have new properties
* lab.meta; // Accumulates through getData, getChildren, and getSibling calls
*/
getData() {
validate('Clinical6 ProjectContent.getData',
isRequired({ version: this.options.version }),
isRequired({ ownerType: this.options.ownerType }),
isRequired({ owner: this.options.owner }));
return (new ProjectContentService()).getProject(this.options).then((results) => {
this._meta = Object.assign({}, results.meta || {}, this._meta);
this._data = results;
return this._data;
});
}
/**
* Get data belonging to a sibling provided the id assuming ProjectContent's type
*
* @param {Number} id - The id of the sibling
* @return {Promise<ProjectContent>}
* @example
* let lab = new ProjectContent('site_start/labs', { id: 23 });
* let other_lab = await lab.getSibling(24);
*/
getSibling(id) {
const params = {
version: this.options.version,
ownerType: this.options.ownerType,
owner: id,
};
return (new ProjectContentService()).getProject(params).then((results) => {
this._meta = Object.assign({}, results.meta || {}, this._meta);
return new ProjectContent('', params, results.data, results.meta || {});
});
}
/**
* Remove child of type belonging to the ProjectContent
*
* @param {String} type - The type of the child being removed
* @param {Number} id - The child data being inserted
*
* @return {Promise<any>} - Promise of the resulting API call
* @example
* let lab = new ProjectContent('site_start/labs', { id: 23 });
* let lab_director = await lab.removeChild('lab_directors', 512);
*/
removeChild(type, id) {
return (new ProjectContentService()).deleteProject(this.options, type, id);
}
/**
* Saves the current ProjectContent object. If it has an id, then update else insert.
*
* @return {Promise<any>}
* @example
* // Create new lab
* let lab = new ProjectContent('site_start/labs');
* lab.name = 'La Jolla Clinic';
* await lab.save(); // id does not exist so it inserts, but will now have name
* // Update existing lab name
* lab.name = 'New Name';
* lab.save();
*/
save() {
return (this.options.owner && this.options.owner !== '')
? (new ProjectContentService()).updateProject(this.options, '', null, this._data)
: (new ProjectContentService()).insertProject(this.options, '', this._data)
.then((results) => {
this._data = results;
this._options.owner = results.id;
});
}
/**
* Update child of type belonging to the ProjectContent
*
* @param {String} type - The type of the child being updated
* @param {Object} child - The child data being updated
* @param {Number} [id] - The id of the child being updated
* @return {Promise<any>}
* @example
* let lab = new ProjectContent('site_start/labs', { id: 23 });
* let lab_directors = await lab.getChildren('lab_directors');
* lab_directors[0].first_name = 'Joe';
* lab.updateChild('lab_directors', lab_directors[0]);
*/
updateChild(type, child, id = undefined) {
return (new ProjectContentService())
.updateProject(this.options, type, id || child.id, child);
}
}
export default ProjectContent;