@noggin/elastic-noggin-sdk
Version:
Elastic Noggin SDK
206 lines (163 loc) • 5.55 kB
text/typescript
import { cloneDeep, merge, isArray, isEqual, union } from 'lodash';
import { IClientT, IEno, IField, II18n, IServerT, ISource, Sid, Tip } from './types';
import { EnoFactory } from '../EnoFactory';
import dataConstants from '../constants';
export { Eno };
interface IToJSONOption {
propWhiteList?: string[];
}
class Eno implements IEno {
readonly tip: Tip = '';
readonly sid: Sid = '';
readonly serverT?: IServerT;
readonly clientT?: IClientT;
readonly source?: ISource;
constructor(proto: IEno) {
merge(this, cloneDeep(proto));
}
createDeletedEno(branch?: Tip): Eno {
const enoFact = new EnoFactory();
enoFact.setProtoToPatch(this);
enoFact.setDeleted(true);
if (branch) {
enoFact.setBranch(branch);
}
return enoFact.makeEno();
}
createSecurityChangedEno(security: Tip, branch?: Tip): Eno {
const enoFact = new EnoFactory();
enoFact.setProtoToPatch(this);
enoFact.setSecurity(security);
if (branch) {
enoFact.setBranch(branch);
}
return enoFact.makeEno();
}
toJson(option: IToJSONOption = { }): IEno {
const json = Object.create(null);
for (const property of Object.keys(this)) {
if (option && option.propWhiteList && option.propWhiteList.indexOf(property) === -1) {
continue;
}
json[property] = cloneDeep((<any>this)[property]);
}
return json;
}
getBranch(): Tip|null {
return this.serverT ?
this.serverT.branch :
this.clientT ?
this.clientT.branch : null;
}
getType(): Tip|null {
return this.source ? this.source.type : null;
}
getSessionId(): Tip|null {
return this.serverT ? this.serverT.session : null;
}
hasError(): boolean {
return !!(this.serverT && this.serverT.error && this.serverT.error.length > 0);
}
getFieldFormula(fieldTip: Tip): string|null {
if (this.source && this.source.field) {
const field = this.source.field.filter((f: IField) => f.tip === fieldTip)[0];
return field && field.formula && field.formula.length > 0 ? field.formula[0] : null;
}
return null;
}
getFieldValues(fieldTip: Tip, lang: string = dataConstants.LANG_DEFAULT): string[] {
if (!this.source || !this.source.field) {
return [];
}
const field = this.source.field.filter((f: IField) => f.tip === fieldTip)[0];
if (!field) {
return [];
}
if (field.value) {
return field.value;
}
if (!field.i18n) {
return [];
}
lang = lang.toLowerCase();
const maybeLang = lang.substr(0, 2);
let maybeLangIndex: number|null = null;
let defaultLangIndex: number|null = null;
for (let i = 0; i < field.i18n.length; i++) {
if (field.i18n[i].lang === lang) {
return field.i18n[i].value || [];
}
if (maybeLangIndex === null && field.i18n[i].lang.substr(0, 2) === maybeLang) {
maybeLangIndex = i;
} else if (defaultLangIndex === null && field.i18n[i].lang === dataConstants.LANG_DEFAULT) {
defaultLangIndex = i;
}
}
if (maybeLangIndex !== null) {
return field.i18n[maybeLangIndex].value || [];
}
if (defaultLangIndex !== null) {
return field.i18n[defaultLangIndex].value || [];
}
return [];
}
getFieldStringValue(fieldTip: Tip, lang: string = dataConstants.LANG_DEFAULT): string | null {
return this.getFieldValues(fieldTip, lang).join(', ') || null;
}
getFieldNumberValue(fieldTip: Tip, lang: string = dataConstants.LANG_DEFAULT): number | null {
const values = this.getFieldValues(fieldTip, lang);
if (values.length === 0) {
return null;
}
const numberValue = parseFloat(values[0]);
if (isNaN(numberValue)) {
return null;
}
return numberValue;
}
getFieldBooleanValue(fieldTip: Tip, lang: string = dataConstants.LANG_DEFAULT): boolean {
const fieldValues = this.getFieldValues(fieldTip, lang);
return fieldValues && fieldValues.length > 0 && fieldValues.filter((value: string) => value !== 'true').length === 0;
}
getFieldJsonValue(fieldTip: Tip): any | null {
const value = this.getFieldValues(fieldTip);
if (value && value.length > 0) {
return JSON.parse(value[0]);
}
return null;
}
getFieldRawI18n(fieldTip: Tip): II18n[] {
const field = this.source.field.filter((f: IField) => f.tip === fieldTip)[0];
if (isArray(field.i18n)) {
return [...field.i18n];
}
if (isArray(field.value)) {
return [{ lang: dataConstants.LANG_DEFAULT, value: field.value }];
}
return [];
}
// Do deep comparison of this eno and the given eno to check if anything is different.
// Not that this does not compare nonce and parent as this is for comparing content
isContentDiff(eno: Eno): boolean {
if (!this.source || !eno.source) {
return true;
}
return this.source.deleted !== eno.source.deleted ||
this.source.type !== eno.source.type ||
this.source.security !== eno.source.security ||
this._isFieldDiff(eno);
}
private _isFieldDiff(eno: Eno): boolean {
if (!this.source || !this.source.field || !eno.source || !eno.source.field) {
return true;
}
const allFieldTips = union(this.source.field.map(iField => iField.tip), eno.source.field.map(iField => iField.tip));
for (const fieldTip of allFieldTips) {
const isDiff = !isEqual(this.getFieldValues(fieldTip), eno.getFieldValues(fieldTip));
if (isDiff) {
return true;
}
}
return false;
}
}