Merge branch 'staging' into sfAllow

pull/1/head
yflory 4 years ago
commit 1321c08a62

@ -8,6 +8,10 @@
overflow-y: auto; overflow-y: auto;
color: @cryptpad_text_col; color: @cryptpad_text_col;
&:empty {
display: none !important;
}
&.cp-comments-readonly { &.cp-comments-readonly {
.cp-comment-actions { .cp-comment-actions {
display: none !important; display: none !important;
@ -61,10 +65,6 @@
} }
} }
#cp-comments-label {
display: none;
}
.cp-comment-container { .cp-comment-container {
outline: none; outline: none;
&:not(:focus) { &:not(:focus) {

@ -44,10 +44,11 @@
} }
/* local mixins */ /* local mixins */
@drive_icon-margin: 10px;
.drive_fileIcon { .drive_fileIcon {
li { li {
display: inline-block; display: inline-block;
margin: 10px 10px; margin: @drive_icon-margin;
width: 140px; width: 140px;
height: 140px; height: 140px;
text-align: center; text-align: center;
@ -475,6 +476,7 @@
margin-top: 10px; margin-top: 10px;
} }
.cp-app-drive-content-info-box { .cp-app-drive-content-info-box {
order: 10;
line-height: 2em; line-height: 2em;
padding: 0.25em 0.75em; padding: 0.25em 0.75em;
margin: 1em; margin: 1em;
@ -497,6 +499,7 @@
} }
} }
#cp-app-drive-content-folder { #cp-app-drive-content-folder {
order: 20;
li { li {
&.cp-app-drive-search-result { &.cp-app-drive-search-result {
display: flex; display: flex;
@ -550,7 +553,10 @@
.cp-app-drive-element-truncated { display: none; } .cp-app-drive-element-truncated { display: none; }
} }
div.cp-app-drive-content-grid { div.cp-app-drive-content-grid {
padding: 20px; padding: 1em;
ul {
margin: -(@drive_icon-margin);
}
.drive_fileIcon; .drive_fileIcon;
li { li {
&.cp-app-drive-element { &.cp-app-drive-element {
@ -758,6 +764,7 @@
} }
& > .cp-app-drive-path { & > .cp-app-drive-path {
order: 1;
width: 100%; width: 100%;
height: @variables_bar-height; height: @variables_bar-height;
line-height: @variables_bar-height; line-height: @variables_bar-height;
@ -778,6 +785,7 @@
flex-grow: 1; flex-grow: 1;
justify-content: flex-end; justify-content: flex-end;
.cp-app-drive-path-element { .cp-app-drive-path-element {
.tools_unselectable();
display: inline-block; display: inline-block;
flex-shrink: 0; flex-shrink: 0;
max-width: 100%; max-width: 100%;
@ -792,7 +800,6 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
transition: all 0.15s; transition: all 0.15s;
cursor: pointer;
&:first-child { &:first-child {
flex-shrink: 1; flex-shrink: 1;
@ -810,12 +817,15 @@
&.cp-app-drive-element-droppable { &.cp-app-drive-element-droppable {
background-color: @drive_droppable-bg; background-color: @drive_droppable-bg;
} }
&:not(.cp-app-drive-element-droppable):hover { &.cp-app-drive-path-clickable {
&:not(.cp-app-drive-path-separator) { cursor: pointer;
text-decoration: underline; &:hover {
} &:not(.cp-app-drive-path-separator) {
& ~ .cp-app-drive-path-element:not(.cp-app-drive-path-separator) { text-decoration: underline;
text-decoration: underline; }
& ~ .cp-app-drive-path-element:not(.cp-app-drive-path-separator) {
text-decoration: underline;
}
} }
} }
} }
@ -931,5 +941,11 @@
text-transform: uppercase; text-transform: uppercase;
cursor: default; cursor: default;
} }
.cp-app-drive-button {
order: 15;
margin: 0 1em;
}
} }

@ -9,7 +9,7 @@
@alertify-input-bg: @colortheme_modal-input; @alertify-input-bg: @colortheme_modal-input;
@alertify-input-fg: @colortheme_modal-input-fg; @alertify-input-fg: @colortheme_modal-input-fg;
input:not(.form-control), textarea, div.cp-textarea { input:not(.form-control):not([type="checkbox"]), textarea, div.cp-textarea {
// background-color: @alertify-input-fg; // background-color: @alertify-input-fg;
color: @cryptpad_text_col; color: @cryptpad_text_col;
border: 1px solid @alertify-input-bg; border: 1px solid @alertify-input-bg;

@ -19,7 +19,11 @@
@import (reference) "./forms.less"; @import (reference) "./forms.less";
@import (reference) "./modals-ui-elements.less"; @import (reference) "./modals-ui-elements.less";
.framework_main(@bg-color, @warn-color, @color) { .framework_main(
@bg-color: @colortheme_default-bg, // color of the toolbar background
@warn-color: @colortheme_default-warn, // color of the warning text in the toolbar
@color: @colortheme_default-color, // Color of the text for the toolbar
) {
--LessLoader_require: LessLoader_currentFile(); --LessLoader_require: LessLoader_currentFile();
// Set the HTML style for the apps which shouldn't have a body scrollbar // Set the HTML style for the apps which shouldn't have a body scrollbar
.app-noscroll_main(); .app-noscroll_main();

@ -713,8 +713,8 @@
box-sizing: border-box; box-sizing: border-box;
cursor: auto; cursor: auto;
width: 300px; width: 300px;
font-size: 30px; font-size: 30px !important;
padding: 0 5px; padding: 0 5px !important;
height: 43px; height: 43px;
} }
} }
@ -1033,6 +1033,7 @@
flex-flow: column; flex-flow: column;
z-index: 10000; //Z cp-toolbar-drawer-content z-index: 10000; //Z cp-toolbar-drawer-content
color: black; color: black;
.tools_unselectable();
.fa { .fa {
font-size: 17px; font-size: 17px;
} }

@ -102,7 +102,6 @@ server {
set $unsafe 0; set $unsafe 0;
# the following assets are loaded via the sandbox domain # the following assets are loaded via the sandbox domain
# they unfortunately still require exceptions to the sandboxing to work correctly. # they unfortunately still require exceptions to the sandboxing to work correctly.
if ($uri = "/pad/inner.html") { set $unsafe 1; }
if ($uri = "/sheet/inner.html") { set $unsafe 1; } if ($uri = "/sheet/inner.html") { set $unsafe 1; }
if ($uri ~ ^\/common\/onlyoffice\/.*\/index\.html.*$) { set $unsafe 1; } if ($uri ~ ^\/common\/onlyoffice\/.*\/index\.html.*$) { set $unsafe 1; }

@ -2,7 +2,8 @@
/* globals Buffer*/ /* globals Buffer*/
const Quota = module.exports; const Quota = module.exports;
const Util = require("../common-util"); //const Util = require("../common-util");
const Keys = require("../keys");
const Package = require('../../package.json'); const Package = require('../../package.json');
const Https = require("https"); const Https = require("https");
@ -19,11 +20,18 @@ Quota.applyCustomLimits = function (Env) {
var customLimits = (function (custom) { var customLimits = (function (custom) {
var limits = {}; var limits = {};
Object.keys(custom).forEach(function (k) { Object.keys(custom).forEach(function (k) {
k.replace(/\/([^\/]+)$/, function (all, safeKey) { var user;
var id = Util.unescapeKeyCharacters(safeKey || ''); try {
limits[id] = custom[k]; user = Keys.parseUser(k);
return ''; } catch (err) {
}); return void Env.Log.error("PARSE_CUSTOM_LIMIT_BLOCK", {
user: k,
error: err.message,
});
}
var unsafeKey = user.pubkey;
limits[unsafeKey] = custom[k];
}); });
return limits; return limits;
}(Env.customLimits || {})); }(Env.customLimits || {}));

@ -0,0 +1 @@
module.exports = require("../www/common/common-signing-keys");

@ -10,7 +10,7 @@ nThen(function (w) {
config.log = _log; config.log = _log;
})); }));
}).nThen(function (w) { }).nThen(function (w) {
FileStorage.create(config, w(function (_store) { FileStorage.create(config, w(function (err, _store) {
config.store = _store; config.store = _store;
// config.taskPath // config.taskPath

@ -9,6 +9,7 @@ var Path = require("path");
var nThen = require("nthen"); var nThen = require("nthen");
var Util = require("./lib/common-util"); var Util = require("./lib/common-util");
var Default = require("./lib/defaults"); var Default = require("./lib/defaults");
var Keys = require("./lib/keys");
var config = require("./lib/load-config"); var config = require("./lib/load-config");
@ -128,7 +129,7 @@ var setHeaders = (function () {
if (Object.keys(headers).length) { if (Object.keys(headers).length) {
return function (req, res) { return function (req, res) {
const h = [ const h = [
/^\/pad\/inner\.html.*/, ///^\/pad\/inner\.html.*/,
/^\/common\/onlyoffice\/.*\/index\.html.*/, /^\/common\/onlyoffice\/.*\/index\.html.*/,
/^\/(sheet|ooslide|oodoc)\/inner\.html.*/, /^\/(sheet|ooslide|oodoc)\/inner\.html.*/,
].some((regex) => { ].some((regex) => {
@ -201,9 +202,11 @@ app.use(/^\/[^\/]*$/, Express.static('customize.dist'));
var admins = []; var admins = [];
try { try {
admins = (config.adminKeys || []).map(function (k) { admins = (config.adminKeys || []).map(function (k) {
k = k.replace(/\/+$/, ''); // return each admin's "unsafeKey"
var s = k.split('/'); // this might throw and invalidate all the other admin's keys
return s[s.length-1].replace(/-/g, '/'); // but we want to get the admin's attention anyway.
// breaking everything is a good way to accomplish that.
return Keys.parseUser(k).pubkey;
}); });
} catch (e) { console.error("Can't parse admin keys"); } } catch (e) { console.error("Can't parse admin keys"); }

@ -1,5 +1,5 @@
(function (window) { (function (window) {
var factory = function (Util, Crypto, Nacl) { var factory = function (Util, Crypto, Keys, Nacl) {
var Hash = window.CryptPad_Hash = {}; var Hash = window.CryptPad_Hash = {};
var uint8ArrayToHex = Util.uint8ArrayToHex; var uint8ArrayToHex = Util.uint8ArrayToHex;
@ -92,9 +92,7 @@ var factory = function (Util, Crypto, Nacl) {
} }
}; };
Hash.getUserHrefFromKeys = function (origin, username, pubkey) { Hash.getPublicSigningKeyString = Keys.serialize;
return origin + '/user/#/1/' + username + '/' + pubkey.replace(/\//g, '-');
};
var fixDuplicateSlashes = function (s) { var fixDuplicateSlashes = function (s) {
return s.replace(/\/+/g, '/'); return s.replace(/\/+/g, '/');
@ -568,14 +566,20 @@ Version 1
}; };
if (typeof(module) !== 'undefined' && module.exports) { if (typeof(module) !== 'undefined' && module.exports) {
module.exports = factory(require("./common-util"), require("chainpad-crypto"), require("tweetnacl/nacl-fast")); module.exports = factory(
require("./common-util"),
require("chainpad-crypto"),
require("./common-signing-keys"),
require("tweetnacl/nacl-fast")
);
} else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) { } else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) {
define([ define([
'/common/common-util.js', '/common/common-util.js',
'/bower_components/chainpad-crypto/crypto.js', '/bower_components/chainpad-crypto/crypto.js',
'/common/common-signing-keys.js',
'/bower_components/tweetnacl/nacl-fast.min.js' '/bower_components/tweetnacl/nacl-fast.min.js'
], function (Util, Crypto) { ], function (Util, Crypto, Keys) {
return factory(Util, Crypto, window.nacl); return factory(Util, Crypto, Keys, window.nacl);
}); });
} else { } else {
// unsupported initialization // unsupported initialization

@ -0,0 +1,89 @@
(function () {
var factory = function () {
var Keys = {};
/* Parse the new format of "Signing Public Keys".
If anything about the input is found to be invalid, return;
this will fall back to the old parsing method
*/
var parseNewUser = function (userString) {
if (!/^\[.*?@.*\]$/.test(userString)) { return; }
var temp = userString.slice(1, -1);
var domain, username, pubkey;
temp = temp
.replace(/\/([a-zA-Z0-9+-]{43}=)$/, function (all, k) {
pubkey = k.replace(/-/g, '/');
return '';
});
if (!pubkey) { return; }
var index = temp.lastIndexOf('@');
if (index < 1) { return; }
domain = temp.slice(index + 1);
username = temp.slice(0, index);
return {
domain: domain,
user: username,
pubkey: pubkey
};
};
var isValidUser = function (parsed) {
if (!parsed) { return; }
if (!(parsed.domain && parsed.user && parsed.pubkey)) { return; }
return true;
};
Keys.parseUser = function (user) {
var parsed = parseNewUser(user);
if (isValidUser(parsed)) { return parsed; }
var domain, username, pubkey;
user.replace(/^https*:\/\/([^\/]+)\/user\/#\/1\/([^\/]+)\/([a-zA-Z0-9+-]{43}=)$/,
function (a, d, u, k) {
domain = d;
username = u;
pubkey = k.replace(/-/g, '/');
return '';
});
if (!domain) { throw new Error("Could not parse user id [" + user + "]"); }
return {
domain: domain,
user: username,
pubkey: pubkey
};
};
/*
0. usernames may contain spaces or many other wacky characters, so enclose the whole thing in square braces so we know its boundaries. If the formatted string does not include these we know it is either a _v1 public key string_ or _an incomplete string_. Start parsing by removing them.
1. public keys should have a fixed length, so slice them off of the end of the string.
2. domains cannot include `@`, so find the last occurence of it in the signing key and slice everything thereafter.
3. the username is everything before the `@`.
*/
Keys.serialize = function (origin, username, pubkey) {
return '[' +
username +
'@' +
origin.replace(/https*:\/\//, '') +
'/' +
pubkey.replace(/\//g, '-') +
']';
// return origin + '/user/#/1/' + username + '/' + pubkey.replace(/\//g, '-');
};
return Keys;
};
if (typeof(module) !== 'undefined' && module.exports) {
module.exports = factory();
} else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) {
define([], factory);
}
}());

@ -2299,7 +2299,9 @@ define([
value = val; value = val;
var $val = $innerblock.find('[data-value="'+val+'"]'); var $val = $innerblock.find('[data-value="'+val+'"]');
var textValue = name || $val.html() || val; var textValue = name || $val.html() || val;
$button.find('.cp-dropdown-button-title').html(textValue); setTimeout(function () {
$button.find('.cp-dropdown-button-title').html(textValue);
});
}; };
$container.getValue = function () { $container.getValue = function () {
return value || ''; return value || '';

@ -1604,6 +1604,26 @@ define([
var allocated = Login.allocateBytes(bytes); var allocated = Login.allocateBytes(bytes);
blockKeys = allocated.blockKeys; blockKeys = allocated.blockKeys;
})); }));
}).nThen(function (waitFor) {
var blockUrl = Block.getBlockUrl(blockKeys);
// Check whether there is a block at that location
Util.fetch(blockUrl, waitFor(function (err, block) {
// If there is no block or the block is invalid, continue.
if (err) {
console.log("no block found");
return;
}
var decryptedBlock = Block.decrypt(block, blockKeys);
if (!decryptedBlock) {
console.error("Found a login block but failed to decrypt");
return;
}
// If there is already a valid block, abort! We risk overriding another user's data
waitFor.abort();
cb({ error: 'EEXISTS' });
}));
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
// Write the new login block // Write the new login block
var temp = { var temp = {
@ -1966,7 +1986,7 @@ define([
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
var blockHash = LocalStore.getBlockHash(); var blockHash = LocalStore.getBlockHash();
if (blockHash) { if (blockHash) {
console.log(blockHash); console.debug("Block hash is present");
var parsed = Block.parseBlockHash(blockHash); var parsed = Block.parseBlockHash(blockHash);
if (typeof(parsed) !== 'object') { if (typeof(parsed) !== 'object') {

@ -114,7 +114,6 @@ define([
var $trashEmptyIcon = $('<span>', {"class": "fa fa-trash-o"}); var $trashEmptyIcon = $('<span>', {"class": "fa fa-trash-o"});
//var $collapseIcon = $('<span>', {"class": "fa fa-minus-square-o cp-app-drive-icon-expcol"}); //var $collapseIcon = $('<span>', {"class": "fa fa-minus-square-o cp-app-drive-icon-expcol"});
var $expandIcon = $('<span>', {"class": "fa fa-plus-square-o cp-app-drive-icon-expcol"}); var $expandIcon = $('<span>', {"class": "fa fa-plus-square-o cp-app-drive-icon-expcol"});
var $emptyTrashIcon = $('<button>', {"class": "fa fa-ban"});
var $listIcon = $('<button>', {"class": "fa fa-list"}); var $listIcon = $('<button>', {"class": "fa fa-list"});
var $gridIcon = $('<button>', {"class": "fa fa-th-large"}); var $gridIcon = $('<button>', {"class": "fa fa-th-large"});
var $sortAscIcon = $('<span>', {"class": "fa fa-angle-up sortasc"}); var $sortAscIcon = $('<span>', {"class": "fa fa-angle-up sortasc"});
@ -448,19 +447,19 @@ define([
h('li', h('a.cp-app-drive-context-delete.dropdown-item.cp-app-drive-context-editable', { h('li', h('a.cp-app-drive-context-delete.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faTrash, 'data-icon': faTrash,
}, Messages.fc_delete)), }, Messages.fc_delete)), // "Move to trash"
h('li', h('a.cp-app-drive-context-deleteowned.dropdown-item.cp-app-drive-context-editable', { h('li', h('a.cp-app-drive-context-deleteowned.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faDelete, 'data-icon': faDelete,
}, Messages.fc_delete_owned)), }, Messages.fc_delete_owned)), // XXX update key? "Delete from the server"
h('li', h('a.cp-app-drive-context-remove.dropdown-item.cp-app-drive-context-editable', { h('li', h('a.cp-app-drive-context-remove.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faDelete, 'data-icon': faTrash,
}, Messages.fc_remove)), }, Messages.fc_remove)), // XXX update key? "Remove from your CryptDrive"
h('li', h('a.cp-app-drive-context-removesf.dropdown-item.cp-app-drive-context-editable', { h('li', h('a.cp-app-drive-context-removesf.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faDelete, 'data-icon': faTrash,
}, Messages.fc_remove_sharedfolder)), }, Messages.fc_remove_sharedfolder)), // XXX update key? "Remove"
$separator.clone()[0], $separator.clone()[0],
h('li', h('a.cp-app-drive-context-properties.dropdown-item', { h('li', h('a.cp-app-drive-context-properties.dropdown-item', {
'tabindex': '-1', 'tabindex': '-1',
@ -1284,18 +1283,12 @@ define([
// If we're not in the trash nor in a shared folder, hide "remove" // If we're not in the trash nor in a shared folder, hide "remove"
if (!manager.isInSharedFolder(path) if (!manager.isInSharedFolder(path)
&& !$element.is('.cp-app-drive-element-sharedf')) { && !$element.is('.cp-app-drive-element-sharedf')) {
// This isn't a shared folder: can't delete shared folder
hide.push('removesf'); hide.push('removesf');
} else if (type === "tree") { } else if (type === "tree") {
// This is a shared folder or an element inside a shsared folder
// ==> can't move to trash
hide.push('delete'); hide.push('delete');
// Don't hide the deleteowned link if the element is a shared folder and
// it is owned
if (manager.isInSharedFolder(path) ||
!$element.is('.cp-app-drive-element-owned')) {
hide.push('deleteowned');
} else {
// This is a shared folder and it is owned
hide.push('removesf');
}
} }
if ($element.closest('[data-ro]').length) { if ($element.closest('[data-ro]').length) {
editable = false; editable = false;
@ -1345,7 +1338,7 @@ define([
break; break;
} }
case 'trash': { case 'trash': {
show = ['remove', 'restore', 'properties']; show = ['remove', 'deleteowned', 'restore', 'properties'];
} }
} }
@ -1662,22 +1655,11 @@ define([
if (paths) { if (paths) {
paths.forEach(function (p) { pathsList.push(p.path); }); paths.forEach(function (p) { pathsList.push(p.path); });
} }
var hasOwned = pathsList.some(function (p) {
// NOTE: Owned pads in shared folders won't be removed from the server
// so we don't have to check, we can use the default message
if (manager.isInSharedFolder(p)) { return false; }
var el = manager.find(p);
var data = manager.isSharedFolder(el) ? manager.getSharedFolderData(el)
: manager.getFileData(el);
return data.owners && data.owners.indexOf(edPublic) !== -1;
});
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [pathsList.length]); var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [pathsList.length]);
if (pathsList.length === 1) { if (pathsList.length === 1) {
msg = hasOwned ? Messages.fm_deleteOwnedPad : Messages.fm_removePermanentlyDialog; msg = Messages.fm_removePermanentlyDialog;
} else if (hasOwned) {
msg = msg + '<br><em>' + Messages.fm_removePermanentlyNote + '</em>';
} }
// XXX update key to tell the user that these pads will still be avialble to other users
UI.confirm(msg, function(res) { UI.confirm(msg, function(res) {
$(window).focus(); $(window).focus();
if (!res) { return; } if (!res) { return; }
@ -2413,17 +2395,55 @@ define([
$gridButton.attr('title', Messages.fm_viewGridButton); $gridButton.attr('title', Messages.fm_viewGridButton);
$container.append($listButton).append($gridButton); $container.append($listButton).append($gridButton);
}; };
var createEmptyTrashButton = function ($container) { var emptyTrashModal = function () {
var $button = $emptyTrashIcon.clone(); var ownedInTrash = manager.ownedInTrash();
$button.addClass('cp-app-drive-toolbar-emptytrash'); var hasOwned = Array.isArray(ownedInTrash) && ownedInTrash.length;
$button.attr('title', Messages.fc_empty); Messages.fm_emptyTrashOwned = "Your trash contains documents you own. You can remove them for everyone or only from your drive"; // XXX
$button.click(function () { var content = h('p', [
UI.confirm(Messages.fm_emptyTrashDialog, function(res) { Messages.fm_emptyTrashDialog,
if (!res) { return; } hasOwned ? h('br') : undefined,
manager.emptyTrash(refresh); hasOwned ? Messages.fm_emptyTrashOwned : undefined // XXX update UI?
]);
var buttons = [{
className: 'cancel',
name: Messages.cancelButton,
onClick: function () {},
keys: [27]
}];
if (hasOwned) {
buttons.push({
className: 'secondary',
name: Messages.fc_delete_owned,
onClick: function () {
manager.emptyTrash(true, refresh);
},
keys: []
}); });
}
buttons.push({
className: 'primary',
// XXX fc_remove: Remove from your CryptDrive
// We may want to use a new key here
name: hasOwned ? Messages.fc_remove : Messages.okButton,
onClick: function () {
manager.emptyTrash(false, refresh);
},
keys: [13]
});
var m = UI.dialog.customModal(content, {
buttons: buttons
});
UI.openCustomModal(m);
};
var createEmptyTrashButton = function () {
var button = h('button.btn.btn-danger', [
h('i.fa.'+faTrash),
h('span', Messages.fc_empty)
]);
$(button).click(function () {
emptyTrashModal();
}); });
$container.append($button); return $(h('div.cp-app-drive-button', button));
}; };
// Get the upload options // Get the upload options
@ -2795,30 +2815,34 @@ define([
$sortBlock.on('click', 'a', onSortByClick); $sortBlock.on('click', 'a', onSortByClick);
return $fhSort; return $fhSort;
}; };
var getFolderListHeader = function () { var getFolderListHeader = function (clickable, small) {
var $fohElement = $('<li>', { var $fohElement = $('<li>', {
'class': 'cp-app-drive-element-header cp-app-drive-element-list' 'class': 'cp-app-drive-element-header cp-app-drive-element-list'
}); });
var clickCls = clickable ? 'cp-app-drive-sort-clickable ' : '';
var onClick = clickable ? onSortByClick : function () {};
//var $fohElement = $('<span>', {'class': 'element'}).appendTo($folderHeader); //var $fohElement = $('<span>', {'class': 'element'}).appendTo($folderHeader);
var $fhIcon = $('<span>', {'class': 'cp-app-drive-content-icon'}); var $fhIcon = $('<span>', {'class': 'cp-app-drive-content-icon'});
var $name = $('<span>', { var $name = $('<span>', {
'class': 'cp-app-drive-element-name cp-app-drive-sort-foldername ' + 'class': 'cp-app-drive-element-name cp-app-drive-sort-foldername ' + clickCls
'cp-app-drive-sort-clickable' }).text(Messages.fm_folderName).click(onClick);
}).text(Messages.fm_folderName).click(onSortByClick);
var $state = $('<span>', {'class': 'cp-app-drive-element-state'}); var $state = $('<span>', {'class': 'cp-app-drive-element-state'});
var $subfolders = $('<span>', { var $subfolders, $files;
'class': 'cp-app-drive-element-folders cp-app-drive-element-list' if (!small) {
}).text(Messages.fm_numberOfFolders); $subfolders = $('<span>', {
var $files = $('<span>', { 'class': 'cp-app-drive-element-folders cp-app-drive-element-list'
'class': 'cp-app-drive-element-files cp-app-drive-element-list' }).text(Messages.fm_numberOfFolders);
}).text(Messages.fm_numberOfFiles); $files = $('<span>', {
'class': 'cp-app-drive-element-files cp-app-drive-element-list'
}).text(Messages.fm_numberOfFiles);
}
var $filler = $('<span>', { var $filler = $('<span>', {
'class': 'cp-app-drive-element-filler cp-app-drive-element-list' 'class': 'cp-app-drive-element-filler cp-app-drive-element-list'
}); });
$fohElement.append($fhIcon).append($name).append($state) $fohElement.append($fhIcon).append($name).append($state)
.append($subfolders).append($files).append($filler); .append($subfolders).append($files).append($filler);
addFolderSortIcon($fohElement); if (clickable) { addFolderSortIcon($fohElement); }
return $fohElement; return $fohElement;
}; };
var addFileSortIcon = function ($list) { var addFileSortIcon = function ($list) {
@ -2875,15 +2899,16 @@ define([
}); });
if (keys.length < 2) { return keys; } if (keys.length < 2) { return keys; }
var mult = asc ? 1 : -1; var mult = asc ? 1 : -1;
var getProp = function (el) { var getProp = function (_el) {
if (folder && root[el] && manager.isSharedFolder(root[el])) { var el = useId ? _el : root[_el];
var title = manager.getSharedFolderData(root[el]).title || el; var sfId = (el && el.root && el.key) ? el.root[el.key] : el;
if (folder && el && manager.isSharedFolder(sfId)) {
var title = manager.getSharedFolderData(sfId).title || el;
return String(title).toLowerCase(); return String(title).toLowerCase();
} else if (folder) { } else if (folder) {
return el.toLowerCase(); return String((el && el.key) || el).toLowerCase();
} }
var id = useId ? el : root[el]; var data = manager.getFileData(el);
var data = manager.getFileData(id);
if (!data) { return ''; } if (!data) { return ''; }
if (prop === 'type') { if (prop === 'type') {
var hrefData = Hash.parsePadUrl(data.href || data.roHref); var hrefData = Hash.parsePadUrl(data.href || data.roHref);
@ -2892,15 +2917,19 @@ define([
if (prop === 'atime' || prop === 'ctime') { if (prop === 'atime' || prop === 'ctime') {
return typeof(data[prop]) === "number" ? data[prop] : new Date(data[prop]); return typeof(data[prop]) === "number" ? data[prop] : new Date(data[prop]);
} }
return (manager.getTitle(id) || "").toLowerCase(); return (manager.getTitle(el) || "").toLowerCase();
}; };
var props = {}; var props = {};
keys.forEach(function (k) { keys.forEach(function (k) {
props[k] = getProp(k); var uid = k;
if (typeof(k) === "object") {
uid = k.uid = Util.uid();
}
props[uid] = getProp(k);
}); });
keys.sort(function(a, b) { keys.sort(function(a, b) {
var _a = props[a]; var _a = props[(a && a.uid) || a];
var _b = props[b]; var _b = props[(b && b.uid) || b];
if (_a < _b) { return mult * -1; } if (_a < _b) { return mult * -1; }
if (_b < _a) { return mult; } if (_b < _a) { return mult; }
return 0; return 0;
@ -3152,6 +3181,8 @@ define([
var displayTrashRoot = function ($list, $folderHeader, $fileHeader) { var displayTrashRoot = function ($list, $folderHeader, $fileHeader) {
var filesList = []; var filesList = [];
var root = files[TRASH]; var root = files[TRASH];
var isEmpty = true;
// Elements in the trash are JS arrays (several elements can have the same name) // Elements in the trash are JS arrays (several elements can have the same name)
Object.keys(root).forEach(function (key) { Object.keys(root).forEach(function (key) {
if (!Array.isArray(root[key])) { if (!Array.isArray(root[key])) {
@ -3167,7 +3198,14 @@ define([
name: key name: key
}); });
}); });
isEmpty = false;
}); });
if (!isEmpty) {
var $empty = createEmptyTrashButton();
$content.append($empty);
}
var sortedFolders = sortTrashElements(true, filesList, null, !getSortFolderDesc()); var sortedFolders = sortTrashElements(true, filesList, null, !getSortFolderDesc());
var sortedFiles = sortTrashElements(false, filesList, APP.store[SORT_FILE_BY], !getSortFileDesc()); var sortedFiles = sortTrashElements(false, filesList, APP.store[SORT_FILE_BY], !getSortFileDesc());
if (manager.hasSubfolder(root, true)) { $list.append($folderHeader); } if (manager.hasSubfolder(root, true)) { $list.append($folderHeader); }
@ -3249,9 +3287,10 @@ define([
$input.focus(); $input.focus();
}); });
getFileListHeader(false).appendTo($list);
$list.closest('#cp-app-drive-content-folder').addClass('cp-app-drive-content-list'); $list.closest('#cp-app-drive-content-folder').addClass('cp-app-drive-content-list');
var filesList = manager.search(value); var filesList = manager.search(value);
var sortable = {};
var sortableFolders = [];
filesList.forEach(function (r) { filesList.forEach(function (r) {
// if r.id === null, then it's a folder, not a file // if r.id === null, then it's a folder, not a file
r.paths.forEach(function (path) { r.paths.forEach(function (path) {
@ -3260,33 +3299,56 @@ define([
var _path = path.slice(); var _path = path.slice();
var key = path.pop(); var key = path.pop();
var root = manager.find(path); var root = manager.find(path);
var isFolder = manager.isFolder(root[key]); var obj = {
var $element = createElement(path, key, root, isFolder); path: path,
$element.addClass('cp-app-drive-element-notrash cp-app-drive-search-result'); _path: _path,
$element.off('contextmenu'); key: key,
$element.contextmenu(openContextMenu('default')); root: root,
$element.data('context', 'default'); data: r.data
if (isFolder) { };
$element.find('.cp-app-drive-element-list').css({ if (manager.isFolder(root[key])) {
visibility: 'hidden' sortableFolders.push(obj);
}).text(''); return;
$element.find('.cp-app-drive-element-folders').css({
visibility: ''
}).text(Messages.fm_folder);
}
if (manager.isPathIn(_path, ['hrefArray'])) {
_path.pop();
_path.push(r.data.title);
} }
var $path = $('<span>', { sortable[root[key]] = obj;
'class': 'cp-app-drive-search-path'
}).appendTo($element.find('.cp-app-drive-element-name'));
createTitle($path, _path);
$list.append($element);
}); });
}); });
var _folders = sortElements(true, [ROOT], sortableFolders, null, !getSortFolderDesc(), true);
var sortableKeys = Object.keys(sortable).map(Number);
var _files = sortElements(false, [ROOT], sortableKeys, APP.store[SORT_FILE_BY], !getSortFileDesc(), true);
var addEl = function (obj, folder) {
var $element = createElement(obj.path, obj.key, obj.root, folder);
$element.addClass('cp-app-drive-element-notrash cp-app-drive-search-result');
$element.off('contextmenu');
$element.contextmenu(openContextMenu('default'));
$element.data('context', 'default');
if (folder) {
$element.find('.cp-app-drive-element-list').css({
visibility: 'hidden'
}).text('');
}
if (manager.isPathIn(obj._path, ['hrefArray'])) {
obj._path.pop();
obj._path.push(obj.data.title);
}
var $path = $('<span>', {
'class': 'cp-app-drive-search-path'
}).appendTo($element.find('.cp-app-drive-element-name'));
createTitle($path, obj._path);
$list.append($element);
};
if (_folders.length) { getFolderListHeader(true, true).appendTo($list); }
_folders.forEach(function (el) {
var obj = el;
addEl(obj, true);
});
if (_files.length) { getFileListHeader(true).appendTo($list); }
_files.forEach(function (el) {
var obj = sortable[el];
addEl(obj, false);
});
setTimeout(collapseDrivePath); setTimeout(collapseDrivePath);
}; };
@ -3431,7 +3493,7 @@ define([
} }
var fId = APP.newSharedFolder; var fId = APP.newSharedFolder;
var data = folders[fId]; var data = folders[fId];
var $folderHeader = getFolderListHeader(); var $folderHeader = getFolderListHeader(true);
var $fileHeader = getFileListHeader(true); var $fileHeader = getFileListHeader(true);
var path = currentPath.slice(1); var path = currentPath.slice(1);
var root = Util.find(data, path); var root = Util.find(data, path);
@ -3538,9 +3600,7 @@ define([
createToolbar(path); createToolbar(path);
if (inTrash || isInRoot) { if (!isSearch) { createTitle($content, path); }
createTitle($content, path);
}
var $info = createInfoBox(path); var $info = createInfoBox(path);
var $dirContent = $('<div>', {id: FOLDER_CONTENT_ID}); var $dirContent = $('<div>', {id: FOLDER_CONTENT_ID});
@ -3552,9 +3612,6 @@ define([
} }
createViewModeButton(APP.toolbar.$bottomR); createViewModeButton(APP.toolbar.$bottomR);
} }
if (inTrash) {
createEmptyTrashButton(APP.toolbar.$bottomR);
}
var $list = $('<ul>').appendTo($dirContent); var $list = $('<ul>').appendTo($dirContent);
@ -3577,7 +3634,6 @@ define([
} }
$content.data('readOnlyFolder', readOnlyFolder); $content.data('readOnlyFolder', readOnlyFolder);
// NewButton can be undefined if we're in read only mode
if (!readOnlyFolder) { if (!readOnlyFolder) {
createNewButton(isInRoot, APP.toolbar.$bottomL); createNewButton(isInRoot, APP.toolbar.$bottomL);
} }
@ -3589,6 +3645,7 @@ define([
} }
*/ */
if (APP.mobile()) { if (APP.mobile()) {
var $context = $('<button>', { var $context = $('<button>', {
id: 'cp-app-drive-toolbar-context-mobile' id: 'cp-app-drive-toolbar-context-mobile'
@ -3616,7 +3673,7 @@ define([
} }
updateContextButton(); updateContextButton();
var $folderHeader = getFolderListHeader(); var $folderHeader = getFolderListHeader(true);
var $fileHeader = getFileListHeader(true); var $fileHeader = getFileListHeader(true);
if (isTemplate) { if (isTemplate) {
@ -3637,7 +3694,7 @@ define([
// ANON_SHARED_FOLDER // ANON_SHARED_FOLDER
displaySharedFolder($list); displaySharedFolder($list);
} else { } else {
$dirContent.contextmenu(openContextMenu('content')); if (!inTrash) { $dirContent.contextmenu(openContextMenu('content')); }
if (manager.hasSubfolder(root)) { $list.append($folderHeader); } if (manager.hasSubfolder(root)) { $list.append($folderHeader); }
// display sub directories // display sub directories
var keys = Object.keys(root); var keys = Object.keys(root);
@ -3728,6 +3785,10 @@ define([
if (files.restrictedFolders[isSharedFolder]) { if (files.restrictedFolders[isSharedFolder]) {
$elementRow.addClass('cp-app-drive-element-restricted'); $elementRow.addClass('cp-app-drive-element-restricted');
} }
if (isSharedFolder) {
var sfData = manager.getSharedFolderData(isSharedFolder);
_addOwnership($elementRow, $(), sfData);
}
var $element = $('<li>').append($elementRow); var $element = $('<li>').append($elementRow);
if (draggable) { $elementRow.attr('draggable', true); } if (draggable) { $elementRow.attr('draggable', true); }
if (collapsable) { if (collapsable) {
@ -3810,17 +3871,17 @@ define([
var sfId = manager.isInSharedFolder(newPath) || (isSharedFolder && root[key]); var sfId = manager.isInSharedFolder(newPath) || (isSharedFolder && root[key]);
var $icon, isCurrentFolder, subfolder; var $icon, isCurrentFolder, subfolder;
if (isSharedFolder) { if (isSharedFolder) {
var fId = root[key];
// Fix path // Fix path
newPath.push(manager.user.userObject.ROOT); newPath.push(manager.user.userObject.ROOT);
isCurrentFolder = manager.comparePath(newPath, currentPath); isCurrentFolder = manager.comparePath(newPath, currentPath);
// Subfolders? // Subfolders?
var newRoot = manager.folders[fId].proxy[manager.user.userObject.ROOT]; var newRoot = manager.folders[sfId].proxy[manager.user.userObject.ROOT];
subfolder = manager.hasSubfolder(newRoot); subfolder = manager.hasSubfolder(newRoot);
// Fix name // Fix name
key = manager.getSharedFolderData(fId).title; key = manager.getSharedFolderData(sfId).title;
// Fix icon // Fix icon
$icon = isCurrentFolder ? $sharedFolderOpenedIcon : $sharedFolderIcon; $icon = isCurrentFolder ? $sharedFolderOpenedIcon : $sharedFolderIcon;
isSharedFolder = sfId;
} else { } else {
var isEmpty = manager.isFolderEmpty(root[key]); var isEmpty = manager.isFolderEmpty(root[key]);
subfolder = manager.hasSubfolder(root[key]); subfolder = manager.hasSubfolder(root[key]);
@ -4026,7 +4087,7 @@ define([
UI.confirm(msgD, function(res) { UI.confirm(msgD, function(res) {
$(window).focus(); $(window).focus();
if (!res) { return; } if (!res) { return; }
manager.delete(pathsList, function () { manager.deleteOwned(pathsList, function () {
pathsList.forEach(LS.removeFoldersOpened); pathsList.forEach(LS.removeFoldersOpened);
removeSelected(); removeSelected();
refresh(); refresh();
@ -4426,10 +4487,7 @@ define([
log(Messages.fm_forbidden); log(Messages.fm_forbidden);
return; return;
} }
UI.confirm(Messages.fm_emptyTrashDialog, function(res) { emptyTrashModal();
if (!res) { return; }
manager.emptyTrash(refresh);
});
} }
else if ($this.hasClass("cp-app-drive-context-remove")) { else if ($this.hasClass("cp-app-drive-context-remove")) {
return void deletePaths(paths); return void deletePaths(paths);

@ -110,7 +110,8 @@ define([
})); }));
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
var curve = $el.attr('data-curve'); var curve = $el.attr('data-curve');
var friend = curve === user.curvePublic ? user : friends[curve]; if (curve === user.curvePublic) { return; }
var friend = friends[curve];
if (!friend) { return; } if (!friend) { return; }
common.mailbox.sendTo("RM_OWNER", { common.mailbox.sendTo("RM_OWNER", {
channel: channel, channel: channel,
@ -896,6 +897,27 @@ define([
$d.append(changePass); $d.append(changePass);
} }
} }
if (owned) {
var deleteOwned = h('button.btn.btn-danger-alt', Messages.fc_delete_owned);
var spinner = UI.makeSpinner();
UI.confirmButton(deleteOwned, {
classes: 'btn-danger'
}, function () {
spinner.spin();
sframeChan.query('Q_DELETE_OWNED', {
teamId: typeof(owned) !== "boolean" ? owned : undefined,
channel: data.channel
}, function (err, obj) {
spinner.done();
if (err || (obj && obj.error)) { UI.warn(Messages.error); }
});
});
$d.append(h('br'));
$d.append(h('div', [
deleteOwned,
spinner.spinner
]));
}
return $d; return $d;
}; };
var drawRight = function () { var drawRight = function () {

@ -478,6 +478,7 @@ define([
store: store, store: store,
}; };
var myData = Messaging.createData(userObject); var myData = Messaging.createData(userObject);
if (!myData.curvePublic) { return void done(); }
Mailbox.sendTo(ctx, 'SAFE_LINKS_DEFAULT', { Mailbox.sendTo(ctx, 'SAFE_LINKS_DEFAULT', {
user: myData, user: myData,

@ -224,13 +224,16 @@ define([
var now = function () { return +new Date(); }; var now = function () { return +new Date(); };
var sortCpIndex = function (hashes) {
return Object.keys(hashes).map(Number).sort(function (a, b) {
return a-b;
});
};
var getLastCp = function (old, i) { var getLastCp = function (old, i) {
var hashes = old ? oldHashes : content.hashes; var hashes = old ? oldHashes : content.hashes;
if (!hashes || !Object.keys(hashes).length) { return {}; } if (!hashes || !Object.keys(hashes).length) { return {}; }
i = i || 0; i = i || 0;
var idx = Object.keys(hashes).map(Number).sort(function (a, b) { var idx = sortCpIndex(hashes);
return a-b;
});
var lastIndex = idx[idx.length - 1 - i]; var lastIndex = idx[idx.length - 1 - i];
var last = JSON.parse(JSON.stringify(hashes[lastIndex])); var last = JSON.parse(JSON.stringify(hashes[lastIndex]));
return last; return last;
@ -308,7 +311,7 @@ define([
return void UI.alert(Messages.oo_saveError); return void UI.alert(Messages.oo_saveError);
} }
// Get the last cp idx // Get the last cp idx
var all = Object.keys(content.hashes || {}).map(Number).sort(); var all = sortCpIndex(content.hashes || {});
var current = all[all.length - 1] || 0; var current = all[all.length - 1] || 0;
// Get the expected cp idx // Get the expected cp idx
var _i = Math.floor(ev.index / CHECKPOINT_INTERVAL); var _i = Math.floor(ev.index / CHECKPOINT_INTERVAL);
@ -1150,6 +1153,7 @@ define([
APP.realtime.onSettle(function () { APP.realtime.onSettle(function () {
APP.getImageURL(name, function(url) { APP.getImageURL(name, function(url) {
debug("CRYPTPAD success add " + name); debug("CRYPTPAD success add " + name);
common.setPadAttribute('atime', +new Date(), null, data.href);
APP.AddImageSuccessCallback({ APP.AddImageSuccessCallback({
name: name, name: name,
url: url url: url
@ -1382,6 +1386,7 @@ define([
}, { }, {
typeInput: $select[0] typeInput: $select[0]
}, true); }, true);
$select.find('button').addClass('btn');
}; };
var x2tImportImagesInternal = function(x2t, images, i, callback) { var x2tImportImagesInternal = function(x2t, images, i, callback) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

@ -0,0 +1,322 @@
<!DOCTYPE html>
<html>
<head>
<title>ONLYOFFICE Document Editor</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=IE8"/>
<meta name="description" content="" />
<meta name="keywords" content="" />
<link rel="icon" href="resources/img/favicon.ico" type="image/x-icon" />
<!-- splash -->
<style type="text/css">
.loadmask {
left: 0;
top: 0;
position: absolute;
height: 100%;
width: 100%;
overflow: hidden;
border: none;
background-color: #f4f4f4;
z-index: 1001;
}
.loader-page {
width: 100%;
height: 170px;
bottom: 42%;
position: absolute;
text-align: center;
line-height: 10px;
}
.loader-logo {
max-height: 160px;
margin-bottom: 10px;
}
.loader-page-romb {
width: 40px;
display: inline-block;
}
.loader-page-text {
width: 100%;
bottom: 42%;
position: absolute;
text-align: center;
color: #888;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 20px;
}
.loader-page-text-loading {
font-size: 14px;
}
.loader-page-text-customer {
font-size: 16px;
margin-bottom: 5px;
}
.romb {
width: 40px;
height: 40px;
-webkit-transform: rotate(135deg) skew(20deg, 20deg);
-moz-transform: rotate(135deg) skew(20deg, 20deg);
-ms-transform: rotate(135deg) skew(20deg, 20deg);
-o-transform: rotate(135deg) skew(20deg, 20deg);
position: absolute;
background: red;
border-radius: 6px;
-webkit-animation: movedown 3s infinite ease;
-moz-animation: movedown 3s infinite ease;
-ms-animation: movedown 3s infinite ease;
-o-animation: movedown 3s infinite ease;
animation: movedown 3s infinite ease;
}
#blue {
z-index: 3;
background: #55bce6;
-webkit-animation-name: blue;
-moz-animation-name: blue;
-ms-animation-name: blue;
-o-animation-name: blue;
animation-name: blue;
}
#red {
z-index:1;
background: #de7a59;
-webkit-animation-name: red;
-moz-animation-name: red;
-ms-animation-name: red;
-o-animation-name: red;
animation-name: red;
}
#green {
z-index: 2;
background: #a1cb5c;
-webkit-animation-name: green;
-moz-animation-name: green;
-ms-animation-name: green;
-o-animation-name: green;
animation-name: green;
}
@-webkit-keyframes red {
0% { top:120px; background: #de7a59; }
10% { top:120px; background: #F2CBBF; }
14% { background: #f4f4f4; top:120px; }
15% { background: #f4f4f4; top:0;}
20% { background: #E6E4E4; }
30% { background: #D2D2D2; }
40% { top:120px; }
100% { top:120px; background: #de7a59; }
}
@keyframes red {
0% { top:120px; background: #de7a59; }
10% { top:120px; background: #F2CBBF; }
14% { background: #f4f4f4; top:120px; }
15% { background: #f4f4f4; top:0; }
20% { background: #E6E4E4; }
30% { background: #D2D2D2; }
40% { top:120px; }
100% { top:120px; background: #de7a59; }
}
@-webkit-keyframes green {
0% { top:110px; background: #a1cb5c; opacity:1; }
10% { top:110px; background: #CBE0AC; opacity:1; }
14% { background: #f4f4f4; top:110px; opacity:1; }
15% { background: #f4f4f4; top:0; opacity:1; }
20% { background: #f4f4f4; top:0; opacity:0; }
25% { background: #EFEFEF; top:0; opacity:1; }
30% { background:#E6E4E4; }
70% { top:110px; }
100% { top:110px; background: #a1cb5c; }
}
@keyframes green {
0% { top:110px; background: #a1cb5c; opacity:1; }
10% { top:110px; background: #CBE0AC; opacity:1; }
14% { background: #f4f4f4; top:110px; opacity:1; }
15% { background: #f4f4f4; top:0; opacity:1; }
20% { background: #f4f4f4; top:0; opacity:0; }
25% { background: #EFEFEF; top:0; opacity:1; }
30% { background:#E6E4E4; }
70% { top:110px; }
100% { top:110px; background: #a1cb5c; }
}
@-webkit-keyframes blue {
0% { top:100px; background: #55bce6; opacity:1; }
10% { top:100px; background: #BFE8F8; opacity:1; }
14% { background: #f4f4f4; top:100px; opacity:1; }
15% { background: #f4f4f4; top:0; opacity:1; }
20% { background: #f4f4f4; top:0; opacity:0; }
25% { background: #f4f4f4; top:0; opacity:0; }
45% { background: #EFEFEF; top:0; opacity:0.2; }
100% { top:100px; background: #55bce6; }
}
@keyframes blue {
0% { top:100px; background: #55bce6; opacity:1; }
10% { top:100px; background: #BFE8F8; opacity:1; }
14% { background: #f4f4f4; top:100px; opacity:1; }
15% { background: #f4f4f4; top:0; opacity:1; }
20% { background: #f4f4f4; top:0; opacity:0; }
25% { background: #f4f4f4; top:0; opacity:0; }
45% { background: #EFEFEF; top:0; opacity:0.2; }
100% { top:100px; background: #55bce6; }
}
</style>
<script>
var userAgent = navigator.userAgent.toLowerCase(),
check = function(regex){ return regex.test(userAgent); },
stopLoading = false;
if (!check(/opera/) && (check(/msie/) || check(/trident/))) {
var m = /msie (\d+\.\d+)/.exec(userAgent);
if (m && parseFloat(m[1]) < 10.0) {
document.write('<div class="app-error-panel">' +
'<div class="message-block">' +
'<div class="message-inner">' +
'<div class="title">Your browser is not supported.</div>' +
'<div class="text">Sorry, Document Editor is currently only supported in the latest versions of the Chrome, Firefox, Safari or Internet Explorer web browsers.</div>' +
'</div>' +
'</div></div>');
stopLoading = true;
}
} else
if (check(/windows\snt/i)) {
var re = /chrome\/(\d+)/i.exec(userAgent);
if (!!re && !!re[1] && !(re[1] > 49)) {
setTimeout(function () {
document.getElementsByTagName('body')[0].className += "winxp";
},0);
}
}
function getUrlParams() {
var e,
a = /\+/g, // Regex for replacing addition symbol with a space
r = /([^&=]+)=?([^&]*)/g,
d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
q = window.location.search.substring(1),
urlParams = {};
while (e = r.exec(q))
urlParams[d(e[1])] = d(e[2]);
return urlParams;
}
function encodeUrlParam(str) {
return str.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
var params = getUrlParams(),
lang = (params["lang"] || 'en').split(/[\-\_]/)[0],
customer = params["customer"] ? ('<div class="loader-page-text-customer">' + encodeUrlParam(params["customer"]) + '</div>') : '',
margin = (customer !== '') ? 50 : 20,
loading = 'Loading...',
logo = params["logo"] ? ((params["logo"] !== 'none') ? ('<img src="' + encodeUrlParam(params["logo"]) + '" class="loader-logo" />') : '') : null;
window.frameEditorId = params["frameEditorId"];
if ( lang == 'de') loading = 'Ladevorgang...';
else if ( lang == 'es') loading = 'Cargando...';
else if ( lang == 'fr') loading = 'Chargement en cours...';
else if ( lang == 'it') loading = 'Caricamento in corso...';
else if ( lang == 'pt') loading = 'Carregando...';
else if ( lang == 'ru') loading = 'Загрузка...';
else if ( lang == 'sl') loading = 'Nalaganje...';
else if ( lang == 'tr') loading = 'Yükleniyor...';
else if ( lang == 'bg') loading = 'Зареждане...';
else if ( lang == 'cs') loading = 'Nahrávám...';
else if ( lang == 'hu') loading = 'Betöltés...';
else if ( lang == 'ja') loading = '読み込み中...';
else if ( lang == 'ko') loading = '로드 중...';
else if ( lang == 'lv') loading = 'Ieladēšana ...';
else if ( lang == 'nl') loading = 'Laden...';
else if ( lang == 'pl') loading = 'Ładowanie...';
else if ( lang == 'sk') loading = 'Nahrávam...';
else if ( lang == 'uk') loading = 'Завантаження...';
else if ( lang == 'vi') loading = 'Đang tải...';
else if ( lang == 'zh') loading = '加载中...';
if ( !stopLoading )
document.write(
'<div id="loading-mask" class="loadmask">' +
'<div class="loader-page" style="margin-bottom: ' + margin + 'px;' + ((logo!==null) ? 'height: auto;' : '') + '">' +
((logo!==null) ? logo :
'<div class="loader-page-romb">' +
'<div class="romb" id="blue"></div>' +
'<div class="romb" id="green"></div>' +
'<div class="romb" id="red"></div>' +
'</div>') +
'</div>' +
'<div class="loader-page-text">' + customer +
'<div class="loader-page-text-loading">' + loading + '</div>' +
'</div>' +
'</div>');
</script>
<link rel="stylesheet" type="text/css" href="../../../apps/documenteditor/main/resources/css/app.css">
</head>
<body>
<script>
window.requireTimeourError = function(){
var reqerr;
if ( lang == 'de') reqerr = 'Die Verbindung ist zu langsam, einige Komponenten konnten nicht geladen werden. Aktualisieren Sie bitte die Seite.';
else if ( lang == 'es') reqerr = 'La conexión es muy lenta, algunos de los componentes no han podido cargar. Por favor recargue la página.';
else if ( lang == 'fr') reqerr = 'La connexion est trop lente, certains des composants n\'ons pas pu être chargé. Veuillez recharger la page.';
else if ( lang == 'ru') reqerr = 'Слишком медленное соединение, не удается загрузить некоторые компоненты. Пожалуйста, обновите страницу.';
else reqerr = 'The connection is too slow, some of the components could not be loaded. Please reload the page.';
return reqerr;
};
var requireTimeoutID = setTimeout(function(){
window.alert(window.requireTimeourError());
window.location.reload();
}, 30000);
var require = {
waitSeconds: 30,
callback: function(){
clearTimeout(requireTimeoutID);
}
};
</script>
<inline src="resources/img/header/buttons.svg" />
<inline src="resources/img/doc-formats/docx.svg" />
<inline src="resources/img/doc-formats/dotx.svg" />
<inline src="resources/img/doc-formats/pdf.svg" />
<inline src="resources/img/doc-formats/pdfa.svg" />
<inline src="resources/img/doc-formats/txt.svg" />
<inline src="resources/img/doc-formats/odt.svg" />
<inline src="resources/img/doc-formats/ott.svg" />
<inline src="resources/img/doc-formats/rtf.svg" />
<inline src="resources/img/doc-formats/html.svg" />
<inline src="resources/img/doc-formats/blank.svg" />
<inline src="resources/img/toolbar/shapetypes.svg" />
<div id="viewport"></div>
<script data-main="app" src="../../../vendor/requirejs/require.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html>
<head>
<title>Compare documents</title>
<meta charset="utf-8" />
<meta name="description" content="Instructions on how to compare and merge two documents" />
<link type="text/css" rel="stylesheet" href="../editor.css" />
<script type="text/javascript" src="../callback.js"></script>
<script type="text/javascript" src="../search/js/page-search.js"></script>
</head>
<body>
<div class="mainpart">
<div class="search-field">
<input id="search" class="searchBar" placeholder="Search" type="text" onkeypress="doSearch(event)">
</div>
<h1>Compare documents</h1>
<p class="note"><b>Note</b>: this option is available in the <b>paid</b> <em>online version</em> only starting from <b>Document Server</b> v. <b>5.5</b>.</p>
<p>If you need to compare and merge two documents, you can use the document <b>Compare</b> feature. It allows to display the differences between two documents and merge the documents by accepting the changes one by one or all at once.</p>
<p>After comparing and merging two documents, the result will be stored on the portal as a new version of the original file<!-- (in the <em>online version</em> of editors)-->. <!--In the desktop version, when you click the <b>Save</b> button, the dialog window will appear where you will be suggested to save a new file.--></p>
<p>If you do not need to merge documents which are being compared, you can reject all the changes so that the original document remains unchanged.</p>
<h3 id="choosedocument">Choose a document for comparison</h3>
<p>To compare two documents, open the original document that you need to compare and select the second document for comparison:</p>
<ol>
<li>switch to the <b>Collaboration</b> tab at the top toolbar and press the <img alt="Compare button" src="../images/comparebutton.png" /> <b>Compare</b> button,</li>
<li>
select one of the following options to load the document:
<ul>
<li>the <b>Document from File</b> option will open the standard dialog window for file selection. Browse your computer hard disk drive for the necessary <em>.docx</em> file and click the <b>Open</b> button.</li>
<li>
the <b>Document from URL</b> option will open the window where you can enter a link to the file stored in a third-party web storage (for example, Nextcloud) if you have corresponding access rights to it. The link must be a <b>direct link for downloading the file</b>. When the link is specified, click the <b>OK</b> button.
<p class="note"><b>Note</b>: The direct link allows to download the file directly without opening it in a web browser. For example, to get a direct link in Nextcloud, find the necessary document in the file list, select the <b>Details</b> option from the file menu. Click the <b>Copy direct link (only works for users who have access to this file/folder)</b> icon to the right of the file name at the details panel. To find out how to get a direct link for downloading the file in a different third-party web storage, please refer to the corresponding third-party service documentation.</p>
</li>
<li class="onlineDocumentFeatures"> the <b>Document from Storage</b> option <!--(available in the <em>online version</em> only)--> will open the <b>Select Data Source</b> window. It displays the list of all the <em>.docx</em> documents stored on your portal you have corresponding access rights to. To navigate between the <b>Documents</b> module sections use the menu in the left part of the window. Select the necessary <em>.docx</em> document and click the <b>OK</b> button.</li>
</ul>
</li>
</ol>
<p>When the second document for comparison is selected, the comparison process will start and the document will look as if it was opened in the <b>Review</b> mode. All the changes are highlighted with a color, and you can view the changes, navigate between them, accept or reject them one by one or all the changes at once. It's also possible to change the display mode and see how the document looks before comparison, in the process of comparison, or how it will look after comparison if you accept all changes.</p>
<h3 id="displaymode">Choose the changes display mode</h3>
<p>Click the <img alt="Display Mode button" src="../images/review_displaymode.png" /> <b>Display Mode</b> button at the top toolbar and select one of the available modes from the list:</p>
<ul>
<li>
<b>Markup</b> - this option is selected by default. It is used to display the document <b>in the process of comparison</b>. This mode allows both to view the changes and edit the document.
<p><img alt="Compare documents - Markup" src="../images/compare_markup.png" /></p>
</li>
<li>
<b>Final</b> - this mode is used to display the document <b>after comparison</b> as if all the changes were accepted. This option does not actually accept all changes, it only allows you to see how the document will look like after you accept all the changes. In this mode, you cannot edit the document.
<p><img alt="Compare documents - Final" src="../images/compare_final.png" /></p>
</li>
<li>
<b>Original</b> - this mode is used to display the document <b>before comparison</b> as if all the changes were rejected. This option does not actually reject all changes, it only allows you to view the document without changes. In this mode, you cannot edit the document.
<p><img alt="Compare documents - Original" src="../images/compare_original.png" /></p>
</li>
</ul>
<h3 id="managechanges">Accept or reject changes</h3>
<p>Use the <img alt="To Previous Change button" src="../images/review_previous.png" /> <b>Previous</b> and the <img alt="To Next Change button" src="../images/review_next.png" /> <b>Next</b> buttons at the top toolbar to navigate among the changes.</p>
<p>To accept the currently selected change you can:</p>
<ul>
<li>click the <img alt="Accept button" src="../images/review_accepttoptoolbar.png" /> <b>Accept</b> button at the top toolbar, or</li>
<li>click the downward arrow below the <b>Accept</b> button and select the <b>Accept Current Change</b> option (in this case, the change will be accepted and you will proceed to the next change), or</li>
<li>click the <b>Accept</b> <img alt="Accept button" src="../images/review_accept.png" /> button of the change notification.</li>
</ul>
<p>To quickly accept all the changes, click the downward arrow below the <img alt="Accept button" src="../images/review_accepttoptoolbar.png" /> <b>Accept</b> button and select the <b>Accept All Changes</b> option.</p>
<p>To reject the current change you can:</p>
<ul>
<li>click the <img alt="Reject button" src="../images/review_rejecttoptoolbar.png" /> <b>Reject</b> button at the top toolbar, or</li>
<li>click the downward arrow below the <b>Reject</b> button and select the <b>Reject Current Change</b> option (in this case, the change will be rejected and you will move on to the next available change), or</li>
<li>click the <b>Reject</b> <img alt="Reject button" src="../images/review_reject.png" /> button of the change notification.</li>
</ul>
<p>To quickly reject all the changes, click the downward arrow below the <img alt="Reject button" src="../images/review_rejecttoptoolbar.png" /> <b>Reject</b> button and select the <b>Reject All Changes</b> option.</p>
<h3 id="comparisonnotes">Additional info on the comparison feature</h3>
<h5>Method of the comparison</h5>
<p>Documents are compared <b>by words</b>. If a word contains a change of at least one character (e.g. if a character was removed or replaced), in the result, the difference will be displayed as the change of the entire word, not the character.</p>
<p>The image below illustrates the case when the original file contains the word 'Characters' and the document for comparison contains the word 'Character'.</p>
<p><img alt="Compare documents - method" src="../images/compare_method.png" /></p>
<h5>Authorship of the document</h5>
<p>When the comparison process is launched, the second document for comparison is being loaded and compared to the current one.</p>
<ul>
<li>If the loaded document contains some data which is not represented in the original document, the data will be marked as added by a reviewer.</li>
<li>If the original document contains some data which is not represented in the loaded document, the data will be marked as deleted by a reviewer.</li>
</ul>
<p>If the authors of the original and loaded documents are the same person, the reviewer is the same user. His/her name is displayed in the change balloon.</p>
<p>If the authors of two files are different users, then the author of the second file loaded for comparison is the author of the added/removed changes.</p>
<h5>Presence of the tracked changes in the compared document</h5>
<p>If the original document contains some changes made in the review mode, they will be accepted in the comparison process. When you choose the second file for comparison, you'll see the corresponding warning message.</p>
<p>In this case, when you choose the <b>Original</b> display mode, the document will not contain any changes.</p>
</div>
</body>
</html>

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<title>Add caption</title>
<meta charset="utf-8" />
<meta name="description" content=">The Caption is a numbered label that you can apply to objects, such as equations, tables, figures and images within your documents" />
<link type="text/css" rel="stylesheet" href="../editor.css" />
<script type="text/javascript" src="../callback.js"></script>
<script type="text/javascript" src="../search/js/page-search.js"></script>
</head>
<body>
<div class="mainpart">
<div class="search-field">
<input id="search" class="searchBar" placeholder="Search" type="text" onkeypress="doSearch(event)">
</div>
<h1>Add caption</h1>
<p>The <b>Caption</b> is a numbered label that you can apply to objects, such as equations, tables, figures and images within your documents.</p>
<p>This makes it easy to reference within your text as there is an easily recognizable label on your object.</p>
<p>To add the caption to an object:</p>
<ul>
<li>select the object which one to apply a caption;</li>
<li>switch to the <b>References</b> tab of the top toolbar;</li>
<li>
click the <img alt="Rich text content control" src="../images/caption_icon.png" /> <b>Caption</b> icon at the top toolbar or right lick o nthe object and select the <b>Insert Caption</b> option to open the <b>Insert Caption</b> dialogue box
<ul>
<li>choose the label to use for your caption by clicking the label drop-down and choosing the object. or</li>
<li>create a new label by clicking the <b>Add label</b> button to open the <b>Add label</b> dialogue box. Enter a name for the label into the label text box. Then click the <b>OK</b> button to add a new label into the label list;</li>
</ul>
<li>check the <b>Include chapter number</b> checkbox to change the numbering for your caption;</li>
<li>in <b>Insert</b> drop-down menu choose <b>Before</b> to place the label above the object or <b>After</b> to place it below the object;</li>
<li>check the <b>Exclude label from caption</b> checkbox to leave only a number for this particular caption in accordance with a sequence number;</li>
<li>you can then choose how to number your caption by assigning a specific style to the caption and adding a separator;</li>
<li>to apply the caption click the <b>OK</b> button.</li>
</ul>
<p><img alt="Content Control settings window" src="../images/insertcaptionbox.png" /></p>
<h2>Deleting a label</h2>
<p>To <b>delete</b> a label you have created, choose the label from the label list within the caption dialogue box then click the <b>Delete label</b> button. The label you created will be immediately deleted.</p>
<p class="note"><b>Note:</b>You may delete labels you have created but you cannot delete the default labels.</p>
<h2>Formatting captions</h2>
<p>As soon as you add a caption, a new style for captions is automatically added to the styles section. In order to change the style for all captions throughout the document, you should follow these steps:</p>
<ul>
<li>select the text a new <b>Caption</b> style will be copied from;</li>
<li>search for the <b>Caption</b> style (highlighted in blue by default) in the styles gallery which you may find on <b>Home</b> tab of the top toolbar;</li>
<li>right click on it and choose the <b>Update from selection</b> option.</li>
</ul>
<p><img alt="Content Control settings window" src="../images/updatefromseleciton.png" /></p>
<h2>Grouping captions up</h2>
<p>If you want to be able to move the object and the caption as one unit, you need <a href="../UsageInstructions/AlignArrangeObjects.htm" onclick="onhyperlinkclick(this)">to group</a> the object and the caption together</p>
<ul>
<li>select the object;</li>
<li>select one of the <b>Wrapping styles</b> using the right sidebar;</li>
<li>add the caption as it is mentioned above;</li>
<li>hold down Shift and select the items you want to group up;</li>
<li><b>right click</b> on either item and choose <b>Arrange</b> > <b>Group</b>.</li>
</ul>
<p><img alt="Content Control settings window" src="../images/Groupup.png" /></p>
<p>Now both items will move simultaneously if you drag them somewhere else in the document.</p>
<p>To unbind the objects click on <b>Arrange</b> > <b>Ungroup</b> respectively.</p>
</div>
</body>
</html>

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<title>Add watermark</title>
<meta charset="utf-8" />
<meta name="description" content="Text watermarks allow to indicate your document status (for example, confidential, draft etc.), image watermarks allow to add an image, for example your company logo." />
<link type="text/css" rel="stylesheet" href="../editor.css" />
<script type="text/javascript" src="../callback.js"></script>
<script type="text/javascript" src="../search/js/page-search.js"></script>
</head>
<body>
<div class="mainpart">
<div class="search-field">
<input id="search" class="searchBar" placeholder="Search" type="text" onkeypress="doSearch(event)">
</div>
<h1>Add watermark</h1>
<p>Watermark is a text or image placed below the main text layer. Text watermarks allow to indicate your document status (for example, confidential, draft etc.), image watermarks allow to add an image, for example your company logo.</p>
<p>To add a watermark within a document:</p>
<ol>
<li>Switch to the <b>Layout</b> tab of the top toolbar.</li>
<li>Click the <img alt="Watermark icon" src="../images/watermark.png" /> <b>Watermark</b> icon at the top toolbar and choose the <b>Custom Watermark</b> option from the menu. After that the <b>Watermark Settings</b> window will appear.</li>
<li>Select a watermark type you wish to insert:
<ul>
<li>Use the <b>Text watermark</b> option and adjust the available parameters:
<p><img alt="Watermark Settings window" src="../images/watermark_settings.png" /></p>
<ul>
<li><b>Language</b> - select one of the available languages from the list,</li>
<li><b>Text</b> - select one of the available text examples on the selected language. For English, the following watermark texts are available: <em>ASAP</em>, <em>CONFIDENTIAL</em>, <em>COPY</em>, <em>DO NOT COPY</em>, <em>DRAFT</em>, <em>ORIGINAL</em>, <em>PERSONAL</em>, <em>SAMPLE</em>, <em>TOP SECRET</em>, <em>URGENT</em>.</li>
<li><b>Font</b> - select the font name and size from the corresponding drop-down lists. Use the icons on the right to set the font color or apply one of the font decoration styles: <em>Bold</em>, <em>Italic</em>, <em>Underline</em>, <em>Strikeout</em>,</li>
<li><b>Semitransparent</b> - check this box if you want to apply transparency,</li>
<li><b>Layout</b> - select the <b>Diagonal</b> or <b>Horizontal</b> option.</li>
</ul>
</li>
<li>Use the <b>Image watermark</b> option and adjust the available parameters:
<p><img alt="Watermark Settings window" src="../images/watermark_settings2.png" /></p>
<ul>
<li>Choose the image file source using one of the buttons: <b>From File</b> or <b>From URL</b> - the image will be displayed in the preview window on the right,</li>
<li><b>Scale</b> - select the necessary scale value from the available ones: <em>Auto</em>, <em>500%</em>, <em>200%</em>, <em>150%</em>, <em>100%</em>, <em>50%</em>.</li>
</ul>
</li>
</ul>
</li>
<li>Click the <b>OK</b> button.</li>
</ol>
<p>To edit the added watermark, open the <b>Watermark Settings</b> window as described above, change the necessary parameters and click <b>OK</b>.</p>
<p>To delete the added watermark click the <img alt="Watermark icon" src="../images/watermark.png" /> <b>Watermark</b> icon at the <b>Layout</b> tab of the top toolbar and choose the <b>Remove Watermark</b> option from the menu. It's also possible to use the <b>None</b> option in the <b>Watermark Settings</b> window.</p>
</div>
</body>
</html>

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<title>Insert symbols and characters</title>
<meta charset="utf-8" />
<meta name="description" content="Insert symbols and characters" />
<link type="text/css" rel="stylesheet" href="../editor.css" />
<script type="text/javascript" src="../callback.js"></script>
<script type="text/javascript" src="../search/js/page-search.js"></script>
</head>
<body>
<div class="mainpart">
<div class="search-field">
<input id="search" class="searchBar" placeholder="Search" type="text" onkeypress="doSearch(event)">
</div>
<h1>Insert symbols and characters</h1>
<p>During working process you may need to insert a symbol which is not on your keyboard. To insert such symbols into your document, use the <img alt="Symbol table icon" src="../images/vector.png" /><b>Insert symbol</b> option and follow these simple steps:</p>
<ul>
<li>place the cursor at the location where a special symbol has to be inserted,</li>
<li>switch to the <b>Insert</b> tab of the top toolbar,</li>
<li>
click the <img alt="Symbol table icon" src="../images/vector.png" /><b>Symbol</b>,
<p><img alt="Insert symbol sidebar " src="../images/insert_symbol_window.png" /></p>
</li>
<li>The <b>Symbol</b> dialog box appears from which you can select the appropriate symbol,</li>
<li>
<p>use the <b>Range</b> section to quickly find the nesessary symbol. All symbols are divided into specific groups, for example, select 'Currency Symbols' if you want to insert a currency character.</p>
<p>If this character is not in the set, select a different font. Many of them also have characters other than the standard set.</p>
<p>Or, enter the Unicode hex value of the symbol you want into the <b>Unicode hex value field</b>. This code can be found in the <b>Character map</b>.</p>
<p>Previously used symbols are also displayed in the <b>Recently used symbols</b> field,</p>
</li>
<li>click <b>Insert</b>. The selected character will be added to the document.</li>
</ul>
<h2>Insert ASCII symbols</h2>
<p>ASCII table is also used to add characters.</p>
<p>To do this, hold down ALT key and use the numeric keypad to enter the character code.</p>
<p class="note"><b>Note</b>: be sure to use the numeric keypad, not the numbers on the main keyboard. To enable the numeric keypad, press the Num Lock key.</p>
<p>For example, to add a paragraph character (§), press and hold down ALT while typing 789, and then release ALT key.</p>
<h2>Insert symbols using Unicode table</h2>
<p>Additional charachters and symbols might also be found via Windows symbol table. To open this table, do one of the following:</p>
<ul>
<li>in the Search field write 'Character table' and open it,</li>
<li>
simultaneously presss Win + R, and then in the following window type <code>charmap.exe</code> and click OK.
<p><img alt="Insert symbol windpow" src="../images/insert_symbols_windows.png" /></p>
</li>
</ul>
<p>In the opened <b>Character Map</b>, select one of the <b>Character sets</b>, <b>Groups</b> and <b>Fonts</b>. Next, click on the nesessary characters, copy them to clipboard and paste in the right place of the document.</p>
</div>
</body>
</html>

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Set up paragraph outline level</title>
<meta charset="utf-8" />
<meta name="description" content="Set up paragraph outline level" />
<link type="text/css" rel="stylesheet" href="../editor.css" />
<script type="text/javascript" src="../callback.js"></script>
<script type="text/javascript" src="../search/js/page-search.js"></script>
</head>
<body>
<div class="mainpart">
<div class="search-field">
<input id="search" class="searchBar" placeholder="Search" type="text" onkeypress="doSearch(event)">
</div>
<h1>Set up paragraph outline level</h1>
<p>Outline level means the paragraph level in the document structure. The following levels are available: <em>Basic Text</em>, <em>Level 1</em> - <em>Level 9</em>. Outline level can be specified in different ways, for example, by using <a href="../UsageInstructions/FormattingPresets.htm" onclick="onhyperlinkclick(this)">heading styles</a>: once you assign a heading style (<em>Heading 1</em> - <em>Heading 9</em>) to a paragraph, it acquires a corresponding outline level. If you assign a level to a paragraph using the paragraph advanced settings, the paragraph acquires the structure level only while its style remains unchanged. The outline level can also be changed at the <a href="../UsageInstructions/CreateTableOfContents.htm#navigation" onclick="onhyperlinkclick(this)"><b>Navigation</b></a> panel on the left using the contextual menu options.</p>
<p>To change a paragraph outline level using the paragraph advanced settings,</p>
<ol>
<li>right-click the text and choose the <b>Paragraph Advanced Settings</b> option from the contextual menu or use the <b>Show advanced settings</b> option at the right sidebar,</li>
<li>open the <b>Paragraph - Advanced Settings</b> window, switch to the <b>Indents &amp; Spacing</b> tab,</li>
<li>select the necessary outline level from the <b>Outline level</b> list.</li>
<li>click the <b>OK</b> button to apply the changes.</li>
</ol>
<p><img alt="Paragraph Advanced Settings - Indents &amp; Spacing" src="../images/paradvsettings_indents.png" /></p>
</div>
</body>
</html>

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html>
<head>
<title>Сравнение документов</title>
<meta charset="utf-8" />
<meta name="description" content="Инструкции по сравнению и объединению двух документов" />
<link type="text/css" rel="stylesheet" href="../editor.css" />
<script type="text/javascript" src="../callback.js"></script>
<script type="text/javascript" src="../search/js/page-search.js"></script>
</head>
<body>
<div class="mainpart">
<div class="search-field">
<input id="search" class="searchBar" placeholder="Search" type="text" onkeypress="doSearch(event)">
</div>
<h1>Сравнение документов</h1>
<p class="note"><b>Примечание</b>: эта возможность доступна только в <b>платной</b> <em>онлайн-версии</em>, начиная с версии <b>5.5</b> <b>Сервера документов</b>.</p>
<p>Если вам требуется сравнить и объединить два документа, вы можете использовать функцию <b>сравнения</b> документов. Она позволяет отобразить различия между двумя документами и объединить документы путем принятия изменений - каждого в отдельности или всех сразу.</p>
<p>После сравнения и объединения двух документов результат будет сохранен на портале как новая версия исходного файла<!-- (в <em>онлайн-версии</em> редакторов)-->. <!--В десктопной версии при нажатии на кнопку <b>Сохранить</b> появится диалоговое окно, в котором будет предложено сохранить новый файл.--></p>
<p>Если объединять сравниваемые документы не требуется, вы можете отклонить все изменения, чтобы исходный документ остался неизмененным.</p>
<h3 id="choosedocument">Выбор документа для сравнения</h3>
<p>Чтобы сравнить два документа, откройте исходный документ, который требуется сравнить, и выберите второй документ для сравнения:</p>
<ol>
<li>перейдите на вкладку <b>Совместная работа</b> на верхней панели инструментов и нажмите на кнопку <img alt="Кнопка Сравнить" src="../images/comparebutton.png" /> <b>Сравнить</b>,</li>
<li>
выберите одну из следующих опций для загрузки документа:
<ul>
<li>при выборе опции <b>Документ из файла</b> откроется стандартное диалоговое окно для выбора файлов. Выберите нужный файл в формате <em>.docx</em> на жестком диске компьютера и нажмите кнопку <b>Открыть</b>.</li>
<li>
при выборе опции <b>Документ с URL-адреса</b> откроется окно, в котором вы можете ввести ссылку на файл, сохраненный в стороннем веб-хранилище (например, Nextcloud), если у вас есть соответствующие права доступа. Ссылка должна быть <b>прямой ссылкой на скачивание файла</b>. Когда ссылка будет указана, нажмите кнопку <b>OK</b>.
<p class="note"><b>Примечание</b>: Прямая ссылка позволяет напрямую скачать файл, не открывая его в браузере. Например, для получения прямой ссылки в Nextcloud найдите нужный документ в списке файлов, выберите в меню файла пункт <b>Подробно</b>. На панели с подробными сведениями о файле нажмите на значок <b>Копировать прямую ссылку (работает только для пользователей с правами доступа к этому файлу или каталогу)</b> справа от имени файла. Чтобы узнать, как получить прямую ссылку на скачивание файла в другом стороннем веб-хранилище, обратитесь к документации по соответствующему стороннему сервису.</p>
</li>
<li class="onlineDocumentFeatures"> при выборе опции <b>Документ из хранилища</b> <!--(доступно только в <em>онлайн-версии</em>)--> откроется окно <b>Выбрать источник данных</b>. В нем отображается список всех документов в формате <em>.docx</em>, сохраненных на портале, к которым у вас есть соответствующие права доступа. Для перехода по разделам модуля <b>Документы</b> используйте меню в левой части окна. Выберите нужный документ <em>.docx</em> и нажмите кнопку <b>OK</b>.</li>
</ul>
</li>
</ol>
<p>После выбора второго документа для сравнения запускается процесс сравнения и документ приобретает вид <b>рецензируемого</b>. Все изменения выделяются цветом, и вы можете просматривать изменения, переходить от одного к другому, принимать или отклонять их по отдельности или все сразу. Также можно изменить режим отображения и посмотреть, как выглядит документ до сравнения, в процессе сравнения или как он будет выглядеть после сравнения, если принять все изменения.</p>
<h3 id="displaymode">Выбор режима отображения изменений</h3>
<p>Нажмите кнопку <img alt="Кнопка Отображение" src="../images/review_displaymode.png" /> <b>Отображение</b> на верхней панели инструментов и выберите из списка один из доступных режимов:</p>
<ul>
<li>
<b>Изменения</b> - этот режим выбран по умолчанию. Он используется, чтобы отобразить документ <b>в процессе сравнения</b>. Этот режим позволяет и просматривать изменения, и редактировать документ.
<p><img alt="Сравнение документов - Изменения" src="../images/compare_markup.png" /></p>
</li>
<li>
<b>Измененный документ</b> - этот режим используется, чтобы отобразить документ <b>после сравнения</b>, как если бы все изменения были приняты. Эта опция не позволяет в действительности принять все изменения, а только дает возможность увидеть, как будет выглядеть документ после того, как вы примете все изменения. В этом режиме документ нельзя редактировать.
<p><img alt="Сравнение документов - Измененный документ" src="../images/compare_final.png" /></p>
</li>
<li>
<b>Исходный документ</b> - этот режим используется, чтобы отобразить документ <b>до сравнения</b>, как если бы все изменения были отклонены. Эта опция не позволяет в действительности отклонить все изменения, а только дает возможность просмотреть документ без изменений. В этом режиме документ нельзя редактировать.
<p><img alt="Сравнение документов - Исходный документ" src="../images/compare_original.png" /></p>
</li>
</ul>
<h3 id="managechanges">Принятие и отклонение изменений</h3>
<p>Используйте кнопки <img alt="Кнопка К предыдущему изменению" src="../images/review_previous.png" /> <b>К предыдущему</b> и <img alt="Кнопка К следующему изменению" src="../images/review_next.png" /> <b>К следующему</b> на верхней панели инструментов для навигации по изменениям.</p>
<p>Чтобы принять выделенное в данный момент изменение, можно сделать следующее:</p>
<ul>
<li>нажмите кнопку <img alt="Кнопка Принять" src="../images/review_accepttoptoolbar.png" /> <b>Принять</b> на верхней панели инструментов или</li>
<li>нажмите направленную вниз стрелку под кнопкой <b>Принять</b> и выберите опцию <b>Принять текущее изменение</b> (в этом случае изменение будет принято, и вы перейдете к следующему изменению) или</li>
<li>нажмите кнопку <b>Принять</b> <img alt="Кнопка Принять" src="../images/review_accept.png" /> во всплывающем оповещении об изменении.</li>
</ul>
<p>Чтобы быстро принять все изменения, нажмите направленную вниз стрелку под кнопкой <img alt="Кнопка Принять" src="../images/review_accepttoptoolbar.png" /> <b>Принять</b> и выберите опцию <b>Принять все изменения</b>.</p>
<p>Чтобы отклонить текущее изменение, можно сделать следующее:</p>
<ul>
<li>нажмите кнопку <img alt="Кнопка Отклонить" src="../images/review_rejecttoptoolbar.png" /> <b>Отклонить</b> на верхней панели инструментов или</li>
<li>нажмите направленную вниз стрелку под кнопкой <b>Отклонить</b> и выберите опцию <b>Отклонить текущее изменение</b> (в этом случае изменение будет отклонено, и вы перейдете к следующему доступному изменению) или</li>
<li>нажмите кнопку <b>Отклонить</b> <img alt="Кнопка Отклонить" src="../images/review_reject.png" /> во всплывающем оповещении об изменении.</li>
</ul>
<p>Чтобы быстро отклонить все изменения, нажмите направленную вниз стрелку под кнопкой <img alt="Кнопка Отклонить" src="../images/review_rejecttoptoolbar.png" /> <b>Отклонить</b> и выберите опцию <b>Отклонить все изменения</b>.</p>
<h3 id="comparisonnotes">Дополнительные сведения о функции сравнения</h3>
<h5>Принцип сравнения</h5>
<p>Сравнение документов ведется <b>по словам</b>. Если слово содержит изменение хотя бы на один символ (например, если символ был удален или заменен), в результате отличие будет отображено как изменение всего слова целиком, а не символа.</p>
<p>Приведенное ниже изображение иллюстрирует случай, когда исходный файл содержит слово 'Символы', а документ для сравнения содержит слово 'Символ'.</p>
<p><img alt="Сравнение документов - принцип" src="../images/compare_method.png" /></p>
<h5>Авторство документа</h5>
<p>При запуске процесса сравнения документов второй документ для сравнения загружается и сравнивается с текущим.</p>
<ul>
<li>Если загруженный документ содержит данные, которые отсутствуют в исходном документе, они будут помечены как добавленные рецензентом.</li>
<li>Если исходный документ содержит данные, которые отсутствуют в загруженном документе, они будут помечены как удаленные рецензентом.</li>
</ul>
<p>Если авторы исходного и загруженного документа совпадают, то рецензентом будет тот же пользователь. Его имя отображается во всплывающем окне с изменением.</p>
<p>Если авторы двух файлов - разные пользователи, то автор второго файла, загруженного для сравнения, будет автором добавленных или удаленных изменений.</p>
<h5>Наличие рецензирования в сравниваемом документе</h5>
<p>Если исходный документ содержит изменения, внесенные в режиме рецензирования, то в результате сравнения документа они будут приняты. При выборе второго файла для сравнения вы увидите соответствующее предупреждение.</p>
<p>В этом случае при выборе режима отображения <b>Исходный документ</b> документ не будет содержать изменений.</p>
</div>
</body>
</html>

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<title>Добавление названия</title>
<meta charset="utf-8" />
<meta name="description" content=">Название - это пронумерованная метка, которую можно применять к объектам, таким как уравнения, таблицы, рисунки и изображения" />
<link type="text/css" rel="stylesheet" href="../editor.css" />
<script type="text/javascript" src="../callback.js"></script>
<script type="text/javascript" src="../search/js/page-search.js"></script>
</head>
<body>
<div class="mainpart">
<div class="search-field">
<input id="search" class="searchBar" placeholder="Search" type="text" onkeypress="doSearch(event)">
</div>
<h1>Добавление названия</h1>
<p><b>Название</b> - это пронумерованная метка, которую можно применять к объектам, таким как уравнения, таблицы, фигуры и изображения.</p>
<p>Данная функция позволяет легко ссылаться на какой-либо объект в вашем тексте, так как на на нем есть легко узнаваемая подпись.</p>
<p>Чтобы добавить <b>Название</b> к объекту, выполните следующие действия:</p>
<ul>
<li>выберите объект, к которому нужно добавить название;</li>
<li>перейдите на вкладку <b>Ссылки</b> верхней панели инструментов;</li>
<li>
щелкните на иконку <img alt="Rich text content control" src="../images/caption_icon.png" /> <b>Название</b> на верхней панели инструментов или щелкнув правой кнопкой по объекту, выберите функцию <b>Вставить название</b>. Откроется диалоговое окно <b>Вставить название</b>
<ul>
<li>выберите подпись для названия, щелкнув на раскрывающийся список и выбрав один из предложенных вариантов, или</li>
<li>создайте новую подпись, нажав кнопку <b>Добавить</b>. В диалоговом окне введите новую подпись в текстовое поле. Затем нажмите кнопку <b>ОК</b>, чтобы добавить новую <b>Подпись</b> в список подписей;</li>
</ul>
<li>в выпадающем списке <b>Вставить</b> выберите <b>Перед</b>, чтобы разместить название над объектом, или <b>После</b>, чтобы разместить его под объектом;</li>
<li>установите флажок напротив <b>Исключить подпись из названия</b>, чтобы оставить только номер для этой конкретной подписи в соответствии с порядковым номером;</li>
<li>установите флажок напротив опции <b>Включить номер главы</b>, чтобы добавить выбранный тип нумерации объектов к названию;</li>
<li>настройте нумерацию подписи, добавив к ней определенный стиль и разделитель;</li>
<li>чтобы применить название, нажмите кнопку <b>ОК</b>.</li>
</ul>
<p><img alt="Content Control settings window" src="../images/insertcaptionbox.png" /></p>
<h2>Удаление подписи</h2>
<p>Чтобы удалить созданную вами подпись, выберите подпись из списка, затем нажмите кнопку <b>Удалить</b>. Данная подпись будет немедленно удалена.</p>
<p class="note"><b>Примечание:</b> вы не можете удалить созданные по умолчанию подписи.</p>
<h2>Форматирование названий</h2>
<p>Как только вы добавляете название, в раздел стилей автоматически добавляется новый стиль для подписей. Чтобы изменить стиль для всех названий в документе, выполните следующие действия:</p>
<ul>
<li>выделите текст из которого будет скопирован новый стиль для названий;</li>
<li>найдите стиль <b>Название</b> (по умолчанию выделен синим цветом) в галерее стилей, которую вы можете найти на вкладке <b>Главная</b> верхней панели инструментов;</li>
<li>щелкните по нему <b>правой кнопкой</b> мыши и выберите пункт <b>Обновить из выделенного фрагмента</b>.</li>
</ul>
<p><img alt="Content Control settings window" src="../images/updatefromseleciton.png" /></p>
<h2>Объединение названий в группы</h2>
<p>Если вы хотите иметь возможность перемещать объект и подпись как одно целое, вам нужно <a href="../UsageInstructions/AlignArrangeObjects.htm" onclick="onhyperlinkclick(this)">сгруппировать</a> объект и подпись вместе. Для этого</p>
<ul>
<li>выберите объект;</li>
<li>выберите один из <b>Стилей обтекания</b>, используя правую боковую панель;</li>
<li>добавьте подпись, как указано выше;</li>
<li>зажмите Shift и выберите элементы, которые вы хотите сгруппировать;</li>
<li>щелкните <b>правой кнопкой</b> мыши любой элемент и выберите <b>Порядок</b> > <b>Сгруппировать</b>.</li>
</ul>
<p><img alt="Content Control settings window" src="../images/Groupup.png" /></p>
<p>Теперь если вы захотите перетащить объекты в другое место документа, они будут перемещаться одновременно.</p>
<p>Чтобы отменить привязку объектов, в контекстном меню выберите пункт <b>Порядок</b>, а затем <b>Разгруппировать</b>.</p>
</div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save