mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-31 13:09:21 +03:00
Updated: ckeditor 4.5.3, jquery 1.11.3, openpgpjs 1.2.0
OpenPGP decrypt fix + Small fixes
This commit is contained in:
parent
4deb083d7d
commit
87887373c1
370 changed files with 10805 additions and 5637 deletions
|
|
@ -245,6 +245,19 @@
|
|||
}, bForce);
|
||||
};
|
||||
|
||||
AdminApp.prototype.bootend = function (callback)
|
||||
{
|
||||
if (progressJs)
|
||||
{
|
||||
progressJs.end();
|
||||
}
|
||||
|
||||
if (callback)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
AdminApp.prototype.bootstart = function ()
|
||||
{
|
||||
AbstractApp.prototype.bootstart.call(this);
|
||||
|
|
@ -280,10 +293,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (progressJs)
|
||||
{
|
||||
progressJs().end();
|
||||
}
|
||||
this.bootend();
|
||||
};
|
||||
|
||||
module.exports = new AdminApp();
|
||||
|
|
|
|||
|
|
@ -1305,11 +1305,19 @@
|
|||
|
||||
AppUser.prototype.bootend = function ()
|
||||
{
|
||||
kn.hideLoading();
|
||||
|
||||
if (progressJs)
|
||||
{
|
||||
progressJs().end();
|
||||
kn.hideLoading();
|
||||
|
||||
progressJs.onbeforeend(function () {
|
||||
$('.progressjs-container').hide().remove();
|
||||
});
|
||||
|
||||
progressJs.set(100).end();
|
||||
}
|
||||
else
|
||||
{
|
||||
kn.hideLoading();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1336,7 +1344,7 @@
|
|||
|
||||
if (progressJs)
|
||||
{
|
||||
progressJs().set(70);
|
||||
progressJs.set(90);
|
||||
}
|
||||
|
||||
Globals.leftPanelDisabled.subscribe(function (bValue) {
|
||||
|
|
@ -1352,7 +1360,6 @@
|
|||
Settings.capa(Enums.Capa.TwoFactorForce) &&
|
||||
Settings.settingsGet('RequireTwoFactor'))
|
||||
{
|
||||
|
||||
this.bootend();
|
||||
this.bootstartTwoFactorScreen();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,6 +209,17 @@
|
|||
}
|
||||
};
|
||||
|
||||
HtmlEditor.prototype.replaceHtml = function (mFind, sReplaceHtml)
|
||||
{
|
||||
if (this.editor && this.__inited && 'wysiwyg' === this.editor.mode)
|
||||
{
|
||||
try {
|
||||
this.editor.setData(
|
||||
this.editor.getData().replace(mFind, sReplaceHtml));
|
||||
} catch (e) {}
|
||||
}
|
||||
};
|
||||
|
||||
HtmlEditor.prototype.setPlain = function (sPlain, bFocus)
|
||||
{
|
||||
if (this.editor && this.__inited)
|
||||
|
|
@ -298,6 +309,36 @@
|
|||
self.focusTrigger();
|
||||
});
|
||||
|
||||
if (window.FileReader)
|
||||
{
|
||||
self.editor.on('drop', function(evt) {
|
||||
if (0 < evt.data.dataTransfer.getFilesCount())
|
||||
{
|
||||
var file = evt.data.dataTransfer.getFile(0);
|
||||
if (file && window.FileReader && evt.data.dataTransfer.id &&
|
||||
file.type && file.type.match(/^image/i))
|
||||
{
|
||||
var
|
||||
id = evt.data.dataTransfer.id,
|
||||
imageId = '[img=' + id +']',
|
||||
reader = new window.FileReader()
|
||||
;
|
||||
|
||||
reader.onloadend = function () {
|
||||
if (reader.result)
|
||||
{
|
||||
self.replaceHtml(imageId, '<img src="' + reader.result + '" />');
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
evt.data.dataTransfer.setData('text/html', imageId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
self.editor.on('instanceReady', function () {
|
||||
|
||||
if (self.editor.removeMenuItem)
|
||||
|
|
|
|||
29
dev/External/ko.js
vendored
29
dev/External/ko.js
vendored
|
|
@ -73,6 +73,35 @@
|
|||
}
|
||||
};
|
||||
|
||||
ko.bindingHandlers.scrollerShadows = {
|
||||
'init': function (oElement) {
|
||||
|
||||
var
|
||||
iLimit = 8,
|
||||
$oEl = $(oElement),
|
||||
$win = $(window),
|
||||
oCont = $oEl.find('[data-scroller-shadows-content]')[0] || null,
|
||||
fFunc = _.throttle(function () {
|
||||
$oEl
|
||||
.toggleClass('scroller-shadow-top', iLimit < oCont.scrollTop)
|
||||
.toggleClass('scroller-shadow-bottom', oCont.scrollTop + iLimit < oCont.scrollHeight - oCont.clientHeight)
|
||||
;
|
||||
}, 100)
|
||||
;
|
||||
|
||||
if (oCont)
|
||||
{
|
||||
$(oCont).on('scroll resize', fFunc);
|
||||
$win.on('resize', fFunc);
|
||||
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(oCont, function () {
|
||||
$(oCont).off();
|
||||
$win.off('resize', fFunc);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ko.bindingHandlers.tooltip = {
|
||||
'init': function (oElement, fValueAccessor) {
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@
|
|||
|
||||
Knoin.prototype.hideLoading = function ()
|
||||
{
|
||||
$('#rl-loading').hide();
|
||||
$('#rl-content').show();
|
||||
$('#rl-loading').hide().remove();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -196,6 +196,16 @@
|
|||
this.hasFlaggedSubMessage(false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Array}
|
||||
*/
|
||||
MessageModel.prototype.getRecipientsEmails = function ()
|
||||
{
|
||||
return _.compact(_.uniq(_.map(this.to.concat(this.cc), function (oItem) {
|
||||
return oItem ? oItem.email : '';
|
||||
})));
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
OpenPgpKeyModel.prototype.armor = '';
|
||||
OpenPgpKeyModel.prototype.isPrivate = false;
|
||||
|
||||
OpenPgpKeyModel.prototype.getNativeKeys = function ()
|
||||
OpenPgpKeyModel.prototype.getNativeKey = function ()
|
||||
{
|
||||
var oKey = null;
|
||||
try
|
||||
|
|
@ -57,17 +57,23 @@
|
|||
oKey = PgpStore.openpgp.key.readArmored(this.armor);
|
||||
if (oKey && !oKey.err && oKey.keys && oKey.keys[0])
|
||||
{
|
||||
return oKey.keys;
|
||||
return oKey;
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
Utils.log(e);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
OpenPgpKeyModel.prototype.getNativeKeys = function ()
|
||||
{
|
||||
var oKey = this.getNativeKey();
|
||||
return oKey && oKey.keys ? oKey.keys : null;
|
||||
};
|
||||
|
||||
module.exports = OpenPgpKeyModel;
|
||||
|
||||
}());
|
||||
|
|
@ -511,12 +511,12 @@
|
|||
/**
|
||||
* @param {Object} oMessageTextBody
|
||||
*/
|
||||
MessageUserStore.prototype.initOpenPgpControls = function (oMessageTextBody)
|
||||
MessageUserStore.prototype.initOpenPgpControls = function (oMessageTextBody, oMessage)
|
||||
{
|
||||
if (oMessageTextBody && oMessageTextBody.find)
|
||||
{
|
||||
oMessageTextBody.find('.b-plain-openpgp:not(.inited)').each(function () {
|
||||
PgpStore.initMessageBodyControls($(this));
|
||||
PgpStore.initMessageBodyControls($(this), oMessage);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -692,7 +692,7 @@
|
|||
|
||||
if (oBody)
|
||||
{
|
||||
this.initOpenPgpControls(oBody);
|
||||
this.initOpenPgpControls(oBody, oMessage);
|
||||
|
||||
this.initBlockquoteSwitcher(oBody);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,13 +73,23 @@
|
|||
}), true));
|
||||
};
|
||||
|
||||
PgpUserStore.prototype.findPrivateKeysByEncryptionKeyIds = function (aEncryptionKeyIds, bReturnWrapKeys)
|
||||
PgpUserStore.prototype.findPrivateKeysByEncryptionKeyIds = function (aEncryptionKeyIds, aRecipients, bReturnWrapKeys)
|
||||
{
|
||||
var self = this;
|
||||
return _.compact(_.flatten(_.map(aEncryptionKeyIds, function (oId) {
|
||||
var self = this, aResult = [];
|
||||
aResult = Utils.isArray(aEncryptionKeyIds) ? _.compact(_.flatten(_.map(aEncryptionKeyIds, function (oId) {
|
||||
var oKey = oId && oId.toHex ? self.findPrivateKeyByHex(oId.toHex()) : null;
|
||||
return oKey ? (bReturnWrapKeys ? [oKey] : oKey.getNativeKeys()) : [null];
|
||||
}), true));
|
||||
}), true)) : [];
|
||||
|
||||
if (0 === aResult.length && Utils.isNonEmptyArray(aRecipients))
|
||||
{
|
||||
aResult = _.compact(_.flatten(_.map(aRecipients, function (sEmail) {
|
||||
var oKey = sEmail ? self.findPrivateKeyByEmailNotNative(sEmail) : null;
|
||||
return oKey ? (bReturnWrapKeys ? [oKey] : oKey.getNativeKeys()) : [null];
|
||||
}), true));
|
||||
}
|
||||
|
||||
return aResult;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -149,44 +159,36 @@
|
|||
return this.findPrivateKeyByEmail(require('Stores/User/Account').email(), sPassword);
|
||||
};
|
||||
|
||||
PgpUserStore.prototype.decryptMessage = function (oMessage, fCallback)
|
||||
PgpUserStore.prototype.decryptMessage = function (oMessage, aRecipients, fCallback)
|
||||
{
|
||||
var self = this, aPrivateKeys = [], aEncryptionKeyIds = [];
|
||||
if (oMessage && oMessage.getSigningKeyIds)
|
||||
var self = this, aPrivateKeys = [];
|
||||
if (oMessage && oMessage.getEncryptionKeyIds)
|
||||
{
|
||||
aEncryptionKeyIds = oMessage.getEncryptionKeyIds();
|
||||
if (aEncryptionKeyIds)
|
||||
aPrivateKeys = this.findPrivateKeysByEncryptionKeyIds(oMessage.getEncryptionKeyIds(), aRecipients, true);
|
||||
if (aPrivateKeys && 0 < aPrivateKeys.length)
|
||||
{
|
||||
aPrivateKeys = this.findPrivateKeysByEncryptionKeyIds(aEncryptionKeyIds, true);
|
||||
if (aPrivateKeys && 0 < aPrivateKeys.length)
|
||||
{
|
||||
kn.showScreenPopup(require('View/Popup/MessageOpenPgp'), [function (oDecriptedKey) {
|
||||
kn.showScreenPopup(require('View/Popup/MessageOpenPgp'), [function (oDecriptedKey) {
|
||||
|
||||
if (oDecriptedKey)
|
||||
if (oDecriptedKey)
|
||||
{
|
||||
var oPrivateKey = null, oDecryptedMessage = null;
|
||||
try
|
||||
{
|
||||
var oPrivateKey = null, oDecryptedMessage = null;
|
||||
try
|
||||
{
|
||||
oDecryptedMessage = oMessage.decrypt(oDecriptedKey);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
oDecryptedMessage = null;
|
||||
}
|
||||
oDecryptedMessage = oMessage.decrypt(oDecriptedKey);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
oDecryptedMessage = null;
|
||||
}
|
||||
|
||||
if (oDecryptedMessage)
|
||||
if (oDecryptedMessage)
|
||||
{
|
||||
oPrivateKey = self.findPrivateKeyByHex(oDecriptedKey.primaryKey.keyid.toHex());
|
||||
if (oPrivateKey)
|
||||
{
|
||||
oPrivateKey = self.findPrivateKeyByHex(oDecriptedKey.primaryKey.keyid.toHex());
|
||||
if (oPrivateKey)
|
||||
{
|
||||
self.verifyMessage(oDecryptedMessage, function (oValidKey, aSigningKeyIds) {
|
||||
fCallback(oPrivateKey, oDecryptedMessage, oValidKey || null, aSigningKeyIds || null);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
fCallback(oPrivateKey, oDecryptedMessage);
|
||||
}
|
||||
self.verifyMessage(oDecryptedMessage, function (oValidKey, aSigningKeyIds) {
|
||||
fCallback(oPrivateKey, oDecryptedMessage, oValidKey || null, aSigningKeyIds || null);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -195,13 +197,17 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
fCallback(null, null);
|
||||
fCallback(oPrivateKey, oDecryptedMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fCallback(null, null);
|
||||
}
|
||||
|
||||
}, aPrivateKeys]);
|
||||
}, aPrivateKeys]);
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -262,7 +268,7 @@
|
|||
oVerControl.removeClass('success').addClass('error').attr('title', sTitle);
|
||||
}
|
||||
|
||||
if (undefined !== sText)
|
||||
if (!Utils.isUnd(sText))
|
||||
{
|
||||
mDom.text(Utils.trim(sText.replace(/(\u200C|\u0002)/g, '')));
|
||||
}
|
||||
|
|
@ -270,8 +276,9 @@
|
|||
|
||||
/**
|
||||
* @param {*} mDom
|
||||
* @param {MessageModel} oRainLoopMessage
|
||||
*/
|
||||
PgpUserStore.prototype.initMessageBodyControls = function (mDom)
|
||||
PgpUserStore.prototype.initMessageBodyControls = function (mDom, oRainLoopMessage)
|
||||
{
|
||||
if (mDom && !mDom.hasClass('inited'))
|
||||
{
|
||||
|
|
@ -282,6 +289,7 @@
|
|||
bEncrypted = mDom.hasClass('encrypted'),
|
||||
bSigned = mDom.hasClass('signed'),
|
||||
oVerControl = null,
|
||||
aRecipients = oRainLoopMessage ? oRainLoopMessage.getRecipientsEmails() : [],
|
||||
sData = ''
|
||||
;
|
||||
|
||||
|
|
@ -313,7 +321,7 @@
|
|||
|
||||
if (oMessage && oMessage.getText && oMessage.verify && oMessage.decrypt)
|
||||
{
|
||||
self.decryptMessage(oMessage, function (oValidPrivateKey, oDecriptedMessage, oValidPublicKey, aSigningKeyIds) {
|
||||
self.decryptMessage(oMessage, aRecipients, function (oValidPrivateKey, oDecriptedMessage, oValidPublicKey, aSigningKeyIds) {
|
||||
|
||||
if (oDecriptedMessage)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ html.csstransitions.rl-started-trigger.no-mobile .b-login-content .loginFormWrap
|
|||
animation: login-form-shake 400ms ease-in-out;
|
||||
}
|
||||
|
||||
&.no-mobile .b-login-content .errorAnimated .buttonLogin {
|
||||
color: #b94a48;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.cssanimations.csstransitions.no-mobile .b-login-content .afterLoginHide {
|
||||
opacity: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -610,7 +610,7 @@ html.cssanimations.rl-anim .messageList .line-loading {
|
|||
}
|
||||
|
||||
.draggablePlace {
|
||||
z-index: 10002;
|
||||
z-index: 10003;
|
||||
color: #fff;
|
||||
background-color: #333;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
|
|
|
|||
|
|
@ -388,8 +388,23 @@ html.rl-no-preview-pane {
|
|||
border-radius: 0;
|
||||
font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;
|
||||
display: block;
|
||||
max-width: 700px;
|
||||
word-wrap: break-word;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
code {
|
||||
display: inline;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -571,6 +586,6 @@ html.rl-message-fullscreen {
|
|||
}
|
||||
}
|
||||
|
||||
.nano-scrolllimit-top .buttonUp {
|
||||
.nano.scroller-shadow-top .buttonUp {
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
html.ssm-state-mobile111 {
|
||||
|
||||
|
||||
&.rl-message-fullscreen {
|
||||
#rl-right {
|
||||
.RL-MailMessageView {
|
||||
|
|
@ -47,8 +47,8 @@ html.ssm-state-mobile111 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#rl-right {
|
||||
.RL-MailMessageView {
|
||||
.messageView {
|
||||
|
|
@ -124,18 +124,18 @@ html.ssm-state-mobile111 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#rl-sub-right {
|
||||
right:0px;
|
||||
left:auto;
|
||||
width:35px;
|
||||
}
|
||||
|
||||
|
||||
#rl-center {
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.b-compose.modal,
|
||||
.b-contacts-content.modal,
|
||||
.b-compose.modal,
|
||||
|
|
@ -144,7 +144,7 @@ html.ssm-state-mobile111 {
|
|||
width: 95%;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
|
||||
.b-compose.modal {
|
||||
.b-header {
|
||||
max-height:130px;
|
||||
|
|
@ -154,10 +154,9 @@ html.ssm-state-mobile111 {
|
|||
.cke_top {
|
||||
max-height:30px;
|
||||
overflow:auto;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.b-advanced-search-content.modal {
|
||||
.control-label {
|
||||
width:60px;
|
||||
|
|
@ -166,5 +165,5 @@ html.ssm-state-mobile111 {
|
|||
margin-left:70px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.nano:before, .nano:after {
|
||||
display: none;
|
||||
|
||||
.nano.scroller-shadow-top:before, .nano.scroller-shadow-bottom:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
|
@ -9,18 +9,14 @@
|
|||
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.fixIndex.nano:before, .fixIndex.nano:after {
|
||||
z-index: 98;
|
||||
}
|
||||
|
||||
.nano:before {
|
||||
.nano.scroller-shadow-top:before {
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
.nano:after {
|
||||
.nano.scroller-shadow-bottom:after {
|
||||
bottom: -10px;
|
||||
}
|
||||
|
||||
.nano.nano-scrolllimit-top:before, .nano.nano-scrolllimit-bottom:after {
|
||||
display: block;
|
||||
.nano.fixIndex.scroller-shadow-top:before, .nano.fixIndex.scroller-shadow-bottom:after {
|
||||
z-index: 98;
|
||||
}
|
||||
|
|
@ -15,6 +15,11 @@
|
|||
-moz-box-shadow: none !important;
|
||||
-webkit-box-shadow: none !important;
|
||||
box-shadow: none !important;
|
||||
border-bottom: 1px solid #b6b6b6 !important;
|
||||
}
|
||||
|
||||
.cke_button_on {
|
||||
background: #ddd !important;
|
||||
}
|
||||
|
||||
.cke_button {
|
||||
|
|
@ -34,6 +39,7 @@
|
|||
font-family: Monaco, Menlo, Consolas, 'Courier New', monospace !important;
|
||||
padding: 10px !important;
|
||||
padding-right: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.cke_plain {
|
||||
|
|
@ -93,12 +99,31 @@
|
|||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
pre, code {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;
|
||||
display: block;
|
||||
word-wrap: break-word;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
code {
|
||||
display: inline;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
opacity: 0;
|
||||
}
|
||||
|
||||
#rl-content {
|
||||
#rl-check {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -739,6 +739,11 @@
|
|||
return false;
|
||||
});
|
||||
|
||||
key('c, w', Enums.KeyState.ContactList, function () {
|
||||
self.newMessageCommand();
|
||||
return false;
|
||||
});
|
||||
|
||||
oDom
|
||||
.on('click', '.e-pagenator .e-page', function () {
|
||||
var oPage = ko.dataFor(this);
|
||||
|
|
|
|||
4
dev/bootstrap.js
vendored
4
dev/bootstrap.js
vendored
|
|
@ -55,11 +55,13 @@
|
|||
|
||||
$(_.delay(function () {
|
||||
|
||||
if (!$('#rl-content').is(':visible'))
|
||||
if (!$('#rl-check').is(':visible'))
|
||||
{
|
||||
Globals.$html.addClass('no-css');
|
||||
}
|
||||
|
||||
$('#rl-check').remove();
|
||||
|
||||
if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0])
|
||||
{
|
||||
$('#rl-templates').html(window['rainloopTEMPLATES'][0]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue