merge all Model JSON @Object parsers into a reviveFromJson()

This commit is contained in:
djmaze 2020-10-18 19:46:47 +02:00
parent 76648f04ae
commit 15e07a73e9
18 changed files with 378 additions and 411 deletions

View file

@ -528,10 +528,9 @@ class AppUser extends AbstractApp {
delegateRunOnDestroy(TemplateStore.templates()); delegateRunOnDestroy(TemplateStore.templates());
TemplateStore.templates( TemplateStore.templates(
data.Result.Templates.map(templateData => { data.Result.Templates.map(templateData =>
const template = new TemplateModel(); TemplateModel.reviveFromJson(templateData)
return template.parse(templateData) ? template : null; ).filter(v => v)
}).filter(v => v)
); );
} }
}); });

View file

@ -12,7 +12,14 @@ export class AbstractModel {
* @param {string} modelName = '' * @param {string} modelName = ''
*/ */
constructor() { constructor() {
// this.sModelName = new.target.name; /*
constructor(props) {
if (new.target === Parent) {
throw new Error("Can't instantiate abstract class!");
}
this.sModelName = new.target.name;
props && Object.entries(props).forEach(([key, value]) => '@' !== key[0] && (this[key] = value));
*/
} }
regDisposables(value) { regDisposables(value) {
@ -29,4 +36,30 @@ export class AbstractModel {
} }
Object.values(this).forEach(disposeOne); Object.values(this).forEach(disposeOne);
} }
/**
* @static
* @param {FetchJson} json
* @returns {boolean}
*/
static validJson(json) {
return !!(json && ('Object/'+this.name.replace('Model', '') === json['@Object']));
}
/**
* @static
* @param {FetchJson} json
* @returns {*Model}
*/
static reviveFromJson(json) {
// Object/Attachment
// Object/Contact
// Object/Email
// Object/Filter
// Object/Folder
// Object/Message
// Object/Template
return this.validJson(json) ? new this(json) : null;
}
} }

View file

@ -41,48 +41,36 @@ class AttachmentModel extends AbstractModel {
/** /**
* @static * @static
* @param {AjaxJsonAttachment} json * @param {FetchJsonAttachment} json
* @returns {?AttachmentModel} * @returns {?AttachmentModel}
*/ */
static newInstanceFromJson(json) { static reviveFromJson(json) {
const attachment = new AttachmentModel(); const attachment = super.reviveFromJson(json);
return attachment.initByJson(json) ? attachment : null; if (attachment) {
} attachment.mimeType = ((json.MimeType || '').toLowerCase()).trim();
attachment.fileName = json.FileName.trim();
/**
* @param {AjaxJsonAttachment} json
* @returns {boolean}
*/
initByJson(json) {
let bResult = false;
if (json && 'Object/Attachment' === json['@Object']) {
this.mimeType = ((json.MimeType || '').toLowerCase()).trim();
this.fileName = json.FileName.trim();
// if it is inline // if it is inline
this.isInline = !!json.IsInline; attachment.isInline = !!json.IsInline;
// if inline image is linked with CID in html // if inline image is linked with CID in html
// and 'src="cid:' or background-image:url(cid:) // and 'src="cid:' or background-image:url(cid:)
this.isLinked = !!json.IsLinked; attachment.isLinked = !!json.IsLinked;
this.isThumbnail = !!json.IsThumbnail; attachment.isThumbnail = !!json.IsThumbnail;
this.cid = json.CID; attachment.cid = json.CID;
this.contentLocation = json.ContentLocation; attachment.contentLocation = json.ContentLocation;
this.download = json.Download; attachment.download = json.Download;
this.folder = json.Folder; attachment.folder = json.Folder;
this.uid = json.Uid; attachment.uid = json.Uid;
this.mimeIndex = json.MimeIndex; attachment.mimeIndex = json.MimeIndex;
this.framed = !!json.Framed; attachment.framed = !!json.Framed;
this.friendlySize = File.friendlySize(json.EstimatedSize); attachment.friendlySize = File.friendlySize(json.EstimatedSize);
this.cidWithoutTags = this.cid.replace(/^<+/, '').replace(/>+$/, ''); attachment.cidWithoutTags = attachment.cid.replace(/^<+/, '').replace(/>+$/, '');
this.fileNameExt = File.getExtension(this.fileName); attachment.fileNameExt = File.getExtension(attachment.fileName);
this.fileType = File.getType(this.fileNameExt, this.mimeType); attachment.fileType = File.getType(attachment.fileNameExt, attachment.mimeType);
bResult = true;
} }
return attachment;
return bResult;
} }
/** /**

View file

@ -10,7 +10,7 @@ export class AttachmentCollectionModel extends AbstractCollectionModel
* @returns {AttachmentCollectionModel} * @returns {AttachmentCollectionModel}
*/ */
static reviveFromJson(items) { static reviveFromJson(items) {
let cb = attachment => AttachmentModel.newInstanceFromJson(attachment), let cb = attachment => AttachmentModel.reviveFromJson(attachment),
result = super.reviveFromJson(items, cb); result = super.reviveFromJson(items, cb);
if (!result) { if (!result) {
result = new AttachmentCollectionModel; result = new AttachmentCollectionModel;

View file

@ -83,7 +83,7 @@ class ComposeAttachmentModel extends AbstractModel {
} }
/** /**
* @param {AjaxJsonComposeAttachment} json * @param {FetchJsonComposeAttachment} json
* @returns {boolean} * @returns {boolean}
*/ */
initByUploadJson(json) { initByUploadJson(json) {

View file

@ -46,28 +46,26 @@ class ContactModel extends AbstractModel {
} }
/** /**
* @param {Object} oItem * @static
* @returns {boolean} * @param {FetchJsonContact} json
* @returns {?ContactModel}
*/ */
parse(json) { static reviveFromJson(json) {
let result = false; const contact = super.reviveFromJson(json);
if (json && 'Object/Contact' === json['@Object']) { if (contact) {
this.idContact = pInt(json.IdContact); contact.idContact = pInt(json.IdContact);
this.display = pString(json.Display); contact.display = pString(json.Display);
this.readOnly = !!json.ReadOnly; contact.readOnly = !!json.ReadOnly;
if (Array.isNotEmpty(json.Properties)) { if (Array.isNotEmpty(json.Properties)) {
json.Properties.forEach(property => { json.Properties.forEach(property => {
if (property && property.Type && null != property.Value && null != property.TypeStr) { if (property && property.Type && null != property.Value && null != property.TypeStr) {
this.properties.push([pInt(property.Type), pString(property.Value), pString(property.TypeStr)]); contact.properties.push([pInt(property.Type), pString(property.Value), pString(property.TypeStr)]);
} }
}); });
} }
result = true;
} }
return contact;
return result;
} }
/** /**

View file

@ -1,5 +1,7 @@
import { encodeHtml } from 'Common/UtilsUser'; import { encodeHtml } from 'Common/UtilsUser';
import { AbstractModel } from 'Knoin/AbstractModel';
'use strict'; 'use strict';
/** /**
@ -258,7 +260,7 @@ class Tokenizer
} }
} }
class EmailModel { class EmailModel extends AbstractModel {
email = ''; email = '';
name = ''; name = '';
dkimStatus = ''; dkimStatus = '';
@ -271,6 +273,7 @@ class EmailModel {
* @param {string=} dkimValue = '' * @param {string=} dkimValue = ''
*/ */
constructor(email = '', name = '', dkimStatus = 'none', dkimValue = '') { constructor(email = '', name = '', dkimStatus = 'none', dkimValue = '') {
super();
this.email = email; this.email = email;
this.name = name; this.name = name;
this.dkimStatus = dkimStatus; this.dkimStatus = dkimStatus;
@ -281,12 +284,20 @@ class EmailModel {
/** /**
* @static * @static
* @param {AjaxJsonEmail} json * @param {FetchJsonEmail} json
* @returns {?EmailModel} * @returns {?EmailModel}
*/ */
static newInstanceFromJson(json) { static reviveFromJson(json) {
const email = new EmailModel(); const email = super.reviveFromJson(json);
return email.initByJson(json) ? email : null; if (email && email.email) {
email.name = json.Name.trim();
email.email = json.Email.trim();
email.dkimStatus = (json.DkimStatus || '').trim();
email.dkimValue = (json.DkimValue || '').trim();
email.clearDuplicateName();
return email;
}
return null;
} }
/** /**
@ -332,25 +343,6 @@ class EmailModel {
return (this.name + ' ' + this.email).toLowerCase().includes(query.toLowerCase()); return (this.name + ' ' + this.email).toLowerCase().includes(query.toLowerCase());
} }
/**
* @param {AjaxJsonEmail} oJsonEmail
* @returns {boolean}
*/
initByJson(json) {
let result = false;
if (json && 'Object/Email' === json['@Object']) {
this.name = json.Name.trim();
this.email = json.Email.trim();
this.dkimStatus = (json.DkimStatus || '').trim();
this.dkimValue = (json.DkimValue || '').trim();
result = !!this.email;
this.clearDuplicateName();
}
return result;
}
/** /**
* @param {boolean} friendlyView = false * @param {boolean} friendlyView = false
* @param {boolean=} wrapWithLink = false * @param {boolean=} wrapWithLink = false

View file

@ -12,7 +12,7 @@ export class EmailCollectionModel extends AbstractCollectionModel
static reviveFromJson(items) { static reviveFromJson(items) {
let result = new EmailCollectionModel; let result = new EmailCollectionModel;
Array.isArray(items) && items.forEach(email => { Array.isArray(items) && items.forEach(email => {
email = EmailModel.newInstanceFromJson(email); email = EmailModel.reviveFromJson(email);
email && result.push(email); email && result.push(email);
}); });
return result; return result;

View file

@ -207,19 +207,24 @@ class FilterModel extends AbstractModel {
this.actionValueFourth(AccountStore.getEmailAddresses().join(', ')); this.actionValueFourth(AccountStore.getEmailAddresses().join(', '));
} }
parse(json) { /**
let result = false; * @static
if (json && 'Object/Filter' === json['@Object']) { * @param {FetchJsonFilter} json
this.id = pString(json.ID); * @returns {?FilterModel}
this.name(pString(json.Name)); */
this.enabled(!!json.Enabled); static reviveFromJson(json) {
const filter = super.reviveFromJson(json);
if (filter) {
filter.id = pString(json.ID);
filter.name(pString(json.Name));
filter.enabled(!!json.Enabled);
this.conditionsType(pString(json.ConditionsType)); filter.conditionsType(pString(json.ConditionsType));
this.conditions([]); filter.conditions([]);
if (Array.isNotEmpty(json.Conditions)) { if (Array.isNotEmpty(json.Conditions)) {
this.conditions( filter.conditions(
json.Conditions.map(aData => { json.Conditions.map(aData => {
const filterCondition = new FilterConditionModel(); const filterCondition = new FilterConditionModel();
return filterCondition && filterCondition.parse(aData) ? filterCondition : null; return filterCondition && filterCondition.parse(aData) ? filterCondition : null;
@ -227,21 +232,18 @@ class FilterModel extends AbstractModel {
); );
} }
this.actionType(pString(json.ActionType)); filter.actionType(pString(json.ActionType));
this.actionValue(pString(json.ActionValue)); filter.actionValue(pString(json.ActionValue));
this.actionValueSecond(pString(json.ActionValueSecond)); filter.actionValueSecond(pString(json.ActionValueSecond));
this.actionValueThird(pString(json.ActionValueThird)); filter.actionValueThird(pString(json.ActionValueThird));
this.actionValueFourth(pString(json.ActionValueFourth)); filter.actionValueFourth(pString(json.ActionValueFourth));
this.actionNoStop(!json.Stop); filter.actionNoStop(!json.Stop);
this.actionKeep(!!json.Keep); filter.actionKeep(!!json.Keep);
this.actionMarkAsRead(!!json.MarkAsRead); filter.actionMarkAsRead(!!json.MarkAsRead);
result = true;
} }
return filter;
return result;
} }
cloneSelf() { cloneSelf() {

View file

@ -43,82 +43,89 @@ class FolderModel extends AbstractModel {
/** /**
* @static * @static
* @param {AjaxJsonFolder} json * @param {FetchJsonFolder} json
* @returns {?FolderModel} * @returns {?FolderModel}
*/ */
static newInstanceFromJson(json) { static reviveFromJson(json) {
const folder = new FolderModel(); const folder = super.reviveFromJson(json);
return folder.initByJson(json) ? folder.initComputed() : null; if (folder) {
} folder.name(json.Name);
folder.delimiter = json.Delimiter;
folder.fullName = json.FullName;
folder.fullNameRaw = json.FullNameRaw;
folder.fullNameHash = json.FullNameHash;
folder.deep = json.FullNameRaw.split(folder.delimiter).length - 1;
folder.selectable = !!json.IsSelectable;
folder.existen = !!json.IsExists;
/** folder.subScribed(!!json.IsSubscribed);
* @returns {FolderModel} folder.checkable(!!json.Checkable);
*/
initComputed() {
this.isInbox = ko.computed(() => FolderType.Inbox === this.type());
this.hasSubScribedSubfolders = ko.computed( folder.isInbox = ko.computed(() => FolderType.Inbox === folder.type());
folder.hasSubScribedSubfolders = ko.computed(
() => () =>
!!this.subFolders().find( !!folder.subFolders().find(
oFolder => (oFolder.subScribed() || oFolder.hasSubScribedSubfolders()) && !oFolder.isSystemFolder() oFolder => (oFolder.subScribed() || oFolder.hasSubScribedSubfolders()) && !oFolder.isSystemFolder()
) )
); );
this.canBeEdited = ko.computed(() => FolderType.User === this.type() && this.existen && this.selectable); folder.canBeEdited = ko.computed(() => FolderType.User === folder.type() && folder.existen && folder.selectable);
this.visible = ko.computed(() => { folder.visible = ko.computed(() => {
const isSubScribed = this.subScribed(), const isSubScribed = folder.subScribed(),
isSubFolders = this.hasSubScribedSubfolders(); isSubFolders = folder.hasSubScribedSubfolders();
return isSubScribed || (isSubFolders && (!this.existen || !this.selectable)); return isSubScribed || (isSubFolders && (!folder.existen || !folder.selectable));
}); });
this.isSystemFolder = ko.computed(() => FolderType.User !== this.type()); folder.isSystemFolder = ko.computed(() => FolderType.User !== folder.type());
this.hidden = ko.computed(() => { folder.hidden = ko.computed(() => {
const isSystem = this.isSystemFolder(), const isSystem = folder.isSystemFolder(),
isSubFolders = this.hasSubScribedSubfolders(); isSubFolders = folder.hasSubScribedSubfolders();
return (isSystem && !isSubFolders) || (!this.selectable && !isSubFolders); return (isSystem && !isSubFolders) || (!folder.selectable && !isSubFolders);
}); });
this.selectableForFolderList = ko.computed(() => !this.isSystemFolder() && this.selectable); folder.selectableForFolderList = ko.computed(() => !folder.isSystemFolder() && folder.selectable);
this.messageCountAll = ko folder.messageCountAll = ko
.computed({ .computed({
read: this.privateMessageCountAll, read: folder.privateMessageCountAll,
write: (iValue) => { write: (iValue) => {
if (isPosNumeric(iValue, true)) { if (isPosNumeric(iValue, true)) {
this.privateMessageCountAll(iValue); folder.privateMessageCountAll(iValue);
} else { } else {
this.privateMessageCountAll.valueHasMutated(); folder.privateMessageCountAll.valueHasMutated();
} }
} }
}) })
.extend({ notify: 'always' }); .extend({ notify: 'always' });
this.messageCountUnread = ko folder.messageCountUnread = ko
.computed({ .computed({
read: this.privateMessageCountUnread, read: folder.privateMessageCountUnread,
write: (value) => { write: (value) => {
if (isPosNumeric(value, true)) { if (isPosNumeric(value, true)) {
this.privateMessageCountUnread(value); folder.privateMessageCountUnread(value);
} else { } else {
this.privateMessageCountUnread.valueHasMutated(); folder.privateMessageCountUnread.valueHasMutated();
} }
} }
}) })
.extend({ notify: 'always' }); .extend({ notify: 'always' });
this.printableUnreadCount = ko.computed(() => { folder.printableUnreadCount = ko.computed(() => {
const count = this.messageCountAll(), const count = folder.messageCountAll(),
unread = this.messageCountUnread(), unread = folder.messageCountUnread(),
type = this.type(); type = folder.type();
if (0 < count) { if (0 < count) {
if (FolderType.Draft === type) { if (FolderType.Draft === type) {
return '' + count; return '' + count;
} else if ( }
if (
0 < unread && 0 < unread &&
FolderType.Trash !== type && FolderType.Trash !== type &&
FolderType.Archive !== type && FolderType.Archive !== type &&
@ -131,24 +138,23 @@ class FolderModel extends AbstractModel {
return ''; return '';
}); });
this.canBeDeleted = ko.computed(() => { folder.canBeDeleted = ko.computed(
const bSystem = this.isSystemFolder(); () => !folder.isSystemFolder() && !folder.subFolders().length
return !bSystem && !this.subFolders().length;
});
this.canBeSubScribed = ko.computed(
() => !this.isSystemFolder() && this.selectable
); );
this.canBeChecked = this.canBeSubScribed; folder.canBeSubScribed = ko.computed(
() => !folder.isSystemFolder() && folder.selectable
);
this.localName = ko.computed(() => { folder.canBeChecked = folder.canBeSubScribed;
folder.localName = ko.computed(() => {
translatorTrigger(); translatorTrigger();
let name = this.name(); let name = folder.name();
const type = this.type(); const type = folder.type();
if (this.isSystemFolder()) { if (folder.isSystemFolder()) {
switch (type) { switch (type) {
case FolderType.Inbox: case FolderType.Inbox:
name = i18n('FOLDER_LIST/INBOX_NAME'); name = i18n('FOLDER_LIST/INBOX_NAME');
@ -175,14 +181,14 @@ class FolderModel extends AbstractModel {
return name; return name;
}); });
this.manageFolderSystemName = ko.computed(() => { folder.manageFolderSystemName = ko.computed(() => {
translatorTrigger(); translatorTrigger();
let suffix = ''; let suffix = '';
const type = this.type(), const type = folder.type(),
name = this.name(); name = folder.name();
if (this.isSystemFolder()) { if (folder.isSystemFolder()) {
switch (type) { switch (type) {
case FolderType.Inbox: case FolderType.Inbox:
suffix = '(' + i18n('FOLDER_LIST/INBOX_NAME') + ')'; suffix = '(' + i18n('FOLDER_LIST/INBOX_NAME') + ')';
@ -213,71 +219,44 @@ class FolderModel extends AbstractModel {
return suffix; return suffix;
}); });
this.collapsed = ko.computed({ folder.collapsed = ko.computed({
read: () => !this.hidden() && this.collapsedPrivate(), read: () => !folder.hidden() && folder.collapsedPrivate(),
write: (value) => { write: (value) => {
this.collapsedPrivate(value); folder.collapsedPrivate(value);
} }
}); });
this.hasUnreadMessages = ko.computed(() => 0 < this.messageCountUnread() && this.printableUnreadCount()); folder.hasUnreadMessages = ko.computed(() => 0 < folder.messageCountUnread() && folder.printableUnreadCount());
this.hasSubScribedUnreadMessagesSubfolders = ko.computed( folder.hasSubScribedUnreadMessagesSubfolders = ko.computed(
() => () =>
!!this.subFolders().find( !!folder.subFolders().find(
folder => folder.hasUnreadMessages() || folder.hasSubScribedUnreadMessagesSubfolders() folder => folder.hasUnreadMessages() || folder.hasSubScribedUnreadMessagesSubfolders()
) )
); );
// subscribe // subscribe
this.name.subscribe(value => this.nameForEdit(value)); folder.name.subscribe(value => folder.nameForEdit(value));
this.edited.subscribe(value => value && this.nameForEdit(this.name())); folder.edited.subscribe(value => value && folder.nameForEdit(folder.name()));
this.messageCountUnread.subscribe((unread) => { folder.messageCountUnread.subscribe((unread) => {
if (FolderType.Inbox === this.type()) { if (FolderType.Inbox === folder.type()) {
dispatchEvent(new CustomEvent('mailbox.inbox-unread-count', {detail:unread})); dispatchEvent(new CustomEvent('mailbox.inbox-unread-count', {detail:unread}));
} }
}); });
}
return this; return folder;
} }
/** /**
* @returns {string} * @returns {string}
*/ */
collapsedCss() { collapsedCss() {
return this.hasSubScribedSubfolders() return 'e-collapsed-sign ' + (this.hasSubScribedSubfolders()
? this.collapsed() ? (this.collapsed() ? 'icon-right-mini' : 'icon-down-mini')
? 'icon-right-mini e-collapsed-sign' : 'icon-none'
: 'icon-down-mini e-collapsed-sign' );
: 'icon-none e-collapsed-sign';
}
/**
* @param {AjaxJsonFolder} json
* @returns {boolean}
*/
initByJson(json) {
let bResult = false;
if (json && 'Object/Folder' === json['@Object']) {
this.name(json.Name);
this.delimiter = json.Delimiter;
this.fullName = json.FullName;
this.fullNameRaw = json.FullNameRaw;
this.fullNameHash = json.FullNameHash;
this.deep = json.FullNameRaw.split(this.delimiter).length - 1;
this.selectable = !!json.IsSelectable;
this.existen = !!json.IsExists;
this.subScribed(!!json.IsSubscribed);
this.checkable(!!json.Checkable);
bResult = true;
}
return bResult;
} }
/** /**

View file

@ -47,7 +47,7 @@ export class FolderCollectionModel extends AbstractCollectionModel
bDisplaySpecSetting = FolderStore.displaySpecSetting(); bDisplaySpecSetting = FolderStore.displaySpecSetting();
return super.reviveFromJson(object, (oFolder, self) => { return super.reviveFromJson(object, (oFolder, self) => {
let oCacheFolder = Cache.getFolderFromCacheList(oFolder.FullNameRaw); let oCacheFolder = Cache.getFolderFromCacheList(oFolder.FullNameRaw);
if (!oCacheFolder && (oCacheFolder = FolderModel.newInstanceFromJson(oFolder))) { if (!oCacheFolder && (oCacheFolder = FolderModel.reviveFromJson(oFolder))) {
if (oFolder.FullNameRaw == self.SystemFolders[ServerFolderType.INBOX]) { if (oFolder.FullNameRaw == self.SystemFolders[ServerFolderType.INBOX]) {
oCacheFolder.type(FolderType.Inbox); oCacheFolder.type(FolderType.Inbox);
Cache.setFolderInboxName(oFolder.FullNameRaw); Cache.setFolderInboxName(oFolder.FullNameRaw);

View file

@ -93,12 +93,49 @@ class MessageModel extends AbstractModel {
/** /**
* @static * @static
* @param {AjaxJsonMessage} oJsonMessage * @param {FetchJsonMessage} json
* @returns {?MessageModel} * @returns {?MessageModel}
*/ */
static newInstanceFromJson(json) { static reviveFromJson(json) {
const oMessageModel = new MessageModel(); const oMessageModel = super.reviveFromJson(json);
return oMessageModel.initByJson(json) ? oMessageModel : null; if (oMessageModel) {
oMessageModel.folderFullNameRaw = json.Folder;
oMessageModel.uid = json.Uid;
oMessageModel.hash = json.Hash;
oMessageModel.requestHash = json.RequestHash;
oMessageModel.size(pInt(json.Size));
oMessageModel.from = EmailCollectionModel.reviveFromJson(json.From);
oMessageModel.to = EmailCollectionModel.reviveFromJson(json.To);
oMessageModel.cc = EmailCollectionModel.reviveFromJson(json.Cc);
oMessageModel.bcc = EmailCollectionModel.reviveFromJson(json.Bcc);
oMessageModel.replyTo = EmailCollectionModel.reviveFromJson(json.ReplyTo);
oMessageModel.deliveredTo = EmailCollectionModel.reviveFromJson(json.DeliveredTo);
oMessageModel.unsubsribeLinks = Array.isNotEmpty(json.UnsubsribeLinks) ? json.UnsubsribeLinks : [];
oMessageModel.subject(json.Subject);
if (isArray(json.SubjectParts)) {
oMessageModel.subjectPrefix(json.SubjectParts[0]);
oMessageModel.subjectSuffix(json.SubjectParts[1]);
} else {
oMessageModel.subjectPrefix('');
oMessageModel.subjectSuffix(oMessageModel.subject());
}
oMessageModel.dateTimeStampInUTC(pInt(json.DateTimeStampInUTC));
oMessageModel.fromEmailString(oMessageModel.from.toString(true));
oMessageModel.fromClearEmailString(oMessageModel.from.toStringClear());
oMessageModel.toEmailsString(oMessageModel.to.toString(true));
oMessageModel.toClearEmailsString(oMessageModel.to.toStringClear());
oMessageModel.threads(isArray(json.Threads) ? json.Threads : []);
oMessageModel.initFlagsByJson(json);
oMessageModel.computeSenderEmail();
}
return oMessageModel;
} }
_reset() { _reset() {
@ -206,7 +243,8 @@ class MessageModel extends AbstractModel {
} }
setFromJson(json) { setFromJson(json) {
if (json && 'Object/Message' === json['@Object']) { let result = MessageModel.validJson(json);
if (result) {
let priority = pInt(json.Priority); let priority = pInt(json.Priority);
this.priority( this.priority(
[MessagePriority.High, MessagePriority.Low].includes(priority) ? priority : MessagePriority.Normal [MessagePriority.High, MessagePriority.Low].includes(priority) ? priority : MessagePriority.Normal
@ -216,62 +254,12 @@ class MessageModel extends AbstractModel {
this.hasAttachments(!!json.HasAttachments); this.hasAttachments(!!json.HasAttachments);
this.attachmentsSpecData(isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []); this.attachmentsSpecData(isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []);
return true;
} }
return false;
}
/**
* @param {AjaxJsonMessage} json
* @returns {boolean}
*/
initByJson(json) {
let result = this.setFromJson(json);
if (result) {
this.folderFullNameRaw = json.Folder;
this.uid = json.Uid;
this.hash = json.Hash;
this.requestHash = json.RequestHash;
this.size(pInt(json.Size));
this.from = EmailCollectionModel.reviveFromJson(json.From);
this.to = EmailCollectionModel.reviveFromJson(json.To);
this.cc = EmailCollectionModel.reviveFromJson(json.Cc);
this.bcc = EmailCollectionModel.reviveFromJson(json.Bcc);
this.replyTo = EmailCollectionModel.reviveFromJson(json.ReplyTo);
this.deliveredTo = EmailCollectionModel.reviveFromJson(json.DeliveredTo);
this.unsubsribeLinks = Array.isNotEmpty(json.UnsubsribeLinks) ? json.UnsubsribeLinks : [];
this.subject(json.Subject);
if (isArray(json.SubjectParts)) {
this.subjectPrefix(json.SubjectParts[0]);
this.subjectSuffix(json.SubjectParts[1]);
} else {
this.subjectPrefix('');
this.subjectSuffix(this.subject());
}
this.dateTimeStampInUTC(pInt(json.DateTimeStampInUTC));
this.fromEmailString(this.from.toString(true));
this.fromClearEmailString(this.from.toStringClear());
this.toEmailsString(this.to.toString(true));
this.toClearEmailsString(this.to.toStringClear());
this.threads(isArray(json.Threads) ? json.Threads : []);
this.initFlagsByJson(json);
this.computeSenderEmail();
}
return result; return result;
} }
/** /**
* @param {AjaxJsonMessage} json * @param {FetchJsonMessage} json
* @returns {boolean} * @returns {boolean}
*/ */
initUpdateByMessageJson(json) { initUpdateByMessageJson(json) {
@ -314,22 +302,19 @@ class MessageModel extends AbstractModel {
} }
/** /**
* @param {AjaxJsonMessage} json * @param {FetchJsonMessage} json
* @returns {boolean} * @returns {boolean}
*/ */
initFlagsByJson(json) { initFlagsByJson(json) {
let result = false; let result = MessageModel.validJson(json);
if (json && 'Object/Message' === json['@Object']) { if (result) {
this.unseen(!json.IsSeen); this.unseen(!json.IsSeen);
this.flagged(!!json.IsFlagged); this.flagged(!!json.IsFlagged);
this.answered(!!json.IsAnswered); this.answered(!!json.IsAnswered);
this.forwarded(!!json.IsForwarded); this.forwarded(!!json.IsForwarded);
this.isReadReceipt(!!json.IsReadReceipt); this.isReadReceipt(!!json.IsReadReceipt);
this.deletedMark(!!json.IsDeleted); this.deletedMark(!!json.IsDeleted);
result = true;
} }
return result; return result;
} }

View file

@ -36,8 +36,7 @@ export class MessageCollectionModel extends AbstractCollectionModel
static reviveFromJson(object, cached) { static reviveFromJson(object, cached) {
let newCount = 0; let newCount = 0;
return super.reviveFromJson(object, message => { return super.reviveFromJson(object, message => {
if (message && 'Object/Message' === message['@Object']) { message = MessageModel.reviveFromJson(message);
message = MessageModel.newInstanceFromJson(message);
if (message) { if (message) {
if (hasNewMessageAndRemoveFromCache(message.folderFullNameRaw, message.uid) && 5 >= newCount) { if (hasNewMessageAndRemoveFromCache(message.folderFullNameRaw, message.uid) && 5 >= newCount) {
++newCount; ++newCount;
@ -49,7 +48,6 @@ export class MessageCollectionModel extends AbstractCollectionModel
cached ? initMessageFlagsFromCache(message) : storeMessageFlagsToCache(message); cached ? initMessageFlagsFromCache(message) : storeMessageFlagsToCache(message);
return message; return message;
} }
}
}); });
} }
} }

View file

@ -22,20 +22,19 @@ class TemplateModel extends AbstractModel {
} }
/** /**
* @returns {boolean} * @static
* @param {FetchJsonTemplate} json
* @returns {?TemplateModel}
*/ */
parse(json) { static reviveFromJson(json) {
let result = false; const template = super.reviveFromJson(json);
if (json && 'Object/Template' === json['@Object']) { if (template) {
this.id = pString(json.ID); template.id = pString(json.ID);
this.name = pString(json.Name); template.name = pString(json.Name);
this.body = pString(json.Body); template.body = pString(json.Body);
this.populated = !!json.Populated; template.populated = !!json.Populated;
result = true;
} }
return template;
return result;
} }
} }

View file

@ -102,10 +102,7 @@ class FiltersUserSettings {
this.serverError(false); this.serverError(false);
this.filters( this.filters(
data.Result.Filters.map(aItem => { data.Result.Filters.map(aItem => FilterModel.reviveFromJson(aItem)).filter(v => v)
const filter = new FilterModel();
return filter && filter.parse(aItem) ? filter : null;
}).filter(v => v)
); );
this.modules(data.Result.Modules ? data.Result.Modules : {}); this.modules(data.Result.Modules ? data.Result.Modules : {});

View file

@ -452,14 +452,13 @@ class MessageUserStore {
if ( if (
data && data &&
MessageModel.validJson(data.Result) &&
message && message &&
data.Result &&
'Object/Message' === data.Result['@Object'] &&
message.folderFullNameRaw === data.Result.Folder message.folderFullNameRaw === data.Result.Folder
) { ) {
const threads = message.threads(); const threads = message.threads();
if (message.uid !== data.Result.Uid && 1 < threads.length && threads.includes(data.Result.Uid)) { if (message.uid !== data.Result.Uid && 1 < threads.length && threads.includes(data.Result.Uid)) {
message = MessageModel.newInstanceFromJson(data.Result); message = MessageModel.reviveFromJson(data.Result);
if (message) { if (message) {
message.threads(threads); message.threads(threads);
initMessageFlagsFromCache(message); initMessageFlagsFromCache(message);
@ -641,7 +640,7 @@ class MessageUserStore {
/** /**
* @param {string} sResult * @param {string} sResult
* @param {AjaxJsonDefaultResponse} oData * @param {FetchJsonDefaultResponse} oData
* @param {boolean} bCached * @param {boolean} bCached
*/ */
onMessageResponse(sResult, oData, bCached) { onMessageResponse(sResult, oData, bCached) {

View file

@ -468,7 +468,7 @@ class ContactsPopupView extends AbstractViewNext {
/** /**
* @param {string} sResult * @param {string} sResult
* @param {AjaxJsonDefaultResponse} oData * @param {FetchJsonDefaultResponse} oData
*/ */
deleteResponse(sResult, oData) { deleteResponse(sResult, oData) {
if (500 < (StorageResultType.Success === sResult && oData && oData.Time ? pInt(oData.Time) : 0)) { if (500 < (StorageResultType.Success === sResult && oData && oData.Time ? pInt(oData.Time) : 0)) {
@ -570,13 +570,11 @@ class ContactsPopupView extends AbstractViewNext {
if (StorageResultType.Success === result && data && data.Result && data.Result.List) { if (StorageResultType.Success === result && data && data.Result && data.Result.List) {
if (Array.isNotEmpty(data.Result.List)) { if (Array.isNotEmpty(data.Result.List)) {
list = data.Result.List.map(item => { data.Result.List.forEach(item => {
const contact = new ContactModel(); item = ContactModel.reviveFromJson(item);
return contact.parse(item) ? contact : null; item && list.push(item);
}); });
list = list.filter(v => v);
count = pInt(data.Result.Count); count = pInt(data.Result.Count);
count = 0 < count ? count : 0; count = 0 < count ? count : 0;
} }

View file

@ -8,6 +8,7 @@ import Remote from 'Remote/User/Fetch';
import { popup, command } from 'Knoin/Knoin'; import { popup, command } from 'Knoin/Knoin';
import { AbstractViewNext } from 'Knoin/AbstractViewNext'; import { AbstractViewNext } from 'Knoin/AbstractViewNext';
import { TemplateModel } from 'Model/Template';
@popup({ @popup({
name: 'View/Popup/Template', name: 'View/Popup/Template',
@ -133,8 +134,7 @@ class TemplatePopupView extends AbstractViewNext {
if ( if (
StorageResultType.Success === result && StorageResultType.Success === result &&
data && data &&
data.Result && TemplateModel.validJson(data.Result) &&
'Object/Template' === data.Result['@Object'] &&
null != data.Result.Body null != data.Result.Body
) { ) {
template.body = data.Result.Body; template.body = data.Result.Body;