mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Split Common/Utils.js
Because admin app doesn't need most of them
This commit is contained in:
parent
167e323c72
commit
1d6a636433
25 changed files with 592 additions and 620 deletions
|
|
@ -1,10 +1,5 @@
|
||||||
import {
|
import { pInt, pString } from 'Common/Utils';
|
||||||
isPosNumeric,
|
import { isPosNumeric, delegateRunOnDestroy, mailToHelper } from 'Common/UtilsUser';
|
||||||
pInt,
|
|
||||||
pString,
|
|
||||||
delegateRunOnDestroy,
|
|
||||||
mailToHelper
|
|
||||||
} from 'Common/Utils';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Layout,
|
Layout,
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,7 @@
|
||||||
import { ComposeType, SaveSettingsStep, FolderType } from 'Common/Enums';
|
import { SaveSettingsStep } from 'Common/Enums';
|
||||||
|
|
||||||
const
|
const
|
||||||
doc = document,
|
doc = document;
|
||||||
tpl = doc.createElement('template'),
|
|
||||||
isArray = Array.isArray,
|
|
||||||
htmlmap = {
|
|
||||||
'&': '&',
|
|
||||||
'<': '<',
|
|
||||||
'>': '>',
|
|
||||||
'"': '"',
|
|
||||||
"'": '''
|
|
||||||
},
|
|
||||||
htmlspecialchars = str => (''+str).replace(/[&<>"']/g, m => htmlmap[m]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {(string|number)} value
|
|
||||||
* @param {boolean=} includeZero = true
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
export function isPosNumeric(value, includeZero = true) {
|
|
||||||
return null != value && (includeZero ? /^[0-9]*$/ : /^[1-9]+[0-9]*$/).test(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {*} value
|
* @param {*} value
|
||||||
|
|
@ -40,63 +21,17 @@ export function pString(value) {
|
||||||
return null != value ? '' + value : '';
|
return null != value ? '' + value : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} text
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function encodeHtml(text) {
|
|
||||||
return null != text ? htmlspecialchars(text.toString()) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} text
|
|
||||||
* @param {number=} len = 100
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function splitPlainText(text, len = 100) {
|
|
||||||
let prefix = '',
|
|
||||||
subText = '',
|
|
||||||
result = text,
|
|
||||||
spacePos = 0,
|
|
||||||
newLinePos = 0;
|
|
||||||
|
|
||||||
while (result.length > len) {
|
|
||||||
subText = result.substr(0, len);
|
|
||||||
spacePos = subText.lastIndexOf(' ');
|
|
||||||
newLinePos = subText.lastIndexOf('\n');
|
|
||||||
|
|
||||||
if (-1 !== newLinePos) {
|
|
||||||
spacePos = newLinePos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-1 === spacePos) {
|
|
||||||
spacePos = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
prefix += subText.substr(0, spacePos) + '\n';
|
|
||||||
result = result.substr(spacePos + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return prefix + result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export function inFocus() {
|
export function inFocus() {
|
||||||
try {
|
try {
|
||||||
if (doc.activeElement) {
|
return doc.activeElement && doc.activeElement.matches(
|
||||||
if (undefined === doc.activeElement.__inFocusCache) {
|
|
||||||
doc.activeElement.__inFocusCache = doc.activeElement.matches(
|
|
||||||
'input,textarea,iframe,.cke_editable'
|
'input,textarea,iframe,.cke_editable'
|
||||||
);
|
);
|
||||||
}
|
} catch (e) {
|
||||||
|
|
||||||
return !!doc.activeElement.__inFocusCache;
|
|
||||||
}
|
|
||||||
} catch (e) {} // eslint-disable-line no-empty
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -109,9 +44,8 @@ export const convertThemeName = theme => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return theme
|
return theme
|
||||||
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
|
||||||
.replace(/([A-Z])/g, ' $1')
|
.replace(/([A-Z])/g, ' $1')
|
||||||
.replace(/\s+/g, ' ')
|
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
||||||
.trim();
|
.trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -134,7 +68,7 @@ export function convertLangName(language, isEng = false) {
|
||||||
* @param {object} item
|
* @param {object} item
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
export function defautOptionsAfterRender(domItem, item) {
|
export function defaultOptionsAfterRender(domItem, item) {
|
||||||
if (item && undefined !== item.disabled && domItem) {
|
if (item && undefined !== item.disabled && domItem) {
|
||||||
domItem.classList.toggle('disabled', domItem.disabled = item.disabled);
|
domItem.classList.toggle('disabled', domItem.disabled = item.disabled);
|
||||||
}
|
}
|
||||||
|
|
@ -152,306 +86,6 @@ export function settingsSaveHelperSimpleFunction(koTrigger, context) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} html
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function htmlToPlain(html) {
|
|
||||||
let pos = 0,
|
|
||||||
limit = 0,
|
|
||||||
iP1 = 0,
|
|
||||||
iP2 = 0,
|
|
||||||
iP3 = 0,
|
|
||||||
text = '';
|
|
||||||
|
|
||||||
const convertBlockquote = (blockquoteText) => {
|
|
||||||
blockquoteText = '> ' + blockquoteText.trim().replace(/\n/gm, '\n> ');
|
|
||||||
return blockquoteText.replace(/(^|\n)([> ]+)/gm, (...args) =>
|
|
||||||
args && 2 < args.length ? args[1] + args[2].replace(/[\s]/g, '').trim() + ' ' : ''
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const convertDivs = (...args) => {
|
|
||||||
if (args && 1 < args.length) {
|
|
||||||
let divText = args[1].trim();
|
|
||||||
if (divText.length) {
|
|
||||||
divText = divText.replace(/<div[^>]*>([\s\S\r\n]*)<\/div>/gim, convertDivs);
|
|
||||||
divText = '\n' + divText.trim() + '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
return divText;
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
};
|
|
||||||
|
|
||||||
const convertPre = (...args) =>
|
|
||||||
args && 1 < args.length
|
|
||||||
? args[1]
|
|
||||||
.toString()
|
|
||||||
.replace(/[\n]/gm, '<br />')
|
|
||||||
.replace(/[\r]/gm, '')
|
|
||||||
: '',
|
|
||||||
fixAttibuteValue = (...args) => (args && 1 < args.length ? '' + args[1] + htmlspecialchars(args[2]) : ''),
|
|
||||||
convertLinks = (...args) => (args && 1 < args.length ? args[1].trim() : '');
|
|
||||||
|
|
||||||
tpl.innerHTML = html
|
|
||||||
.replace(/<p[^>]*><\/p>/gi, '')
|
|
||||||
.replace(/<pre[^>]*>([\s\S\r\n\t]*)<\/pre>/gim, convertPre)
|
|
||||||
.replace(/[\s]+/gm, ' ')
|
|
||||||
.replace(/((?:href|data)\s?=\s?)("[^"]+?"|'[^']+?')/gim, fixAttibuteValue)
|
|
||||||
.replace(/<br[^>]*>/gim, '\n')
|
|
||||||
.replace(/<\/h[\d]>/gi, '\n')
|
|
||||||
.replace(/<\/p>/gi, '\n\n')
|
|
||||||
.replace(/<ul[^>]*>/gim, '\n')
|
|
||||||
.replace(/<\/ul>/gi, '\n')
|
|
||||||
.replace(/<li[^>]*>/gim, ' * ')
|
|
||||||
.replace(/<\/li>/gi, '\n')
|
|
||||||
.replace(/<\/td>/gi, '\n')
|
|
||||||
.replace(/<\/tr>/gi, '\n')
|
|
||||||
.replace(/<hr[^>]*>/gim, '\n_______________________________\n\n')
|
|
||||||
.replace(/<div[^>]*>([\s\S\r\n]*)<\/div>/gim, convertDivs)
|
|
||||||
.replace(/<blockquote[^>]*>/gim, '\n__bq__start__\n')
|
|
||||||
.replace(/<\/blockquote>/gim, '\n__bq__end__\n')
|
|
||||||
.replace(/<a [^>]*>([\s\S\r\n]*?)<\/a>/gim, convertLinks)
|
|
||||||
.replace(/<\/div>/gi, '\n')
|
|
||||||
.replace(/ /gi, ' ')
|
|
||||||
.replace(/"/gi, '"')
|
|
||||||
.replace(/<[^>]*>/gm, '');
|
|
||||||
|
|
||||||
text = splitPlainText(tpl.innerText
|
|
||||||
.replace(/\n[ \t]+/gm, '\n')
|
|
||||||
.replace(/[\n]{3,}/gm, '\n\n')
|
|
||||||
.replace(/>/gi, '>')
|
|
||||||
.replace(/</gi, '<')
|
|
||||||
.replace(/&/gi, '&')
|
|
||||||
);
|
|
||||||
|
|
||||||
pos = 0;
|
|
||||||
limit = 800;
|
|
||||||
|
|
||||||
while (0 < limit) {
|
|
||||||
--limit;
|
|
||||||
iP1 = text.indexOf('__bq__start__', pos);
|
|
||||||
if (-1 < iP1) {
|
|
||||||
iP2 = text.indexOf('__bq__start__', iP1 + 5);
|
|
||||||
iP3 = text.indexOf('__bq__end__', iP1 + 5);
|
|
||||||
|
|
||||||
if ((-1 === iP2 || iP3 < iP2) && iP1 < iP3) {
|
|
||||||
text = text.substr(0, iP1) + convertBlockquote(text.substring(iP1 + 13, iP3)) + text.substr(iP3 + 11);
|
|
||||||
pos = 0;
|
|
||||||
} else if (-1 < iP2 && iP2 < iP3) {
|
|
||||||
pos = iP2 - 1;
|
|
||||||
} else {
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return text.replace(/__bq__start__|__bq__end__/gm, '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} plain
|
|
||||||
* @param {boolean} findEmailAndLinksInText = false
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function plainToHtml(plain) {
|
|
||||||
plain = plain.toString().replace(/\r/g, '');
|
|
||||||
plain = plain.replace(/^>[> ]>+/gm, ([match]) => (match ? match.replace(/[ ]+/g, '') : match));
|
|
||||||
|
|
||||||
let bIn = false,
|
|
||||||
bDo = true,
|
|
||||||
bStart = true,
|
|
||||||
aNextText = [],
|
|
||||||
aText = plain.split('\n');
|
|
||||||
|
|
||||||
do {
|
|
||||||
bDo = false;
|
|
||||||
aNextText = [];
|
|
||||||
aText.forEach(sLine => {
|
|
||||||
bStart = '>' === sLine.substr(0, 1);
|
|
||||||
if (bStart && !bIn) {
|
|
||||||
bDo = true;
|
|
||||||
bIn = true;
|
|
||||||
aNextText.push('~~~blockquote~~~');
|
|
||||||
aNextText.push(sLine.substr(1));
|
|
||||||
} else if (!bStart && bIn) {
|
|
||||||
if (sLine) {
|
|
||||||
bIn = false;
|
|
||||||
aNextText.push('~~~/blockquote~~~');
|
|
||||||
aNextText.push(sLine);
|
|
||||||
} else {
|
|
||||||
aNextText.push(sLine);
|
|
||||||
}
|
|
||||||
} else if (bStart && bIn) {
|
|
||||||
aNextText.push(sLine.substr(1));
|
|
||||||
} else {
|
|
||||||
aNextText.push(sLine);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (bIn) {
|
|
||||||
bIn = false;
|
|
||||||
aNextText.push('~~~/blockquote~~~');
|
|
||||||
}
|
|
||||||
|
|
||||||
aText = aNextText;
|
|
||||||
} while (bDo);
|
|
||||||
|
|
||||||
return aText.join('\n')
|
|
||||||
// .replace(/~~~\/blockquote~~~\n~~~blockquote~~~/g, '\n')
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/~~~blockquote~~~[\s]*/g, '<blockquote>')
|
|
||||||
.replace(/[\s]*~~~\/blockquote~~~/g, '</blockquote>')
|
|
||||||
.replace(/\n/g, '<br />');
|
|
||||||
}
|
|
||||||
|
|
||||||
rl.Utils = {
|
|
||||||
htmlToPlain: htmlToPlain,
|
|
||||||
plainToHtml: plainToHtml
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Array} aSystem
|
|
||||||
* @param {Array} aList
|
|
||||||
* @param {Array=} aDisabled
|
|
||||||
* @param {Array=} aHeaderLines
|
|
||||||
* @param {?number=} iUnDeep
|
|
||||||
* @param {Function=} fDisableCallback
|
|
||||||
* @param {Function=} fVisibleCallback
|
|
||||||
* @param {Function=} fRenameCallback
|
|
||||||
* @param {boolean=} bSystem
|
|
||||||
* @param {boolean=} bBuildUnvisible
|
|
||||||
* @returns {Array}
|
|
||||||
*/
|
|
||||||
export function folderListOptionsBuilder(
|
|
||||||
aSystem,
|
|
||||||
aList,
|
|
||||||
aDisabled,
|
|
||||||
aHeaderLines,
|
|
||||||
iUnDeep,
|
|
||||||
fDisableCallback,
|
|
||||||
fVisibleCallback,
|
|
||||||
fRenameCallback,
|
|
||||||
bSystem,
|
|
||||||
bBuildUnvisible
|
|
||||||
) {
|
|
||||||
let /**
|
|
||||||
* @type {?FolderModel}
|
|
||||||
*/
|
|
||||||
bSep = false,
|
|
||||||
aResult = [];
|
|
||||||
|
|
||||||
const sDeepPrefix = '\u00A0\u00A0\u00A0';
|
|
||||||
|
|
||||||
bBuildUnvisible = undefined === bBuildUnvisible ? false : !!bBuildUnvisible;
|
|
||||||
bSystem = null == bSystem ? 0 < aSystem.length : bSystem;
|
|
||||||
iUnDeep = null == iUnDeep ? 0 : iUnDeep;
|
|
||||||
fDisableCallback = null != fDisableCallback ? fDisableCallback : null;
|
|
||||||
fVisibleCallback = null != fVisibleCallback ? fVisibleCallback : null;
|
|
||||||
fRenameCallback = null != fRenameCallback ? fRenameCallback : null;
|
|
||||||
|
|
||||||
if (!isArray(aDisabled)) {
|
|
||||||
aDisabled = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isArray(aHeaderLines)) {
|
|
||||||
aHeaderLines = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
aHeaderLines.forEach(line => {
|
|
||||||
aResult.push({
|
|
||||||
id: line[0],
|
|
||||||
name: line[1],
|
|
||||||
system: false,
|
|
||||||
dividerbar: false,
|
|
||||||
disabled: false
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
bSep = true;
|
|
||||||
aSystem.forEach(oItem => {
|
|
||||||
if (fVisibleCallback ? fVisibleCallback(oItem) : true) {
|
|
||||||
aResult.push({
|
|
||||||
id: oItem.fullNameRaw,
|
|
||||||
name: fRenameCallback ? fRenameCallback(oItem) : oItem.name(),
|
|
||||||
system: true,
|
|
||||||
dividerbar: bSep,
|
|
||||||
disabled:
|
|
||||||
!oItem.selectable ||
|
|
||||||
aDisabled.includes(oItem.fullNameRaw) ||
|
|
||||||
(fDisableCallback ? fDisableCallback(oItem) : false)
|
|
||||||
});
|
|
||||||
bSep = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bSep = true;
|
|
||||||
aList.forEach(oItem => {
|
|
||||||
// if (oItem.subScribed() || !oItem.existen || bBuildUnvisible)
|
|
||||||
if (
|
|
||||||
(oItem.subScribed() || !oItem.existen || bBuildUnvisible) &&
|
|
||||||
(oItem.selectable || oItem.hasSubScribedSubfolders())
|
|
||||||
) {
|
|
||||||
if (fVisibleCallback ? fVisibleCallback(oItem) : true) {
|
|
||||||
if (FolderType.User === oItem.type() || !bSystem || oItem.hasSubScribedSubfolders()) {
|
|
||||||
aResult.push({
|
|
||||||
id: oItem.fullNameRaw,
|
|
||||||
name:
|
|
||||||
new Array(oItem.deep + 1 - iUnDeep).join(sDeepPrefix) +
|
|
||||||
(fRenameCallback ? fRenameCallback(oItem) : oItem.name()),
|
|
||||||
system: false,
|
|
||||||
dividerbar: bSep,
|
|
||||||
disabled:
|
|
||||||
!oItem.selectable ||
|
|
||||||
aDisabled.includes(oItem.fullNameRaw) ||
|
|
||||||
(fDisableCallback ? fDisableCallback(oItem) : false)
|
|
||||||
});
|
|
||||||
bSep = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oItem.subScribed() && oItem.subFolders().length) {
|
|
||||||
aResult = aResult.concat(
|
|
||||||
folderListOptionsBuilder(
|
|
||||||
[],
|
|
||||||
oItem.subFolders(),
|
|
||||||
aDisabled,
|
|
||||||
[],
|
|
||||||
iUnDeep,
|
|
||||||
fDisableCallback,
|
|
||||||
fVisibleCallback,
|
|
||||||
fRenameCallback,
|
|
||||||
bSystem,
|
|
||||||
bBuildUnvisible
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return aResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Object|Array} objectOrObjects
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
export function delegateRunOnDestroy(objectOrObjects) {
|
|
||||||
if (objectOrObjects) {
|
|
||||||
if (isArray(objectOrObjects)) {
|
|
||||||
objectOrObjects.forEach(item => delegateRunOnDestroy(item));
|
|
||||||
} else {
|
|
||||||
objectOrObjects.onDestroy && objectOrObjects.onDestroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let __themeTimer = 0,
|
let __themeTimer = 0,
|
||||||
__themeAjax = null;
|
__themeAjax = null;
|
||||||
|
|
||||||
|
|
@ -494,7 +128,7 @@ export function changeTheme(value, themeTrigger = ()=>{}) {
|
||||||
}
|
}
|
||||||
rl.fetchJSON(url, init)
|
rl.fetchJSON(url, init)
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data && isArray(data) && 2 === data.length) {
|
if (data && Array.isArray(data) && 2 === data.length) {
|
||||||
if (themeLink && !themeStyle) {
|
if (themeLink && !themeStyle) {
|
||||||
themeStyle = doc.createElement('style');
|
themeStyle = doc.createElement('style');
|
||||||
themeStyle.id = 'app-theme-style';
|
themeStyle.id = 'app-theme-style';
|
||||||
|
|
@ -514,175 +148,3 @@ export function changeTheme(value, themeTrigger = ()=>{}) {
|
||||||
.then(clearTimer, clearTimer);
|
.then(clearTimer, clearTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {function}
|
|
||||||
*/
|
|
||||||
export function computedPaginatorHelper(koCurrentPage, koPageCount) {
|
|
||||||
return () => {
|
|
||||||
const currentPage = koCurrentPage(),
|
|
||||||
pageCount = koPageCount(),
|
|
||||||
result = [],
|
|
||||||
fAdd = (index, push = true, customName = '') => {
|
|
||||||
const data = {
|
|
||||||
current: index === currentPage,
|
|
||||||
name: customName ? customName.toString() : index.toString(),
|
|
||||||
custom: !!customName,
|
|
||||||
title: customName ? index.toString() : '',
|
|
||||||
value: index.toString()
|
|
||||||
};
|
|
||||||
|
|
||||||
if (push) {
|
|
||||||
result.push(data);
|
|
||||||
} else {
|
|
||||||
result.unshift(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let prev = 0,
|
|
||||||
next = 0,
|
|
||||||
limit = 2;
|
|
||||||
|
|
||||||
if (1 < pageCount || (0 < pageCount && pageCount < currentPage)) {
|
|
||||||
if (pageCount < currentPage) {
|
|
||||||
fAdd(pageCount);
|
|
||||||
prev = pageCount;
|
|
||||||
next = pageCount;
|
|
||||||
} else {
|
|
||||||
if (3 >= currentPage || pageCount - 2 <= currentPage) {
|
|
||||||
limit += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
fAdd(currentPage);
|
|
||||||
prev = currentPage;
|
|
||||||
next = currentPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (0 < limit) {
|
|
||||||
--prev;
|
|
||||||
++next;
|
|
||||||
|
|
||||||
if (0 < prev) {
|
|
||||||
fAdd(prev, false);
|
|
||||||
--limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pageCount >= next) {
|
|
||||||
fAdd(next, true);
|
|
||||||
--limit;
|
|
||||||
} else if (0 >= prev) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (3 === prev) {
|
|
||||||
fAdd(2, false);
|
|
||||||
} else if (3 < prev) {
|
|
||||||
fAdd(Math.round((prev - 1) / 2), false, '...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pageCount - 2 === next) {
|
|
||||||
fAdd(pageCount - 1, true);
|
|
||||||
} else if (pageCount - 2 > next) {
|
|
||||||
fAdd(Math.round((pageCount + next) / 2), true, '...');
|
|
||||||
}
|
|
||||||
|
|
||||||
// first and last
|
|
||||||
if (1 < prev) {
|
|
||||||
fAdd(1, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pageCount > next) {
|
|
||||||
fAdd(pageCount, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} color
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
export function isTransparent(color) {
|
|
||||||
return 'rgba(0, 0, 0, 0)' === color || 'transparent' === color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} mailToUrl
|
|
||||||
* @param {Function} PopupComposeViewModel
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
export function mailToHelper(mailToUrl, PopupComposeViewModel) {
|
|
||||||
if (
|
|
||||||
mailToUrl &&
|
|
||||||
'mailto:' ===
|
|
||||||
mailToUrl
|
|
||||||
.toString()
|
|
||||||
.substr(0, 7)
|
|
||||||
.toLowerCase()
|
|
||||||
) {
|
|
||||||
if (!PopupComposeViewModel) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
mailToUrl = mailToUrl.toString().substr(7);
|
|
||||||
|
|
||||||
let to = [],
|
|
||||||
cc = null,
|
|
||||||
bcc = null,
|
|
||||||
params = {};
|
|
||||||
|
|
||||||
const email = mailToUrl.replace(/\?.+$/, ''),
|
|
||||||
query = mailToUrl.replace(/^[^?]*\?/, ''),
|
|
||||||
EmailModel = require('Model/Email').default;
|
|
||||||
|
|
||||||
query.split('&').forEach(temp => {
|
|
||||||
temp = temp.split('=');
|
|
||||||
params[decodeURIComponent(temp[0])] = decodeURIComponent(temp[1]);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (undefined !== params.to) {
|
|
||||||
to = EmailModel.parseEmailLine(decodeURIComponent(email + ',' + params.to));
|
|
||||||
to = Object.values(
|
|
||||||
to.reduce((result, value) => {
|
|
||||||
if (value) {
|
|
||||||
if (result[value.email]) {
|
|
||||||
if (!result[value.email].name) {
|
|
||||||
result[value.email] = value;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result[value.email] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}, {})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
to = EmailModel.parseEmailLine(email);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (undefined !== params.cc) {
|
|
||||||
cc = EmailModel.parseEmailLine(decodeURIComponent(params.cc));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (undefined !== params.bcc) {
|
|
||||||
bcc = EmailModel.parseEmailLine(decodeURIComponent(params.bcc));
|
|
||||||
}
|
|
||||||
|
|
||||||
require('Knoin/Knoin').showScreenPopup(PopupComposeViewModel, [
|
|
||||||
ComposeType.Empty,
|
|
||||||
null,
|
|
||||||
to,
|
|
||||||
cc,
|
|
||||||
bcc,
|
|
||||||
null == params.subject ? null : pString(decodeURIComponent(params.subject)),
|
|
||||||
null == params.body ? null : plainToHtml(pString(decodeURIComponent(params.body)))
|
|
||||||
]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
535
dev/Common/UtilsUser.js
Normal file
535
dev/Common/UtilsUser.js
Normal file
|
|
@ -0,0 +1,535 @@
|
||||||
|
import { ComposeType, FolderType } from 'Common/Enums';
|
||||||
|
import { pString } from 'Common/Utils';
|
||||||
|
|
||||||
|
const
|
||||||
|
tpl = document.createElement('template'),
|
||||||
|
isArray = Array.isArray,
|
||||||
|
htmlmap = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
"'": '''
|
||||||
|
},
|
||||||
|
htmlspecialchars = str => (''+str).replace(/[&<>"']/g, m => htmlmap[m]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {(string|number)} value
|
||||||
|
* @param {boolean=} includeZero = true
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isPosNumeric(value, includeZero = true) {
|
||||||
|
return null != value && (includeZero ? /^[0-9]*$/ : /^[1-9]+[0-9]*$/).test(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} text
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function encodeHtml(text) {
|
||||||
|
return null != text ? htmlspecialchars(text.toString()) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} text
|
||||||
|
* @param {number=} len = 100
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function splitPlainText(text, len = 100) {
|
||||||
|
let prefix = '',
|
||||||
|
subText = '',
|
||||||
|
result = text,
|
||||||
|
spacePos = 0,
|
||||||
|
newLinePos = 0;
|
||||||
|
|
||||||
|
while (result.length > len) {
|
||||||
|
subText = result.substr(0, len);
|
||||||
|
spacePos = subText.lastIndexOf(' ');
|
||||||
|
newLinePos = subText.lastIndexOf('\n');
|
||||||
|
|
||||||
|
if (-1 !== newLinePos) {
|
||||||
|
spacePos = newLinePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 === spacePos) {
|
||||||
|
spacePos = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix += subText.substr(0, spacePos) + '\n';
|
||||||
|
result = result.substr(spacePos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefix + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} html
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function htmlToPlain(html) {
|
||||||
|
let pos = 0,
|
||||||
|
limit = 0,
|
||||||
|
iP1 = 0,
|
||||||
|
iP2 = 0,
|
||||||
|
iP3 = 0,
|
||||||
|
text = '';
|
||||||
|
|
||||||
|
const convertBlockquote = (blockquoteText) => {
|
||||||
|
blockquoteText = '> ' + blockquoteText.trim().replace(/\n/gm, '\n> ');
|
||||||
|
return blockquoteText.replace(/(^|\n)([> ]+)/gm, (...args) =>
|
||||||
|
args && 2 < args.length ? args[1] + args[2].replace(/[\s]/g, '').trim() + ' ' : ''
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertDivs = (...args) => {
|
||||||
|
if (args && 1 < args.length) {
|
||||||
|
let divText = args[1].trim();
|
||||||
|
if (divText.length) {
|
||||||
|
divText = divText.replace(/<div[^>]*>([\s\S\r\n]*)<\/div>/gim, convertDivs);
|
||||||
|
divText = '\n' + divText.trim() + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
return divText;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertPre = (...args) =>
|
||||||
|
args && 1 < args.length
|
||||||
|
? args[1]
|
||||||
|
.toString()
|
||||||
|
.replace(/[\n]/gm, '<br />')
|
||||||
|
.replace(/[\r]/gm, '')
|
||||||
|
: '',
|
||||||
|
fixAttibuteValue = (...args) => (args && 1 < args.length ? '' + args[1] + htmlspecialchars(args[2]) : ''),
|
||||||
|
convertLinks = (...args) => (args && 1 < args.length ? args[1].trim() : '');
|
||||||
|
|
||||||
|
tpl.innerHTML = html
|
||||||
|
.replace(/<p[^>]*><\/p>/gi, '')
|
||||||
|
.replace(/<pre[^>]*>([\s\S\r\n\t]*)<\/pre>/gim, convertPre)
|
||||||
|
.replace(/[\s]+/gm, ' ')
|
||||||
|
.replace(/((?:href|data)\s?=\s?)("[^"]+?"|'[^']+?')/gim, fixAttibuteValue)
|
||||||
|
.replace(/<br[^>]*>/gim, '\n')
|
||||||
|
.replace(/<\/h[\d]>/gi, '\n')
|
||||||
|
.replace(/<\/p>/gi, '\n\n')
|
||||||
|
.replace(/<ul[^>]*>/gim, '\n')
|
||||||
|
.replace(/<\/ul>/gi, '\n')
|
||||||
|
.replace(/<li[^>]*>/gim, ' * ')
|
||||||
|
.replace(/<\/li>/gi, '\n')
|
||||||
|
.replace(/<\/td>/gi, '\n')
|
||||||
|
.replace(/<\/tr>/gi, '\n')
|
||||||
|
.replace(/<hr[^>]*>/gim, '\n_______________________________\n\n')
|
||||||
|
.replace(/<div[^>]*>([\s\S\r\n]*)<\/div>/gim, convertDivs)
|
||||||
|
.replace(/<blockquote[^>]*>/gim, '\n__bq__start__\n')
|
||||||
|
.replace(/<\/blockquote>/gim, '\n__bq__end__\n')
|
||||||
|
.replace(/<a [^>]*>([\s\S\r\n]*?)<\/a>/gim, convertLinks)
|
||||||
|
.replace(/<\/div>/gi, '\n')
|
||||||
|
.replace(/ /gi, ' ')
|
||||||
|
.replace(/"/gi, '"')
|
||||||
|
.replace(/<[^>]*>/gm, '');
|
||||||
|
|
||||||
|
text = splitPlainText(tpl.innerText
|
||||||
|
.replace(/\n[ \t]+/gm, '\n')
|
||||||
|
.replace(/[\n]{3,}/gm, '\n\n')
|
||||||
|
.replace(/>/gi, '>')
|
||||||
|
.replace(/</gi, '<')
|
||||||
|
.replace(/&/gi, '&')
|
||||||
|
);
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
limit = 800;
|
||||||
|
|
||||||
|
while (0 < limit) {
|
||||||
|
--limit;
|
||||||
|
iP1 = text.indexOf('__bq__start__', pos);
|
||||||
|
if (-1 < iP1) {
|
||||||
|
iP2 = text.indexOf('__bq__start__', iP1 + 5);
|
||||||
|
iP3 = text.indexOf('__bq__end__', iP1 + 5);
|
||||||
|
|
||||||
|
if ((-1 === iP2 || iP3 < iP2) && iP1 < iP3) {
|
||||||
|
text = text.substr(0, iP1) + convertBlockquote(text.substring(iP1 + 13, iP3)) + text.substr(iP3 + 11);
|
||||||
|
pos = 0;
|
||||||
|
} else if (-1 < iP2 && iP2 < iP3) {
|
||||||
|
pos = iP2 - 1;
|
||||||
|
} else {
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.replace(/__bq__start__|__bq__end__/gm, '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} plain
|
||||||
|
* @param {boolean} findEmailAndLinksInText = false
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function plainToHtml(plain) {
|
||||||
|
plain = plain.toString().replace(/\r/g, '');
|
||||||
|
plain = plain.replace(/^>[> ]>+/gm, ([match]) => (match ? match.replace(/[ ]+/g, '') : match));
|
||||||
|
|
||||||
|
let bIn = false,
|
||||||
|
bDo = true,
|
||||||
|
bStart = true,
|
||||||
|
aNextText = [],
|
||||||
|
aText = plain.split('\n');
|
||||||
|
|
||||||
|
do {
|
||||||
|
bDo = false;
|
||||||
|
aNextText = [];
|
||||||
|
aText.forEach(sLine => {
|
||||||
|
bStart = '>' === sLine.substr(0, 1);
|
||||||
|
if (bStart && !bIn) {
|
||||||
|
bDo = true;
|
||||||
|
bIn = true;
|
||||||
|
aNextText.push('~~~blockquote~~~');
|
||||||
|
aNextText.push(sLine.substr(1));
|
||||||
|
} else if (!bStart && bIn) {
|
||||||
|
if (sLine) {
|
||||||
|
bIn = false;
|
||||||
|
aNextText.push('~~~/blockquote~~~');
|
||||||
|
aNextText.push(sLine);
|
||||||
|
} else {
|
||||||
|
aNextText.push(sLine);
|
||||||
|
}
|
||||||
|
} else if (bStart && bIn) {
|
||||||
|
aNextText.push(sLine.substr(1));
|
||||||
|
} else {
|
||||||
|
aNextText.push(sLine);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (bIn) {
|
||||||
|
bIn = false;
|
||||||
|
aNextText.push('~~~/blockquote~~~');
|
||||||
|
}
|
||||||
|
|
||||||
|
aText = aNextText;
|
||||||
|
} while (bDo);
|
||||||
|
|
||||||
|
return aText.join('\n')
|
||||||
|
// .replace(/~~~\/blockquote~~~\n~~~blockquote~~~/g, '\n')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/~~~blockquote~~~[\s]*/g, '<blockquote>')
|
||||||
|
.replace(/[\s]*~~~\/blockquote~~~/g, '</blockquote>')
|
||||||
|
.replace(/\n/g, '<br />');
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.Utils = {
|
||||||
|
htmlToPlain: htmlToPlain,
|
||||||
|
plainToHtml: plainToHtml
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array} aSystem
|
||||||
|
* @param {Array} aList
|
||||||
|
* @param {Array=} aDisabled
|
||||||
|
* @param {Array=} aHeaderLines
|
||||||
|
* @param {?number=} iUnDeep
|
||||||
|
* @param {Function=} fDisableCallback
|
||||||
|
* @param {Function=} fVisibleCallback
|
||||||
|
* @param {Function=} fRenameCallback
|
||||||
|
* @param {boolean=} bSystem
|
||||||
|
* @param {boolean=} bBuildUnvisible
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
|
export function folderListOptionsBuilder(
|
||||||
|
aSystem,
|
||||||
|
aList,
|
||||||
|
aDisabled,
|
||||||
|
aHeaderLines,
|
||||||
|
iUnDeep,
|
||||||
|
fDisableCallback,
|
||||||
|
fVisibleCallback,
|
||||||
|
fRenameCallback,
|
||||||
|
bSystem,
|
||||||
|
bBuildUnvisible
|
||||||
|
) {
|
||||||
|
let /**
|
||||||
|
* @type {?FolderModel}
|
||||||
|
*/
|
||||||
|
bSep = false,
|
||||||
|
aResult = [];
|
||||||
|
|
||||||
|
const sDeepPrefix = '\u00A0\u00A0\u00A0';
|
||||||
|
|
||||||
|
bBuildUnvisible = undefined === bBuildUnvisible ? false : !!bBuildUnvisible;
|
||||||
|
bSystem = null == bSystem ? 0 < aSystem.length : bSystem;
|
||||||
|
iUnDeep = null == iUnDeep ? 0 : iUnDeep;
|
||||||
|
fDisableCallback = null != fDisableCallback ? fDisableCallback : null;
|
||||||
|
fVisibleCallback = null != fVisibleCallback ? fVisibleCallback : null;
|
||||||
|
fRenameCallback = null != fRenameCallback ? fRenameCallback : null;
|
||||||
|
|
||||||
|
if (!isArray(aDisabled)) {
|
||||||
|
aDisabled = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isArray(aHeaderLines)) {
|
||||||
|
aHeaderLines = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
aHeaderLines.forEach(line => {
|
||||||
|
aResult.push({
|
||||||
|
id: line[0],
|
||||||
|
name: line[1],
|
||||||
|
system: false,
|
||||||
|
dividerbar: false,
|
||||||
|
disabled: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
bSep = true;
|
||||||
|
aSystem.forEach(oItem => {
|
||||||
|
if (fVisibleCallback ? fVisibleCallback(oItem) : true) {
|
||||||
|
aResult.push({
|
||||||
|
id: oItem.fullNameRaw,
|
||||||
|
name: fRenameCallback ? fRenameCallback(oItem) : oItem.name(),
|
||||||
|
system: true,
|
||||||
|
dividerbar: bSep,
|
||||||
|
disabled:
|
||||||
|
!oItem.selectable ||
|
||||||
|
aDisabled.includes(oItem.fullNameRaw) ||
|
||||||
|
(fDisableCallback ? fDisableCallback(oItem) : false)
|
||||||
|
});
|
||||||
|
bSep = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bSep = true;
|
||||||
|
aList.forEach(oItem => {
|
||||||
|
// if (oItem.subScribed() || !oItem.existen || bBuildUnvisible)
|
||||||
|
if (
|
||||||
|
(oItem.subScribed() || !oItem.existen || bBuildUnvisible) &&
|
||||||
|
(oItem.selectable || oItem.hasSubScribedSubfolders())
|
||||||
|
) {
|
||||||
|
if (fVisibleCallback ? fVisibleCallback(oItem) : true) {
|
||||||
|
if (FolderType.User === oItem.type() || !bSystem || oItem.hasSubScribedSubfolders()) {
|
||||||
|
aResult.push({
|
||||||
|
id: oItem.fullNameRaw,
|
||||||
|
name:
|
||||||
|
new Array(oItem.deep + 1 - iUnDeep).join(sDeepPrefix) +
|
||||||
|
(fRenameCallback ? fRenameCallback(oItem) : oItem.name()),
|
||||||
|
system: false,
|
||||||
|
dividerbar: bSep,
|
||||||
|
disabled:
|
||||||
|
!oItem.selectable ||
|
||||||
|
aDisabled.includes(oItem.fullNameRaw) ||
|
||||||
|
(fDisableCallback ? fDisableCallback(oItem) : false)
|
||||||
|
});
|
||||||
|
bSep = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oItem.subScribed() && oItem.subFolders().length) {
|
||||||
|
aResult = aResult.concat(
|
||||||
|
folderListOptionsBuilder(
|
||||||
|
[],
|
||||||
|
oItem.subFolders(),
|
||||||
|
aDisabled,
|
||||||
|
[],
|
||||||
|
iUnDeep,
|
||||||
|
fDisableCallback,
|
||||||
|
fVisibleCallback,
|
||||||
|
fRenameCallback,
|
||||||
|
bSystem,
|
||||||
|
bBuildUnvisible
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return aResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object|Array} objectOrObjects
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function delegateRunOnDestroy(objectOrObjects) {
|
||||||
|
if (objectOrObjects) {
|
||||||
|
if (isArray(objectOrObjects)) {
|
||||||
|
objectOrObjects.forEach(item => delegateRunOnDestroy(item));
|
||||||
|
} else {
|
||||||
|
objectOrObjects.onDestroy && objectOrObjects.onDestroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {function}
|
||||||
|
*/
|
||||||
|
export function computedPaginatorHelper(koCurrentPage, koPageCount) {
|
||||||
|
return () => {
|
||||||
|
const currentPage = koCurrentPage(),
|
||||||
|
pageCount = koPageCount(),
|
||||||
|
result = [],
|
||||||
|
fAdd = (index, push = true, customName = '') => {
|
||||||
|
const data = {
|
||||||
|
current: index === currentPage,
|
||||||
|
name: customName ? customName.toString() : index.toString(),
|
||||||
|
custom: !!customName,
|
||||||
|
title: customName ? index.toString() : '',
|
||||||
|
value: index.toString()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (push) {
|
||||||
|
result.push(data);
|
||||||
|
} else {
|
||||||
|
result.unshift(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let prev = 0,
|
||||||
|
next = 0,
|
||||||
|
limit = 2;
|
||||||
|
|
||||||
|
if (1 < pageCount || (0 < pageCount && pageCount < currentPage)) {
|
||||||
|
if (pageCount < currentPage) {
|
||||||
|
fAdd(pageCount);
|
||||||
|
prev = pageCount;
|
||||||
|
next = pageCount;
|
||||||
|
} else {
|
||||||
|
if (3 >= currentPage || pageCount - 2 <= currentPage) {
|
||||||
|
limit += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fAdd(currentPage);
|
||||||
|
prev = currentPage;
|
||||||
|
next = currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (0 < limit) {
|
||||||
|
--prev;
|
||||||
|
++next;
|
||||||
|
|
||||||
|
if (0 < prev) {
|
||||||
|
fAdd(prev, false);
|
||||||
|
--limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageCount >= next) {
|
||||||
|
fAdd(next, true);
|
||||||
|
--limit;
|
||||||
|
} else if (0 >= prev) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (3 === prev) {
|
||||||
|
fAdd(2, false);
|
||||||
|
} else if (3 < prev) {
|
||||||
|
fAdd(Math.round((prev - 1) / 2), false, '...');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageCount - 2 === next) {
|
||||||
|
fAdd(pageCount - 1, true);
|
||||||
|
} else if (pageCount - 2 > next) {
|
||||||
|
fAdd(Math.round((pageCount + next) / 2), true, '...');
|
||||||
|
}
|
||||||
|
|
||||||
|
// first and last
|
||||||
|
if (1 < prev) {
|
||||||
|
fAdd(1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageCount > next) {
|
||||||
|
fAdd(pageCount, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} color
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isTransparent(color) {
|
||||||
|
return 'rgba(0, 0, 0, 0)' === color || 'transparent' === color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} mailToUrl
|
||||||
|
* @param {Function} PopupComposeViewModel
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function mailToHelper(mailToUrl, PopupComposeViewModel) {
|
||||||
|
if (
|
||||||
|
mailToUrl &&
|
||||||
|
'mailto:' ===
|
||||||
|
mailToUrl
|
||||||
|
.toString()
|
||||||
|
.substr(0, 7)
|
||||||
|
.toLowerCase()
|
||||||
|
) {
|
||||||
|
if (!PopupComposeViewModel) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mailToUrl = mailToUrl.toString().substr(7);
|
||||||
|
|
||||||
|
let to = [],
|
||||||
|
cc = null,
|
||||||
|
bcc = null,
|
||||||
|
params = {};
|
||||||
|
|
||||||
|
const email = mailToUrl.replace(/\?.+$/, ''),
|
||||||
|
query = mailToUrl.replace(/^[^?]*\?/, ''),
|
||||||
|
EmailModel = require('Model/Email').default;
|
||||||
|
|
||||||
|
query.split('&').forEach(temp => {
|
||||||
|
temp = temp.split('=');
|
||||||
|
params[decodeURIComponent(temp[0])] = decodeURIComponent(temp[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (undefined !== params.to) {
|
||||||
|
to = EmailModel.parseEmailLine(decodeURIComponent(email + ',' + params.to));
|
||||||
|
to = Object.values(
|
||||||
|
to.reduce((result, value) => {
|
||||||
|
if (value) {
|
||||||
|
if (result[value.email]) {
|
||||||
|
if (!result[value.email].name) {
|
||||||
|
result[value.email] = value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result[value.email] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
to = EmailModel.parseEmailLine(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (undefined !== params.cc) {
|
||||||
|
cc = EmailModel.parseEmailLine(decodeURIComponent(params.cc));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (undefined !== params.bcc) {
|
||||||
|
bcc = EmailModel.parseEmailLine(decodeURIComponent(params.bcc));
|
||||||
|
}
|
||||||
|
|
||||||
|
require('Knoin/Knoin').showScreenPopup(PopupComposeViewModel, [
|
||||||
|
ComposeType.Empty,
|
||||||
|
null,
|
||||||
|
to,
|
||||||
|
cc,
|
||||||
|
bcc,
|
||||||
|
null == params.subject ? null : pString(decodeURIComponent(params.subject)),
|
||||||
|
null == params.body ? null : plainToHtml(pString(decodeURIComponent(params.body)))
|
||||||
|
]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { i18n } from 'Common/Translator';
|
import { i18n } from 'Common/Translator';
|
||||||
import { defautOptionsAfterRender } from 'Common/Utils';
|
import { defaultOptionsAfterRender } from 'Common/Utils';
|
||||||
import { componentExportHelper } from 'Component/Abstract';
|
import { componentExportHelper } from 'Component/Abstract';
|
||||||
import { AbstractInput } from 'Component/AbstractInput';
|
import { AbstractInput } from 'Component/AbstractInput';
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ class SelectComponent extends AbstractInput {
|
||||||
this.optionsCaption = i18n(this.optionsCaption);
|
this.optionsCaption = i18n(this.optionsCaption);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.defautOptionsAfterRender = defautOptionsAfterRender;
|
this.defaultOptionsAfterRender = defaultOptionsAfterRender;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { encodeHtml } from 'Common/Utils';
|
import { encodeHtml } from 'Common/UtilsUser';
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
|
|
||||||
import { FilterRulesType, FiltersAction } from 'Common/Enums';
|
import { FilterRulesType, FiltersAction } from 'Common/Enums';
|
||||||
import { pString, delegateRunOnDestroy } from 'Common/Utils';
|
import { pString } from 'Common/Utils';
|
||||||
|
import { delegateRunOnDestroy } from 'Common/UtilsUser';
|
||||||
import { i18n } from 'Common/Translator';
|
import { i18n } from 'Common/Translator';
|
||||||
import { getFolderFromCacheList } from 'Common/Cache';
|
import { getFolderFromCacheList } from 'Common/Cache';
|
||||||
|
|
||||||
|
|
@ -114,17 +115,9 @@ class FilterModel extends AbstractModel {
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.regDisposables(
|
this.regDisposables(this.name.subscribe(sValue => this.name.error(!sValue)));
|
||||||
this.name.subscribe((sValue) => {
|
|
||||||
this.name.error(!sValue);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
this.regDisposables(
|
this.regDisposables(this.actionValue.subscribe(sValue => this.actionValue.error(!sValue)));
|
||||||
this.actionValue.subscribe((sValue) => {
|
|
||||||
this.actionValue.error(!sValue);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
this.regDisposables([this.actionNoStop, this.actionTemplate]);
|
this.regDisposables([this.actionNoStop, this.actionTemplate]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
|
|
||||||
import { FolderType } from 'Common/Enums';
|
import { FolderType } from 'Common/Enums';
|
||||||
import { isPosNumeric } from 'Common/Utils';
|
import { isPosNumeric } from 'Common/UtilsUser';
|
||||||
import { i18n, trigger as translatorTrigger } from 'Common/Translator';
|
import { i18n, trigger as translatorTrigger } from 'Common/Translator';
|
||||||
import { getFolderInboxName } from 'Common/Cache';
|
import { getFolderInboxName } from 'Common/Cache';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,8 @@ import ko from 'ko';
|
||||||
import { MessagePriority, SignedVerifyStatus } from 'Common/Enums';
|
import { MessagePriority, SignedVerifyStatus } from 'Common/Enums';
|
||||||
import { i18n } from 'Common/Translator';
|
import { i18n } from 'Common/Translator';
|
||||||
|
|
||||||
import {
|
import { pInt } from 'Common/Utils';
|
||||||
pInt,
|
import { encodeHtml } from 'Common/UtilsUser';
|
||||||
encodeHtml
|
|
||||||
} from 'Common/Utils';
|
|
||||||
|
|
||||||
import { messageViewLink, messageDownloadLink } from 'Common/Links';
|
import { messageViewLink, messageDownloadLink } from 'Common/Links';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
|
|
||||||
import { settingsSaveHelperSimpleFunction, defautOptionsAfterRender } from 'Common/Utils';
|
import { settingsSaveHelperSimpleFunction, defaultOptionsAfterRender } from 'Common/Utils';
|
||||||
|
|
||||||
import { SaveSettingsStep, StorageResultType } from 'Common/Enums';
|
import { SaveSettingsStep, StorageResultType } from 'Common/Enums';
|
||||||
import Remote from 'Remote/Admin/Fetch';
|
import Remote from 'Remote/Admin/Fetch';
|
||||||
|
|
@ -10,7 +10,7 @@ const settingsGet = rl.settings.get;
|
||||||
|
|
||||||
class ContactsAdminSettings {
|
class ContactsAdminSettings {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.defautOptionsAfterRender = defautOptionsAfterRender;
|
this.defaultOptionsAfterRender = defaultOptionsAfterRender;
|
||||||
this.enableContacts = ko.observable(!!settingsGet('ContactsEnable'));
|
this.enableContacts = ko.observable(!!settingsGet('ContactsEnable'));
|
||||||
this.contactsSync = ko.observable(!!settingsGet('ContactsSync'));
|
this.contactsSync = ko.observable(!!settingsGet('ContactsSync'));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
|
|
||||||
import { delegateRunOnDestroy } from 'Common/Utils';
|
import { delegateRunOnDestroy } from 'Common/UtilsUser';
|
||||||
import { StorageResultType, Notification } from 'Common/Enums';
|
import { StorageResultType, Notification } from 'Common/Enums';
|
||||||
import { getNotification } from 'Common/Translator';
|
import { getNotification } from 'Common/Translator';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
|
|
||||||
import { delegateRunOnDestroy } from 'Common/Utils';
|
import { delegateRunOnDestroy } from 'Common/UtilsUser';
|
||||||
|
|
||||||
import PgpStore from 'Stores/User/Pgp';
|
import PgpStore from 'Stores/User/Pgp';
|
||||||
import SettingsStore from 'Stores/User/Settings';
|
import SettingsStore from 'Stores/User/Settings';
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import ko from 'ko';
|
||||||
|
|
||||||
import { FolderType } from 'Common/Enums';
|
import { FolderType } from 'Common/Enums';
|
||||||
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
||||||
import { folderListOptionsBuilder } from 'Common/Utils';
|
import { folderListOptionsBuilder } from 'Common/UtilsUser';
|
||||||
import { getFolderInboxName, getFolderFromCacheList } from 'Common/Cache';
|
import { getFolderInboxName, getFolderFromCacheList } from 'Common/Cache';
|
||||||
|
|
||||||
class FolderUserStore {
|
class FolderUserStore {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,8 @@ import ko from 'ko';
|
||||||
|
|
||||||
import { Layout, Focused, MessageSetAction, StorageResultType, Notification } from 'Common/Enums';
|
import { Layout, Focused, MessageSetAction, StorageResultType, Notification } from 'Common/Enums';
|
||||||
|
|
||||||
import {
|
import { pInt, pString } from 'Common/Utils';
|
||||||
pInt,
|
import { plainToHtml } from 'Common/UtilsUser';
|
||||||
pString,
|
|
||||||
plainToHtml
|
|
||||||
} from 'Common/Utils';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getFolderInboxName,
|
getFolderInboxName,
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,8 @@ import {
|
||||||
UploadErrorCode
|
UploadErrorCode
|
||||||
} from 'Common/Enums';
|
} from 'Common/Enums';
|
||||||
|
|
||||||
import {
|
import { inFocus, pInt } from 'Common/Utils';
|
||||||
encodeHtml,
|
import { encodeHtml, delegateRunOnDestroy } from 'Common/UtilsUser';
|
||||||
inFocus,
|
|
||||||
delegateRunOnDestroy,
|
|
||||||
pInt
|
|
||||||
} from 'Common/Utils';
|
|
||||||
|
|
||||||
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
||||||
import { upload } from 'Common/Links';
|
import { upload } from 'Common/Links';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
|
|
||||||
import { pString, defautOptionsAfterRender } from 'Common/Utils';
|
import { pString, defaultOptionsAfterRender } from 'Common/Utils';
|
||||||
|
|
||||||
import { KeyState } from 'Common/Enums';
|
import { KeyState } from 'Common/Enums';
|
||||||
import { i18n } from 'Common/Translator';
|
import { i18n } from 'Common/Translator';
|
||||||
|
|
@ -93,10 +93,10 @@ class ComposeOpenPgpPopupView extends AbstractViewNext {
|
||||||
|
|
||||||
this.sDefaultKeyScope = KeyState.PopupComposeOpenPGP;
|
this.sDefaultKeyScope = KeyState.PopupComposeOpenPGP;
|
||||||
|
|
||||||
this.defautOptionsAfterRender = defautOptionsAfterRender;
|
this.defaultOptionsAfterRender = defaultOptionsAfterRender;
|
||||||
|
|
||||||
this.addOptionClass = (domOption, item) => {
|
this.addOptionClass = (domOption, item) => {
|
||||||
this.defautOptionsAfterRender(domOption, item);
|
this.defaultOptionsAfterRender(domOption, item);
|
||||||
|
|
||||||
if (item && undefined !== item.class && domOption) {
|
if (item && undefined !== item.class && domOption) {
|
||||||
domOption.classList.add(item.class);
|
domOption.classList.add(item.class);
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,8 @@ import {
|
||||||
KeyState
|
KeyState
|
||||||
} from 'Common/Enums';
|
} from 'Common/Enums';
|
||||||
|
|
||||||
import {
|
import { pInt } from 'Common/Utils';
|
||||||
delegateRunOnDestroy,
|
import { delegateRunOnDestroy, computedPaginatorHelper } from 'Common/UtilsUser';
|
||||||
computedPaginatorHelper,
|
|
||||||
pInt
|
|
||||||
} from 'Common/Utils';
|
|
||||||
|
|
||||||
import { Selector } from 'Common/Selector';
|
import { Selector } from 'Common/Selector';
|
||||||
import { exportContactsVcf, exportContactsCsv, uploadContacts } from 'Common/Links';
|
import { exportContactsVcf, exportContactsCsv, uploadContacts } from 'Common/Links';
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
|
|
||||||
import { FiltersAction, FilterConditionField, FilterConditionType } from 'Common/Enums';
|
import { FiltersAction, FilterConditionField, FilterConditionType } from 'Common/Enums';
|
||||||
import { defautOptionsAfterRender } from 'Common/Utils';
|
import { defaultOptionsAfterRender } from 'Common/Utils';
|
||||||
import { i18n, initOnStartOrLangChange } from 'Common/Translator';
|
import { i18n, initOnStartOrLangChange } from 'Common/Translator';
|
||||||
|
|
||||||
import FilterStore from 'Stores/User/Filter';
|
import FilterStore from 'Stores/User/Filter';
|
||||||
|
|
@ -27,7 +27,7 @@ class FilterPopupView extends AbstractViewNext {
|
||||||
|
|
||||||
this.allowMarkAsRead = ko.observable(false);
|
this.allowMarkAsRead = ko.observable(false);
|
||||||
|
|
||||||
this.defautOptionsAfterRender = defautOptionsAfterRender;
|
this.defaultOptionsAfterRender = defaultOptionsAfterRender;
|
||||||
this.folderSelectList = FolderStore.folderMenuForFilters;
|
this.folderSelectList = FolderStore.folderMenuForFilters;
|
||||||
this.selectedFolderValue = ko.observable('');
|
this.selectedFolderValue = ko.observable('');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ import ko from 'ko';
|
||||||
|
|
||||||
import { Notification } from 'Common/Enums';
|
import { Notification } from 'Common/Enums';
|
||||||
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
||||||
import { defautOptionsAfterRender, folderListOptionsBuilder } from 'Common/Utils';
|
import { defaultOptionsAfterRender } from 'Common/Utils';
|
||||||
|
import { folderListOptionsBuilder } from 'Common/UtilsUser';
|
||||||
|
|
||||||
import FolderStore from 'Stores/User/Folder';
|
import FolderStore from 'Stores/User/Folder';
|
||||||
|
|
||||||
|
|
@ -40,7 +41,7 @@ class FolderCreateView extends AbstractViewNext {
|
||||||
return folderListOptionsBuilder([], list, [], top, null, fDisableCallback, null, fRenameCallback);
|
return folderListOptionsBuilder([], list, [], top, null, fDisableCallback, null, fRenameCallback);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.defautOptionsAfterRender = defautOptionsAfterRender;
|
this.defaultOptionsAfterRender = defaultOptionsAfterRender;
|
||||||
}
|
}
|
||||||
|
|
||||||
@command((self) => self.simpleFolderNameValidation(self.folderName()))
|
@command((self) => self.simpleFolderNameValidation(self.folderName()))
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ import ko from 'ko';
|
||||||
|
|
||||||
import { SetSystemFoldersNotification } from 'Common/Enums';
|
import { SetSystemFoldersNotification } from 'Common/Enums';
|
||||||
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
||||||
import { folderListOptionsBuilder, defautOptionsAfterRender } from 'Common/Utils';
|
import { defaultOptionsAfterRender } from 'Common/Utils';
|
||||||
|
import { folderListOptionsBuilder } from 'Common/UtilsUser';
|
||||||
import { initOnStartOrLangChange, i18n } from 'Common/Translator';
|
import { initOnStartOrLangChange, i18n } from 'Common/Translator';
|
||||||
|
|
||||||
import FolderStore from 'Stores/User/Folder';
|
import FolderStore from 'Stores/User/Folder';
|
||||||
|
|
@ -84,7 +85,7 @@ class FolderSystemPopupView extends AbstractViewNext {
|
||||||
FolderStore.trashFolder.subscribe(fCallback);
|
FolderStore.trashFolder.subscribe(fCallback);
|
||||||
FolderStore.archiveFolder.subscribe(fCallback);
|
FolderStore.archiveFolder.subscribe(fCallback);
|
||||||
|
|
||||||
this.defautOptionsAfterRender = defautOptionsAfterRender;
|
this.defaultOptionsAfterRender = defaultOptionsAfterRender;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
||||||
|
|
||||||
import { leftPanelDisabled, moveAction } from 'Common/Globals';
|
import { leftPanelDisabled, moveAction } from 'Common/Globals';
|
||||||
|
|
||||||
import { computedPaginatorHelper } from 'Common/Utils';
|
import { computedPaginatorHelper } from 'Common/UtilsUser';
|
||||||
import { File } from 'Common/File';
|
import { File } from 'Common/File';
|
||||||
|
|
||||||
import { mailBox, append } from 'Common/Links';
|
import { mailBox, append } from 'Common/Links';
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,8 @@ import {
|
||||||
|
|
||||||
import { $htmlCL, leftPanelDisabled, keyScopeReal, moveAction } from 'Common/Globals';
|
import { $htmlCL, leftPanelDisabled, keyScopeReal, moveAction } from 'Common/Globals';
|
||||||
|
|
||||||
import {
|
import { inFocus } from 'Common/Utils';
|
||||||
inFocus,
|
import { mailToHelper, isTransparent } from 'Common/UtilsUser';
|
||||||
mailToHelper,
|
|
||||||
isTransparent
|
|
||||||
} from 'Common/Utils';
|
|
||||||
|
|
||||||
import Audio from 'Common/Audio';
|
import Audio from 'Common/Audio';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
<!-- /ko -->
|
<!-- /ko -->
|
||||||
<select data-bind="options: options, value: value, enable: enable, optionsText: optionsText, optionsValue: optionsValue,
|
<select data-bind="options: options, value: value, enable: enable, optionsText: optionsText, optionsValue: optionsValue,
|
||||||
optionsCaption: optionsCaption, css: className, optionsAfterRender: defautOptionsAfterRender"></select>
|
optionsCaption: optionsCaption, css: className, optionsAfterRender: defaultOptionsAfterRender"></select>
|
||||||
<!-- ko if: labeled -->
|
<!-- ko if: labeled -->
|
||||||
|
|
||||||
<span class="i18n" data-bind="attr: {'data-i18n': label}"></span>
|
<span class="i18n" data-bind="attr: {'data-i18n': label}"></span>
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<select data-bind="options: parentFolderSelectList, value: selectedParentValue,
|
<select data-bind="options: parentFolderSelectList, value: selectedParentValue,
|
||||||
optionsText: 'name', optionsValue: 'id', optionsAfterRender: defautOptionsAfterRender"></select>
|
optionsText: 'name', optionsValue: 'id', optionsAfterRender: defaultOptionsAfterRender"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<select data-bind="options: folderSelectList, value: sentFolder,
|
<select data-bind="options: folderSelectList, value: sentFolder,
|
||||||
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defautOptionsAfterRender"></select>
|
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defaultOptionsAfterRender"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<select data-bind="options: folderSelectList, value: draftFolder,
|
<select data-bind="options: folderSelectList, value: draftFolder,
|
||||||
optionsText: 'name', optionsValue: 'id', optionsAfterRender: defautOptionsAfterRender"></select>
|
optionsText: 'name', optionsValue: 'id', optionsAfterRender: defaultOptionsAfterRender"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<select data-bind="options: folderSelectList, value: spamFolder,
|
<select data-bind="options: folderSelectList, value: spamFolder,
|
||||||
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defautOptionsAfterRender"></select>
|
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defaultOptionsAfterRender"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<select data-bind="options: folderSelectList, value: trashFolder,
|
<select data-bind="options: folderSelectList, value: trashFolder,
|
||||||
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defautOptionsAfterRender"></select>
|
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defaultOptionsAfterRender"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<select data-bind="options: folderSelectList, value: archiveFolder,
|
<select data-bind="options: folderSelectList, value: archiveFolder,
|
||||||
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defautOptionsAfterRender"></select>
|
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defaultOptionsAfterRender"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="control-group" data-bind="css: {'error': actionValue.error}">
|
<div class="control-group" data-bind="css: {'error': actionValue.error}">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<select class="span3" data-bind="options: $root.folderSelectList, value: $root.selectedFolderValue,
|
<select class="span3" data-bind="options: $root.folderSelectList, value: $root.selectedFolderValue,
|
||||||
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defautOptionsAfterRender"></select>
|
optionsText: 'name', optionsValue: 'id', optionsAfterRender: $root.defaultOptionsAfterRender"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue