src/helpers/content/Content.js
import ContentType from './ContentType';
import ContentModel from '../../models/content/Content';
import ContentService from '../../services/ContentService';
import StatusService from '../../services/StatusService';
import Commentable from '../../utilities/mixins/Commentable';
import Helper from '../Helper';
// import Storage from '../Storage';
import { aggregate } from '../../utilities/ClassUtility';
import { validate, hasToken, isRequired } from '../../utilities/ValidationUtility';
import { clinical6 } from '../..';
/**
* Helper class representing Content.
*/
class Content extends aggregate(ContentModel, Helper, Commentable) {
/**
* Creates an instance of Content.
*
* @param {String|ContentType} contentType - Content Type string
* @param {Object} json - The data of the object for ContentModel
* @param {?Number} json.id - The ID of the content
* @param {?String} json.title - Title of the content
* @param {?String} json.description - A description related to the content
* @param {?String} json.created_at - The time at which the content was created
* @param {?String} json.updated_at - The time at which the content was updated
* @param {?Number} json.position - The platform position content is put
* @param {?Array} json.tags - The tags to describe the content
* @param {?Object} json.brand - The brand to describe the content
* @param {?Object} [options={}] - Options available to support the API.
* @param {?String} options.version - Version defaults to 'v2'
* @param {?String} options.owner_type - Owner Type defaults to 'mobile_user'
* @param {?Object} [meta={}] - Meta data supporting this item
*/
constructor(contentType = undefined, json = {}, options = {}, meta = {}) {
let _json;
if (typeof contentType === 'string'
|| (typeof contentType === 'object' && contentType.type === 'dynamic_content__content_types')
|| !contentType) {
super(json);
this.contentType = contentType;
_json = json;
} else {
super(contentType);
_json = contentType;
}
// console.log(_json);
/** @type {Object} */
this._options = { version: 'v2' };
// copy over data
this.options = options;
this._data = _json;
/** @type {Object} */
this._meta = meta;
this.deserializeRelationshipStubs(_json);
this.syncRelationships(_json);
}
/**
* Set the attribute of the current content
*
* @param {String} key - A String indicating the attribute key
* @param {(String|Number)} value - Needs to be a String or Number
*
* @example
* myContent.set('title', 'The Tale of Two Cities');
*/
set(key, value) {
/** @type {Any} */
this[key] = value;
}
/**
* Get the value of an attribute of the current content
*
* @param {String} key - A String indicating the attribute key
* @return {(String|Number)} - The value of the attribute
*
* @example
* myContent.get('title');
*/
get(key) {
return this[key];
}
/**
* Set _data to set information to the current object.
*
* @param {Object} data - A json object
*/
set _data(data) {
Object.assign(this, new ContentModel(data));
}
/**
* Get _data to quickly get the raw data without options.
*/
get _data() {
const clone = JSON.parse(JSON.stringify(this));
delete clone._options;
delete clone._meta;
return clone;
}
/**
* Get objectType
* @return {String} - Object Type
*/
get objectType() { return 'dynamic_content/content'; }
/**
* Set the options used for API calls
* - owner (unique identifier / id)
* - ownerType (content type)
* - version
*
* @param {Object} options - A json object with options
*/
/** @type {Object} */
get options() {
return this._options;
}
/**
* Set the options used for API calls
* - owner (unique identifier / id)
* - ownerType (content type)
* - version
*
* @type {Object}
* @param {Object} options - A json object with options
*/
set options(options) {
Object.assign(this._options, options);
}
/** @type {String} */
get ownerType() { return this._options.owner_type; }
/** @type {String} */
set ownerType(ownerType) { this._options.owner_type = ownerType; }
/** @type {User} */
get owner() {
return this._owner;
}
/** @type {User} */
set owner(owner) {
/** @type {User} */
this._owner = owner;
}
/**
* Get resource
* @return {String} - resource - this.content_type
*/
get resource() {
return this.content_type;
}
/**
* Get status
* @return {String} - Status
*/
get status() {
return this._status;
}
/** @type {String} */
set status(status) {
/** @type {String} */
this._status = status;
}
/** @type {User} */
get mobileUser() {
return this._mobile_user;
}
/** @type {User} */
set mobileUser(mobileUser) {
/** @type {User} */
this._mobile_user = mobileUser;
}
/** @type {ContentType} */
get contentType() {
return this._relationships.content_type;
}
/** @type {ContentType} */
set contentType(contentType) {
if (!this._relationships) {
this._relationships = {};
}
if (typeof contentType === 'string') {
/** @type {ContentType} */
this._relationships.content_type = new ContentType({ permanent_link: contentType });
// this.syncRelationships();
} else {
this._relationships.content_type = contentType;
}
}
/** @type {String} - The type */
static get type() {
return 'dynamic_content__contents';
}
/**
* Synchronize the relationships from storage to the current object
*
* @return {Promise}
*/
async syncRelationships(json) {
await super.syncRelationships(json);
if (this.contentType && this.contentType.permanentLink && !this.contentType.id) {
// Handle Content Type by Permlink (not id);
const types = await clinical6.get(ContentType);
if (types && types.find) {
this.contentType = types.find(c => (this.contentType.permanentLink === c.permanentLink));
}
// TODO insert content type when it doesn't exist
// else {
// this.contentType = await this.contentType.save();
// }
}
}
// syncRelationships() {
// const storage = new Storage();
// const permanentLink = this.contentType.permanentLink;
// const self = this;
// return super.syncRelationships().then(() => new Promise((resolve) => {
// if (!self.contentType.id) {
// // Handle Content Type by Permlink (not id);
// storage.contentTypes.then((typesMap) => {
// const typesArray = Object.values(typesMap);
// self.contentType = typesArray.find(c => (permanentLink === c.permanentLink));
// resolve(self);
// });
// } else {
// resolve(self);
// }
// }));
// }
/**
* Deletes a content
* @return {Promise} - Returns a promise via ajax call.
*
* @example
* import { Content, Client } from 'clinical6';
*
* // Removes content from server and local storage
* const content = new Content({...});
* content.delete();
*
* // No longer in storage
* Client.instance.storageUtility.has('contents', { id: 1 });
*/
delete() {
const service = new ContentService();
return service.delete(this);
}
/**
* Get Status and set it to this._status
*
* @return {Promise<any>} - A Promise containing the status (String)
*
* @example
* myContent.getStatus((status) => {
* console.log('status', status);
* console.log('status', myContent.status);
* });
*/
getStatus() {
validate('Content getStatus()',
hasToken(),
isRequired({
content_type: this.content_type,
name: this.tags[0].name,
ownerType: this.ownerType,
owner: this.owner,
}));
const objectType = this.content_type;
const object = this.tags[0].name;
return (new StatusService()).getStatus(objectType, object, this.ownerType, this.owner)
.then(data => (this._status = data.status.value));
}
/**
* Saves the current instance of Content
*
* @return {Object} - Returns a promise via ajax call.
*
* @example
* let car = new client.Content();
* car.set('content_type', 'car');
* car.set('title', 'My Car');
* car.set('make', 'Toyota')
* car.set('model', 'Corolla')
* car.set('year', 2006)
* // inserts
* car.save().then(() => {
* // car now has id
* car.set('year', 2007);
* return car.save(); // car had id so this last save is an update
* });
*/
save() {
return (this.id) ? (new ContentService()).update(this) : (new ContentService()).insert(this);
}
}
export default Content;