Merge branch 'develop' into feature/de-embed-fill-form

This commit is contained in:
Julia Radzhabova 2021-05-17 19:21:12 +03:00
commit 60c43641a3
1016 changed files with 75212 additions and 238727 deletions

View file

@ -51,6 +51,11 @@
editCommentAuthorOnly: <can edit your own comments only> // default = false
deleteCommentAuthorOnly: <can delete your own comments only> // default = false,
reviewGroups: ["Group1", ""] // current user can accept/reject review changes made by users from Group1 and users without a group. [] - use groups, but can't change any group's changes
commentGroups: { // {} - use groups, but can't view/edit/delete any group's comments
view: ["Group1", ""] // current user can view comments made by users from Group1 and users without a group.
edit: ["Group1", ""] // current user can edit comments made by users from Group1 and users without a group.
remove: ["Group1", ""] // current user can remove comments made by users from Group1 and users without a group.
}
}
},
editorConfig: {
@ -129,7 +134,7 @@
anonymous: { // set name for anonymous user
request: bool (default: true), // enable set name
label: string (default: "Guest") // postfix for user name
}
},
chat: true,
comments: true,
zoom: 100,
@ -156,8 +161,13 @@
plugins: true // can run plugins in document
macrosMode: 'warn' // warn about automatic macros, 'enable', 'disable', 'warn',
trackChanges: undefined // true/false - open editor with track changes mode on/off,
hideRulers: false, // hide or show rulers on first loading (presentation or document editor)
hideRulers: false // hide or show rulers on first loading (presentation or document editor)
hideNotes: false // hide or show notes panel on first loading (presentation editor)
},
coEditing: {
mode: 'fast', // <coauthoring mode>, 'fast' or 'strict'. if 'fast' and 'customization.autosave'=false -> set 'customization.autosave'=true
change: true, // can change co-authoring mode
},
plugins: {
autostart: ['asc.{FFE1F462-1EA2-4391-990D-4CC84940B754}'],
pluginsData: [
@ -166,6 +176,9 @@
"speech/config.json",
"clipart/config.json",
]
},
wopi: { // only for wopi
FileNameMaxLength: 250 // max filename length for rename, 250 by default
}
},
events: {
@ -657,6 +670,13 @@
});
};
var _requestClose = function(data) {
_sendCommand({
command: 'requestClose',
data: data
});
};
var _processMouse = function(evt) {
var r = iframe.getBoundingClientRect();
var data = {
@ -672,6 +692,22 @@
});
};
var _grabFocus = function(data) {
setTimeout(function(){
_sendCommand({
command: 'grabFocus',
data: data
});
}, 10);
};
var _blurFocus = function(data) {
_sendCommand({
command: 'blurFocus',
data: data
});
};
var _serviceCommand = function(command, data) {
_sendCommand({
command: 'internalCommand',
@ -703,7 +739,10 @@
insertImage : _insertImage,
setMailMergeRecipients: _setMailMergeRecipients,
setRevisedFile : _setRevisedFile,
setFavorite : _setFavorite
setFavorite : _setFavorite,
requestClose : _requestClose,
grabFocus : _grabFocus,
blurFocus : _blurFocus
}
};

View file

@ -0,0 +1,355 @@
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<!--
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
-->
<title>ONLYOFFICE</title>
<style type="text/css">
html {
height: 100%;
width: 100%;
}
body {
background: #fff;
color: #333;
font-family: Arial, Tahoma,sans-serif;
font-size: 12px;
font-weight: normal;
height: 100%;
margin: 0;
overflow-y: hidden;
padding: 0;
text-decoration: none;
}
.form {
height: 100%;
}
div {
margin: 0;
padding: 0;
}
.app-error-panel {
position: absolute;
width: 100%;
height: 100%;
top: 0;
background-color: #f4f4f4;
z-index: 10;
}
.message-block {
display: inline-block;
vertical-align: middle;
width: 100%;
}
.message-inner {
width: 550px;
margin: auto;
padding: 30px;
background-color: #e3e3e3;
text-align: center;
}
.title {
font-size: 24px;
margin: 0 0 14px;
}
.text {
font-size: 16px;
}
</style>
</head>
<body>
<div class="form">
<div id="iframeEditor">
</div>
</div>
<script type="text/javascript" src="../../web-apps/apps/api/documents/api.js"></script>
<script type="text/javascript" language="javascript">
var docEditor;
var postMessageOrigin;
var lang = "en-US";
var startTime;
var documentChanged;
var sendNotificationTimer;
var sessionId;
var fileInfo;
var innerAlert = function (message) {
if (console && console.log)
console.log(message);
};
var commandMap = {
'Blur_Focus': function (data) {
innerAlert('Blur_Focus');
docEditor.blurFocus();
},
'Grab_Focus': function (data) {
innerAlert('Grab_Focus');
docEditor.grabFocus();
},
'Host_PostmessageReady': function (data) {
innerAlert('Host_PostmessageReady');
}
};
var _postMessage = function(msgId, msgData) {
if (window.parent && window.JSON) {
msgData = msgData || {};
msgData["ui-language"] = lang;
msgData["wdUserSession"] = sessionId;
var msg = {
"MessageId": msgId,
"SendTime": Date.now(),
"Values": msgData
};
window.parent.postMessage(window.JSON.stringify(msg), postMessageOrigin);
}
};
var _onMessage = function(msg) {
if (msg.origin !== postMessageOrigin) return;
var data = msg.data;
if (Object.prototype.toString.apply(data) !== '[object String]' || !window.JSON) {
return;
}
var cmd, handler;
try {
cmd = window.JSON.parse(data)
} catch(e) {
cmd = '';
}
if (cmd) {
handler = commandMap[cmd.MessageId];
if (handler) {
handler.call(this, cmd);
}
}
};
var fn = function(e) { _onMessage(e); };
if (window.attachEvent) {
window.attachEvent('onmessage', fn);
} else {
window.addEventListener('message', fn, false);
}
var onAppReady = function () {
_postMessage('App_LoadingStatus', {
"DocumentLoadedTime": Date.now() - startTime
});
innerAlert("App ready");
};
var sendEditNotification = function () {
documentChanged && _postMessage('Edit_Notification', {});
documentChanged = false;
};
var onDocumentStateChange = function (event) {
if (event.data) {
documentChanged = true;
if (sendNotificationTimer===undefined) {
sendNotificationTimer = setInterval(sendEditNotification, 30000);
sendEditNotification();
}
}
};
var onRequestRename = function (event) {
if (event.data) {
_postMessage('File_Rename', {
"NewName": event.data
});
}
};
var onRequestClose = function () {
if (fileInfo.ClosePostMessage)
_postMessage('UI_Close', {});
else if (fileInfo.CloseUrl)
window.parent.location.href = fileInfo.CloseUrl;
};
var onRequestEditRights = function () {
if (fileInfo.EditModePostMessage)
_postMessage('UI_Edit', {});
else if (fileInfo.HostEditUrl)
window.open(fileInfo.HostEditUrl, "_blank");
};
var onRequestSharingSettings = function (event) {
if (fileInfo.FileSharingPostMessage)
_postMessage('UI_Sharing', {});
else if (fileInfo.FileSharingUrl)
window.open(fileInfo.FileSharingUrl, "_blank");
};
var onRequestHistory = function (event) {
if (fileInfo.FileVersionPostMessage)
_postMessage('UI_FileVersions', {});
else if (fileInfo.FileVersionUrl)
window.open(fileInfo.FileVersionUrl, "_blank");
};
var onError = function (event) {
if (event)
innerAlert(event.data);
};
var connectEditor = function () {
fileInfo = <%- JSON.stringify(fileInfo) %>;
var key = "<%- key %>";
var userAuth = <%- JSON.stringify(userAuth) %>;
var token = "<%- token %>";
var queryParams = <%- JSON.stringify(queryParams) %>;
if (!fileInfo.BaseFileName) {
showError();
return;
}
var fileType = fileInfo.BaseFileName ? fileInfo.BaseFileName.substr(fileInfo.BaseFileName.lastIndexOf('.') + 1) : "";
var config = {
"width": "100%",
"height": "100%",
"type": "desktop",
"documentType": queryParams.documenttype,
"token": token,
"document": {
"title": fileInfo.BreadcrumbDocName || fileInfo.BaseFileName,
"url": userAuth.wopiSrc,
"fileType": fileInfo.FileExtension ? fileInfo.FileExtension.substr(1) : fileType,
"key": key,
"info": {
"folder": fileInfo.BreadcrumbFolderName
},
"permissions": {
"edit": !fileInfo.ReadOnly && fileInfo.UserCanWrite,
"review": (fileInfo.SupportsReviewing===false) ? false : (fileInfo.UserCanReview===false ? false : fileInfo.UserCanReview),
"copy": fileInfo.CopyPasteRestrictions!=="CurrentDocumentOnly" && fileInfo.CopyPasteRestrictions!=="BlockAll",
"print": !fileInfo.DisablePrint && !fileInfo.HidePrintOption
}
},
"editorConfig": {
"mode": queryParams.mode,
"lang": queryParams.lang || queryParams.ui || "en-US",
"region": queryParams.rs,
"callbackUrl": JSON.stringify(userAuth),
"user": {
"id": fileInfo.UserId,
"name": fileInfo.IsAnonymousUser ? "" : fileInfo.UserFriendlyName
},
"customization": {
"about": true,
"goback": {
"url": fileInfo.BreadcrumbFolderUrl
},
"customer": {
"name": fileInfo.BreadcrumbBrandName,
"www": fileInfo.BreadcrumbBrandUrl
},
"chat": queryParams.dchat!=="1",
"uiTheme": queryParams.thm==="1" ? "theme-light" : (queryParams.thm==="2" ? "theme-dark" : undefined)
},
"coEditing": {
"mode": "fast",
"change": false
},
"wopi": {
"FileNameMaxLength": fileInfo.FileNameMaxLength && fileInfo.FileNameMaxLength>0 ? fileInfo.FileNameMaxLength : 250
}
},
"events": {
"onAppReady": onAppReady,
"onDocumentStateChange": fileInfo.EditNotificationPostMessage ? onDocumentStateChange : undefined,
'onRequestEditRights': fileInfo.EditModePostMessage || fileInfo.HostEditUrl ? onRequestEditRights : undefined,
"onError": onError,
"onRequestClose": fileInfo.ClosePostMessage || fileInfo.CloseUrl ? onRequestClose : undefined,
"onRequestRename": fileInfo.SupportsRename && fileInfo.UserCanRename ? onRequestRename : undefined,
"onRequestSharingSettings": fileInfo.FileSharingPostMessage || fileInfo.FileSharingUrl ? onRequestSharingSettings : undefined,
"onRequestHistory": fileInfo.FileVersionUrl || fileInfo.FileVersionPostMessage ? onRequestHistory : undefined
}
};
postMessageOrigin = fileInfo.PostMessageOrigin;
if (postMessageOrigin && (typeof postMessageOrigin === 'string') && postMessageOrigin.charAt(postMessageOrigin.length-1)=='/')
postMessageOrigin = postMessageOrigin.substring(0, postMessageOrigin.length - 1);
lang = config.editorConfig.lang;
sessionId = userAuth.userSessionId;
startTime = Date.now();
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
fixSize();
};
var fixSize = function () {
var wrapEl = document.getElementsByClassName("form");
if (wrapEl.length) {
wrapEl[0].style.height = screen.availHeight + "px";
window.scrollTo(0, -1);
wrapEl[0].style.height = window.innerHeight + "px";
}
};
var showError = function(msg, title) {
msg = msg || 'Sorry, editor could not be loaded. Please contact your administrator.';
var newDiv = document.createElement("div");
newDiv.className = "app-error-panel";
newDiv.innerHTML = '<div class="message-block">' +
'<div class="message-inner">' +
(title ? '<div class="title">' + title + '</div>' : '') +
'<div class="text">' + msg + '</div>' +
'</div>' +
'</div>';
document.body.appendChild(newDiv);
};
if (window.addEventListener) {
window.addEventListener("load", connectEditor);
window.addEventListener("resize", fixSize);
} else if (window.attachEvent) {
window.attachEvent("onload", connectEditor);
window.attachEvent("onresize", fixSize);
}
</script>
</body>
</html>

View file

@ -30,8 +30,8 @@
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
if (Common === undefined)
var Common = {};
if (window.Common === undefined)
window.Common = {};
Common.component = Common.component || {};

View file

@ -31,8 +31,8 @@
*
*/
if (Common === undefined) {
var Common = {};
if (window.Common === undefined) {
window.Common = {};
}
Common.Gateway = new(function() {
@ -126,6 +126,18 @@ if (Common === undefined) {
'setFavorite': function(data) {
$me.trigger('setfavorite', data);
},
'requestClose': function(data) {
$me.trigger('requestclose', data);
},
'blurFocus': function(data) {
$me.trigger('blurfocus', data);
},
'grabFocus': function(data) {
$me.trigger('grabfocus', data);
}
};
@ -330,6 +342,10 @@ if (Common === undefined) {
_postMessage({event:'onRequestCreateNew'});
},
pluginsReady: function() {
_postMessage({ event: 'onPluginsReady' });
},
on: function(event, handler){
var localHandler = function(event, data){
handler.call(me, data)

View file

@ -95,7 +95,7 @@ define([
value : 'unchecked',
template : _.template('<label class="checkbox-indeterminate"><input id="<%= id %>" type="checkbox" class="checkbox__native">' +
'<label for="<%= id %>" class="checkbox__shape"></label><span><%= labelText %></span></label>'),
'<label for="<%= id %>" class="checkbox__shape"></label><span></span></label>'),
initialize : function(options) {
Common.UI.BaseView.prototype.initialize.call(this, options);
@ -108,7 +108,6 @@ define([
var me = this;
if (!me.rendered) {
var elem = this.template({
labelText: this.options.labelText,
id: Common.UI.getId('chb-')
});
if (parentEl) {
@ -120,7 +119,9 @@ define([
this.$chk = me.$el.find('input[type=checkbox]');
this.$label = me.$el.find('label.checkbox-indeterminate');
this.$span = me.$label.find('span');
this.$chk.on('click', this.onItemCheck.bind(this));
this.$label.on('keydown', this.onKeyDown.bind(this));
this.rendered = true;
}
@ -131,6 +132,8 @@ define([
if (this.options.value!==undefined)
this.setValue(this.options.value, true);
this.setCaption(this.options.labelText);
// handle events
return this;
},
@ -143,6 +146,10 @@ define([
if (disabled !== this.disabled) {
this.$label.toggleClass('disabled', disabled);
(disabled) ? this.$chk.attr({disabled: disabled}) : this.$chk.removeAttr('disabled');
if (this.tabindex!==undefined) {
disabled && (this.tabindex = this.$label.attr('tabindex'));
this.$label.attr('tabindex', disabled ? "-1" : this.tabindex);
}
}
this.disabled = disabled;
@ -193,7 +200,28 @@ define([
},
setCaption: function(text) {
this.$label.find('span').text(text);
this.$span.text(text);
this.$span.css('visibility', text ? 'visible' : 'hidden');
},
onKeyDown: function(e) {
if (e.isDefaultPrevented())
return;
if (e.keyCode === Common.UI.Keys.SPACE)
this.onItemCheck(e);
},
focus: function() {
this.$label && this.$label.focus();
},
setTabIndex: function(tabindex) {
if (!this.rendered)
return;
this.tabindex = tabindex.toString();
!this.disabled && this.$label.attr('tabindex', this.tabindex);
}
});
});

View file

@ -279,7 +279,7 @@ define([
Common.UI.ComboBoxColor = Common.UI.ComboBox.extend(_.extend({
template: _.template([
'<div class="input-group combobox input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
'<div class="input-group combobox combo-color input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
'<div class="form-control" style="padding:2px 14px 2px 3px; <%= style %> display: block;">',
'<div style="display: inline-block;overflow: hidden;width: 100%;height: 100%;"></div>',
'</div>',
@ -292,7 +292,7 @@ define([
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
'<% } else { %>',
'<li id="<%= item.id %>" data-value="<%= item.value %>">',
'<a tabindex="-1" type="menuitem" style="padding: 5px;"><div style="height: 15px;background-color: #<%= item.value %>"></div></a>',
'<a tabindex="-1" type="menuitem" style="padding: 5px;"><div style="height: 15px;<%= item.styleStr %>"><%= scope.getDisplayValue(item) %></div></a>',
'</li>',
'<% } %>',
'<% }); %>',
@ -319,12 +319,13 @@ define([
updateFormControl: function(record) {
var formcontrol = $(this.el).find('.form-control > div');
formcontrol[0].innerHTML = record.get('displayValue');
if (record.get('value')!=-1) {
formcontrol[0].innerHTML = '';
formcontrol.css({'background': '#' + record.get('value'), 'margin-top': '0'});
formcontrol.css({'margin-top': '0'});
formcontrol.css(record.get('styleObj'));
} else {
formcontrol[0].innerHTML = record.get('displayValue');
formcontrol.css({'background': '', 'margin-top': '1px'});
formcontrol.css({'margin-top': '1px'});
formcontrol.css(record.get('styleObj'));
}
},
@ -339,8 +340,9 @@ define([
$('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
} else {
var formcontrol = $(this.el).find('.form-control > div');
formcontrol[0].innerHTML = '';
formcontrol.css('background', '');
formcontrol[0].innerHTML = value;
formcontrol.css('margin-top', '1px');
formcontrol.css({'color': '', 'text-align': '', 'background': '', 'border': ''});
}
},
@ -357,7 +359,7 @@ define([
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
'<% } else { %>',
'<li id="<%= item.id %>" data-value="<%= item.value %>">',
'<a tabindex="-1" type="menuitem" style="padding: 5px;"><div style="height: 15px;background-color: #<%= item.value %>"></div></a>',
'<a tabindex="-1" type="menuitem" style="padding: 5px;"><div style="height: 15px;<%= item.styleStr %>"><%= scope.getDisplayValue(item) %></div></a>',
'</li>',
'<% } %>',
'<% }); %>'
@ -382,4 +384,120 @@ define([
}, Common.UI.ComboBoxColor || {}));
Common.UI.ComboBoxIcons= Common.UI.ComboBox.extend(_.extend({
template: _.template([
'<div class="input-group combobox combo-color input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
'<div class="form-control" style="padding:2px 0 2px 3px; <%= style %> display: block;">',
'<div style="display: inline-block;overflow: hidden;width: 100%;height: 100%;"></div>',
'</div>',
'<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">',
'<span class="caret"></span>',
'</button>',
'<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
'<% _.each(items, function(item) { %>',
'<% if (item.value==-1) { %>',
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
'<% } else { %>',
'<li id="<%= item.id %>" data-value="<%= item.value %>">',
'<a tabindex="-1" type="menuitem" style="padding: 5px;">',
'<% _.each(item.data.iconSet, function(icon) { %>',
'<img src="<%= item.data.icons.at(icon-1).get(\'icon\') %>" style="width:16px;height:16px;margin-right: 5px;">',
'<% }) %>',
'</a>',
'</li>',
'<% } %>',
'<% }); %>',
'</ul>',
'</div>'
].join('')),
itemClicked: function (e) {
var el = $(e.currentTarget).parent();
this._selectedItem = this.store.findWhere({
id: el.attr('id')
});
if (this._selectedItem) {
$('.selected', $(this.el)).removeClass('selected');
el.addClass('selected');
this.updateFormControl(this._selectedItem);
this.trigger('selected', this, _.extend({}, this._selectedItem.toJSON()), e);
e.preventDefault();
}
},
updateFormControl: function(record) {
var formcontrol = $(this.el).find('.form-control > div');
if (record.get('value')!=-1) {
var str = '';
_.each(record.get('data').iconSet, function(icon) {
str += '<img src="' + record.get('data').icons.at(icon-1).get("icon") + '" style="width:16px;height:16px;margin-right: 5px;">';
});
formcontrol[0].innerHTML = str;
formcontrol.css({'margin-top': '0'});
} else {
formcontrol[0].innerHTML = record.get('displayValue');
formcontrol.css({'margin-top': '1px'});
}
},
setValue: function(value) {
var obj;
this._selectedItem = this.store.findWhere((obj={}, obj[this.valueField]=value, obj));
$('.selected', $(this.el)).removeClass('selected');
if (this._selectedItem) {
this.updateFormControl(this._selectedItem);
$('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
} else {
var formcontrol = $(this.el).find('.form-control > div');
formcontrol[0].innerHTML = value;
formcontrol.css({'margin-top': '1px'});
}
},
onResetItems: function() {
if (this.itemsTemplate) {
$(this.el).find('ul').html( $(this.itemsTemplate({
items: this.store.toJSON(),
scope: this
})));
} else {
$(this.el).find('ul').html(_.template([
'<% _.each(items, function(item) { %>',
'<% if (item.value==-1) { %>',
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
'<% } else { %>',
'<li id="<%= item.id %>" data-value="<%= item.value %>">',
'<a tabindex="-1" type="menuitem" style="padding: 5px;">',
'<% _.each(item.data.iconSet, function(icon) { %>',
'<img src="<%= item.data.icons.at(icon-1).get(\'icon\') %>" style="width:16px;height:16px;margin-right: 5px;">',
'<% }) %>',
'</a>',
'</li>',
'<% } %>',
'<% }); %>'
].join(''))({
items: this.store.toJSON(),
scope: this
}));
}
if (!_.isUndefined(this.scroller)) {
this.scroller.destroy();
delete this.scroller;
}
this.scroller = new Common.UI.Scroller(_.extend({
el: $('.dropdown-menu', this.cmpEl),
minScrollbarLength : 40,
includePadding : true,
wheelSpeed: 10,
alwaysVisibleY: this.scrollAlwaysVisible
}, this.options.scroller));
}
}, Common.UI.ComboBoxIcons || {}));
});

View file

@ -58,9 +58,26 @@ Common.UI.FocusManager = new(function() {
}
fields.forEach(function(field) {
if (field) {
var item = (field.cmp && typeof field.selector == 'string') ? field : {cmp: field, selector: '.form-control'};
var item = {};
if (field.cmp && typeof field.selector == 'string')
item = field;
else {
item.cmp = field;
if (field instanceof Common.UI.ListView)
item.selector = '.listview';
else if (field instanceof Common.UI.CheckBox)
item.selector = '.checkbox-indeterminate';
else if (field instanceof Common.UI.RadioBox)
item.selector = '.radiobox';
else if (field instanceof Common.UI.TreeView)
item.selector = '.treeview';
else if (field instanceof Common.UI.Button)
item.selector = 'button';
else
item.selector = '.form-control';
}
item.el = (item.cmp.$el || $(item.cmp.el || item.cmp)).find(item.selector).addBack().filter(item.selector);
item.el && item.el.attr && item.el.attr('tabindex', _tabindex.toString());
item.el && item.el.attr && (item.cmp.setTabIndex ? item.cmp.setTabIndex(_tabindex) : item.el.attr('tabindex', _tabindex.toString()));
arr.push(item);
}
});

View file

@ -54,11 +54,12 @@ define([
showLast: true,
simpleAddMode: false,
keyMoveDirection: 'vertical',
itemTemplate: _.template('<div id="<%= id %>" class="list-item" style=""><%= value %></div>')
itemTemplate: _.template('<div id="<%= id %>" class="list-item" style=""><%= value %></div>'),
cls: ''
},
template: _.template([
'<div class="listview inner"></div>'
'<div class="listview inner <%= cls %>"></div>'
].join('')),
onResetItems : function() {

View file

@ -55,7 +55,7 @@ define([
values: [0, 100],
colorValues: ['#000000', '#ffffff'],
currentThumb: 0,
thumbTemplate: '<div class="thumb img-commonctrl" style="">' +
thumbTemplate: '<div class="thumb" style="">' +
'<div class="thumb-top"><div class="thumb-top-inner"></div></div>' +
'<div class="thumb-bottom"><div class="thumb-bottom-inner"></div></div>' +
'</div>'

View file

@ -72,7 +72,7 @@ define([
rendered : false,
template : _.template('<label class="radiobox"><input type="radio" name="<%= name %>" id="<%= id %>" class="button__radiobox">' +
'<label for="<%= id %>" class="radiobox__shape"></label><span><%= labelText %></span></label>'),
'<label for="<%= id %>" class="radiobox__shape"></label><span></span></label>'),
initialize : function(options) {
Common.UI.BaseView.prototype.initialize.call(this, options);
@ -89,6 +89,8 @@ define([
if (this.options.checked!==undefined)
this.setValue(this.options.checked, true);
this.setCaption(this.options.labelText);
// handle events
this.$radio.on('click', _.bind(this.onItemCheck, this));
},
@ -103,6 +105,8 @@ define([
this.$radio = el.find('input[type=radio]');
this.$label = el.find('label.radiobox');
this.$span = this.$label.find('span');
this.$label.on('keydown', this.onKeyDown.bind(this));
this.rendered = true;
return this;
@ -116,6 +120,10 @@ define([
this.$label.toggleClass('disabled', disabled);
this.$radio.toggleClass('disabled', disabled);
(disabled) ? this.$radio.attr({disabled: disabled}) : this.$radio.removeAttr('disabled');
if (this.tabindex!==undefined) {
disabled && (this.tabindex = this.$label.attr('tabindex'));
this.$label.attr('tabindex', disabled ? "-1" : this.tabindex);
}
}
this.disabled = disabled;
@ -152,7 +160,28 @@ define([
},
setCaption: function(text) {
this.$label.find('span').text(text);
this.$span.text(text);
this.$span.css('visibility', text ? 'visible' : 'hidden');
},
onKeyDown: function(e) {
if (e.isDefaultPrevented())
return;
if (e.keyCode === Common.UI.Keys.SPACE)
this.onItemCheck(e);
},
focus: function() {
this.$label && this.$label.focus();
},
setTabIndex: function(tabindex) {
if (!this.rendered)
return;
this.tabindex = tabindex.toString();
!this.disabled && this.$label.attr('tabindex', this.tabindex);
}
});
});

View file

@ -473,7 +473,7 @@ define([
function autoSize(window) {
var text_cnt = window.getChild('.info-box');
var text = window.getChild('.info-box span');
var text = window.getChild('.info-box .text > span');
var footer = window.getChild('.footer');
var header = window.getChild('.header');
var body = window.getChild('.body');
@ -488,14 +488,14 @@ define([
options.width = options.maxwidth;
}
if (options.width=='auto') {
text_cnt.height(Math.max(text.height() + ((check.length>0) ? (check.height() + parseInt(check.css('margin-top'))) : 0), icon_height));
text_cnt.height(Math.max(text.height(), icon_height) + ((check.length>0) ? (check.height() + parseInt(check.css('margin-top'))) : 0));
body.height(parseInt(text_cnt.css('height')) + parseInt(footer.css('height')));
window.setSize(text.position().left + text.width() + parseInt(text_cnt.css('padding-right')),
parseInt(body.css('height')) + parseInt(header.css('height')));
} else {
text.css('white-space', 'normal');
window.setWidth(options.width);
text_cnt.height(Math.max(text.height() + ((check.length>0) ? (check.height() + parseInt(check.css('margin-top'))) : 0), icon_height));
text_cnt.height(Math.max(text.height(), icon_height) + ((check.length>0) ? (check.height() + parseInt(check.css('margin-top'))) : 0));
body.height(parseInt(text_cnt.css('height')) + parseInt(footer.css('height')));
window.setHeight(parseInt(body.css('height')) + parseInt(header.css('height')));
}
@ -769,6 +769,9 @@ define([
'-o-transform': 'scale(1)',
'opacity': '1'
});
setTimeout(function () {
me.fireEvent('animate:after', me);
}, 210);
}, 1);
setTimeout(function () {
@ -779,6 +782,9 @@ define([
this.$window.css({opacity: 1});
this.$window.addClass('notransform');
this.fireEvent('show', this);
setTimeout(function () {
me.fireEvent('animate:after', me);
}, 10);
}
Common.NotificationCenter.trigger('window:show', this);

View file

@ -128,7 +128,8 @@ define([
'comment:addDummyComment': _.bind(this.onAddDummyComment, this)
},
'Common.Views.ReviewChanges': {
'comment:removeComments': _.bind(this.onRemoveComments, this)
'comment:removeComments': _.bind(this.onRemoveComments, this),
'comment:resolveComments': _.bind(this.onResolveComments, this)
}
});
@ -217,7 +218,7 @@ define([
comment.asc_putTime(this.utcDateToString(new Date()));
comment.asc_putOnlyOfficeTime(this.ooDateToString(new Date()));
comment.asc_putUserId(this.currentUserId);
comment.asc_putUserName(Common.Utils.UserInfoParser.getCurrentName());
comment.asc_putUserName(AscCommon.UserInfoParser.getCurrentName());
comment.asc_putSolved(false);
if (!_.isUndefined(comment.asc_putDocumentFlag)) {
@ -241,6 +242,13 @@ define([
this.api.asc_RemoveAllComments(type=='my' || !this.mode.canDeleteComments, type=='current');// 1 param = true if remove only my comments, 2 param - remove current comments
}
},
onResolveComments: function (type) {
if (this.api) {
this.api.asc_ResolveAllComments(type=='my' || !this.mode.canEditComments, type=='current');// 1 param = true if resolve only my comments, 2 param - resolve current comments
}
},
onResolveComment: function (uid) {
var t = this,
reply = null,
@ -355,7 +363,7 @@ define([
ascComment.asc_putTime(t.utcDateToString(new Date(comment.get('time'))));
ascComment.asc_putOnlyOfficeTime(t.ooDateToString(new Date(comment.get('time'))));
ascComment.asc_putUserId(t.currentUserId);
ascComment.asc_putUserName(Common.Utils.UserInfoParser.getCurrentName());
ascComment.asc_putUserName(AscCommon.UserInfoParser.getCurrentName());
ascComment.asc_putSolved(comment.get('resolved'));
ascComment.asc_putGuid(comment.get('guid'));
ascComment.asc_putUserData(comment.get('userdata'));
@ -432,7 +440,7 @@ define([
if (reply.get('id') === replyId && !_.isUndefined(replyVal)) {
addReply.asc_putText(replyVal);
addReply.asc_putUserId(me.currentUserId);
addReply.asc_putUserName(Common.Utils.UserInfoParser.getCurrentName());
addReply.asc_putUserName(AscCommon.UserInfoParser.getCurrentName());
} else {
addReply.asc_putText(reply.get('reply'));
addReply.asc_putUserId(reply.get('userid'));
@ -512,7 +520,7 @@ define([
addReply.asc_putTime(me.utcDateToString(new Date()));
addReply.asc_putOnlyOfficeTime(me.ooDateToString(new Date()));
addReply.asc_putUserId(me.currentUserId);
addReply.asc_putUserName(Common.Utils.UserInfoParser.getCurrentName());
addReply.asc_putUserName(AscCommon.UserInfoParser.getCurrentName());
ascComment.asc_addReply(addReply);
@ -777,8 +785,9 @@ define([
comment.set('userdata', data.asc_getUserData());
comment.set('time', date.getTime());
comment.set('date', t.dateToLocaleTimeString(date));
comment.set('editable', t.mode.canEditComments || (data.asc_getUserId() == t.currentUserId));
comment.set('removable', t.mode.canDeleteComments || (data.asc_getUserId() == t.currentUserId));
comment.set('editable', (t.mode.canEditComments || (data.asc_getUserId() == t.currentUserId)) && AscCommon.UserInfoParser.canEditComment(data.asc_getUserName()));
comment.set('removable', (t.mode.canDeleteComments || (data.asc_getUserId() == t.currentUserId)) && AscCommon.UserInfoParser.canDeleteComment(data.asc_getUserName()));
comment.set('hide', !AscCommon.UserInfoParser.canViewComment(data.asc_getUserName()));
replies = _.clone(comment.get('replys'));
@ -804,13 +813,18 @@ define([
editTextInPopover : false,
showReplyInPopover : false,
scope : t.view,
editable : t.mode.canEditComments || (data.asc_getReply(i).asc_getUserId() == t.currentUserId),
removable : t.mode.canDeleteComments || (data.asc_getReply(i).asc_getUserId() == t.currentUserId)
editable : (t.mode.canEditComments || (data.asc_getReply(i).asc_getUserId() == t.currentUserId)) && AscCommon.UserInfoParser.canEditComment(data.asc_getReply(i).asc_getUserName()),
removable : (t.mode.canDeleteComments || (data.asc_getReply(i).asc_getUserId() == t.currentUserId)) && AscCommon.UserInfoParser.canDeleteComment(data.asc_getReply(i).asc_getUserName()),
hide : !AscCommon.UserInfoParser.canViewComment(data.asc_getReply(i).asc_getUserName())
}));
}
comment.set('replys', replies);
if (!this.popoverComments.findWhere({hide: false})) {
this.getPopover() && this.getPopover().hideComments();
}
if (!silentUpdate) {
this.updateComments(false, true);
@ -925,12 +939,15 @@ define([
});
this.popoverComments.reset(comments);
if (popover.isVisible()) {
popover.hide();
}
if (this.popoverComments.findWhere({hide: false})) {
if (popover.isVisible()) {
popover.hide();
}
popover.setLeftTop(posX, posY, leftX);
popover.showComments(animate, false, true, text);
popover.setLeftTop(posX, posY, leftX);
popover.showComments(animate, false, true, text);
} else
popover.hideComments();
}
this.isModeChanged = false;
},
@ -1008,9 +1025,12 @@ define([
});
this.popoverComments.reset(comments);
useAnimation = true;
this.getPopover().showComments(useAnimation, undefined, undefined, text);
} else if (!this.getPopover().isVisible()) {
if (this.popoverComments.findWhere({hide: false})) {
useAnimation = true;
this.getPopover().showComments(useAnimation, undefined, undefined, text);
} else
this.getPopover().hideComments();
} else if (!this.getPopover().isVisible() && this.popoverComments.findWhere({hide: false})) {
this.getPopover().showComments(false, undefined, undefined, text);
}
@ -1250,8 +1270,9 @@ define([
showReplyInPopover : false,
hideAddReply : !_.isUndefined(this.hidereply) ? this.hidereply : (this.showPopover ? true : false),
scope : this.view,
editable : this.mode.canEditComments || (data.asc_getUserId() == this.currentUserId),
removable : this.mode.canDeleteComments || (data.asc_getUserId() == this.currentUserId),
editable : (this.mode.canEditComments || (data.asc_getUserId() == this.currentUserId)) && AscCommon.UserInfoParser.canEditComment(data.asc_getUserName()),
removable : (this.mode.canDeleteComments || (data.asc_getUserId() == this.currentUserId)) && AscCommon.UserInfoParser.canDeleteComment(data.asc_getUserName()),
hide : !AscCommon.UserInfoParser.canViewComment(data.asc_getUserName()),
hint : !this.mode.canComments,
groupName : (groupname && groupname.length>1) ? groupname[1] : null
});
@ -1288,8 +1309,9 @@ define([
editTextInPopover : false,
showReplyInPopover : false,
scope : this.view,
editable : this.mode.canEditComments || (data.asc_getReply(i).asc_getUserId() == this.currentUserId),
removable : this.mode.canDeleteComments || (data.asc_getReply(i).asc_getUserId() == this.currentUserId)
editable : (this.mode.canEditComments || (data.asc_getReply(i).asc_getUserId() == this.currentUserId)) && AscCommon.UserInfoParser.canEditComment(data.asc_getReply(i).asc_getUserName()),
removable : (this.mode.canDeleteComments || (data.asc_getReply(i).asc_getUserId() == this.currentUserId)) && AscCommon.UserInfoParser.canDeleteComment(data.asc_getReply(i).asc_getUserName()),
hide : !AscCommon.UserInfoParser.canViewComment(data.asc_getReply(i).asc_getUserName())
}));
}
}
@ -1319,7 +1341,7 @@ define([
time: date.getTime(),
date: this.dateToLocaleTimeString(date),
userid: this.currentUserId,
username: Common.Utils.UserInfoParser.getCurrentName(),
username: AscCommon.UserInfoParser.getCurrentName(),
usercolor: (user) ? user.get('color') : null,
editTextInPopover: true,
showReplyInPopover: false,
@ -1383,7 +1405,7 @@ define([
comment.asc_putTime(this.utcDateToString(new Date()));
comment.asc_putOnlyOfficeTime(this.ooDateToString(new Date()));
comment.asc_putUserId(this.currentUserId);
comment.asc_putUserName(Common.Utils.UserInfoParser.getCurrentName());
comment.asc_putUserName(AscCommon.UserInfoParser.getCurrentName());
comment.asc_putSolved(false);
if (!_.isUndefined(comment.asc_putDocumentFlag))
@ -1450,13 +1472,13 @@ define([
for (i = 0; i < comments.length; ++i) {
comment = this.findComment(comments[i].asc_getId());
if (comment) {
comment.set('editTextInPopover', t.mode.canEditComments);// dont't edit comment when customization->commentAuthorOnly is true or when permissions.editCommentAuthorOnly is true
comment.set('editTextInPopover', t.mode.canEditComments && AscCommon.UserInfoParser.canEditComment(comment.username));// dont't edit comment when customization->commentAuthorOnly is true or when permissions.editCommentAuthorOnly is true
comment.set('hint', false);
this.popoverComments.push(comment);
}
}
if (this.getPopover() && this.popoverComments.length>0) {
if (this.getPopover() && this.popoverComments.length>0 && this.popoverComments.findWhere({hide: false})) {
if (this.getPopover().isVisible()) {
this.getPopover().hide();
}

View file

@ -206,7 +206,7 @@ define([
plugin.set_Name(item.get('name'));
plugin.set_Guid(item.get('guid'));
plugin.set_BaseUrl(item.get('baseUrl'));
plugin.set_MinVersion(item.get('minVersion'));
plugin.set_MinVersion && plugin.set_MinVersion(item.get('minVersion'));
var variations = item.get('variations'),
variationsArr = [];
@ -241,6 +241,7 @@ define([
this.api.asc_pluginsRegister('', arr);
if (storePlugins.hasVisible())
Common.NotificationCenter.trigger('tab:visible', 'plugins', true);
Common.Gateway.pluginsReady();
},
onAddPlugin: function (model) {

View file

@ -464,7 +464,7 @@ define([
scope : me.view,
hint : !me.appConfig.canReview,
goto : (item.get_MoveType() == Asc.c_oAscRevisionsMove.MoveTo || item.get_MoveType() == Asc.c_oAscRevisionsMove.MoveFrom),
editable : me.appConfig.isReviewOnly && (item.get_UserId() == me.currentUserId) || !me.appConfig.isReviewOnly && (!me.appConfig.canUseReviewPermissions || me.checkUserGroups(item.get_UserName()))
editable : me.appConfig.isReviewOnly && (item.get_UserId() == me.currentUserId) || !me.appConfig.isReviewOnly && (!me.appConfig.canUseReviewPermissions || AscCommon.UserInfoParser.canEditReview(item.get_UserName()))
});
arr.push(change);
@ -472,15 +472,10 @@ define([
return arr;
},
checkUserGroups: function(username) {
var groups = Common.Utils.UserInfoParser.getParsedGroups(username);
return Common.Utils.UserInfoParser.getCurrentGroups() && groups && (_.intersection(Common.Utils.UserInfoParser.getCurrentGroups(), (groups.length>0) ? groups : [""]).length>0);
},
getUserName: function(id){
if (this.userCollection && id!==null){
var rec = this.userCollection.findUser(id);
if (rec) return Common.Utils.UserInfoParser.getParsedName(rec.get('username'));
if (rec) return AscCommon.UserInfoParser.getParsedName(rec.get('username'));
}
return '';
},
@ -582,7 +577,7 @@ define([
this.view.turnChanges(state, global);
if (userId && this.userCollection) {
var rec = this.userCollection.findOriginalUser(userId);
rec && this.showTips(Common.Utils.String.format(globalFlag ? this.textOnGlobal : this.textOffGlobal, Common.Utils.UserInfoParser.getParsedName(rec.get('username'))));
rec && this.showTips(Common.Utils.String.format(globalFlag ? this.textOnGlobal : this.textOffGlobal, AscCommon.UserInfoParser.getParsedName(rec.get('username'))));
}
}
},
@ -824,8 +819,9 @@ define([
me.view.turnChat(state);
});
}
if (me.view && me.view.btnCommentRemove) {
me.view.btnCommentRemove.setDisabled(!Common.localStorage.getBool(me.view.appPrefix + "settings-livecomment", true));
if (me.view) {
me.view.btnCommentRemove && me.view.btnCommentRemove.setDisabled(!Common.localStorage.getBool(me.view.appPrefix + "settings-livecomment", true));
me.view.btnCommentResolve && me.view.btnCommentResolve.setDisabled(!Common.localStorage.getBool(me.view.appPrefix + "settings-livecomment", true));
}
},
@ -958,6 +954,7 @@ define([
if (!this.view) return;
var value = Common.Utils.InternalSettings.get(this.view.appPrefix + "settings-livecomment");
(value!==undefined) && this.view.btnCommentRemove && this.view.btnCommentRemove.setDisabled(mode != 'show' && !value);
(value!==undefined) && this.view.btnCommentResolve && this.view.btnCommentResolve.setDisabled(mode != 'show' && !value);
},
textInserted: '<b>Inserted:</b>',

View file

@ -56,6 +56,12 @@ function onDropDownKeyDown(e) {
e.stopPropagation();
}
}
} else if ($this.hasClass('move-focus')) {
if (!(/^(27|13|9|32)/.test(e.keyCode) && !e.ctrlKey && !e.altKey)) {
patchDropDownKeyDown.call(this, e);
e.preventDefault();
e.stopPropagation();
}
} else {
patchDropDownKeyDown.call(this, e);
e.preventDefault();

View file

@ -98,7 +98,8 @@ define([
editTextInPopover : false,
scope : null,
editable : true,
removable : true
removable : true,
hide : false
}
});
});

View file

@ -22,9 +22,13 @@
<!-- replys elements -->
<% var add_arrow = true; %>
<% if (replys.length) { %>
<div class="reply-arrow img-commonctrl"></div>
<% _.each(replys, function (item, index) { %>
<% if (!item.get("hide")) { %>
<% if (add_arrow) { add_arrow = false; %>
<div class="reply-arrow img-commonctrl"></div>
<% } %>
<div class="reply-item-ct" <% if (scope.viewmode && index==replys.length-1) { %>style="padding-bottom: 0;" <% } %>;>
<div class="user-name">
<div class="color" style="display: inline-block; background-color: <% if (item.get("usercolor")!==null) { %><%=item.get("usercolor")%><% } else { %> #cfcfcf <% } %>; " ></div><%= scope.getUserName(item.get("username")) %>
@ -50,13 +54,14 @@
</div>
<% } %>
</div>
<% } %>
<% }); %>
<% } %>
<!-- add reply button -->
<% if (!showReply && !scope.viewmode) { %>
<% if (replys.length) { %>
<% if (replys.length && !add_arrow) { %>
<label class="user-reply" style="margin-left: 20px; margin-top: 5px;" role="presentation" tabindex="-1">textAddReply</label>
<% } else { %>
<label class="user-reply" role="presentation" tabindex="-1">textAddReply</label>
@ -73,7 +78,9 @@
<% if (removable) { %>
<div class="btn-delete img-commonctrl"></div>
<% } %>
<% if (editable) { %>
<div class="btn-resolve <% if (resolved) print('comment-resolved') %>" data-toggle="tooltip"></div>
<% } %>
</div>
<% } %>

View file

@ -1,3 +1,4 @@
<% if (!hide) { %>
<div id="<%=id%>" class="user-comment-item">
<!-- comment block -->
@ -22,9 +23,13 @@
<!-- replys elements -->
<% var add_arrow = true; %>
<% if (replys.length) { %>
<div class="reply-arrow img-commonctrl"></div>
<% _.each(replys, function (item) { %>
<% if (!item.get("hide")) { %>
<% if (add_arrow) { add_arrow = false; %>
<div class="reply-arrow img-commonctrl"></div>
<% } %>
<div class="reply-item-ct">
<div class="user-name">
<div class="color" style="display: inline-block; background-color: <% if (item.get("usercolor")!==null) { %><%=item.get("usercolor")%><% } else { %> #cfcfcf <% } %>; " ></div><%= scope.getUserName(item.get("username")) %>
@ -49,15 +54,15 @@
<button class="btn normal dlg-btn btn-inner-close">textClose</button>
</div>
<% } %>
</div>
</div>
<% } %>
<% }); %>
<% } %>
<!-- add reply button -->
<% if (!showReplyInPopover && !hideAddReply && !hint) { %>
<% if (replys.length) { %>
<% if (replys.length && !add_arrow) { %>
<label class="user-reply" style="margin-left: 20px; margin-top: 5px;" role="presentation" tabindex="-1">textAddReply</label>
<% } else { %>
<label class="user-reply" role="presentation" tabindex="-1">textAddReply</label>
@ -74,7 +79,9 @@
<% if (removable) { %>
<div class="btn-delete img-commonctrl"></div>
<% } %>
<% if (editable) { %>
<div class="btn-resolve <% if (resolved) print('comment-resolved') %>" data-toggle="tooltip"></div>
<% } %>
</div>
<% } %>
@ -95,4 +102,5 @@
<div class="lock-author" style="cursor: default;"><%=lockuserid%></div>
<% } %>
</div>
</div>
<% } %>

View file

@ -38,10 +38,11 @@
*
*/
if (Common === undefined) {
var Common = {};
if ( window.Common === undefined ) {
window.Common = {};
}
// TODO: move to Common.Utils
Common.util = Common.util||{};
Common.util.LanguageInfo = new(function() {

View file

@ -541,4 +541,60 @@ define(function(){ 'use strict';
}
}
})(), Common.define.chartData || {});
Common.define.conditionalData = _.extend( new(function() {
return {
textDate: 'Date',
textYesterday: 'Yesterday',
textToday: 'Today',
textTomorrow: 'Tomorrow',
textLast7days: 'In the last 7 days',
textLastWeek: 'Last week',
textThisWeek: 'This week',
textNextWeek: 'Next week',
textLastMonth: 'Last month',
textThisMonth: 'This month',
textNextMonth: 'Next month',
textText: 'Text',
textContains: 'Contains',
textNotContains: 'Does not contain',
textBegins: 'Begins with',
textEnds: 'Ends with',
textAverage: 'Average',
textAbove: 'Above',
textBelow: 'Below',
textEqAbove: 'Equal to or above',
textEqBelow: 'Equal to or below',
text1Above: '1 std dev above',
text1Below: '1 std dev below',
text2Above: '2 std dev above',
text2Below: '2 std dev below',
text3Above: '3 std dev above',
text3Below: '3 std dev below',
textGreater: 'Greater than',
textGreaterEq: 'Greater than or equal to',
textLess: 'Less than',
textLessEq: 'Less than or equal to',
textEqual: 'Equal to',
textNotEqual: 'Not equal to',
textBetween: 'Between',
textNotBetween: 'Not between',
textTop: 'Top',
textBottom: 'Bottom',
textBlank: 'Blank',
textError: 'Error',
textBlanks: 'Contains blanks',
textNotBlanks: 'Does not contain blanks',
textErrors: 'Contains errors',
textNotErrors: 'Does not contain errors',
textDuplicate: 'Duplicate',
textUnique: 'Unique',
textDataBar: 'Data bar',
textIconSets: 'Icon sets',
textFormula: 'Formula',
exampleText: 'AaBbCcYyZz',
noFormatText: 'No format set',
textValue: 'Value is'
}
})(), Common.define.conditionalData || {});
});

View file

@ -32,7 +32,7 @@ var params = (function() {
return urlParams;
})();
if ( !!params.uitheme && localStorage.getItem("ui-theme") != params.uitheme)
if ( !!params.uitheme && !localStorage.getItem("ui-theme") )
localStorage.setItem("ui-theme", params.uitheme);
var ui_theme_name = localStorage.getItem("ui-theme");

View file

@ -30,15 +30,26 @@
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
if (Common === undefined) {
var Common = {};
if (window.Common === undefined) {
window.Common = {};
}
if (Common.Utils === undefined) {
Common.Utils = {};
}
Common.Utils = _.extend(new(function() {
function _extend_object(dest, source) {
if ( typeof _ != "undefined" ) {
return _.extend({}, dest, source);
} else
if ( !!Object ) {
return Object.assign({}, dest, source);
}
return source;
}
var utils = new(function() {
var userAgent = navigator.userAgent.toLowerCase(),
check = function(regex){
return regex.test(userAgent);
@ -114,7 +125,8 @@ Common.Utils = _.extend(new(function() {
CSV: 1,
TXT: 2,
Paste: 3,
Columns: 4
Columns: 4,
Data: 5
},
isMobile = /android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent || navigator.vendor || window.opera),
me = this,
@ -236,7 +248,9 @@ Common.Utils = _.extend(new(function() {
croppedGeometry: function() {return {left:0, top: Common.Utils.InternalSettings.get('window-inactive-area-top'),
width: me.innerWidth, height: me.innerHeight - Common.Utils.InternalSettings.get('window-inactive-area-top')}}
}
})(), Common.Utils || {});
})();
Common.Utils = _extend_object(Common.Utils, utils);
Common.Utils.ThemeColor = new(function() {
return {
@ -308,7 +322,7 @@ Common.Utils.ThemeColor = new(function() {
},
colorValue2EffectId: function(clr){
if (typeof(clr) == 'object' && clr.effectValue !== undefined && this.effectcolors) {
if (typeof(clr) == 'object' && clr && clr.effectValue !== undefined && this.effectcolors) {
for (var i = 0; i < this.effectcolors.length; i++) {
if (this.effectcolors[i].effectValue===clr.effectValue && clr.color.toUpperCase()===this.effectcolors[i].color.toUpperCase()) {
clr.effectId = this.effectcolors[i].effectId;
@ -321,7 +335,7 @@ Common.Utils.ThemeColor = new(function() {
}
})();
Common.Utils.Metric = _.extend( new(function() {
var metrics = new(function() {
var me = this;
me.c_MetricUnits = {
@ -392,7 +406,9 @@ Common.Utils.Metric = _.extend( new(function() {
return value;
}
}
})(), Common.Utils.Metric || {});
})();
Common.Utils.Metric = _extend_object(Common.Utils.Metric, metrics);
Common.Utils.RGBColor = function(colorString) {
var r, g, b;
@ -571,7 +587,8 @@ Common.Utils.String = new (function() {
},
htmlEncode: function(string) {
return _.escape(string);
return (typeof _ !== 'undefined') ? _.escape(string) :
string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
},
htmlDecode: function(string) {
@ -726,9 +743,9 @@ Common.Utils.applyCustomizationPlugins = function(plugins) {
Common.Utils.fillUserInfo = function(info, lang, defname) {
var _user = info || {};
!_user.id && (_user.id = ('uid-' + Date.now()));
_user.fullname = _.isEmpty(_user.name) ? defname : _user.name;
_user.group && (_user.fullname = (_user.group).toString() + Common.Utils.UserInfoParser.getSeparator() + _user.fullname);
_user.guest = _.isEmpty(_user.name);
_user.fullname = !_user.name ? defname : _user.name;
_user.group && (_user.fullname = (_user.group).toString() + AscCommon.UserInfoParser.getSeparator() + _user.fullname);
_user.guest = !_user.name;
return _user;
};
@ -982,12 +999,8 @@ Common.Utils.ModalWindow = new(function() {
})();
Common.Utils.UserInfoParser = new(function() {
var parse = false,
separator = String.fromCharCode(160),
username = '',
usergroups,
reviewPermissions,
reviewGroups;
var parse = false;
var separator = String.fromCharCode(160);
return {
setParser: function(value) {
parse = !!value;
@ -1013,36 +1026,6 @@ Common.Utils.UserInfoParser = new(function() {
return groups;
} else
return undefined;
},
setCurrentName: function(name) {
username = name;
this.setReviewPermissions(reviewGroups, reviewPermissions);
},
getCurrentName: function() {
return username;
},
setReviewPermissions: function(groups, permissions) {
if (groups) {
if (typeof groups == 'object' && groups.length>0)
usergroups = groups;
reviewGroups = groups;
} else if (permissions) {
var arr = [],
arrgroups = this.getParsedGroups(username);
arrgroups && arrgroups.forEach(function(group) {
var item = permissions[group.trim()];
item && (arr = arr.concat(item));
});
usergroups = arr;
reviewPermissions = permissions;
}
},
getCurrentGroups: function() {
return usergroups;
}
}
})();

View file

@ -86,6 +86,8 @@ define([
var $window = this.getChild();
$window.find('.dlg-btn').on('click', _.bind(this.onDlgBtnClick, this));
this.on('animate:after', _.bind(this.onAnimateAfter, this));
this.btnsCategory = [];
_.each($window.find('.btn-category'), function(item, index) {
var btnEl = $(item);
@ -173,6 +175,10 @@ define([
if (this.storageName)
Common.localStorage.setItem(this.storageName, this.getActiveCategory());
Common.UI.Window.prototype.close.call(this, suppressevent);
},
onAnimateAfter: function() {
}
}, Common.Views.AdvancedSettingsWindow || {}));
});

View file

@ -337,6 +337,7 @@ define([ 'text!common/main/lib/template/AutoCorrectDialog.template',
this.btnsCategory[0].on('click', _.bind(this.onMathCategoryClick, this, false));
this.btnsCategory[1].on('click', _.bind(this.onRecCategoryClick, this, false));
this.btnsCategory[2].on('click', _.bind(this.onAutoformatCategoryClick, this, false));
this.afterRender();
},
@ -351,10 +352,12 @@ define([ 'text!common/main/lib/template/AutoCorrectDialog.template',
},
getFocusedComponents: function() {
return [
this.inputReplace, this.inputBy, {cmp: this.mathList, selector: '.listview'}, // 0 tab
this.inputRecFind, {cmp: this.mathRecList, selector: '.listview'} // 1 tab
];
var arr = [
this.chReplaceType, this.inputReplace, this.inputBy, this.mathList, this.btnReset, this.btnEdit, this.btnDelete, // 0 tab
this.inputRecFind, this.mathRecList, this.btnResetRec, this.btnAddRec, this.btnDeleteRec // 1 tab
];
arr = arr.concat(this.chNewRows ? [this.chNewRows] : [this.chQuotes, this.chHyphens, this.chBulleted, this.chNumbered]);
return arr;
},
getSettings: function() {
@ -395,6 +398,7 @@ define([ 'text!common/main/lib/template/AutoCorrectDialog.template',
var value = this.getActiveCategory();
if (value==0) this.onMathCategoryClick(true);
else if (value==1) this.onRecCategoryClick(true);
else if (value==2) this.onAutoformatCategoryClick(true);
},
close: function() {
@ -417,6 +421,13 @@ define([ 'text!common/main/lib/template/AutoCorrectDialog.template',
}
},
onAutoformatCategoryClick: function(delay) {
var me = this;
_.delay(function(){
me.chNewRows ? me.chNewRows.focus() : me.chQuotes.focus();
},delay ? 50 : 0);
},
onDelete: function() {
var rec = this.mathList.getSelectedRec();
if (rec) {

View file

@ -267,7 +267,7 @@ define([
},
getUserName: function (username) {
return Common.Utils.String.htmlEncode(Common.Utils.UserInfoParser.getParsedName(username));
return Common.Utils.String.htmlEncode(AscCommon.UserInfoParser.getParsedName(username));
},
hide: function () {

View file

@ -656,7 +656,7 @@ define([
return Common.Utils.String.ellipsis(Common.Utils.String.htmlEncode(quote), 120, true);
},
getUserName: function (username) {
return Common.Utils.String.htmlEncode(Common.Utils.UserInfoParser.getParsedName(username));
return Common.Utils.String.htmlEncode(AscCommon.UserInfoParser.getParsedName(username));
},
pickLink: function (message) {

View file

@ -136,7 +136,7 @@ define([
users: collection.chain().filter(function(item){return item.get('online') && !item.get('view')}).groupBy(function(item) {return item.get('idOriginal');}).value(),
usertpl: _.template(templateUserItem),
fnEncode: function(username) {
return Common.Utils.String.htmlEncode(Common.Utils.UserInfoParser.getParsedName(username));
return Common.Utils.String.htmlEncode(AscCommon.UserInfoParser.getParsedName(username));
}
}));
@ -782,7 +782,8 @@ define([
textAdvSettings: 'Advanced Settings',
tipViewSettings: 'View Settings',
textRemoveFavorite: 'Remove from Favorites',
textAddFavorite: 'Mark as favorite'
textAddFavorite: 'Mark as favorite',
textHideNotes: 'Hide Notes'
}
}(), Common.Views.Header || {}))
});

View file

@ -90,7 +90,7 @@ define([
'<% } %>',
'<div class="user-name">',
'<div class="color" style="display: inline-block; background-color:' + '<%=usercolor%>;' + '" >',
'</div><%= Common.Utils.String.htmlEncode(Common.Utils.UserInfoParser.getParsedName(username)) %>',
'</div><%= Common.Utils.String.htmlEncode(AscCommon.UserInfoParser.getParsedName(username)) %>',
'</div>',
'<% if (canRestore && selected) { %>',
'<label class="revision-restore" role="presentation" tabindex="-1">' + this.textRestore + '</label>',

View file

@ -57,10 +57,22 @@ define([
if (options.preview) {
width = 414;
height = 277;
height = (options.type==Common.Utils.importTextType.Data) ? 385 : 277;
} else {
width = (options.type !== Common.Utils.importTextType.DRM) ? 340 : (options.warning ? 420 : 280);
height = (options.type == Common.Utils.importTextType.CSV || options.type == Common.Utils.importTextType.Paste || options.type == Common.Utils.importTextType.Columns) ? 190 : (options.warning ? 187 : 147);
switch (options.type) {
case Common.Utils.importTextType.CSV:
case Common.Utils.importTextType.Paste:
case Common.Utils.importTextType.Columns:
height = 190;
break;
case Common.Utils.importTextType.Data:
height = 245;
break;
default:
height = options.warning ? 187 : 147;
break;
}
}
_.extend(_options, {
@ -114,13 +126,13 @@ define([
'</div>',
'</div>',
'<% } %>',
'<% if (type == Common.Utils.importTextType.Paste || type == Common.Utils.importTextType.Columns) { %>',
'<% if (type == Common.Utils.importTextType.Paste || type == Common.Utils.importTextType.Columns || type == Common.Utils.importTextType.Data) { %>',
'<div style="display: inline-block; margin-bottom:15px;width: 100%;">',
'<label class="header">' + t.txtDelimiter + '</label>',
'<div>',
'<div id="id-delimiters-combo" class="input-group-nr" style="max-width: 100px;display: inline-block; vertical-align: middle;"></div>',
'<div id="id-delimiter-other" class="input-row" style="display: inline-block; vertical-align: middle;margin-left: 10px;"></div>',
'<button type="button" class="btn btn-text-default" id="id-delimiters-advanced" style="min-width:100px; display: inline-block;float:right;">' + t.txtAdvanced + '</button>',
'<button type="button" class="btn auto btn-text-default" id="id-delimiters-advanced" style="min-width:100px; display: inline-block;float:right;">' + t.txtAdvanced + '</button>',
'</div>',
'</div>',
'<% } %>',
@ -138,6 +150,10 @@ define([
'</div>',
'</div>',
'<% } %>',
'<% if (type == Common.Utils.importTextType.Data) { %>',
'<label class="header" style="margin-top:15px;">' + t.txtDestData + '</label>',
'<div id="id-open-data-range" class="input-row" style="width: 100%;"></div>',
'<% } %>',
'<% } %>',
'</div>',
'</div>',
@ -204,6 +220,21 @@ define([
(this.previewData) ? this.previewCallback(this.previewData) : this.updatePreview();
}
}
if (this.type == Common.Utils.importTextType.Data) {
this.txtDestRange = new Common.UI.InputFieldBtn({
el : $('#id-open-data-range'),
name : 'range',
style : 'width: 100%;',
btnHint : this.textSelectData,
allowBlank : true,
validateOnChange: true,
validateOnBlur: false
});
this.txtDestRange.on('button:click', _.bind(this.onSelectData, this));
this.dataDestValid = this.api.asc_getActiveRangeStr(Asc.referenceType.A, true);
this.txtDestRange.setValue(this.dataDestValid);
}
this.onPrimary = function() {
me._handleInput('ok');
return false;
@ -211,16 +242,31 @@ define([
}
},
getFocusedComponents: function() {
var arr = [];
this.inputPwd && arr.push(this.inputPwd);
this.cmbEncoding && arr.push(this.cmbEncoding);
this.cmbDelimiter && arr.push(this.cmbDelimiter);
this.inputDelimiter && arr.push(this.inputDelimiter);
this.btnAdvanced && arr.push(this.btnAdvanced);
this.txtDestRange && arr.push(this.txtDestRange);
return arr;
},
show: function() {
Common.UI.Window.prototype.show.apply(this, arguments);
var me = this;
if (this.type == Common.Utils.importTextType.DRM) {
var me = this;
setTimeout(function(){
me.inputPwd.cmpEl.find('input').focus();
me.inputPwd.focus();
if (me.validatePwd)
me.inputPwd.checkValidate();
}, 500);
} else {
var cmp = me.txtDestRange ? me.txtDestRange : (me.cmbEncoding ? me.cmbEncoding : me.cmbDelimiter);
cmp && setTimeout(function(){cmp.focus();}, 500);
}
},
@ -235,8 +281,12 @@ define([
_handleInput: function(state) {
if (this.handler) {
if (this.type == Common.Utils.importTextType.DRM) {
this.handler.call(this, state, this.inputPwd.getValue());
this.handler.call(this, state, {drmOptions: new Asc.asc_CDRMAdvancedOptions(this.inputPwd.getValue())});
} else {
if ( this.type == Common.Utils.importTextType.Data && state == 'ok' && !this.isRangeValid() ) {
return;
}
var encoding = (this.cmbEncoding && !this.cmbEncoding.isDisabled()) ? this.cmbEncoding.getValue() :
((this.settings && this.settings.asc_getCodePage()) ? this.settings.asc_getCodePage() : 0),
delimiter = this.cmbDelimiter ? this.cmbDelimiter.getValue() : null,
@ -248,7 +298,14 @@ define([
var decimal = this.separatorOptions ? this.separatorOptions.decimal : undefined,
thousands = this.separatorOptions ? this.separatorOptions.thousands : undefined;
this.handler.call(this, state, encoding, delimiter, delimiterChar, decimal, thousands);
var options = new Asc.asc_CTextOptions(encoding, delimiter, delimiterChar);
decimal && options.asc_setNumberDecimalSeparator(decimal);
thousands && options.asc_setNumberGroupSeparator(thousands);
this.handler.call(this, state, {
textOptions: options,
range: this.txtDestRange ? this.txtDestRange.getValue() : '',
data: this.data
});
}
}
@ -302,7 +359,8 @@ define([
editable: false,
disabled: true,
search: true,
itemsTemplate: itemsTemplate
itemsTemplate: itemsTemplate,
takeFocusOnClose: true
});
this.cmbEncoding.setDisabled(false);
@ -321,7 +379,7 @@ define([
ul.find('li div').width(width);
}
if (this.type == Common.Utils.importTextType.CSV || this.type == Common.Utils.importTextType.Paste || this.type == Common.Utils.importTextType.Columns) {
if (this.type == Common.Utils.importTextType.CSV || this.type == Common.Utils.importTextType.Paste || this.type == Common.Utils.importTextType.Columns || this.type == Common.Utils.importTextType.Data) {
this.cmbDelimiter = new Common.UI.ComboBox({
el: $('#id-delimiters-combo', this.$window),
style: 'width: 100px;',
@ -334,7 +392,8 @@ define([
{value: 1, displayValue: this.txtTab},
{value: 5, displayValue: this.txtSpace},
{value: -1, displayValue: this.txtOther}],
editable: false
editable: false,
takeFocusOnClose: true
});
this.cmbDelimiter.setValue( (this.settings && this.settings.asc_getDelimiter()) ? this.settings.asc_getDelimiter() : 4);
this.cmbDelimiter.on('selected', _.bind(this.onCmbDelimiterSelect, this));
@ -351,7 +410,7 @@ define([
if (this.preview)
this.inputDelimiter.on ('changing', _.bind(this.updatePreview, this));
if (this.type == Common.Utils.importTextType.Paste || this.type == Common.Utils.importTextType.Columns) {
if (this.type == Common.Utils.importTextType.Paste || this.type == Common.Utils.importTextType.Columns || this.type == Common.Utils.importTextType.Data) {
this.btnAdvanced = new Common.UI.Button({
el: $('#id-delimiters-advanced')
});
@ -383,6 +442,14 @@ define([
}
this.api.asc_TextImport(options, _.bind(this.previewCallback, this), this.type == Common.Utils.importTextType.Paste);
break;
case Common.Utils.importTextType.Data:
var options = new Asc.asc_CTextOptions(encoding, delimiter, delimiterChar);
if (this.separatorOptions) {
options.asc_setNumberDecimalSeparator(this.separatorOptions.decimal);
options.asc_setNumberGroupSeparator(this.separatorOptions.thousands);
}
this.api.asc_decodeBuffer(this.preview, options, _.bind(this.previewCallback, this));
break;
}
},
@ -424,7 +491,7 @@ define([
delete this.scrollerX;
}
if (this.type == Common.Utils.importTextType.CSV || this.type == Common.Utils.importTextType.Paste || this.type == Common.Utils.importTextType.Columns) {
if (this.type == Common.Utils.importTextType.CSV || this.type == Common.Utils.importTextType.Paste || this.type == Common.Utils.importTextType.Columns || this.type == Common.Utils.importTextType.Data) {
var maxlength = 0;
for (var i=0; i<data.length; i++) {
if (data[i].length>maxlength)
@ -492,6 +559,60 @@ define([
})).show();
},
onSelectData: function(type) {
var me = this,
txtRange = me.txtDestRange;
if (me.api) {
var handlerDlg = function(dlg, result) {
if (result == 'ok') {
var txt = dlg.getSettings();
me.dataDestValid = txt;
txtRange.setValue(txt);
txtRange.checkValidate();
}
};
var win = new SSE.Views.CellRangeDialog({
handler: handlerDlg
}).on('close', function() {
me.show();
_.delay(function(){
txtRange.focus();
},1);
});
var xy = me.$window.offset();
me.hide();
win.show(xy.left + 160, xy.top + 125);
win.setSettings({
api : me.api,
range : (!_.isEmpty(txtRange.getValue()) && (txtRange.checkValidate()==true)) ? txtRange.getValue() : (me.dataDestValid),
type : Asc.c_oAscSelectionDialogType.Chart
});
}
},
isRangeValid: function() {
var isvalid = true,
txtError = '';
if (_.isEmpty(this.txtDestRange.getValue())) {
isvalid = false;
txtError = this.txtEmpty;
} else {
isvalid = this.api.asc_checkDataRange(Asc.c_oAscSelectionDialogType.Chart, this.txtDestRange.getValue());
isvalid = (isvalid == Asc.c_oAscError.ID.No);
!isvalid && (txtError = this.textInvalidRange);
}
if (!isvalid) {
this.txtDestRange.showError([txtError]);
this.txtDestRange.focus();
return isvalid;
}
return isvalid;
},
txtDelimiter : "Delimiter",
txtEncoding : "Encoding ",
txtSpace : "Space",
@ -508,7 +629,11 @@ define([
txtSemicolon: 'Semicolon',
txtProtected: 'Once you enter the password and open the file, the current password to the file will be reset.',
txtAdvanced: 'Advanced',
txtOpenFile: "Enter a password to open the file"
txtOpenFile: "Enter a password to open the file",
textSelectData: 'Select data',
txtDestData: 'Choose where to put the data',
txtEmpty: 'This field is required',
textInvalidRange: 'Invalid cells range'
}, Common.Views.OpenDialog || {}));
});

View file

@ -79,8 +79,8 @@ define([
var me = this,
$window = me.getChild(),
items = this.options.items,
checked = true,
checkedIndex = -1;
checked = true;
this.checkedIndex = -1;
if (items) {
for (var i=0; i<items.length; i++) {
var item = items[i];
@ -98,14 +98,22 @@ define([
}));
if ((checked || item.checked)&& !item.disabled) {
checked = false;
checkedIndex = i;
this.checkedIndex = i;
}
}
(checkedIndex>=0) && this.radio[checkedIndex].setValue(true);
(this.checkedIndex>=0) && this.radio[this.checkedIndex].setValue(true);
}
$window.find('.dlg-btn').on('click', _.bind(this.onBtnClick, this));
},
getFocusedComponents: function() {
return this.radio;
},
getDefaultFocusableComponent: function () {
return (this.checkedIndex>=0) ? this.radio[this.checkedIndex] : null;
},
_handleInput: function(state) {
if (this.options.handler) {
this.options.handler.call(this, this, state);

View file

@ -116,13 +116,12 @@ define([
}
},
show: function() {
Common.UI.Window.prototype.show.apply(this, arguments);
getFocusedComponents: function() {
return [this.inputPwd, this.repeatPwd];
},
var me = this;
setTimeout(function(){
me.inputPwd.cmpEl.find('input').focus();
}, 500);
getDefaultFocusableComponent: function () {
return this.inputPwd;
},
onPrimary: function(event) {
@ -138,12 +137,12 @@ define([
if (this.handler) {
if (state == 'ok') {
if (this.inputPwd.checkValidate() !== true) {
this.inputPwd.cmpEl.find('input').focus();
this.inputPwd.focus();
return;
}
if (this.inputPwd.getValue() !== this.repeatPwd.getValue()) {
this.repeatPwd.checkValidate();
this.repeatPwd.cmpEl.find('input').focus();
this.repeatPwd.focus();
return;
}
}

View file

@ -76,6 +76,7 @@ define([
el : $('#id-dlg-newname'),
style : 'width: 100%;',
validateOnBlur: false,
maxLength: me.options.maxLength,
validation : function(value) {
return (/[\t*\+:\"<>?|\\\\/]/gim.test(value)) ? me.txtInvalidName + "*+:\"<>?|\/" : true;
}

View file

@ -65,6 +65,7 @@ define([
'<div class="group">' +
'<span class="btn-slot text x-huge slot-comment"></span>' +
'<span class="btn-slot text x-huge" id="slot-comment-remove"></span>' +
'<span class="btn-slot text x-huge" id="slot-comment-resolve"></span>' +
'</div>' +
'<div class="separator long comments"></div>' +
'<div class="group">' +
@ -208,6 +209,15 @@ define([
me.fireEvent('comment:removeComments', [item.value]);
});
}
if (this.btnCommentResolve) {
this.btnCommentResolve.on('click', function (e) {
me.fireEvent('comment:resolveComments', ['current']);
});
this.btnCommentResolve.menu.on('item:click', function (menu, item, e) {
me.fireEvent('comment:resolveComments', [item.value]);
});
}
}
return {
@ -219,6 +229,8 @@ define([
Common.UI.BaseView.prototype.initialize.call(this, options);
this.appConfig = options.mode;
var filter = Common.localStorage.getKeysFilter();
this.appPrefix = (filter && filter.length) ? filter.split(',')[0] : '';
if ( this.appConfig.canReview ) {
this.btnAccept = new Common.UI.Button({
@ -318,7 +330,7 @@ define([
});
}
if (this.appConfig.isEdit && !this.appConfig.isOffline && this.appConfig.canCoAuthoring) {
if (this.appConfig.isEdit && !this.appConfig.isOffline && this.appConfig.canCoAuthoring && this.appConfig.canChangeCoAuthoring) {
this.btnCoAuthMode = new Common.UI.Button({
cls: 'btn-toolbar x-huge icon-top',
iconCls: 'toolbar__icon btn-ic-coedit',
@ -354,11 +366,14 @@ define([
split: true,
iconCls: 'toolbar__icon btn-rem-comment'
});
this.btnCommentResolve = new Common.UI.Button({
cls: 'btn-toolbar x-huge icon-top',
caption: this.txtCommentResolve,
split: true,
iconCls: 'toolbar__icon btn-resolve-all'
});
}
var filter = Common.localStorage.getKeysFilter();
this.appPrefix = (filter && filter.length) ? filter.split(',')[0] : '';
Common.NotificationCenter.on('app:ready', this.onAppReady.bind(this));
},
@ -501,13 +516,7 @@ define([
]
}));
me.btnCoAuthMode.updateHint(me.tipCoAuthMode);
var value = Common.localStorage.getItem(me.appPrefix + "settings-coauthmode");
if (value===null && !Common.localStorage.itemExists(me.appPrefix + "settings-autosave") &&
config.customization && config.customization.autosave===false) {
value = 0; // use customization.autosave only when de-settings-coauthmode and de-settings-autosave are null
}
me.turnCoAuthMode((value===null || parseInt(value) == 1) && !(config.isDesktopApp && config.isOffline) && config.canCoAuthoring);
me.turnCoAuthMode(Common.Utils.InternalSettings.get(me.appPrefix + "settings-coauthmode"));
}
if (me.btnCommentRemove) {
@ -532,6 +541,28 @@ define([
me.btnCommentRemove.updateHint([me.tipCommentRemCurrent, me.tipCommentRem]);
}
if (me.btnCommentResolve) {
var items = [
{
caption: config.canEditComments ? me.txtCommentResolveCurrent : me.txtCommentResolveMyCurrent,
value: 'current'
},
{
caption: me.txtCommentResolveMy,
value: 'my'
}
];
if (config.canEditComments)
items.push({
caption: me.txtCommentResolveAll,
value: 'all'
});
me.btnCommentResolve.setMenu(
new Common.UI.Menu({items: items})
);
me.btnCommentResolve.updateHint([me.tipCommentResolveCurrent, me.tipCommentResolve]);
}
var separator_sharing = !(me.btnSharing || me.btnCoAuthMode) ? me.$el.find('.separator.sharing') : '.separator.sharing',
separator_comments = !(config.canComments && config.canCoAuthoring) ? me.$el.find('.separator.comments') : '.separator.comments',
separator_review = !(config.canReview || config.canViewReview) ? me.$el.find('.separator.review') : '.separator.review',
@ -591,6 +622,7 @@ define([
this.btnHistory && this.btnHistory.render(this.$el.find('#slot-btn-history'));
this.btnChat && this.btnChat.render(this.$el.find('#slot-btn-chat'));
this.btnCommentRemove && this.btnCommentRemove.render(this.$el.find('#slot-comment-remove'));
this.btnCommentResolve && this.btnCommentResolve.render(this.$el.find('#slot-comment-resolve'));
return this.$el;
},
@ -670,7 +702,7 @@ define([
},
getUserName: function (username) {
return Common.Utils.String.htmlEncode(Common.Utils.UserInfoParser.getParsedName(username));
return Common.Utils.String.htmlEncode(AscCommon.UserInfoParser.getParsedName(username));
},
turnChanges: function(state, global) {
@ -742,6 +774,7 @@ define([
// this.btnChat && this.btnChat.setDisabled(state);
this.btnCommentRemove && this.btnCommentRemove.setDisabled(state || !Common.Utils.InternalSettings.get(this.appPrefix + "settings-livecomment"));
this.btnCommentResolve && this.btnCommentResolve.setDisabled(state || !Common.Utils.InternalSettings.get(this.appPrefix + "settings-livecomment"));
},
onLostEditRights: function() {
@ -804,6 +837,13 @@ define([
txtCommentRemMyCurrent: 'Remove My Current Comments',
txtCommentRemMy: 'Remove My Comments',
txtCommentRemAll: 'Remove All Comments',
txtCommentResolve: 'Resolve',
tipCommentResolveCurrent: 'Resolve current comments',
tipCommentResolve: 'Resolve comments',
txtCommentResolveCurrent: 'Resolve Current Comments',
txtCommentResolveMyCurrent: 'Resolve My Current Comments',
txtCommentResolveMy: 'Resolve My Comments',
txtCommentResolveAll: 'Resolve All Comments',
txtOnGlobal: 'ON for me and everyone',
txtOffGlobal: 'OFF for me and everyone',
txtOn: 'ON for me',

View file

@ -143,7 +143,7 @@ define([
},
getFocusedComponents: function() {
return [this.inputName, this.inputTitle, this.inputEmail, this.textareaInstructions];
return [this.inputName, this.inputTitle, this.inputEmail, this.textareaInstructions, this.chDate];
},
getDefaultFocusableComponent: function () {

View file

@ -752,9 +752,9 @@ define([
el: $window.find('#symbol-table-special-list'),
store: new Common.UI.DataViewStore(data),
simpleAddMode: true,
template: _.template(['<div class="listview inner" style=""></div>'].join('')),
cls: 'dbl-clickable',
itemTemplate: _.template([
'<div id="<%= id %>" class="list-item" style="pointer-events:none;width: 100%;display:flex;">',
'<div id="<%= id %>" class="list-item" style="width: 100%;display:flex;">',
'<div style="width:70px;text-align: center; padding-right: 5px;"><%= symbol %></div>',
'<div style="flex-grow:1;padding-right: 5px;"><%= description %></div>',
'<% if (' + this.showShortcutKey + ') { %>',

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

View file

@ -229,7 +229,7 @@
.inner-box-caption {
line-height: 18px;
padding: 0 4px;
padding: 0 2px;
display: flex;
align-items: center;
@ -303,6 +303,14 @@
}
}
.icon-top.btn-group {
&.x-huge, .x-huge {
.inner-box-caption {
padding-right: 4px;
}
}
}
.icon-top {
&.x-huge {
.btn&, .btn-group& .btn-toolbar {
@ -341,6 +349,11 @@
border: @scaled-one-px-value-ie solid @border-regular-control-ie;
border: @scaled-one-px-value solid @border-regular-control;
.border-radius(@border-radius-small);
&:focus:not(.disabled) {
border-color: @border-control-focus-ie;
border-color: @border-control-focus;
}
}
&:before,
@ -737,6 +750,11 @@
padding-right: 10px;
}
&:focus:not(.disabled) {
border-color: @border-control-focus-ie;
border-color: @border-control-focus;
}
&:hover:not(.disabled),
.over:not(.disabled) {
background-color: @highlight-button-hover-ie !important;
@ -788,6 +806,7 @@
&.active:not(.disabled) {
background-color: @highlight-button-pressed-ie !important;
background-color: @highlight-button-pressed !important;
color: @text-normal-pressed-ie;
color: @text-normal-pressed;
}
@ -934,6 +953,12 @@
&.active {
background-color: @background-normal-ie !important;
background-color: @background-normal !important;
&:not(:disabled) {
svg.icon {
opacity: inherit;
}
}
}
&:active:not(.disabled),
@ -949,6 +974,57 @@
}
}
.cnt-lang {
color: @text-normal-ie;
color: @text-normal;
height: 20px;
line-height: 18px;
border: 0;
.border-radius(1px);
vertical-align: middle;
.dropdown-toggle {
margin: 0 6px 0 4px;
}
&:hover:not(.disabled) {
background-color: @highlight-button-hover-ie;
background-color: @highlight-button-hover;
}
&[disabled], &.disabled {
opacity: @component-disabled-opacity;
}
.caret {
width: 4px;
height: 4px;
border: solid 1px @icon-normal-ie;
border: solid 1px @icon-normal;
border-bottom: none;
border-right: none;
background-image: none;
transition: transform 0.2s ease;
transform: rotate(-135deg) translate(1px,1px);
}
&.open:not(.disabled){
&, .status-label {
color: @text-normal-pressed-ie;
color: @text-normal-pressed;
}
background-color: @highlight-button-pressed-ie;
background-color: @highlight-button-pressed;
.caret {
transform: rotate(45deg);
border-color: @icon-normal-pressed-ie;
border-color: @icon-normal-pressed;
}
}
}
// Dialog buttons
// ------------------------

View file

@ -20,6 +20,12 @@
position: absolute;
left: 0;
margin-top: auto;
+ span {
outline: @scaled-one-px-value-ie dotted transparent;
outline: @scaled-one-px-value dotted transparent;
display: inline-block;
}
}
&:checked:not(:indeterminate) {
@ -65,4 +71,18 @@
}
}
}
&:focus:not(.disabled) {
input[type=checkbox] {
+ label {
border-color: @border-control-focus-ie;
border-color: @border-control-focus;
+ span {
outline-color: @border-control-focus-ie;
outline-color: @border-control-focus;
}
}
}
}
}

View file

@ -115,8 +115,8 @@
--component-normal-icon-opacity: .8;
--component-hover-icon-opacity: .8;
--component-active-icon-opacity: .8;
--component-active-hover-icon-opacity: .8;
--component-active-icon-opacity: 1;
--component-active-hover-icon-opacity: 1;
--component-disabled-opacity: .3;
--header-component-normal-icon-opacity: 1;

View file

@ -224,6 +224,8 @@
@header-component-active-hover-icon-opacity: var(--header-component-active-hover-icon-opacity, 1);
@menu-icon-item-checked-offset-x: var(--menu-icon-item-checked-offset-x, 0);
@img-border-type-filter: var(--image-border-types-filter, none);
@img-border-type-filter-selected: var(--image-border-types-filter-selected, none);
// Canvas
// ---------------------------

View file

@ -51,3 +51,9 @@
}
}
}
.combo-color {
.form-control:not(input) {
cursor: pointer;
}
}

View file

@ -143,8 +143,8 @@
width: auto;
position: relative;
border: none;
.box-shadow(0 0 0 @scaled-one-px-value-ie @background-normal-ie);
.box-shadow(0 0 0 @scaled-one-px-value @background-normal);
//.box-shadow(0 0 0 @scaled-one-px-value-ie @background-normal-ie);
//.box-shadow(0 0 0 @scaled-one-px-value @background-normal);
> div {
background-repeat: no-repeat;

View file

@ -1,5 +1,3 @@
@img-borders-filter: var(--image-border-types-filter);
@img-borders-filter-selected: var(--image-border-types-filter-selected);
.combobox {
display: block;
@ -33,8 +31,8 @@
float: none;
.image {
-webkit-filter: @img-borders-filter;
filter: @img-borders-filter;
-webkit-filter: @img-border-type-filter;
filter: @img-border-type-filter;
}
}
@ -98,6 +96,16 @@
}
}
&.input-group-nr {
.btn {
&:active {
.caret {
border-color: @icon-normal;
}
}
}
}
li {
a {
white-space: pre;
@ -126,22 +134,22 @@
// ------------------------
li {
img {
-webkit-filter: @img-borders-filter;
filter: @img-borders-filter;
-webkit-filter: @img-border-type-filter;
filter: @img-border-type-filter;
}
canvas {
-webkit-filter: @img-borders-filter;
filter: @img-borders-filter;
-webkit-filter: @img-border-type-filter;
filter: @img-border-type-filter;
}
&.selected {
img {
-webkit-filter: @img-borders-filter-selected;
filter: @img-borders-filter-selected;
-webkit-filter: @img-border-type-filter-selected;
filter: @img-border-type-filter-selected;
}
canvas {
-webkit-filter: @img-borders-filter-selected;
filter: @img-borders-filter-selected;
-webkit-filter: @img-border-type-filter-selected;
filter: @img-border-type-filter-selected;
}
}

View file

@ -39,8 +39,8 @@
&:focus, &.focus {
outline: 0;
color: @text-normal-pressed-ie;
color: @text-normal-pressed;
color: @text-normal-ie;
color: @text-normal;
background-color: @highlight-button-hover-ie;
background-color: @highlight-button-hover;
}
@ -55,14 +55,14 @@
&.over > a {
text-decoration: none;
color: @text-normal-pressed-ie;
color: @text-normal-pressed;
//color: @text-normal-pressed-ie;
//color: @text-normal-pressed;
background-color: @highlight-button-hover-ie;
background-color: @highlight-button-hover;
&:after {
border-left-color: @icon-normal-pressed-ie;
border-left-color: @icon-normal-pressed;
border-left-color: @icon-normal-ie;
border-left-color: @icon-normal;
}
}

View file

@ -138,7 +138,6 @@ textarea.form-control:focus {
right: 22px;
}
}
input {
padding-right: 20px;
}

View file

@ -79,6 +79,10 @@
opacity: @component-disabled-opacity;
}
}
.dbl-clickable& .list-item {
pointer-events: none;
}
}
.no-borders > .listview .item {

View file

@ -77,7 +77,7 @@
}
}
.icon {
.icon.img-commonctrl {
float: left;
width: 35px;
height: 35px;

View file

@ -23,6 +23,12 @@
border: @scaled-one-px-value-ie solid @border-regular-control-ie;
border: @scaled-one-px-value solid @border-regular-control;
border-radius: 50%;
+ span {
outline: @scaled-one-px-value-ie dotted transparent;
outline: @scaled-one-px-value dotted transparent;
display: inline-block;
}
}
&:checked {
@ -49,4 +55,18 @@
}
}
}
&:focus:not(.disabled) {
input[type=radio] {
+ label {
border-color: @border-control-focus-ie;
border-color: @border-control-focus;
+ span {
outline-color: @border-control-focus-ie;
outline-color: @border-control-focus;
}
}
}
}
}

View file

@ -90,6 +90,12 @@
.background-ximage('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAAIUlEQVR42mNgAILz/0GQAQo+/gdBBqLAqE5ydH5k+sgEANHgUH2JtDRHAAAAAElFTkSuQmCC',
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAaAgMAAADZOtQaAAAACVBMVEUAAADPz8/x8fFVrc9qAAAAAXRSTlMAQObYZgAAABZJREFUeNpjYAgNYOBaxcDEgAsMLXkA/sUJfm1m4l8AAAAASUVORK5CYII=', 14px);
.pixel-ratio__1_5 & {
//background-image: ~"url(@{common-image-const-path}/controls/Scroll_center@1.5x.png)";
background-image: data-uri('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAATAgMAAAACIK4YAAAACVBMVEUAAADPz8/x8fFVrc9qAAAAAXRSTlMAQObYZgAAABRJREFUeNpjYAxl4FrBwYAK6CwIAOsnB3Hkb0WyAAAAAElFTkSuQmCC');
background-size: 14px auto;
}
background-repeat: no-repeat;
background-position: 0 center;
.border-radius(2px);

View file

@ -1,4 +1,6 @@
.table-styler {
background-color: @canvas-content-background;
table {
&.transparent {
background-color: @canvas-content-background !important;

View file

@ -216,6 +216,14 @@
&:last-child {
padding-right: 6px;
}
&.small {
padding-left: 10px;
+ .separator {
margin-left: 10px;
}
}
}
.elset {
@ -640,3 +648,58 @@
}
}
}
.item-databar {
.icon {
width: 25px;
height: 25px;
}
svg.icon {
display: inline-block;
vertical-align: middle;
fill: @icon-normal-ie;
fill: @icon-normal;
}
width: 25px;
height: 25px;
}
.item-colorscale {
.icon {
width: 25px;
height: 25px;
}
svg.icon {
display: inline-block;
vertical-align: middle;
fill: @icon-normal-ie;
fill: @icon-normal;
}
width: 25px;
height: 25px;
}
.menu-iconsets {
margin: 5px 5px 0 10px;
.group-items-container > div {
margin-right: 8px !important;
&:not(:hover),
&:not(.selected) {
.box-shadow(none);
}
}
.item-iconset {
img {
margin: 2px;
}
width: 100px;
height: 20px;
}
}

View file

@ -0,0 +1,186 @@
import React, { useState, useEffect } from 'react';
import { f7, ListItem, List, Icon } from 'framework7-react';
import { useTranslation } from 'react-i18next';
const ThemeColors = ({ themeColors, onColorClick, curColor }) => {
return (
<div className='palette'>
{themeColors.map((row, rowIndex) => {
return(
<div key={`tc-row-${rowIndex}`} className='row'>
{row.map((effect, index) => {
return(
<a key={`tc-${rowIndex}-${index}`}
className={(curColor && curColor.color === effect.color && curColor.effectValue === effect.effectValue) ? 'active' : ''}
style={{ background: `#${effect.color}`}}
onClick={() => {onColorClick(effect.color, effect.effectId, effect.effectValue)}}
></a>
)
})}
</div>
)
})}
</div>
)
};
const StandartColors = ({ options, standartColors, onColorClick, curColor }) => {
return (
<div className='palette'>
{standartColors.map((color, index) => {
return(
index === 0 && options.transparent ?
<a key={`sc-${index}`}
className={`transparent ${'transparent' === curColor ? 'active' : ''}`}
onClick={() => {onColorClick('transparent')}}
></a> :
<a key={`sc-${index}`}
className={curColor && curColor === color ? ' active' : ''}
style={{ background: `#${color}` }}
onClick={() => {onColorClick(color)}}
></a>
)
})}
</div>
)
};
const CustomColors = ({ options, customColors, onColorClick, curColor }) => {
const colors = customColors.length > 0 ? customColors : [];
const emptyItems = [];
if (colors.length < options.customcolors) {
for (let i = colors.length; i < options.customcolors; i++) {
emptyItems.push(<a className='empty-color'
key={`dc-empty${i}`}
onClick={() => {onColorClick('empty')}}
></a>)
}
}
return (
<div className='palette'>
{colors && colors.length > 0 && colors.map((color, index) => {
return(
<a key={`dc-${index}`}
className={curColor && curColor === color ? 'active' : ''}
style={{background: `#${color}`}}
onClick={() => {onColorClick(color)}}
></a>
)
})}
{emptyItems.length > 0 && emptyItems}
</div>
)
};
const ThemeColorPalette = props => {
const {t} = useTranslation();
const _t = t('Common.ThemeColorPalette', {returnObjects: true});
const options = {
customcolors: props.customcolors || 10,
standardcolors: props.standardcolors || 10,
themecolors: props.themecolors || 10,
effects: props.effects || 5,
//allowReselect: props.allowReselect !== false,
transparent: props.transparent || false,
value: props.value || '000000',
cls: props.cls || ''
};
const curColor = props.curColor;
const themeColors = [];
const effectColors = Common.Utils.ThemeColor.getEffectColors();
let row = -1;
effectColors.forEach((effect, index) => {
if (0 == index % options.themecolors) {
themeColors.push([]);
row++;
}
themeColors[row].push(effect);
});
const standartColors = Common.Utils.ThemeColor.getStandartColors();
// custom color
let customColors = props.customColors;
if (customColors.length < 1) {
customColors = localStorage.getItem('mobile-custom-colors');
customColors = customColors ? customColors.toLowerCase().split(',') : [];
}
return (
<div className={'color-palettes' + (props.cls ? (' ' + props.cls) : '')}>
<List>
<ListItem className='theme-colors'>
<div>{ _t.textThemeColors }</div>
<ThemeColors themeColors={themeColors} onColorClick={props.changeColor} curColor={curColor}/>
</ListItem>
<ListItem className='standart-colors'>
<div>{ _t.textStandartColors }</div>
<StandartColors options={options} standartColors={standartColors} onColorClick={props.changeColor} curColor={curColor}/>
</ListItem>
<ListItem className='dynamic-colors'>
<div>{ _t.textCustomColors }</div>
<CustomColors options={options} customColors={customColors} onColorClick={props.changeColor} curColor={curColor}/>
</ListItem>
</List>
</div>
)
};
const CustomColorPicker = props => {
//Function to convert rgb color to hex format
const hexDigits = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
const hex = x => {
return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
};
const rgb2hex = rgb => {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
};
let currentColor = props.currentColor;
if (props.autoColor) {
currentColor = rgb2hex(props.autoColor);
}
if (currentColor === 'transparent' || !currentColor) {
currentColor = 'ffffff';
}
const countDynamicColors = props.countdynamiccolors || 10;
const [stateColor, setColor] = useState(`#${currentColor}`);
useEffect(() => {
if (document.getElementsByClassName('color-picker-wheel').length < 1) {
const colorPicker = f7.colorPicker.create({
containerEl: document.getElementsByClassName('color-picker-container')[0],
value: {
hex: `#${currentColor}`
},
on: {
change: function (value) {
setColor(value.getValue().hex);
}
}
});
}
});
const addNewColor = (color) => {
let colors = localStorage.getItem('mobile-custom-colors');
colors = colors ? colors.split(',') : [];
const newColor = color.slice(1);
if (colors.push(newColor) > countDynamicColors) colors.shift(); // 10 - dynamiccolors
localStorage.setItem('mobile-custom-colors', colors.join().toLowerCase());
props.onAddNewColor && props.onAddNewColor(colors, newColor);
};
return(
<div id='color-picker'>
<div className='color-picker-container'></div>
<div className='right-block'>
<div className='color-hsb-preview'>
<div className='new-color-hsb-preview' style={{backgroundColor: stateColor}}></div>
<div className='current-color-hsb-preview' style={{backgroundColor: `#${currentColor}`}}></div>
</div>
<a href='#' id='add-new-color' className='button button-round' onClick={()=>{addNewColor(stateColor)}}>
<Icon icon={'icon-plus'} slot="media" />
</a>
</div>
</div>
)
};
export { ThemeColorPalette, CustomColorPicker };

View file

@ -254,7 +254,7 @@ define([
var me = this;
var usersArray = [];
_.each(editUsers, function(item){
var name = Common.Utils.UserInfoParser.getParsedName(item.asc_getUserName());
var name = AscCommon.UserInfoParser.getParsedName(item.asc_getUserName());
var initials = me.getInitials(name);
if((item.asc_getState()!==false) && !item.asc_getView()) {
var userAttr = {
@ -698,7 +698,7 @@ define([
userColor = item.get_UserColor(),
goto = (item.get_MoveType() == Asc.c_oAscRevisionsMove.MoveTo || item.get_MoveType() == Asc.c_oAscRevisionsMove.MoveFrom);
date = me.dateToLocaleTimeString(date);
var editable = me.appConfig.isReviewOnly && (item.get_UserId() == _userId) || !me.appConfig.isReviewOnly && (!me.appConfig.canUseReviewPermissions || me.checkUserGroups(item.get_UserName()));
var editable = me.appConfig.isReviewOnly && (item.get_UserId() == _userId) || !me.appConfig.isReviewOnly && (!me.appConfig.canUseReviewPermissions || AscCommon.UserInfoParser.canEditReview(item.get_UserName()));
arr.push({date: date, user: user, usercolor: userColor, changetext: changetext, goto: goto, editable: editable});
});
arrChangeReview = arr;
@ -710,11 +710,6 @@ define([
this.updateInfoChange();
},
checkUserGroups: function(username) {
var groups = Common.Utils.UserInfoParser.getParsedGroups(username);
return Common.Utils.UserInfoParser.getCurrentGroups() && groups && (_.intersection(Common.Utils.UserInfoParser.getCurrentGroups(), (groups.length>0) ? groups : [""]).length>0);
},
dateToLocaleTimeString: function (date) {
function format(date) {
var strTime,
@ -774,7 +769,7 @@ define([
},
getInitials: function(name) {
var fio = Common.Utils.UserInfoParser.getParsedName(name).split(' ');
var fio = AscCommon.UserInfoParser.getParsedName(name).split(' ');
var initials = fio[0].substring(0, 1).toUpperCase();
for (var i=fio.length-1; i>0; i--) {
if (fio[i][0]!=='(' && fio[i][0]!==')') {
@ -795,6 +790,16 @@ define([
return comment;
},
findVisibleComment: function(uid) {
var comment;
if (this.groupCollectionFilter.length !== 0) {
comment = this.findVisibleCommentInGroup(uid);
} else if (this.collectionComments.length !== 0) {
comment = _.findWhere(this.collectionComments, {uid: uid, hide: false});
}
return comment;
},
apiShowComments: function(uid) {
var comments,
me = this;
@ -992,12 +997,15 @@ define([
onViewPrevComment: function() {
if (this.showComments && this.showComments.length > 0) {
if (this.indexCurrentComment - 1 < 0) {
this.indexCurrentComment = this.showComments.length - 1;
} else {
this.indexCurrentComment -= 1;
for (var i=0; i<this.showComments.length; i++) {
if (this.indexCurrentComment - 1 < 0) {
this.indexCurrentComment = this.showComments.length - 1;
} else {
this.indexCurrentComment -= 1;
}
if (this.view.renderViewComments(this.showComments, this.indexCurrentComment))
break;
}
this.view.renderViewComments(this.showComments, this.indexCurrentComment);
var me = this;
_.defer(function () {
$('.comment-menu').single('click', _.buffered(me.initMenuComments, 100, me));
@ -1009,12 +1017,15 @@ define([
onViewNextComment: function() {
if (this.showComments && this.showComments.length > 0) {
if (this.indexCurrentComment + 1 === this.showComments.length) {
this.indexCurrentComment = 0;
} else {
this.indexCurrentComment += 1;
for (var i=0; i<this.showComments.length; i++) {
if (this.indexCurrentComment + 1 === this.showComments.length) {
this.indexCurrentComment = 0;
} else {
this.indexCurrentComment += 1;
}
if (this.view.renderViewComments(this.showComments, this.indexCurrentComment))
break;
}
this.view.renderViewComments(this.showComments, this.indexCurrentComment);
var me = this;
_.defer(function () {
$('.comment-menu').single('click', _.buffered(me.initMenuComments, 100, me));
@ -1135,16 +1146,18 @@ define([
caption: me.textEdit,
event: 'edit'
});
if (!comment.resolved) {
_menuItems.push({
caption: me.textResolve,
event: 'resolve'
});
} else {
_menuItems.push({
caption: me.textReopen,
event: 'resolve'
});
if (comment.editable) {
if (!comment.resolved) {
_menuItems.push({
caption: me.textResolve,
event: 'resolve'
});
} else {
_menuItems.push({
caption: me.textReopen,
event: 'resolve'
});
}
}
if ($('.container-collaboration').length > 0) {
_menuItems.push({
@ -1544,8 +1557,9 @@ define([
reply : data.asc_getReply(i).asc_getText(),
time : date.getTime(),
userInitials : this.getInitials(username),
editable : this.appConfig.canEditComments || (data.asc_getReply(i).asc_getUserId() == _userId),
removable : this.appConfig.canDeleteComments || (data.asc_getReply(i).asc_getUserId() == _userId)
editable : (this.appConfig.canEditComments || (data.asc_getReply(i).asc_getUserId() == _userId)) && AscCommon.UserInfoParser.canEditComment(username),
removable : (this.appConfig.canDeleteComments || (data.asc_getReply(i).asc_getUserId() == _userId)) && AscCommon.UserInfoParser.canDeleteComment(username),
hide : !AscCommon.UserInfoParser.canViewComment(data.asc_getReply(i).asc_getUserName())
});
}
}
@ -1574,8 +1588,9 @@ define([
replys : [],
groupName : (groupname && groupname.length>1) ? groupname[1] : null,
userInitials : this.getInitials(username),
editable : this.appConfig.canEditComments || (data.asc_getUserId() == _userId),
removable : this.appConfig.canDeleteComments || (data.asc_getUserId() == _userId)
editable : (this.appConfig.canEditComments || (data.asc_getUserId() == _userId)) && AscCommon.UserInfoParser.canEditComment(username),
removable : (this.appConfig.canDeleteComments || (data.asc_getUserId() == _userId)) && AscCommon.UserInfoParser.canDeleteComment(username),
hide : !AscCommon.UserInfoParser.canViewComment(username)
};
if (comment) {
var replies = this.readSDKReplies(data);
@ -1611,8 +1626,9 @@ define([
comment.quote = data.asc_getQuoteText();
comment.time = date.getTime();
comment.date = me.dateToLocaleTimeString(date);
comment.editable = me.appConfig.canEditComments || (data.asc_getUserId() == _userId);
comment.removable = me.appConfig.canDeleteComments || (data.asc_getUserId() == _userId);
comment.editable = (me.appConfig.canEditComments || (data.asc_getUserId() == _userId)) && AscCommon.UserInfoParser.canEditComment(data.asc_getUserName());
comment.removable = (me.appConfig.canDeleteComments || (data.asc_getUserId() == _userId)) && AscCommon.UserInfoParser.canDeleteComment(data.asc_getUserName());
comment.hide = !AscCommon.UserInfoParser.canViewComment(data.asc_getUserName());
replies = _.clone(comment.replys);
@ -1637,8 +1653,9 @@ define([
reply : data.asc_getReply(i).asc_getText(),
time : dateReply.getTime(),
userInitials : me.getInitials(username),
editable : me.appConfig.canEditComments || (data.asc_getReply(i).asc_getUserId() == _userId),
removable : me.appConfig.canDeleteComments || (data.asc_getReply(i).asc_getUserId() == _userId)
editable : (me.appConfig.canEditComments || (data.asc_getReply(i).asc_getUserId() == _userId)) && AscCommon.UserInfoParser.canEditComment(username),
removable : (me.appConfig.canDeleteComments || (data.asc_getReply(i).asc_getUserId() == _userId)) && AscCommon.UserInfoParser.canDeleteComment(username),
hide : !AscCommon.UserInfoParser.canViewComment(username)
});
}
comment.replys = replies;
@ -1710,6 +1727,15 @@ define([
}
},
findVisibleCommentInGroup: function (id) {
for (var name in this.groupCollectionComments) {
var store = this.groupCollectionComments[name];
var id = _.isArray(id) ? id[0] : id;
var model = _.findWhere(store, {uid: id, hide: false});
if (model) return model;
}
},
onApiRemoveComment: function (id, silentUpdate) {
function remove (collection, key) {
if(collection instanceof Array) {

View file

@ -0,0 +1,245 @@
import React, { Component, Fragment } from 'react';
import { f7 } from 'framework7-react';
import {observer, inject} from "mobx-react";
import { Device } from '../../../../common/mobile/utils/device';
import ContextMenuView, { idContextMenuElement, ActionsWithExtraItems } from '../view/ContextMenu';
const idCntextMenuTargetElement = '#idx-context-menu-target';
class ContextMenuController extends Component {
constructor(props) {
super(props);
this.state = {
opened: false,
items: [],
openedMore: false,
extraItems: []
};
this.onMenuItemClick = this.onMenuItemClick.bind(this);
this.onMenuClosed = this.onMenuClosed.bind(this);
this.onActionClosed = this.onActionClosed.bind(this);
this.onDocumentReady = this.onDocumentReady.bind(this);
this.onApiOpenContextMenu = this.onApiOpenContextMenu.bind(this);
this.onApiHideContextMenu = this.onApiHideContextMenu.bind(this);
this.onApiShowForeignCursorLabel = this.onApiShowForeignCursorLabel.bind(this);
this.onApiHideForeignCursorLabel = this.onApiHideForeignCursorLabel.bind(this);
}
onDocumentReady() {
this.$targetEl = $$(idCntextMenuTargetElement);
if ( !this.$targetEl.length ) {
// this.$targetEl = $$('<div id="idx-context-menu-target" style="position:absolute;width:15px;height:15px;background-color:green;z-index:1;"></div>');
this.$targetEl = $$(`<div id="${idCntextMenuTargetElement.substr(1)}" style="position:absolute;"></div>`);
this.$targetEl.css({left: '-10000px', top: '-10000px'});
$$('#editor_sdk').append(this.$targetEl);
}
const api = Common.EditorApi.get();
api.asc_registerCallback('asc_onShowPopMenu', this.onApiOpenContextMenu);
api.asc_registerCallback('asc_onHidePopMenu', this.onApiHideContextMenu);
api.asc_registerCallback('asc_onShowForeignCursorLabel', this.onApiShowForeignCursorLabel);
api.asc_registerCallback('asc_onHideForeignCursorLabel', this.onApiHideForeignCursorLabel);
}
offsetPopoverTop(popover) {
var app = popover.app,
$el = popover.$el,
$targetEl = popover.$targetEl;
const width = $el.width(),
height = $el.height();
$el.removeClass('popover-on-left popover-on-right popover-on-top popover-on-bottom popover-on-middle').css({
left: '',
top: ''
});
let targetOffsetLeft, targetOffsetTop;
// var safeAreaTop = parseInt($('html').css('--f7-safe-area-top'), 10);
let safeAreaLeft = parseInt($('html').css('--f7-safe-area-left'), 10),
safeAreaRight = parseInt($('html').css('--f7-safe-area-right'), 10);
// if (Number.isNaN(safeAreaTop)) safeAreaTop = 0;
if (Number.isNaN(safeAreaLeft)) safeAreaLeft = 0;
if (Number.isNaN(safeAreaRight)) safeAreaRight = 0;
if ($targetEl && $targetEl.length > 0) {
let targetOffset = $targetEl.offset();
targetOffsetLeft = targetOffset.left - app.left;
targetOffsetTop = targetOffset.top - app.top;
let targetParentPage = $targetEl.parents('.page');
if (targetParentPage.length > 0) {
targetOffsetTop -= targetParentPage[0].scrollTop;
}
}
let position = 'top';
let top = targetOffsetTop - height - 10;
top = Math.max(8, Math.min(top, app.height - height - 8)); // Horizontal Position
let hPosition;
// if (targetOffsetLeft < app.width / 2) {
// hPosition = 'right';
// left = position === 'middle' ? targetOffsetLeft + targetWidth : targetOffsetLeft;
// } else {
// hPosition = 'left';
// left = position === 'middle' ? targetOffsetLeft - width : targetOffsetLeft + targetWidth - width;
// }
hPosition = 'middle';
let left = targetOffsetLeft - width / 2;
left = Math.max(8, Math.min(left, app.width - width - 8 - safeAreaRight), safeAreaLeft);
$el.addClass(`popover-on-${position} popover-on-${hPosition}`);
$el.css({top: `${top}px`,
left: `${left}px`});
}
onApiOpenContextMenu(x, y) {
if ( !this.state.opened && $$('.dialog.modal-in').length < 1) {
this.setState({
items: this.initMenuItems(),
extraItems: this.initExtraItems()
});
if ( this.state.items.length > 0 ) {
this.$targetEl.css({left: `${x}px`, top: `${y}px`});
const popover = f7.popover.open(idContextMenuElement, idCntextMenuTargetElement);
if (Device.android)
this.offsetPopoverTop(popover);
this.setState(state => {
return {opened: true}
});
}
}
}
onApiHideContextMenu() {
if ( this.state.opened ) {
$$(idContextMenuElement).hide();
f7.popover.close(idContextMenuElement, false);
this.$targetEl.css({left: '-10000px', top: '-10000px'});
this.setState({opened: false});
}
}
onMenuClosed() {
this.$targetEl.css({left: '-10000px', top: '-10000px'});
this.setState({opened: false});
// (async () => {
// await 1 && this.setState(state => {
// this.$targetEl.css({left: '-10000px', top: '-10000px'});
// return ({opened: false});
// });
// })();
}
onActionClosed() {
this.setState({openedMore: false});
}
onMenuItemClick(action) {
this.onApiHideContextMenu();
if (action === 'showActionSheet') {
this.setState({openedMore: true});
}
}
onApiShowForeignCursorLabel(UserId, X, Y, color) {
/** coauthoring begin **/
const tipHeight = 20;
if (!this.fastCoAuthTips) {
this.fastCoAuthTips = [];
}
let src;
for (let i=0; i<this.fastCoAuthTips.length; i++) {
if (this.fastCoAuthTips[i].attr('userid') === UserId) {
src = this.fastCoAuthTips[i];
break;
}
}
if (!src) {
src = $$(`<div class="username-tip"></div>`);
src.attr('userid', UserId);
src.css({'background-color': '#'+Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b())});
src.text(this.getUserName(UserId));
$$('#id_main_parent').append(src);
this.fastCoAuthTips.push(src);
//src.fadeIn(150);
src[0].classList.add('active');
$$('#id_main_view').append(src);
}
src.css({
top: (Y - tipHeight) + 'px',
left: X + 'px'});
/** coauthoring end **/
}
onApiHideForeignCursorLabel(userId) {
/** coauthoring begin **/
for (let i=0; i<this.fastCoAuthTips.length; i++) {
if (this.fastCoAuthTips[i].attr('userid') == userId) {
const src = this.fastCoAuthTips[i];
//this.fastCoAuthTips[i].fadeOut(150, () => {src.remove()});
src[0].classList.remove('active');
src.remove();
this.fastCoAuthTips.splice(i, 1);
break;
}
}
/** coauthoring end **/
}
componentWillUnmount() {
Common.Notifications.off('document:ready', this.onDocumentReady);
const api = Common.EditorApi.get();
api.asc_unregisterCallback('asc_onShowPopMenu', this.onApiOpenContextMenu);
api.asc_unregisterCallback('asc_onHidePopMenu', this.onApiHideContextMenu);
api.asc_unregisterCallback('asc_onShowForeignCursorLabel', this.onApiShowForeignCursorLabel);
api.asc_unregisterCallback('asc_onHideForeignCursorLabel', this.onApiHideForeignCursorLabel);
}
componentDidMount() {
if ( !Common.EditorApi ) {
Common.Notifications.on({
'document:ready': this.onDocumentReady
});
} else {
this.onDocumentReady();
}
}
initMenuItems() {
return [];
}
initExtraItems () {
return [];
}
render() {
return (
<Fragment>
<ContextMenuView items={this.state.items} onMenuClosed={this.onMenuClosed} onMenuItemClick={this.onMenuItemClick} />
<ActionsWithExtraItems items={this.state.extraItems} onMenuItemClick={this.onMenuItemClick} opened={this.state.openedMore} onActionClosed={this.onActionClosed}/>
</Fragment>
)
}
}
export default ContextMenuController;

View file

@ -269,6 +269,7 @@ define([
arr.push(plugin);
});
me.api.asc_pluginsRegister('', arr);
Common.Gateway.pluginsReady();
},
getPlugins: function(pluginsData, fetchFunction) {

View file

@ -0,0 +1,288 @@
import React, { useEffect, useState } from 'react';
import { inject, observer } from 'mobx-react';
import { f7 } from 'framework7-react';
import { Device } from '../../utils/device';
const PluginsController = inject('storeAppOptions')(observer(props => {
const { storeAppOptions } = props;
let configPlugins = {autostart:[]},
serverPlugins = {autostart:[]},
modal,
iframe;
useEffect(() => {
const onDocumentReady = () => {
Common.Notifications.on('engineCreated', api => {
api.asc_registerCallback("asc_onPluginShow", showPluginModal);
api.asc_registerCallback("asc_onPluginClose", pluginClose);
api.asc_registerCallback("asc_onPluginResize", pluginResize);
api.asc_registerCallback('asc_onPluginsInit', onPluginsInit);
if(!storeAppOptions.customization || storeAppOptions.plugins !== false) {
loadPlugins();
}
});
Common.Gateway.on('init', loadConfig);
};
onDocumentReady();
return () => {
const api = Common.EditorApi.get();
api.asc_unregisterCallback("asc_onPluginShow", showPluginModal);
api.asc_unregisterCallback("asc_onPluginClose", pluginClose);
api.asc_unregisterCallback("asc_onPluginResize", pluginResize);
api.asc_unregisterCallback('asc_onPluginsInit', onPluginsInit);
Common.Gateway.off('init', loadConfig);
};
});
const onDlgBtnClick = e => {
const api = Common.EditorApi.get();
let index = $$(e.currentTarget).index();
api.asc_pluginButtonClick(index);
};
const showPluginModal = (plugin, variationIndex, frameId, urlAddition) => {
let isAndroid = Device.android;
let variation = plugin.get_Variations()[variationIndex];
if (variation.get_Visual()) {
let url = variation.get_Url();
url = ((plugin.get_BaseUrl().length == 0) ? url : plugin.get_BaseUrl()) + url;
if (urlAddition)
url += urlAddition;
let isCustomWindow = variation.get_CustomWindow(),
arrBtns = variation.get_Buttons(),
newBtns = [],
size = variation.get_Size();
if (arrBtns.length) {
arrBtns.forEach((b, index) => {
if ((storeAppOptions.isEdit || b.isViewer !== false)) {
newBtns[index] = {
text: b.text,
attributes: {result: index}
};
}
});
}
f7.popover.close('.document-menu.modal-in', false);
modal = f7.dialog.create({
title: '',
text: '',
content: '<div id="plugin-frame" class="">'+'</div>',
buttons : isCustomWindow ? undefined : newBtns
}).open();
iframe = document.createElement("iframe");
iframe.id = frameId;
iframe.name = 'pluginFrameEditor';
iframe.width = '100%';
iframe.height = '100%';
iframe.align = "top";
iframe.frameBorder = 0;
iframe.scrolling = "no";
iframe.src = url;
$$('#plugin-frame').append(iframe);
modal.$el.find('.dialog-button').on('click', onDlgBtnClick);
modal.$el.css({
margin: '0',
width: '90%',
left: '5%',
height: 'auto'
});
modal.$el.find('.dialog-inner').css({padding: '0'});
if (Device.phone) {
let height = Math.min(size[1], 240);
modal.$el.find('#plugin-frame').css({height: height + 'px'});
} else {
let height = Math.min(size[1], 500);
modal.$el.find('#plugin-frame').css({height: height + 'px'});
}
if (isAndroid) {
$$('.view.collaboration-root-view.navbar-through').removeClass('navbar-through').addClass('navbar-fixed');
$$('.view.collaboration-root-view .navbar').prependTo('.view.collaboration-root-view > .pages > .page');
}
}
};
const pluginClose = plugin => {
if (iframe) {
iframe = null;
}
};
const pluginResize = size => {
if (Device.phone) {
let height = Math.min(size[1], 240);
modal.$el.find('#plugin-frame').css({height: height + 'px'});
} else {
let height = Math.min(size[1], 500);
modal.$el.find('#plugin-frame').css({height: height + 'px'});
}
};
const getPlugins = (pluginsData, fetchFunction) => {
if (!pluginsData || pluginsData.length < 1)
return Promise.resolve([]);
fetchFunction = fetchFunction || function (url) {
return fetch(url)
.then(function(response) {
if (response.ok) return response.json();
else return Promise.reject(url);
}).then(function(json) {
json.baseUrl = url.substring(0, url.lastIndexOf("config.json"));
return json;
});
};
let loaded = [];
return pluginsData.map(fetchFunction).reduce(function (previousPromise, currentPromise) {
return previousPromise
.then(function()
{
return currentPromise;
})
.then(function(item)
{
loaded.push(item);
return Promise.resolve(item);
})
.catch(function(item)
{
return Promise.resolve(item);
});
}, Promise.resolve())
.then(function ()
{
return Promise.resolve(loaded);
});
};
const loadConfig = data => {
configPlugins.config = data.config.plugins;
};
const onPluginsInit = pluginsdata => {
!(pluginsdata instanceof Array) && (pluginsdata = pluginsdata["pluginsData"]);
registerPlugins(pluginsdata)
};
const registerPlugins = plugins => {
let arr = [];
plugins.forEach(item => {
let plugin = new Asc.CPlugin();
plugin.set_Name(item['name']);
plugin.set_Guid(item['guid']);
plugin.set_BaseUrl(item['baseUrl']);
let variations = item['variations'],
variationsArr = [];
variations.forEach(itemVar => {
let variation = new Asc.CPluginVariation();
variation.set_Description(itemVar['description']);
variation.set_Url(itemVar['url']);
variation.set_Icons(itemVar['icons']);
variation.set_Visual(itemVar['isVisual']);
variation.set_CustomWindow(itemVar['isCustomWindow']);
variation.set_System(itemVar['isSystem']);
variation.set_Viewer(itemVar['isViewer']);
variation.set_EditorsSupport(itemVar['EditorsSupport']);
variation.set_Modal(itemVar['isModal']);
variation.set_InsideMode(itemVar['isInsideMode']);
variation.set_InitDataType(itemVar['initDataType']);
variation.set_InitData(itemVar['initData']);
variation.set_UpdateOleOnResize(itemVar['isUpdateOleOnResize']);
variation.set_Buttons(itemVar['buttons']);
variation.set_Size(itemVar['size']);
variation.set_InitOnSelectionChanged(itemVar['initOnSelectionChanged']);
variation.set_Events(itemVar['events']);
variationsArr.push(variation);
});
plugin["set_Variations"](variationsArr);
arr.push(plugin);
});
const api = Common.EditorApi.get();
api.asc_pluginsRegister('', arr);
};
const mergePlugins = () => {
if (serverPlugins.plugins !== undefined && configPlugins.plugins !== undefined) {
let arr = [],
plugins = configPlugins;
if (plugins.plugins && plugins.plugins.length > 0) {
arr = plugins.plugins;
}
plugins = serverPlugins;
if (plugins.plugins && plugins.plugins.length > 0) {
arr = arr.concat(plugins.plugins);
}
registerPlugins(arr);
}
};
const loadPlugins = () => {
if (configPlugins.config) {
getPlugins(configPlugins.config.pluginsData)
.then(function(loaded)
{
configPlugins.plugins = loaded;
mergePlugins();
});
} else {
configPlugins.plugins = false;
}
let server_plugins_url = '../../../../plugins.json';
Common.Utils.loadConfig(server_plugins_url, function (obj) {
if (obj != 'error') {
serverPlugins.config = obj;
getPlugins(serverPlugins.config.pluginsData)
.then(function(loaded)
{
serverPlugins.plugins = loaded;
mergePlugins();
});
} else
serverPlugins.plugins = false;
});
};
return <></>
}));
export default PluginsController;

View file

@ -0,0 +1,12 @@
import React from 'react';
import {SearchView, SearchSettingsView} from '../view/Search';
const SearchController = props => {
const onSearchQuery = params => {
console.log('on search: ' + params);
};
return <SearchView onSearchQuery={onSearchQuery} />
};
export {SearchController, SearchView, SearchSettingsView};

View file

@ -0,0 +1,92 @@
import React, { Component } from 'react'
import { f7 } from 'framework7-react';
import {observer, inject} from "mobx-react"
import { LocalStorage } from '../../../utils/LocalStorage';
import { withTranslation } from 'react-i18next';
class CollaborationController extends Component {
constructor(props){
super(props);
Common.Notifications.on('engineCreated', (api) => {
api.asc_registerCallback('asc_onAuthParticipantsChanged', this.onChangeEditUsers.bind(this));
api.asc_registerCallback('asc_onParticipantsChanged', this.onChangeEditUsers.bind(this));
api.asc_registerCallback('asc_onConnectionStateChanged', this.onUserConnection.bind(this));
api.asc_registerCallback('asc_onCoAuthoringDisconnect', this.onCoAuthoringDisconnect.bind(this));
api.asc_registerCallback('asc_OnTryUndoInFastCollaborative', this.onTryUndoInFastCollaborative.bind(this));
});
Common.Notifications.on('document:ready', this.onDocumentReady.bind(this));
}
onDocumentReady() {
const api = Common.EditorApi.get();
const appOptions = this.props.storeAppOptions;
/** coauthoring begin **/
let isFastCoauth;
if (appOptions.isEdit && appOptions.canLicense && !appOptions.isOffline && appOptions.canCoAuthoring) {
// Force ON fast co-authoring mode
isFastCoauth = true;
api.asc_SetFastCollaborative(isFastCoauth);
if (window.editorType === 'de') {
const value = LocalStorage.getItem((isFastCoauth) ? "de-settings-showchanges-fast" : "de-settings-showchanges-strict");
if (value !== null) {
api.SetCollaborativeMarksShowType(
value === 'all' ? Asc.c_oAscCollaborativeMarksShowType.All :
value === 'none' ? Asc.c_oAscCollaborativeMarksShowType.None : Asc.c_oAscCollaborativeMarksShowType.LastChanges);
} else {
api.SetCollaborativeMarksShowType(isFastCoauth ? Asc.c_oAscCollaborativeMarksShowType.None : Asc.c_oAscCollaborativeMarksShowType.LastChanges);
}
}
} else if (!appOptions.isEdit && appOptions.isRestrictedEdit) {
isFastCoauth = true;
api.asc_SetFastCollaborative(isFastCoauth);
window.editorType === 'de' && api.SetCollaborativeMarksShowType(Asc.c_oAscCollaborativeMarksShowType.None);
api.asc_setAutoSaveGap(1);
} else {
isFastCoauth = false;
api.asc_SetFastCollaborative(isFastCoauth);
window.editorType === 'de' && api.SetCollaborativeMarksShowType(Asc.c_oAscCollaborativeMarksShowType.None);
}
if (appOptions.isEdit) {
let value;
if (window.editorType === 'sse') {
value = appOptions.canAutosave ? 1 : 0; // FORCE AUTOSAVE
} else {
value = isFastCoauth; // Common.localStorage.getItem("de-settings-autosave");
value = (!isFastCoauth && value !== null) ? parseInt(value) : (appOptions.canCoAuthoring ? 1 : 0);
}
api.asc_setAutoSaveGap(value);
}
/** coauthoring end **/
}
onChangeEditUsers(users) {
const storeUsers = this.props.users;
storeUsers.reset(users);
storeUsers.setCurrentUser(this.props.storeAppOptions.user.id);
}
onUserConnection(change) {
this.props.users.connection(change);
}
onCoAuthoringDisconnect() {
this.props.users.resetDisconnected(true);
}
onTryUndoInFastCollaborative() {
const { t } = this.props;
const _t = t("Common.Collaboration", { returnObjects: true });
f7.dialog.alert(_t.textTryUndoRedo, _t.notcriticalErrorTitle);
}
render() {
return null
}
}
export default inject('users', 'storeAppOptions')(observer(withTranslation()(CollaborationController)));

View file

@ -0,0 +1,585 @@
import React, {Component, Fragment} from 'react';
import { inject, observer } from "mobx-react";
import { f7 } from 'framework7-react';
import {Device} from '../../../../../common/mobile/utils/device';
import { withTranslation} from 'react-i18next';
import { LocalStorage } from '../../../utils/LocalStorage';
import {AddComment, EditComment, AddReply, EditReply, ViewComments, ViewCurrentComments} from '../../view/collaboration/Comments';
// utils
const timeZoneOffsetInMs = (new Date()).getTimezoneOffset() * 60000;
const utcDateToString = (date) => {
if (Object.prototype.toString.call(date) === '[object Date]')
return (date.getTime() - timeZoneOffsetInMs).toString();
return '';
};
const ooDateToString = (date) => {
if (Object.prototype.toString.call(date) === '[object Date]')
return (date.getTime()).toString();
return '';
};
const stringOOToLocalDate = (date) => {
if (typeof date === 'string')
return parseInt(date);
return 0;
};
const stringUtcToLocalDate = (date) => {
if (typeof date === 'string')
return parseInt(date) + timeZoneOffsetInMs;
return 0;
};
const dateToLocaleTimeString = (date) => {
const format = (date) => {
let hours = date.getHours();
let minutes = date.getMinutes();
let ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0' + minutes : minutes;
return hours + ':' + minutes + ' ' + ampm;
};
// MM/dd/yyyy hh:mm AM
return (date.getMonth() + 1) + '/' + (date.getDate()) + '/' + date.getFullYear() + ' ' + format(date);
};
//end utils
class CommentsController extends Component {
constructor(props) {
super(props);
this.usersStore = this.props.users;
this.appOptions = this.props.storeAppOptions;
this.storeComments = this.props.storeComments;
Common.Notifications.on('engineCreated', api => {
api.asc_registerCallback('asc_onAddComment', this.addComment.bind(this));
api.asc_registerCallback('asc_onAddComments', this.addComments.bind(this));
api.asc_registerCallback('asc_onRemoveComment', this.removeComment.bind(this));
api.asc_registerCallback('asc_onRemoveComments', this.removeComments.bind(this));
api.asc_registerCallback('asc_onChangeCommentData', this.changeCommentData.bind(this));
api.asc_registerCallback('asc_onShowComment', this.changeShowComments.bind(this));
api.asc_registerCallback('asc_onHideComment', this.hideComments.bind(this));
if (window.editorType === 'sse') {
api.asc_registerCallback('asc_onActiveSheetChanged', this.onApiActiveSheetChanged.bind(this));
Common.Notifications.on('comments:filterchange', this.onFilterChange.bind(this));
Common.Notifications.on('sheet:active', this.onApiActiveSheetChanged.bind(this));
}
});
Common.Notifications.on('document:ready', () => {
if (window.editorType === 'de' || window.editorType === 'sse') {
const api = Common.EditorApi.get();
/** coauthoring begin **/
const isLiveCommenting = LocalStorage.getBool(`${window.editorType}-mobile-settings-livecomment`, true);
const resolved = LocalStorage.getBool(`${window.editorType}-settings-resolvedcomment`, true);
isLiveCommenting ? api.asc_showComments(resolved) : api.asc_hideComments();
/** coauthoring end **/
}
this.curUserId = this.props.users.currentUser.asc_getIdOriginal();
});
}
onApiActiveSheetChanged (index) {
this.onFilterChange(['doc', 'sheet' + Common.EditorApi.get().asc_getWorksheetId(index)]);
}
addComment (id, data) {
const comment = this.readSDKComment(id, data);
if (comment) {
this.storeComments.addComment(comment);
}
}
addComments (data) {
for (let i = 0; i < data.length; ++i) {
const comment = this.readSDKComment(data[i].asc_getId(), data[i]);
this.storeComments.addComment(comment);
}
}
removeComment (id) {
this.storeComments.removeComment(id);
}
removeComments (data) {
for (let i = 0; i < data.length; i++) {
this.removeComment(data[i]);
}
}
changeShowComments (id) {
this.storeComments.changeShowComment(id);
}
hideComments () {
//Common.Notifications.trigger('closeviewcomment');
}
changeCommentData (id, data) {
const changeComment = {};
const date = (data.asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getOnlyOfficeTime())) :
((data.asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getTime())));
let user = this.usersStore.searchUserById(data.asc_getUserId());
changeComment.comment = data.asc_getText();
changeComment.userId = data.asc_getUserId();
changeComment.userName = data.asc_getUserName();
changeComment.userColor = (user) ? user.asc_getColor() : null;
changeComment.resolved = data.asc_getSolved();
changeComment.quote = data.asc_getQuoteText();
changeComment.time = date.getTime();
changeComment.date = dateToLocaleTimeString(date);
changeComment.editable = this.appOptions.canEditComments || (data.asc_getUserId() === this.curUserId);
changeComment.removable = this.appOptions.canDeleteComments || (data.asc_getUserId() === this.curUserId);
let dateReply = null;
const replies = [];
const repliesCount = data.asc_getRepliesCount();
for (let i = 0; i < repliesCount; ++i) {
dateReply = (data.asc_getReply(i).asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getReply(i).asc_getOnlyOfficeTime())) :
((data.asc_getReply(i).asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getReply(i).asc_getTime())));
user = this.usersStore.searchUserById(data.asc_getReply(i).asc_getUserId());
const userName = data.asc_getReply(i).asc_getUserName();
replies.push({
ind: i,
userId: data.asc_getReply(i).asc_getUserId(),
userName: userName,
userColor: (user) ? user.asc_getColor() : null,
date: dateToLocaleTimeString(dateReply),
reply: data.asc_getReply(i).asc_getText(),
time: dateReply.getTime(),
userInitials: this.usersStore.getInitials(userName),
editable: this.appOptions.canEditComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId),
removable: this.appOptions.canDeleteComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId)
});
}
changeComment.replies = replies;
this.props.storeComments.changeComment(id, changeComment);
}
onFilterChange (filter) {
this.storeComments.changeFilter(filter);
}
readSDKComment (id, data) {
const date = (data.asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getOnlyOfficeTime())) :
((data.asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getTime())));
const user = this.usersStore.searchUserById(data.asc_getUserId());
const groupName = id.substr(0, id.lastIndexOf('_')+1).match(/^(doc|sheet[0-9_]+)_/);
const userName = data.asc_getUserName();
const comment = {
uid : id,
userId : data.asc_getUserId(),
userName : userName,
userColor : (user) ? user.asc_getColor() : null,
date : dateToLocaleTimeString(date),
quote : data.asc_getQuoteText(),
comment : data.asc_getText(),
resolved : data.asc_getSolved(),
unattached : !!data.asc_getDocumentFlag ? data.asc_getDocumentFlag() : false,
time : date.getTime(),
replies : [],
groupName : (groupName && groupName.length>1) ? groupName[1] : null,
userInitials : this.usersStore.getInitials(userName),
editable : this.appOptions.canEditComments || (data.asc_getUserId() === this.curUserId),
removable : this.appOptions.canDeleteComments || (data.asc_getUserId() === this.curUserId)
};
if (comment) {
const replies = this.readSDKReplies(data);
if (replies.length > 0) {
comment.replies = replies;
}
}
return comment;
}
readSDKReplies (data) {
const replies = [];
const repliesCount = data.asc_getRepliesCount();
let i = 0;
let date = null;
if (repliesCount) {
for (i = 0; i < repliesCount; ++i) {
date = (data.asc_getReply(i).asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getReply(i).asc_getOnlyOfficeTime())) :
((data.asc_getReply(i).asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getReply(i).asc_getTime())));
const user = this.usersStore.searchUserById(data.asc_getReply(i).asc_getUserId());
const userName = data.asc_getReply(i).asc_getUserName();
replies.push({
ind : i,
userId : data.asc_getReply(i).asc_getUserId(),
userName : userName,
userColor : (user) ? user.asc_getColor() : null,
date : dateToLocaleTimeString(date),
reply : data.asc_getReply(i).asc_getText(),
time : date.getTime(),
userInitials : this.usersStore.getInitials(userName),
editable : this.appOptions.canEditComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId),
removable : this.appOptions.canDeleteComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId)
});
}
}
return replies;
}
render() {
return null;
}
}
class AddCommentController extends Component {
constructor(props) {
super(props);
this.closeAddComment = this.closeAddComment.bind(this);
this.getUserInfo = this.getUserInfo.bind(this);
this.onAddNewComment = this.onAddNewComment.bind(this);
this.state = {
isOpen: false
};
Common.Notifications.on('addcomment', () => {
this.setState({isOpen: true});
});
}
closeAddComment () {
this.setState({isOpen: false});
}
getUserInfo () {
this.currentUser = this.props.users.currentUser;
if (!this.currentUser) {
this.currentUser = this.props.users.setCurrentUser(this.props.storeAppOptions.user.id);
}
const name = this.currentUser.asc_getUserName();
return {
name: name,
initials: this.props.users.getInitials(name),
color: this.currentUser.asc_getColor()
};
}
onAddNewComment (commentText, documentFlag) {
const api = Common.EditorApi.get();
let comment;
if (typeof Asc.asc_CCommentDataWord !== 'undefined') {
comment = new Asc.asc_CCommentDataWord(null);
} else {
comment = new Asc.asc_CCommentData(null);
}
if (commentText.length > 0) {
comment.asc_putText(commentText);
comment.asc_putTime(utcDateToString(new Date()));
comment.asc_putOnlyOfficeTime(ooDateToString(new Date()));
comment.asc_putUserId(this.currentUser.asc_getIdOriginal());
comment.asc_putUserName(this.currentUser.asc_getUserName());
comment.asc_putSolved(false);
!!comment.asc_putDocumentFlag && comment.asc_putDocumentFlag(documentFlag);
api.asc_addComment(comment);
}
}
render() {
return(
this.state.isOpen ? <AddComment userInfo={this.getUserInfo()} onAddNewComment={this.onAddNewComment} closeAddComment={this.closeAddComment}/> : null
)
}
}
class EditCommentController extends Component {
constructor (props) {
super(props);
this.onEditComment = this.onEditComment.bind(this);
this.onAddReply = this.onAddReply.bind(this);
this.onEditReply = this.onEditReply.bind(this);
}
getUserInfo () {
this.currentUser = this.props.users.currentUser;
const name = this.currentUser.asc_getUserName();
return {
name: name,
initials: this.props.users.getInitials(name),
color: this.currentUser.asc_getColor()
};
}
onChangeComment (comment) {
const ascComment = typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null);
if (ascComment && comment) {
ascComment.asc_putText(comment.comment);
ascComment.asc_putQuoteText(comment.quote);
ascComment.asc_putTime(utcDateToString(new Date(comment.time)));
ascComment.asc_putOnlyOfficeTime(ooDateToString(new Date(comment.time)));
ascComment.asc_putUserId(comment.userId);
ascComment.asc_putUserName(comment.userName);
ascComment.asc_putSolved(comment.resolved);
ascComment.asc_putGuid(comment.guid);
if (!!ascComment.asc_putDocumentFlag) {
ascComment.asc_putDocumentFlag(comment.unattached);
}
const reply = comment.replies;
if (reply && reply.length > 0) {
reply.forEach((reply) => {
const addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) {
addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time)));
addReply.asc_putOnlyOfficeTime(ooDateToString(new Date(reply.time)));
addReply.asc_putUserId(reply.userId);
addReply.asc_putUserName(reply.userName);
ascComment.asc_addReply(addReply);
}
});
}
const api = Common.EditorApi.get();
api.asc_changeComment(comment.uid, ascComment);
}
}
onEditComment (comment, text) {
const changeComment = {...comment};
changeComment.comment = text.trim();
const user = this.props.users.currentUser;
changeComment.userid = user.asc_getIdOriginal();
changeComment.username = user.asc_getUserName();
this.onChangeComment(changeComment);
}
onAddReply (comment, replyVal) {
let reply = null;
let addReply = null;
const ascComment = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (ascComment) {
ascComment.asc_putText(comment.comment);
ascComment.asc_putQuoteText(comment.quote);
ascComment.asc_putTime(utcDateToString(new Date(comment.time)));
ascComment.asc_putOnlyOfficeTime(ooDateToString(new Date(comment.time)));
ascComment.asc_putUserId(comment.userId);
ascComment.asc_putUserName(comment.userName);
ascComment.asc_putSolved(comment.resolved);
ascComment.asc_putGuid(comment.guid);
if (!!ascComment.asc_putDocumentFlag) {
ascComment.asc_putDocumentFlag(comment.unattached);
}
reply = comment.replies;
if (reply && reply.length) {
reply.forEach(function (reply) {
addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) {
addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time)));
addReply.asc_putOnlyOfficeTime(ooDateToString(new Date(reply.time)));
addReply.asc_putUserId(reply.userId);
addReply.asc_putUserName(reply.userName);
ascComment.asc_addReply(addReply);
}
});
}
addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) {
addReply.asc_putText(replyVal);
addReply.asc_putTime(utcDateToString(new Date()));
addReply.asc_putOnlyOfficeTime(ooDateToString(new Date()));
const currentUser = this.props.users.currentUser;
addReply.asc_putUserId(currentUser.asc_getIdOriginal());
addReply.asc_putUserName(currentUser.asc_getUserName());
ascComment.asc_addReply(addReply);
const api = Common.EditorApi.get();
api.asc_changeComment(comment.uid, ascComment);
}
}
}
onEditReply (comment, reply, textReply) {
const currentUser = this.props.users.currentUser;
const indReply = reply.ind;
const changeComment = {...comment};
changeComment.replies = [...comment.replies];
changeComment.replies[indReply] = {...reply};
changeComment.replies[indReply].reply = textReply;
changeComment.replies[indReply].userid = currentUser.asc_getIdOriginal();
changeComment.replies[indReply].username = currentUser.asc_getUserName();
this.onChangeComment(changeComment);
}
render() {
const storeComments = this.props.storeComments;
const comment = storeComments.currentComment;
return (
<Fragment>
{storeComments.isOpenEditComment && <EditComment comment={comment} onEditComment={this.onEditComment}/>}
{storeComments.isOpenAddReply && <AddReply userInfo={this.getUserInfo()} comment={comment} onAddReply={this.onAddReply}/>}
{storeComments.isOpenEditReply && <EditReply comment={comment} reply={storeComments.currentReply} onEditReply={this.onEditReply}/>}
</Fragment>
)
}
}
class ViewCommentsController extends Component {
constructor (props) {
super(props);
this.onCommentMenuClick = this.onCommentMenuClick.bind(this);
this.onResolveComment = this.onResolveComment.bind(this);
this.closeViewCurComments = this.closeViewCurComments.bind(this);
this.state = {
isOpenViewCurComments: false
};
Common.Notifications.on('viewcomment', () => {
this.setState({isOpenViewCurComments: true});
});
Common.Notifications.on('closeviewcomment', () => {
this.closeViewCurComments();
});
}
closeViewCurComments () {
f7.sheet.close('#view-comment-sheet');
this.setState({isOpenViewCurComments: false});
}
onResolveComment (comment) {
let reply = null,
addReply = null,
ascComment = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (ascComment && comment) {
ascComment.asc_putText(comment.comment);
ascComment.asc_putQuoteText(comment.quote);
ascComment.asc_putTime(utcDateToString(new Date(comment.time)));
ascComment.asc_putOnlyOfficeTime(ooDateToString(new Date(comment.time)));
ascComment.asc_putUserId(comment.userId);
ascComment.asc_putUserName(comment.userName);
ascComment.asc_putSolved(!comment.resolved);
ascComment.asc_putGuid(comment.guid);
if (!!ascComment.asc_putDocumentFlag) {
ascComment.asc_putDocumentFlag(comment.unattached);
}
reply = comment.replies;
if (reply && reply.length > 0) {
reply.forEach((reply) => {
addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) {
addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time)));
addReply.asc_putOnlyOfficeTime(ooDateToString(new Date(reply.time)));
addReply.asc_putUserId(reply.userId);
addReply.asc_putUserName(reply.userName);
ascComment.asc_addReply(addReply);
}
});
}
const api = Common.EditorApi.get();
api.asc_changeComment(comment.uid, ascComment);
}
}
deleteComment (comment) {
const api = Common.EditorApi.get();
comment && api.asc_removeComment(comment.uid);
}
deleteReply (comment, reply) {
let replies = null,
addReply = null,
ascComment = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
const indReply = reply.ind;
if (ascComment && comment) {
ascComment.asc_putText(comment.comment);
ascComment.asc_putQuoteText(comment.quote);
ascComment.asc_putTime(utcDateToString(new Date(comment.time)));
ascComment.asc_putOnlyOfficeTime(ooDateToString(new Date(comment.time)));
ascComment.asc_putUserId(comment.userId);
ascComment.asc_putUserName(comment.userName);
ascComment.asc_putSolved(comment.resolved);
ascComment.asc_putGuid(comment.guid);
if (!!ascComment.asc_putDocumentFlag) {
ascComment.asc_putDocumentFlag(comment.unattached);
}
replies = comment.replies;
if (replies && replies.length) {
replies.forEach((reply) => {
if (reply.ind !== indReply) {
addReply = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) {
addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time)));
addReply.asc_putOnlyOfficeTime(ooDateToString(new Date(reply.time)));
addReply.asc_putUserId(reply.userId);
addReply.asc_putUserName(reply.userName);
ascComment.asc_addReply(addReply);
}
}
});
}
const api = Common.EditorApi.get();
api.asc_changeComment(comment.uid, ascComment);
}
}
onCommentMenuClick (action, comment, reply) {
const { t } = this.props;
const _t = t("Common.Collaboration", { returnObjects: true });
switch (action) {
case 'editComment':
this.props.storeComments.openEditComment(true, comment);
break;
case 'resolve':
this.onResolveComment(comment);
break;
case 'deleteComment':
f7.dialog.confirm(
_t.textMessageDeleteComment,
_t.textDeleteComment,
() => {
this.deleteComment(comment);
}
);
break;
case 'editReply':
this.props.storeComments.openEditReply(true, comment, reply);
break;
case 'deleteReply':
f7.dialog.confirm(
_t.textMessageDeleteReply,
_t.textDeleteReply,
() => {
this.deleteReply(comment, reply);
}
);
break;
case 'addReply':
this.props.storeComments.openAddReply(true, comment);
break;
}
}
render() {
return(
<Fragment>
{this.props.allComments && <ViewComments onCommentMenuClick={this.onCommentMenuClick} onResolveComment={this.onResolveComment} />}
{this.state.isOpenViewCurComments && <ViewCurrentComments opened={this.state.isOpenViewCurComments}
closeCurComments={this.closeViewCurComments}
onCommentMenuClick={this.onCommentMenuClick}
onResolveComment={this.onResolveComment}
/>}
</Fragment>
)
}
}
const _CommentsController = inject('storeAppOptions', 'storeComments', 'users')(observer(CommentsController));
const _AddCommentController = inject('storeAppOptions', 'storeComments', 'users')(observer(AddCommentController));
const _EditCommentController = inject('storeComments', 'users')(observer(EditCommentController));
const _ViewCommentsController = inject('storeComments', 'users')(observer(withTranslation()(ViewCommentsController)));
export {
_CommentsController as CommentsController,
_AddCommentController as AddCommentController,
_EditCommentController as EditCommentController,
_ViewCommentsController as ViewCommentsController
};

View file

@ -0,0 +1,535 @@
import React, { Component } from 'react'
import Notifications from '../../../utils/notifications.js'
import {observer, inject} from "mobx-react"
import { withTranslation } from 'react-i18next';
import {PageReview, PageReviewChange} from "../../view/collaboration/Review";
import {LocalStorage} from "../../../utils/LocalStorage";
class InitReview extends Component {
constructor(props){
super(props);
Common.Notifications.on('engineCreated', api => {
api.asc_registerCallback('asc_onShowRevisionsChange', this.onChangeReview.bind(this));
});
Common.Notifications.on('document:ready', () => {
const api = Common.EditorApi.get();
const appOptions = props.storeAppOptions;
api.asc_SetTrackRevisions(appOptions.isReviewOnly || LocalStorage.getBool("de-mobile-track-changes-" + (appOptions.fileKey || '')));
// Init display mode
if (!appOptions.canReview) {
const canViewReview = appOptions.isEdit || api.asc_HaveRevisionsChanges(true);
appOptions.setCanViewReview(canViewReview);
if (canViewReview) {
let viewReviewMode = LocalStorage.getItem("de-view-review-mode");
if (viewReviewMode === null)
viewReviewMode = appOptions.customization && /^(original|final|markup)$/i.test(appOptions.customization.reviewDisplay) ? appOptions.customization.reviewDisplay.toLocaleLowerCase() : 'original';
viewReviewMode = (appOptions.isEdit || appOptions.isRestrictedEdit) ? 'markup' : viewReviewMode;
const displayMode = viewReviewMode.toLocaleLowerCase();
if (displayMode === 'final') {
api.asc_BeginViewModeInReview(true);
} else if (displayMode === 'original') {
api.asc_BeginViewModeInReview(false);
} else {
api.asc_EndViewModeInReview();
}
props.storeReview.changeDisplayMode(displayMode);
}
}
});
}
onChangeReview (data) {
const storeReview = this.props.storeReview;
storeReview.changeArrReview(data);
}
render() {
return null
}
}
class Review extends Component {
constructor(props) {
super(props);
this.onTrackChanges = this.onTrackChanges.bind(this);
this.onDisplayMode = this.onDisplayMode.bind(this);
this.appConfig = props.storeAppOptions;
this.editorPrefix = window.editorType || '';
let trackChanges = typeof this.appConfig.customization == 'object' ? this.appConfig.customization.trackChanges : undefined;
trackChanges = this.appConfig.isReviewOnly || trackChanges === true || trackChanges !== false
&& LocalStorage.getBool(`${this.editorPrefix}-mobile-track-changes-${this.appConfig.fileKey || ''}`);
this.state = {
trackChanges: trackChanges
}
}
onTrackChanges (checked) {
const api = Common.EditorApi.get();
if ( this.appConfig.isReviewOnly ) {
this.setState({trackChanges: true});
} else {
this.setState({trackChanges: checked});
api.asc_SetTrackRevisions(checked);
LocalStorage.setBool(`${this.editorPrefix}-mobile-track-changes-${this.appConfig.fileKey || ''}`, checked);
}
}
onAcceptAll () {
const api = Common.EditorApi.get();
api.asc_AcceptAllChanges();
}
onRejectAll () {
const api = Common.EditorApi.get();
api.asc_RejectAllChanges();
}
onDisplayMode (mode) {
const api = Common.EditorApi.get();
if (mode === 'final') {
api.asc_BeginViewModeInReview(true);
} else if (mode === 'original') {
api.asc_BeginViewModeInReview(false);
} else {
api.asc_EndViewModeInReview();
}
!this.appConfig.canReview && LocalStorage.setItem("de-view-review-mode", mode);
this.props.storeReview.changeDisplayMode(mode);
}
render() {
const displayMode = this.props.storeReview.displayMode;
const isReviewOnly = this.appConfig.isReviewOnly;
const canReview = this.appConfig.canReview;
const canUseReviewPermissions = this.appConfig.canUseReviewPermissions;
const isRestrictedEdit = this.appConfig.isRestrictedEdit;
return (
<PageReview isReviewOnly={isReviewOnly}
canReview={canReview}
canUseReviewPermissions={canUseReviewPermissions}
isRestrictedEdit={isRestrictedEdit}
displayMode={displayMode}
trackChanges={this.state.trackChanges}
onTrackChanges={this.onTrackChanges}
onAcceptAll={this.onAcceptAll}
onRejectAll={this.onRejectAll}
onDisplayMode={this.onDisplayMode}
noBack={this.props.noBack}
/>
)
}
}
class ReviewChange extends Component {
constructor (props) {
super(props);
this.onAcceptCurrentChange = this.onAcceptCurrentChange.bind(this);
this.onRejectCurrentChange = this.onRejectCurrentChange.bind(this);
this.onGotoNextChange = this.onGotoNextChange.bind(this);
this.onDeleteChange = this.onDeleteChange.bind(this);
this.appConfig = props.storeAppOptions;
if (this.appConfig && this.appConfig.canUseReviewPermissions) {
const permissions = this.appConfig.customization.reviewPermissions;
let arr = [];
const groups = Common.Utils.UserInfoParser.getParsedGroups(Common.Utils.UserInfoParser.getCurrentName());
groups && groups.forEach(function(group) {
const item = permissions[group.trim()];
item && (arr = arr.concat(item));
});
this.currentUserGroups = arr;
}
}
intersection (arr1, arr2) { //Computes the list of values that are the intersection of all the arrays.
const arr = [];
arr1.forEach((item1) => {
arr2.forEach((item2) => {
if (item1 === item2) {
arr.push(item2);
}
});
});
return arr;
}
checkUserGroups (username) {
const groups = Common.Utils.UserInfoParser.getParsedGroups(username);
return this.currentUserGroups && groups && (this.intersection(this.currentUserGroups, (groups.length>0) ? groups : [""]).length>0);
}
dateToLocaleTimeString (date) {
const format = (date) => {
let strTime,
hours = date.getHours(),
minutes = date.getMinutes(),
ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0' + minutes : minutes;
strTime = hours + ':' + minutes + ' ' + ampm;
return strTime;
};
// MM/dd/yyyy hh:mm AM
return (date.getMonth() + 1) + '/' + (date.getDate()) + '/' + date.getFullYear() + ' ' + format(date);
}
getArrChangeReview (data) {
const api = Common.EditorApi.get();
const { t } = this.props;
const _t = t("Common.Collaboration", { returnObjects: true });
if (data.length === 0) return [];
const arr = [];
const c_paragraphLinerule = {
LINERULE_LEAST: 0,
LINERULE_AUTO: 1,
LINERULE_EXACT: 2
};
data.forEach((item) => {
let changeText = [], proptext = [],
value = item.get_Value(),
movetype = item.get_MoveType();
switch (item.get_Type()) {
case Asc.c_oAscRevisionsChangeType.TextAdd:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}`}><b>{movetype === Asc.c_oAscRevisionsMove.NoMove ? _t.textInserted : _t.textParaMoveTo}</b></label>);
if (typeof value == 'object') {
value.forEach( (obj) => {
if (typeof obj === 'string')
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-1`}> {Common.Utils.String.htmlEncode(obj)}</label>);
else {
switch (obj) {
case 0:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-2`}> &lt;{_t.textImage}&gt;</label>);
break;
case 1:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-3`}> &lt;{_t.textShape}&gt;</label>);
break;
case 2:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-4`}> &lt;{_t.textChart}&gt;</label>);
break;
case 3:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-5`}> &lt;{_t.textEquation}&gt;</label>);
break;
}
}
})
} else if (typeof value === 'string') {
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-6`}> {Common.Utils.String.htmlEncode(value)}</label>);
}
break;
case Asc.c_oAscRevisionsChangeType.TextRem:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}`}><b>{(movetype === Asc.c_oAscRevisionsMove.NoMove) ? _t.textDeleted : (item.is_MovedDown() ? _t.textParaMoveFromDown : _t.textParaMoveFromUp)}</b></label>);
if (typeof value == 'object') {
value.forEach( (obj) => {
if (typeof obj === 'string')
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-1`}> {Common.Utils.String.htmlEncode(obj)}</label>);
else {
switch (obj) {
case 0:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-2`}> &lt;{_t.textImage}&gt;</label>);
break;
case 1:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-3`}> &lt;{_t.textShape}&gt;</label>);
break;
case 2:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-4`}> &lt;{_t.textChart}&gt;</label>);
break;
case 3:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-5`}> &lt;{_t.textEquation}&gt;</label>);
break;
}
}
})
} else if (typeof value === 'string') {
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-6`}> {Common.Utils.String.htmlEncode(value)}</label>);
}
break;
case Asc.c_oAscRevisionsChangeType.ParaAdd:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaAdd}`}><b>{_t.textParaInserted}</b> </label>);
break;
case Asc.c_oAscRevisionsChangeType.ParaRem:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaRem}`}><b>{_t.textParaDeleted}</b> </label>);
break;
case Asc.c_oAscRevisionsChangeType.TextPr:
if (value.Get_Bold() !== undefined)
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-1`}>{(value.Get_Bold() ? '' : _t.textNot) + _t.textBold}</label>);
if (value.Get_Italic() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-02`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-2`}>{(value.Get_Italic() ? '' : _t.textNot) + _t.textItalic}</label>);
}
if (value.Get_Underline() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-03`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-3`}>{(value.Get_Underline() ? '' : _t.textNot) + _t.textUnderline}</label>);
}
if (value.Get_Strikeout() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-04`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-4`}>{(value.Get_Strikeout() ? '' : _t.textNot) + _t.textStrikeout}</label>);
}
if (value.Get_DStrikeout() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-05`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-5`}>{(value.Get_DStrikeout() ? '' : _t.textNot) + _t.textDStrikeout}</label>);
}
if (value.Get_Caps() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-06`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-6`}>{(value.Get_Caps() ? '' : _t.textNot) + _t.textCaps}</label>);
}
if (value.Get_SmallCaps() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-07`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-7`}>{(value.Get_SmallCaps() ? '' : _t.textNot) + _t.textSmallCaps}</label>);
}
if (value.Get_VertAlign() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-08`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-8`}>{((value.Get_VertAlign() == 1) ? _t.textSuperScript : ((value.Get_VertAlign() == 2) ? _t.textSubScript : _t.textBaseline))}</label>);
}
if (value.Get_Color() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-09`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-9`}>{_t.textColor}</label>);
}
if (value.Get_Highlight() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-010`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-10`}>{_t.textHighlight}</label>);
}
if (value.Get_Shd() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-011`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-11`}>{_t.textShd}</label>);
}
if (value.Get_FontFamily() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-012`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-12`}>{value.Get_FontFamily()}</label>);
}
if (value.Get_FontSize() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-013`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-13`}>{value.Get_FontSize()}</label>);
}
if (value.Get_Spacing() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-014`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-14`}>{_t.textSpacing} {Common.Utils.Metric.fnRecalcFromMM(value.Get_Spacing()).toFixed(2)} {Common.Utils.Metric.getCurrentMetricName()}</label>);
}
if (value.Get_Position() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-015`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-15`}>{_t.textPosition} {Common.Utils.Metric.fnRecalcFromMM(value.Get_Position()).toFixed(2)} {Common.Utils.Metric.getCurrentMetricName()}</label>);
}
if (value.Get_Lang() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-016`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-16`}>{Common.util.LanguageInfo.getLocalLanguageName(value.Get_Lang())[1]}</label>);
}
if (proptext.length > 0) {
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-17`}><b>{_t.textFormatted}: </b></label>);
proptext.forEach((item) => {
changeText.push(item);
});
} else {
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextPr}-18`}><b>{_t.textFormatted}</b></label>);
}
break;
case Asc.c_oAscRevisionsChangeType.ParaPr:
if (value.Get_ContextualSpacing())
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-1`}>{(value.Get_ContextualSpacing() ? _t.textContextual : _t.textNoContextual)}</label>);
if (value.Get_IndLeft() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-02`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-2`}>{_t.textIndentLeft} {Common.Utils.Metric.fnRecalcFromMM(value.Get_IndLeft()).toFixed(2)} {Common.Utils.Metric.getCurrentMetricName()}</label>);
}
if (value.Get_IndRight() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-03`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-3`}>{_t.textIndentRight} {Common.Utils.Metric.fnRecalcFromMM(value.Get_IndRight()).toFixed(2)} {Common.Utils.Metric.getCurrentMetricName()}</label>);
}
if (value.Get_IndFirstLine() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-04`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-4`}>{_t.textFirstLine} {Common.Utils.Metric.fnRecalcFromMM(value.Get_IndFirstLine()).toFixed(2)} {Common.Utils.Metric.getCurrentMetricName()}</label>);
}
if (value.Get_Jc() !== undefined) {
switch (value.Get_Jc()) {
case 0:
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-05`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-5`}>{_t.textRight}</label>);
break;
case 1:
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-06`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-6`}>{_t.textLeft}</label>);
break;
case 2:
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-07`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-7`}>{_t.textCenter}</label>);
break;
case 3:
proptext.length > 0 && proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-08`}>, </label>);
proptext.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-8`}>{_t.textJustify}</label>);
break;
}
}
if (value.Get_KeepLines() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`keepLines-01`}>, </label>);
proptext.push(<label key={`keepLines-1`}>{(value.Get_KeepLines() ? _t.textKeepLines : _t.textNoKeepLines)}</label>);
}
if (value.Get_KeepNext()) {
proptext.length > 0 && proptext.push(<label key={`keepNext-01`}>, </label>);
proptext.push(<label key={`keepNext-1`}>{(value.Get_KeepNext() ? _t.textKeepNext : _t.textNoKeepNext)}</label>);
}
if (value.Get_PageBreakBefore()) {
proptext.length > 0 && proptext.push(<label key={`breakBefore-01`}>, </label>);
proptext.push(<label key={`breakBefore-1`}>{(value.Get_PageBreakBefore() ? _t.textBreakBefore : _t.textNoBreakBefore)}</label>);
}
if (value.Get_SpacingLineRule() !== undefined && value.Get_SpacingLine() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`spacingLineRule-01`}>, </label>);
proptext.push(<label key={`spacingLineRule-1`}>{t.textLineSpacing}</label>);
proptext.push(<label key={`spacingLineRule-2`}>{((value.Get_SpacingLineRule() == c_paragraphLinerule.LINERULE_LEAST) ? _t.textAtLeast : ((value.Get_SpacingLineRule() == c_paragraphLinerule.LINERULE_AUTO) ? _t.textMultiple : _t.textExact))} </label>);
proptext.push(<label key={`spacingLineRule-3`}>{((value.Get_SpacingLineRule() == c_paragraphLinerule.LINERULE_AUTO) ? value.Get_SpacingLine() : Common.Utils.Metric.fnRecalcFromMM(value.Get_SpacingLine()).toFixed(2) + ' ' + Common.Utils.Metric.getCurrentMetricName())}</label>);
}
if (value.Get_SpacingBeforeAutoSpacing()) {
proptext.length > 0 && proptext.push(<label key={`spacingBeforeAutoSpacing-01`}>, </label>);
proptext.push(<label key={`spacingBeforeAutoSpacing-1`}>{_t.textSpacingBefore} {_t.textAuto}</label>);
}
else if (value.Get_SpacingBefore() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`spacingBefore-01`}>, </label>);
proptext.push(<label key={`spacingBefore-1`}>{_t.textSpacingBefore} {Common.Utils.Metric.fnRecalcFromMM(value.Get_SpacingBefore()).toFixed(2)} {Common.Utils.Metric.getCurrentMetricName()}</label>);
}
if (value.Get_SpacingAfterAutoSpacing()) {
proptext.length > 0 && proptext.push(<label key={`spacingAfterAutoSpacing-01`}>, </label>);
proptext.push(<label key={`spacingAfterAutoSpacing-1`}>{_t.textSpacingAfter} {_t.textAuto}</label>);
}
else if (value.Get_SpacingAfter() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`spacingAfter-01`}>, </label>);
proptext.push(<label key={`spacingAfter-1`}>{_t.textSpacingAfter} {Common.Utils.Metric.fnRecalcFromMM(value.Get_SpacingAfter()).toFixed(2)} {Common.Utils.Metric.getCurrentMetricName()}</label>);
}
if (value.Get_WidowControl()) {
proptext.length > 0 && proptext.push(<label key={`widowControl-01`}>, </label>);
proptext.push(<label key={`widowControl-1`}>{(value.Get_WidowControl() ? _t.textWidow : _t.textNoWidow)}</label>);
}
if (value.Get_Tabs() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`tabs-01`}>, </label>);
proptext.push(<label key={`tabs-1`}>{_t.textTabs}</label>);
}
if (value.Get_NumPr() !== undefined) {
proptext.length > 0 && proptext.push(<label key={`num-01`}>, </label>);
proptext.push(<label key={`num-1`}>{_t.textNum}</label>)
}
if (value.Get_PStyle() !== undefined) {
const style = api.asc_GetStyleNameById(value.Get_PStyle());
if (style.length > 0) {
proptext.length > 0 && proptext.push(<label key={`style-01`}>, </label>);
proptext.push(<label key={`style-1`}>{style}</label>);
}
}
if (proptext.length > 0) {
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-9`}><b>{_t.textParaFormatted}: </b></label>);
proptext.forEach((item) => {
changeText.push(item);
});
} else {
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-10`}><b>{_t.textParaFormatted}</b></label>);
}
break;
case Asc.c_oAscRevisionsChangeType.TablePr:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-11`}><b>{_t.textTableChanged}</b></label>);
break;
case Asc.c_oAscRevisionsChangeType.RowsAdd:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-12`}><b>{_t.textTableRowsAdd}</b></label>);
break;
case Asc.c_oAscRevisionsChangeType.RowsRem:
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.ParaPr}-13`}><b>{_t.textTableRowsDel}</b></label>);
break;
}
let date = (item.get_DateTime() == '') ? new Date() : new Date(item.get_DateTime());
const user = item.get_UserName();
const userColor = item.get_UserColor();
const goto = (item.get_MoveType() == Asc.c_oAscRevisionsMove.MoveTo || item.get_MoveType() == Asc.c_oAscRevisionsMove.MoveFrom);
date = this.dateToLocaleTimeString(date);
const editable = this.appConfig.isReviewOnly && (item.get_UserId() == this.appConfig.user.id) || !this.appConfig.isReviewOnly && (!this.appConfig.canUseReviewPermissions || this.checkUserGroups(item.get_UserName()));
arr.push({date: date, user: user, userColor: userColor, changeText: changeText, goto: goto, editable: editable});
});
return arr;
}
onPrevChange () {
const api = Common.EditorApi.get();
api.asc_GetPrevRevisionsChange();
}
onNextChange () {
const api = Common.EditorApi.get();
api.asc_GetNextRevisionsChange();
}
onAcceptCurrentChange () {
const api = Common.EditorApi.get();
api.asc_AcceptChanges(this.dataChanges[0]);
setTimeout(() => {
api.asc_GetNextRevisionsChange();
});
}
onRejectCurrentChange () {
const api = Common.EditorApi.get();
api.asc_RejectChanges(this.dataChanges[0]);
setTimeout(() => {
api.asc_GetNextRevisionsChange();
});
}
onGotoNextChange () {
const api = Common.EditorApi.get();
api.asc_FollowRevisionMove(this.dataChanges[0]);
}
onDeleteChange () {
const api = Common.EditorApi.get();
api.asc_RejectChanges(this.dataChanges[0]);
}
render() {
this.dataChanges = this.props.storeReview.dataChanges;
const arrChangeReview = this.getArrChangeReview(this.dataChanges);
let change;
let goto = false;
if (arrChangeReview.length > 0) {
change = {
date: arrChangeReview[0].date,
user: arrChangeReview[0].user,
userName: Common.Utils.String.htmlEncode(Common.Utils.UserInfoParser.getParsedName(arrChangeReview[0].user)),
color: arrChangeReview[0].userColor.get_hex(),
text: arrChangeReview[0].changeText,
initials: this.props.users.getInitials(arrChangeReview[0].user),
editable: arrChangeReview[0].editable
};
goto = arrChangeReview[0].goto;
}
const isReviewOnly = this.appConfig.isReviewOnly;
const canReview = this.appConfig.canReview;
const displayMode = this.props.storeReview.displayMode;
return (
<PageReviewChange change={change}
goto={goto}
isReviewOnly={isReviewOnly}
canReview={canReview}
displayMode={displayMode}
onPrevChange={this.onPrevChange}
onNextChange={this.onNextChange}
onAcceptCurrentChange={this.onAcceptCurrentChange}
onRejectCurrentChange={this.onRejectCurrentChange}
onGotoNextChange={this.onGotoNextChange}
onDeleteChange={this.onDeleteChange}
noBack={this.props.noBack}
/>
)
}
}
const InitReviewController = inject("storeAppOptions", "storeReview")(observer(InitReview));
const ReviewController = inject("storeAppOptions", "storeReview")(observer(Review));
const ReviewChangeController = withTranslation()(inject("storeAppOptions", "storeReview", "users")(observer(ReviewChange)));
export {InitReviewController, ReviewController, ReviewChangeController};

View file

@ -0,0 +1,127 @@
import {makeObservable, observable, action, computed} from 'mobx';
export class storeComments {
constructor() {
makeObservable(this, {
collectionComments: observable,
groupCollectionComments: observable,
filter: observable,
showComments: observable,
changeShowComment: action,
addComment: action,
removeComment: action,
changeComment: action,
changeFilter: action,
groupCollectionFilter: computed,
isOpenEditComment: observable,
openEditComment: action,
isOpenAddReply: observable,
openAddReply: action,
isOpenEditReply: observable,
openEditReply: action
})
}
collectionComments = [];
groupCollectionComments = [];
filter = undefined;
showComments = [];
changeShowComment (uid) {
this.showComments.length = 0;
uid.forEach((item) => {
this.showComments.push(this.findComment(item));
});
}
addComment (comment) {
comment.groupName ? this.groupCollectionComments.push(comment) : this.collectionComments.push(comment);
}
removeComment (id) {
const collection = this.collectionComments.length > 0 ? this.collectionComments : this.groupCollectionComments;
const index = collection.findIndex((comment) => {
return comment.uid === id;
});
if (index !== -1) {
collection.splice(index, 1);
}
}
changeComment (id, changeComment) {
const comment = this.findComment(id);
if (comment) {
comment.comment = changeComment.comment;
comment.userId = changeComment.userId;
comment.userName = changeComment.userName;
comment.userColor = changeComment.userColor;
comment.resolved = changeComment.resolved;
comment.quote = changeComment.quote;
comment.time = changeComment.time;
comment.date = changeComment.date;
comment.editable = changeComment.editable;
comment.removable = changeComment.removable;
comment.replies = changeComment.replies;
}
}
changeFilter (filter) {
this.filter = filter;
}
findComment (id) {
const collection = this.collectionComments.length > 0 ? this.collectionComments : this.groupCollectionComments;
let comment = collection.find((item) => {
return item.uid === id;
});
return comment;
}
get groupCollectionFilter () {
if (this.filter && this.groupCollectionComments.length > 0) {
const arr = [];
this.filter.forEach((groupName) => {
this.groupCollectionComments.forEach((comment) => {
if (comment.groupName === groupName) {
arr.push(comment);
}
});
});
return arr;
}
return false;
}
// Edit comment
currentComment = null;
isOpenEditComment = false;
openEditComment (open, comment) {
if (open !== this.isOpenEditComment) {
this.currentComment = open ? comment : null;
this.isOpenEditComment = open;
}
}
currentReply = null;
isOpenAddReply = false;
openAddReply (open, comment) {
if (open !== this.isOpenAddReply) {
this.currentComment = open ? comment : null;
this.isOpenAddReply = open;
}
}
isOpenEditReply = false;
openEditReply (open, comment, reply) {
if (open !== this.isOpenEditReply) {
this.currentComment = open ? comment : null;
this.currentReply = open ? reply : null;
this.isOpenEditReply = open;
}
}
}

View file

@ -0,0 +1,129 @@
import {makeObservable, observable, action, computed} from 'mobx';
export class storeUsers {
constructor() {
makeObservable(this, {
users: observable,
reset: action,
currentUser: observable,
setCurrentUser: action,
connection: action,
isDisconnected: observable,
resetDisconnected: action,
hasEditUsers: computed,
editUsers: computed
})
}
users = [];
currentUser;
isDisconnected = false;
reset (users) {
this.users = Object.values(users)
}
setCurrentUser (id) {
this.users.forEach((item) => {
if (item.asc_getIdOriginal() === id) {
this.currentUser = item;
}
});
return this.currentUser;
}
connection (change) {
let changed = false;
for (let uid in this.users) {
if (undefined !== uid) {
const user = this.users[uid];
if (user && user.asc_getId() === change.asc_getId()) {
this.users[uid] = change;
changed = true;
}
}
}
!changed && change && (this.users[change.asc_getId()] = change);
}
resetDisconnected (isDisconnected) {
this.isDisconnected = isDisconnected;
}
getInitials (name) {
const fio = Common.Utils.UserInfoParser.getParsedName(name).split(' ');
let initials = fio[0].substring(0, 1).toUpperCase();
for (let i = fio.length-1; i>0; i--) {
if (fio[i][0]!=='(' && fio[i][0]!==')') {
initials += fio[i].substring(0, 1).toUpperCase();
break;
}
}
return initials;
}
searchUserById (id) {
let user = null;
this.users.forEach((item) => {
if (item.asc_getIdOriginal() === id) {
user = item;
}
});
return user;
}
searchUserByCurrentId (id) {
let user = null;
this.users.forEach((item) => {
if (item.asc_getId() === id) {
user = item;
}
});
return user;
}
get hasEditUsers () {
let length = 0;
this.users.forEach((item) => {
if ((item.asc_getState()!==false) && !item.asc_getView()) {
length++;
}
});
return (length >= 1);
}
get editUsers () {
const idArray = [];
const usersArray = [];
const curUserId = this.currentUser.asc_getIdOriginal();
this.users.forEach((item) => {
const name = AscCommon.UserInfoParser.getParsedName(item.asc_getUserName());
if((item.asc_getState() !== false) && !item.asc_getView()) {
const idOriginal = item.asc_getIdOriginal();
const ind = idArray.indexOf(idOriginal);
if (ind !== -1) {
usersArray[ind].count = usersArray[ind].count + 1;
} else {
const userAttr = {
color: item.asc_getColor(),
id: item.asc_getId(),
idOriginal: item.asc_getIdOriginal(),
name: name,
view: item.asc_getView(),
initials: this.getInitials(name),
count: 1
};
if(idOriginal === curUserId) {
usersArray.unshift(userAttr);
idArray.unshift(idOriginal);
} else {
usersArray.push(userAttr);
idArray.push(idOriginal);
}
}
}
});
return usersArray;
}
}

View file

@ -0,0 +1,127 @@
import React, { Fragment } from 'react';
import { observer, inject } from "mobx-react";
import { Page, Navbar, Link } from "framework7-react";
import { useTranslation } from "react-i18next";
const PageAbout = props => {
const { t } = useTranslation();
const _t = t("About", { returnObjects: true });
const store = props.storeAppOptions;
const isCanBranding = store.canBranding;
const licInfo = isCanBranding ? store.customization : null;
const customer = licInfo ? licInfo.customer : null;
const nameCustomer = customer ? customer.name : null;
const mailCustomer = customer ? customer.mail : null;
const addressCustomer = customer ? customer.address : null;
const urlCustomer = customer ? customer.www : null;
const infoCustomer = customer ? customer.info : null;
const logoCustomer = customer ? customer.logo : null;
const publisherUrl = __PUBLISHER_URL__,
publisherPrintUrl = publisherUrl.replace(/https?:\/{2}|\/$/,"");
const editors = {
de: 'DOCUMENT EDITOR',
pe: 'PRESENTATION EDITOR',
sse: 'SPREADSHEET EDITOR'
};
const nameEditor = editors[editorType];
return (
<Page className="about">
<Navbar title={_t.textAbout} backLink={_t.textBack} />
{licInfo && typeof licInfo == 'object' && typeof(customer) == 'object' ? (
<Fragment>
<div className="content-block">
{logoCustomer && logoCustomer.length ? (
<div id="settings-about-logo" className="settings-about-logo">
<img src={logoCustomer} alt="" />
</div>
) : null}
</div>
<div className="content-block">
<h3>{nameEditor}</h3>
<h3>{_t.textVersion} {__PRODUCT_VERSION__}</h3>
</div>
<div className="content-block">
{nameCustomer && nameCustomer.length ? (
<h3 id="settings-about-name" className="vendor">{nameCustomer}</h3>
) : null}
{addressCustomer && addressCustomer.length ? (
<p>
<label>{_t.textAddress}:</label>
<Link id="settings-about-address" className="external">{addressCustomer}</Link>
</p>
) : null}
{mailCustomer && mailCustomer.length ? (
<p>
<label>{_t.textEmail}:</label>
<Link id="settings-about-email" className="external" target="_blank" href={"mailto:"+mailCustomer}>{mailCustomer}</Link>
</p>
) : null}
{urlCustomer && urlCustomer.length ? (
<p>
<Link id="settings-about-url" className="external" target="_blank"
href={!/^https?:\/{2}/i.test(urlCustomer) ? "http:\/\/" : '' + urlCustomer}>
{urlCustomer}
</Link>
</p>
) : null}
{infoCustomer && infoCustomer.length ? (
<p>
<label id="settings-about-info">{infoCustomer}</label>
</p>
) : null}
</div>
<div className="content-block" id="settings-about-licensor">
<div className="content-block-inner"></div>
<p>
<label>{_t.textPoweredBy}</label>
</p>
<h3 className="vendor">{__PUBLISHER_NAME__}</h3>
<p>
<Link className="external" target="_blank" href={publisherUrl}>{publisherPrintUrl}</Link>
</p>
</div>
</Fragment>
) : (
<Fragment>
<div className="content-block">
<div className="logo"></div>
</div>
<div className="content-block">
<h3>{nameEditor}</h3>
<h3>{_t.textVersion} {__PRODUCT_VERSION__}</h3>
</div>
<div className="content-block">
<h3 id="settings-about-name" className="vendor">{__PUBLISHER_NAME__}</h3>
<p>
<label>{_t.textAddress}:</label>
<a id="settings-about-address" className="external">{__PUBLISHER_ADDRESS__}</a>
</p>
<p>
<label>{_t.textEmail}:</label>
<a id="settings-about-email" className="external" href={`mailto:${__SUPPORT_EMAIL__}`}>{__SUPPORT_EMAIL__}</a>
</p>
<p>
<label>{_t.textTel}:</label>
<a id="settings-about-tel" className="external" href={`tel:${__PUBLISHER_PHONE__}`}>{__PUBLISHER_PHONE__}</a>
</p>
<p>
<a id="settings-about-url" className="external" target="_blank" href={publisherUrl}>{publisherPrintUrl}</a>
</p>
</div>
</Fragment>
)}
</Page>
);
};
const About = inject("storeAppOptions")(observer(PageAbout));
About.appVersion = () => (__PRODUCT_VERSION__);
About.compareVersions = () => /d$/.test(__PRODUCT_VERSION__);
About.developVersion = () => /(?:d|debug)$/.test(__PRODUCT_VERSION__);
export default About;

View file

@ -165,66 +165,73 @@ define([
renderViewComments: function(comments, indCurComment) {
var isAndroid = Framework7.prototype.device.android === true;
var me = this;
var res = false;
if ($('.page-view-comments .page-content').length > 0) {
var template = '';
if (comments && comments.length > 0) {
template = '<div class="list-block">' +
'<ul id="comments-list">';
var comment = comments[indCurComment];
template += '<li class="comment item-content" data-uid="' + comment.uid + '">' +
'<div class="item-inner">' +
'<div class="header-comment"><div class="comment-left">';
if (isAndroid) {
template += '<div class="initials-comment" style="background-color: ' + (comment.usercolor ? comment.usercolor : '#cfcfcf') + ';">' + comment.userInitials + '</div><div>';
}
template += '<div class="user-name">' + me.getUserName(comment.username) + '</div>' +
'<div class="comment-date">' + comment.date + '</div>';
if (isAndroid) {
res = !comment.hide;
if (res) {
template = '<div class="list-block">' +
'<ul id="comments-list">';
template += '<li class="comment item-content" data-uid="' + comment.uid + '">' +
'<div class="item-inner">' +
'<div class="header-comment"><div class="comment-left">';
if (isAndroid) {
template += '<div class="initials-comment" style="background-color: ' + (comment.usercolor ? comment.usercolor : '#cfcfcf') + ';">' + comment.userInitials + '</div><div>';
}
template += '<div class="user-name">' + me.getUserName(comment.username) + '</div>' +
'<div class="comment-date">' + comment.date + '</div>';
if (isAndroid) {
template += '</div>';
}
template += '</div>';
}
template += '</div>';
if (!me.viewmode) {
template += '<div class="comment-right">' +
'<div class="comment-resolve"><i class="icon icon-resolve-comment' + (comment.resolved ? ' check' : '') + '"></i></div>' +
'<div class="comment-menu"><i class="icon icon-menu-comment"></i></div>' +
'</div>';
}
template += '</div>';
if (comment.quote) template += '<div class="comment-quote" data-ind="' + comment.uid + '">' + me.sliceQuote(comment.quote) + '</div>';
template += '<div class="comment-text"><pre>' + comment.comment + '</pre></div>';
if (comment.replys.length > 0) {
template += '<ul class="list-reply">';
_.each(comment.replys, function (reply) {
template += '<li class="reply-item" data-ind="' + reply.ind + '">' +
'<div class="header-reply">' +
'<div class="reply-left">';
if (isAndroid) {
template += '<div class="initials-reply" style="background-color: ' + (reply.usercolor ? reply.usercolor : '#cfcfcf') + ';">' + reply.userInitials + '</div><div>'
}
template += '<div class="user-name">' + me.getUserName(reply.username) + '</div>' +
'<div class="reply-date">' + reply.date + '</div>' +
if (!me.viewmode) {
template += '<div class="comment-right">' +
'<div class="comment-resolve"><i class="icon icon-resolve-comment' + (comment.resolved ? ' check' : '') + '"></i></div>' +
'<div class="comment-menu"><i class="icon icon-menu-comment"></i></div>' +
'</div>';
if (isAndroid) {
template += '</div>';
}
if ((reply.editable || reply.removable) && !me.viewmode) {
template += '<div class="reply-menu"><i class="icon icon-menu-comment"></i></div>';
}
template += '</div>' +
'<div class="reply-text"><pre>' + reply.reply + '</pre></div>' +
'</li>';
});
template += '</ul>'
}
}
template += '</div>';
template += '</div>' +
'</li>';
template += '</ul></div>';
$('.page-view-comments .page-content').html(template);
if (comment.quote) template += '<div class="comment-quote" data-ind="' + comment.uid + '">' + me.sliceQuote(comment.quote) + '</div>';
template += '<div class="comment-text"><pre>' + comment.comment + '</pre></div>';
if (comment.replys.length > 0) {
template += '<ul class="list-reply">';
_.each(comment.replys, function (reply) {
if (!reply.hide) {
template += '<li class="reply-item" data-ind="' + reply.ind + '">' +
'<div class="header-reply">' +
'<div class="reply-left">';
if (isAndroid) {
template += '<div class="initials-reply" style="background-color: ' + (reply.usercolor ? reply.usercolor : '#cfcfcf') + ';">' + reply.userInitials + '</div><div>'
}
template += '<div class="user-name">' + me.getUserName(reply.username) + '</div>' +
'<div class="reply-date">' + reply.date + '</div>' +
'</div>';
if (isAndroid) {
template += '</div>';
}
if ((reply.editable || reply.removable) && !me.viewmode) {
template += '<div class="reply-menu"><i class="icon icon-menu-comment"></i></div>';
}
template += '</div>' +
'<div class="reply-text"><pre>' + reply.reply + '</pre></div>' +
'</li>';
}
});
template += '</ul>'
}
template += '</div>' +
'</li>';
template += '</ul></div>';
$('.page-view-comments .page-content').html(template);
}
}
}
Common.Utils.addScrollIfNeed('.page-view-comments.page', '.page-view-comments .page-content');
return res;
},
renderComments: function (comments) {
@ -245,6 +252,7 @@ define([
items = [];
_.each(sortComments, function (comment) {
var itemTemplate = [
'<% if (!item.hide) { %>',
'<li class="comment item-content" data-uid="<%= item.uid %>">',
'<div class="item-inner">',
'<div class="header-comment"><div class="comment-left">',
@ -267,6 +275,7 @@ define([
'<% if(replys > 0) {%>',
'<ul class="list-reply">',
'<% _.each(item.replys, function (reply) { %>',
'<% if (!reply.hide) { %>',
'<li class="reply-item" data-ind="<%= reply.ind %>">',
'<div class="header-reply">',
'<div class="reply-left">',
@ -281,11 +290,13 @@ define([
'</div>',
'<div class="reply-text"><pre><%= reply.reply %></pre></div>',
'</li>',
'<% } %>',
'<% }); %>',
'</ul>',
'<% } %>',
'</div>',
'</li>'
'</li>',
'<% } %>'
].join('');
items.push(_.template(itemTemplate)({
android: Framework7.prototype.device.android,
@ -451,7 +462,7 @@ define([
},
getUserName: function (username) {
return Common.Utils.String.htmlEncode(Common.Utils.UserInfoParser.getParsedName(username));
return Common.Utils.String.htmlEncode(AscCommon.UserInfoParser.getParsedName(username));
},
textCollaboration: 'Collaboration',

View file

@ -0,0 +1,62 @@
import React, { Component } from 'react';
import { Popover, List, ListItem, ListButton, Link, Icon, Actions, ActionsGroup, ActionsButton } from 'framework7-react';
import { f7 } from 'framework7-react';
import { useTranslation } from 'react-i18next';
const idContextMenuElement = "idx-context-menu-popover";
class ContextMenuView extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
// f7.popover.open('#idx-context-menu-popover', '#idx-context-menu-target');
}
render() {
const buttons = this.props.items || {};
return (
<Popover id={idContextMenuElement}
className="document-menu"
backdrop={false}
closeByBackdropClick={false}
closeByOutsideClick={false}
onPopoverClosed={e => this.props.onMenuClosed()}
>
<List className="list-block">
{buttons.map((b, index) =>
!b.icon ?
<ListButton title={b.caption} key={index} onClick={e => this.props.onMenuItemClick(b.event)} /> :
<ListButton key={index} onClick={e => this.props.onMenuItemClick(b.event)}>
<Icon slot="media" icon={`icon_mask ${b.icon}`} />
</ListButton>
)}
</List>
</Popover>
)
}
}
const ActionsWithExtraItems = ({items, onMenuItemClick, opened, onActionClosed}) => {
const { t } = useTranslation();
const _t = t('ContextMenu', {returnObjects: true});
return (
<Actions opened={opened} onActionsClosed={() => onActionClosed()}>
<ActionsGroup>
{items.length > 0 && items.map((item, index)=>{
return(
<ActionsButton key={`act-${index}`} onClick={() => {onMenuItemClick(item.event)}}>{item.caption}</ActionsButton>
)
})}
</ActionsGroup>
<ActionsGroup>
<ActionsButton>{_t.menuCancel}</ActionsButton>
</ActionsGroup>
</Actions>
)
};
const exportedIdMenuElemen = `#${idContextMenuElement}`;
export {ContextMenuView as default, exportedIdMenuElemen as idContextMenuElement, ActionsWithExtraItems};

View file

@ -0,0 +1,324 @@
import React, { Component } from 'react';
import { Searchbar, Popover, Popup, View, Page, List, ListItem, Navbar, NavRight, Link } from 'framework7-react';
import { Toggle } from 'framework7-react';
import { f7 } from 'framework7-react';
import { Dom7 } from 'framework7';
import { Device } from '../../../../common/mobile/utils/device';
import { observable, runInAction } from "mobx";
import { observer } from "mobx-react";
const searchOptions = observable({
usereplace: false,
isReplaceAll: false
});
const popoverStyle = {
height: '300px'
};
const SEARCH_BACKWARD = 'back';
const SEARCH_FORWARD = 'next';
class SearchSettingsView extends Component {
constructor(props) {
super(props);
this.state = {
useReplace: false,
// caseSensitive: false,
// markResults: false
searchIn: 0,
searchBy: 1,
lookIn: 1,
isMatchCase: false,
isMatchCell: false,
isReplaceAll: false
};
}
onFindReplaceClick(action) {
runInAction(() => {
searchOptions.usereplace = action == 'replace';
searchOptions.isReplaceAll = action == 'replace-all';
});
this.setState({
useReplace: searchOptions.usereplace,
isReplaceAll: searchOptions.isReplaceAll
});
if (this.onReplaceChecked) {}
}
extraSearchOptions() {
}
render() {
const show_popover = !Device.phone;
// const navbar =
// <Navbar title="Find and replace">
// {!show_popover &&
// <NavRight>
// <Link popupClose=".search-settings-popup">Done</Link>
// </NavRight>
// }
// </Navbar>;
const extra = this.extraSearchOptions();
const content =
<View style={show_popover ? popoverStyle : null}>
{/* <Page>
{navbar} */}
{extra}
{/* </Page> */}
</View>;
return (
show_popover ?
<Popover id="idx-search-settings" className="popover__titled">{content}</Popover> :
<Popup id="idx-search-settings" className="search-settings-popup">{content}</Popup>
)
}
}
// @observer
class SearchView extends Component {
constructor(props) {
super(props);
this.state = {
searchQuery: '',
replaceQuery: ''
};
const $$ = Dom7;
$$(document).on('page:init', (e, page) => {
if ( page.name == 'home' ) {
this.searchbar = f7.searchbar.create({
el: '.searchbar',
customSearch: true,
expandable: true,
backdrop: false,
on: {
search: (bar, curval, prevval) => {
},
enable: this.onSearchbarShow.bind(this, true),
disable: this.onSearchbarShow.bind(this, false)
}
});
// function iOSVersion() {
// var ua = navigator.userAgent;
// var m;
// return (m = /(iPad|iPhone|iphone).*?(OS |os |OS\_)(\d+((_|\.)\d)?((_|\.)\d)?)/.exec(ua)) ? parseFloat(m[3]) : 0;
// }
const $editor = $$('#editor_sdk');
// const $replaceLink = $$('#replace-link');
if (false /* iOSVersion < 13 */) {
// $editor.on('mousedown touchstart', this.onEditorTouchStart.bind(this));
// $editor.on('mouseup touchend', this.onEditorTouchEnd.bind(this));
} else {
// $editor.on('pointerdown', this.onEditorTouchStart.bind(this));
// $editor.on('pointerup', this.onEditorTouchEnd.bind(this));
}
$editor.on('pointerdown', this.onEditorTouchStart.bind(this));
$editor.on('pointerup', this.onEditorTouchEnd.bind(this));
// $replaceLink.on('click', this.onReplaceHold.bind(this));
}
});
this.onSettingsClick = this.onSettingsClick.bind(this);
this.onSearchClick = this.onSearchClick.bind(this);
this.onReplaceClick = this.onReplaceClick.bind(this);
}
componentDidMount(){
const $$ = Dom7;
this.$replace = $$('#idx-replace-val');
}
onSettingsClick(e) {
if ( Device.phone ) {
f7.popup.open('.search-settings-popup');
} else f7.popover.open('#idx-search-settings', '#idx-btn-search-settings');
}
searchParams() {
let params = {
find: this.searchbar.query
};
if (searchOptions.usereplace) {
params.replace = this.$replace.val();
}
return params;
}
onSearchClick(action) {
if (this.searchbar && this.state.searchQuery) {
if (this.props.onSearchQuery) {
let params = this.searchParams();
params.find = this.state.searchQuery;
params.forward = action != SEARCH_BACKWARD;
// console.log(params);
this.props.onSearchQuery(params);
}
}
}
onReplaceClick() {
if (this.searchbar && this.state.searchQuery) {
if (this.props.onReplaceQuery) {
let params = this.searchParams();
params.find = this.state.searchQuery;
// console.log(params);
this.props.onReplaceQuery(params);
}
}
}
onReplaceAllClick() {
if (this.searchbar && this.state.searchQuery) {
if (this.props.onReplaceAllQuery) {
let params = this.searchParams();
params.find = this.state.searchQuery;
// console.log(params);
this.props.onReplaceAllQuery(params);
}
}
}
onSearchbarShow(isshowed, bar) {
if ( !isshowed ) {
this.$replace.val('');
}
}
onEditorTouchStart(e) {
this.startPoint = this.pointerPosition(e);
// console.log(this.startPoint);
}
onEditorTouchEnd(e) {
const endPoint = this.pointerPosition(e);
// console.log(endPoint);
if (this.searchbar.enabled) {
let distance;
if(this.startPoint) {
distance = (!!this.startPoint.x || !!this.startPoint.y) ? 0 :
Math.sqrt((endPoint.x -= this.startPoint.x) * endPoint.x + (endPoint.y -= this.startPoint.y) * endPoint.y);
} else {
distance = 0;
}
// const distance = (this.startPoint === undefined || this.startPoint === undefined) ? 0 :
// Math.sqrt((endPoint.x -= this.startPoint.x) * endPoint.x + (endPoint.y -= this.startPoint.y) * endPoint.y);
if (distance < 1) {
this.searchbar.disable();
}
}
}
pointerPosition(e) {
let out = {x:0, y:0};
if ( e.type == 'touchstart' || e.type == 'touchend' ) {
const touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
out.x = touch.pageX;
out.y = touch.pageY;
} else if ( e.type == 'mousedown' || e.type == 'mouseup' ) {
out.x = e.pageX;
out.y = e.pageY;
}
return out;
}
changeSearchQuery(value) {
this.setState({
searchQuery: value
});
}
changeReplaceQuery(value) {
this.setState({
replaceQuery: value
});
}
render() {
const usereplace = searchOptions.usereplace;
const isReplaceAll = searchOptions.isReplaceAll;
const hidden = {display: "none"};
const searchQuery = this.state.searchQuery;
// const replaceQuery = this.state.replaceQuery;
const isIos = Device.ios;
const { _t } = this.props;
if(this.searchbar && this.searchbar.enabled) {
usereplace || isReplaceAll ? this.searchbar.el.classList.add('replace') : this.searchbar.el.classList.remove('replace');
}
return (
<form className="searchbar">
{isIos ? <div className="searchbar-bg"></div> : null}
<div className="searchbar-inner">
<div className="buttons-row searchbar-inner__left">
<a id="idx-btn-search-settings" className="link icon-only no-fastclick" onClick={this.onSettingsClick}>
<i className="icon icon-settings" />
</a>
</div>
<div className="searchbar-inner__center">
<div className="searchbar-input-wrap">
<input placeholder={_t.textSearch} type="search" maxLength="255"
onChange={e => {this.changeSearchQuery(e.target.value)}} />
{isIos ? <i className="searchbar-icon" /> : null}
<span className="input-clear-button" onClick={() => this.changeSearchQuery('')} />
</div>
{/* {usereplace || isReplaceAll ? */}
<div className="searchbar-input-wrap" style={usereplace || isReplaceAll ? null : hidden}>
{/* style={!usereplace ? hidden: null} */}
<input placeholder={_t.textReplace} type="search" maxLength="255" id="idx-replace-val"
onChange={e => {this.changeReplaceQuery(e.target.value)}} />
{isIos ? <i className="searchbar-icon" /> : null}
<span className="input-clear-button" onClick={() => this.changeReplaceQuery('')} />
</div>
{/* */}
</div>
<div className="buttons-row searchbar-inner__right">
<div className="buttons-row buttons-row-replace">
{/* <a id="replace-link" className={"link " + (searchQuery.trim().length ? "" : "disabled")} style={!usereplace ? hidden: null} onClick={() => this.onReplaceClick()}>{_t.textReplace}</a>
<a id="replace-all-link" className={"link " + (searchQuery.trim().length ? "" : "disabled")} style={!usereplace ? hidden: null} onClick={() => this.onReplaceAllClick()}>{_t.textReplaceAll}</a> */}
{isReplaceAll ? (
<a id="replace-all-link" className={"link " + (searchQuery.trim().length ? "" : "disabled")} onClick={() => this.onReplaceAllClick()}>{_t.textReplaceAll}</a>
) : usereplace ? (
<a id="replace-link" className={"link " + (searchQuery.trim().length ? "" : "disabled")} onClick={() => this.onReplaceClick()}>{_t.textReplace}</a>
) : null}
</div>
<div className="buttons-row">
<a className={"link icon-only prev no-fastclick " + (searchQuery.trim().length ? "" : "disabled")} onClick={() => this.onSearchClick(SEARCH_BACKWARD)}>
<i className="icon icon-prev" />
</a>
<a className={"link icon-only next no-fastclick " + (searchQuery.trim().length ? "" : "disabled")} onClick={() => this.onSearchClick(SEARCH_FORWARD)}>
<i className="icon icon-next" />
</a>
</div>
</div>
</div>
</form>
)
}
}
const SearchViewWithObserver = observer(SearchView);
export {SearchViewWithObserver as SearchView, SearchSettingsView};

View file

@ -0,0 +1,171 @@
import React, { Component, useEffect } from 'react';
import { observer, inject } from "mobx-react";
import { Popover, List, ListItem, Navbar, NavRight, Sheet, BlockTitle, Page, View, Icon, Link } from 'framework7-react';
import { f7 } from 'framework7-react';
import { useTranslation } from 'react-i18next';
import {Device} from "../../../utils/device";
import {ReviewController, ReviewChangeController} from "../../controller/collaboration/Review";
import {PageDisplayMode} from "./Review";
import {ViewCommentsController} from "../../controller/collaboration/Comments";
const PageUsers = inject("users")(observer(props => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const storeUsers = props.users;
return (
<Page name="collab__users" className='page-users'>
<Navbar title={_t.textUsers} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose=".coauth__sheet">
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
<BlockTitle>{_t.textEditUser}</BlockTitle>
<List className="coauth__list">
{storeUsers.editUsers.map((user, i) => (
<ListItem title={user.name + (user.count > 1 ? ` (${user.count})` : '')} key={i}>
<div slot="media" className='color' style={{backgroundColor: user.color}}>
{user.initials}
</div>
</ListItem>
))}
</List>
</Page>
)
}));
const routes = [
{
path: '/users/',
component: PageUsers
},
{
path: '/review/',
component: ReviewController
},
{
path: '/cm-review/',
component: ReviewController,
options: {
props: {
noBack: true
}
}
},
{
path: '/display-mode/',
component: PageDisplayMode
},
{
path: '/review-change/',
component: ReviewChangeController
},
{
path: '/cm-review-change/',
component: ReviewChangeController,
options: {
props: {
noBack: true
}
}
},
{
path: '/comments/',
component: ViewCommentsController,
options: {
props: {
allComments: true
}
}
}
];
const PageCollaboration = inject('storeAppOptions')(observer(props => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const appOptions = props.storeAppOptions;
return (
<View style={props.style} stackPages={true} routes={routes} url={props.page && `/${props.page}/`}>
<Page name="collab__main">
<Navbar title={_t.textCollaboration}>
{Device.phone &&
<NavRight>
<Link sheetClose=".coauth__sheet">
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
<List>
<ListItem link={'/users/'} title={_t.textUsers}>
<Icon slot="media" icon="icon-users"></Icon>
</ListItem>
{appOptions.canViewComments &&
<ListItem link='/comments/' title={_t.textComments}>
<Icon slot="media" icon="icon-insert-comment"></Icon>
</ListItem>
}
{window.editorType === 'de' && (appOptions.canReview || appOptions.canViewReview) &&
<ListItem link={'/review/'} title={_t.textReview}>
<Icon slot="media" icon="icon-review"></Icon>
</ListItem>
}
</List>
</Page>
</View>
)
}));
class CollaborationView extends Component {
constructor(props) {
super(props);
this.onoptionclick = this.onoptionclick.bind(this);
}
onoptionclick(page){
f7.views.current.router.navigate(page);
}
render() {
const show_popover = this.props.usePopover;
return (
show_popover ?
<Popover id="coauth-popover" className="popover__titled" onPopoverClosed={() => this.props.onclosed()} closeByOutsideClick={false}>
<PageCollaboration style={{height: '410px'}} page={this.props.page}/>
</Popover> :
<Sheet className="coauth__sheet" push onSheetClosed={() => this.props.onclosed()}>
<PageCollaboration page={this.props.page}/>
</Sheet>
)
}
}
const Collaboration = props => {
useEffect(() => {
if ( Device.phone ) {
f7.sheet.open('.coauth__sheet');
} else {
f7.popover.open('#coauth-popover', '#btn-coauth');
}
return () => {
// component will unmount
}
});
const onviewclosed = () => {
if ( props.onclosed ) props.onclosed();
};
return (
<CollaborationView usePopover={!Device.phone} onclosed={onviewclosed} page={props.page}/>
)
};
export {PageCollaboration}
export default Collaboration;

View file

@ -0,0 +1,879 @@
import React, {useState, useEffect, Fragment} from 'react';
import {observer, inject} from "mobx-react";
import { f7, Popup, Sheet, Popover, Page, Toolbar, Navbar, NavLeft, NavRight, NavTitle, Link, Input, Icon, List, ListItem, Actions, ActionsGroup, ActionsButton } from 'framework7-react';
import { useTranslation } from 'react-i18next';
import {Device} from '../../../utils/device';
// Utils
const sliceQuote = (text) => {
if (text) {
let sliced = text.slice(0, 100);
if (sliced.length < text.length) {
sliced += '...';
return sliced;
}
return text;
}
};
// Add comment
const AddCommentPopup = inject("storeComments")(observer(props => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
useEffect(() => {
f7.popup.open('.add-comment-popup');
});
const userInfo = props.userInfo;
const [stateText, setText] = useState('');
return (
<Popup className="add-comment-popup">
<Navbar>
<NavLeft>
<Link onClick={() => {
f7.popup.close('.add-comment-popup');
setTimeout(() => {
props.closeAddComment();
}, 500)
}}>{_t.textCancel}</Link>
</NavLeft>
<NavTitle>{_t.textAddComment}</NavTitle>
<NavRight>
<Link className={stateText.length === 0 && 'disabled'}
onClick={() => {
f7.popup.close('.add-comment-popup');
setTimeout(() => {
props.closeAddComment();
props.onAddNewComment(stateText, false)
}, 500);
}}>
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
</Link>
</NavRight>
</Navbar>
<div className='wrap-comment'>
<div className="comment-header">
{Device.android &&
<div className='initials' style={{backgroundColor: `${userInfo.color}`}}>{userInfo.initials}</div>
}
<div className='name'>{userInfo.name}</div>
</div>
<div className='wrap-textarea'>
<Input type='textarea' placeholder={_t.textAddComment} autofocus value={stateText} onChange={(event) => {setText(event.target.value);}}></Input>
</div>
</div>
</Popup>
)
}));
const AddCommentDialog = inject("storeComments")(observer(props => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const userInfo = props.userInfo;
const templateInitials = `<div class="initials" style="background-color: ${userInfo.color};">${userInfo.initials}</div>`;
useEffect(() => {
f7.dialog.create({
destroyOnClose: true,
containerEl: document.getElementById('add-comment-dialog'),
content:
`<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="left">
<a href="#" id="comment-cancel">${_t.textCancel}</a>
</div>
<div class="title">${_t.textAddComment}</div>
<div class="right">
<a href="#" class="done" id="comment-done">${ Device.android ? '<i class="icon icon-done-comment-white"></i>' : _t.textDone}</a>
</div>
</div>
</div>
<div class='wrap-comment'>
<div class="comment-header">
${Device.android ? templateInitials : ''}
<div class='name'>${userInfo.name}</div>
</div>
<div class='wrap-textarea'>
<textarea id='comment-text' placeholder='${_t.textAddComment}' autofocus></textarea>
</div>
</div>`,
on: {
opened: () => {
const cancel = document.getElementById('comment-cancel');
cancel.addEventListener('click', () => {
f7.dialog.close();
props.closeAddComment();
});
const done = document.getElementById('comment-done');
done.addEventListener('click', () => {
const value = document.getElementById('comment-text').value;
if (value.length > 0) {
f7.dialog.close();
props.closeAddComment();
props.onAddNewComment(value, false);
}
});
const area = document.getElementById('comment-text');
area.addEventListener('input', (event) => {
if (event.target.value.length === 0 && !done.classList.contains('disabled')) {
done.classList.add('disabled');
} else if (event.target.value.length > 0 && done.classList.contains('disabled')) {
done.classList.remove('disabled');
}
});
done.classList.add('disabled');
}
}
}).open();
});
return (
<div id='add-comment-dialog' className="add-comment-dialog"></div>
);
}));
const AddComment = props => {
return (
Device.phone ?
<AddCommentPopup {...props} /> :
<AddCommentDialog {...props} />
)
};
// Actions
const CommentActions = ({comment, onCommentMenuClick, opened, openActionComment}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
return (
<Actions id='comment-menu' opened={opened} onActionsClosed={() => openActionComment(false)}>
<ActionsGroup>
{comment && <Fragment>
{comment.editable && <ActionsButton onClick={() => {onCommentMenuClick('editComment', comment);}}>{_t.textEdit}</ActionsButton>}
{!comment.resolved ?
<ActionsButton onClick={() => {onCommentMenuClick('resolve', comment);}}>{_t.textResolve}</ActionsButton> :
<ActionsButton onClick={() => {onCommentMenuClick('resolve', comment);}}>{_t.textReopen}</ActionsButton>
}
<ActionsButton onClick={() => {onCommentMenuClick('addReply', comment);}}>{_t.textAddReply}</ActionsButton>
{comment.removable && <ActionsButton color='red' onClick={() => {onCommentMenuClick('deleteComment', comment);}}>{_t.textDeleteComment}</ActionsButton>}
</Fragment>
}
</ActionsGroup>
<ActionsGroup>
<ActionsButton>{_t.textCancel}</ActionsButton>
</ActionsGroup>
</Actions>
)
};
const ReplyActions = ({comment, reply, onCommentMenuClick, opened, openActionReply}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
return (
<Actions id='reply-menu' opened={opened} onActionsClosed={() => openActionReply(false)}>
<ActionsGroup>
{reply && <Fragment>
{reply.editable && <ActionsButton onClick={() => {onCommentMenuClick('editReply', comment, reply);}}>{_t.textEdit}</ActionsButton>}
{reply.removable && <ActionsButton color='red' onClick={() => {onCommentMenuClick('deleteReply', comment, reply);}}>{_t.textDeleteReply}</ActionsButton>}
</Fragment>
}
</ActionsGroup>
<ActionsGroup>
<ActionsButton>{_t.textCancel}</ActionsButton>
</ActionsGroup>
</Actions>
)
};
// Edit comment
const EditCommentPopup = inject("storeComments")(observer(({storeComments, comment, onEditComment}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
useEffect(() => {
f7.popup.open('.edit-comment-popup');
});
const [stateText, setText] = useState(comment.comment);
return (
<Popup className="edit-comment-popup">
<Navbar>
<NavLeft>
<Link onClick={() => {
f7.popup.close('.edit-comment-popup');
setTimeout(() => {
storeComments.openEditComment(false);
}, 500);
}}>{_t.textCancel}</Link>
</NavLeft>
<NavTitle>{_t.textEditComment}</NavTitle>
<NavRight>
<Link className={stateText.length === 0 && 'disabled'}
onClick={() => {
f7.popup.close('.edit-comment-popup');
setTimeout(() => {
storeComments.openEditComment(false);
onEditComment(comment, stateText);
}, 500);
}}
>
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
</Link>
</NavRight>
</Navbar>
<div className='wrap-comment'>
<div className="comment-header">
{Device.android &&
<div className='initials' style={{backgroundColor: `${comment.userColor}`}}>{comment.userInitials}</div>
}
<div>
<div className='name'>{comment.userName}</div>
<div className='comment-date'>{comment.date}</div>
</div>
</div>
<div className='wrap-textarea'>
<Input type='textarea' placeholder={_t.textEditComment} autofocus value={stateText} onChange={(event) => {setText(event.target.value);}}></Input>
</div>
</div>
</Popup>
)
}));
const EditCommentDialog = inject("storeComments")(observer(({storeComments, comment, onEditComment}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const templateInitials = `<div class="initials" style="background-color: ${comment.userColor};">${comment.userInitials}</div>`;
useEffect(() => {
f7.dialog.create({
destroyOnClose: true,
containerEl: document.getElementById('edit-comment-dialog'),
content:
`<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="left">
<a href="#" id="comment-cancel">${_t.textCancel}</a>
</div>
<div class="title">${_t.textEditComment}</div>
<div class="right">
<a href="#" class="done" id="comment-done">${ Device.android ? '<i class="icon icon-done-comment-white"></i>' : _t.textDone}</a>
</div>
</div>
</div>
<div class='wrap-comment'>
<div class="comment-header">
${Device.android ? templateInitials : ''}
<div>
<div class='name'>${comment.userName}</div>
<div class='comment-date'>${comment.date}</div>
</div>
</div>
<div class='wrap-textarea'>
<textarea id='comment-text' placeholder='${_t.textEditComment}' autofocus>${comment.comment}</textarea>
</div>
</div>`,
on: {
opened: () => {
const cancel = document.getElementById('comment-cancel');
cancel.addEventListener('click', () => {
f7.dialog.close();
storeComments.openEditComment(false);
});
const done = document.getElementById('comment-done');
done.addEventListener('click', () => {
const value = document.getElementById('comment-text').value;
if (value.length > 0) {
onEditComment(comment, value);
f7.dialog.close();
storeComments.openEditComment(false);
}
});
const area = document.getElementById('comment-text');
area.addEventListener('input', (event) => {
if (event.target.value.length === 0 && !done.classList.contains('disabled')) {
done.classList.add('disabled');
} else if (event.target.value.length > 0 && done.classList.contains('disabled')) {
done.classList.remove('disabled');
}
});
},
open: () => {
$$('.dialog-backdrop.backdrop-in')[0].classList.add('over-popover');
},
closed: () => {
$$('.dialog-backdrop.backdrop-in')[0].classList.remove('over-popover');
}
}
}).open();
});
return (
<div id='edit-comment-dialog' className="edit-comment-dialog"></div>
);
}));
const EditComment = ({comment, onEditComment}) => {
return (
Device.phone ?
<EditCommentPopup comment={comment} onEditComment={onEditComment}/> :
<EditCommentDialog comment={comment} onEditComment={onEditComment}/>
)
};
const AddReplyPopup = inject("storeComments")(observer(({storeComments, userInfo, comment, onAddReply}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
useEffect(() => {
f7.popup.open('.add-reply-popup');
});
const [stateText, setText] = useState('');
return (
<Popup className="add-reply-popup">
<Navbar>
<NavLeft>
<Link onClick={() => {
f7.popup.close('.add-reply-popup');
setTimeout(() => {
storeComments.openAddReply(false);
}, 500);
}}>{_t.textCancel}</Link>
</NavLeft>
<NavTitle>{_t.textAddReply}</NavTitle>
<NavRight>
<Link className={stateText.length === 0 && 'disabled'}
onClick={() => {
f7.popup.close('.add-reply-popup');
setTimeout(() => {
storeComments.openAddReply(false);
onAddReply(comment, stateText);
}, 500);
}}>
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
</Link>
</NavRight>
</Navbar>
<div className='wrap-comment'>
<div className="comment-header">
{Device.android &&
<div className='initials' style={{backgroundColor: `${userInfo.color}`}}>{userInfo.initials}</div>
}
<div className='name'>{userInfo.name}</div>
</div>
<div className='wrap-textarea'>
<Input type='textarea' placeholder={_t.textAddReply} autofocus value={stateText} onChange={(event) => {setText(event.target.value);}}></Input>
</div>
</div>
</Popup>
)
}));
const AddReplyDialog = inject("storeComments")(observer(({storeComments, userInfo, comment, onAddReply}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const templateInitials = `<div class="initials" style="background-color: ${userInfo.color};">${userInfo.initials}</div>`;
useEffect(() => {
f7.dialog.create({
destroyOnClose: true,
containerEl: document.getElementById('add-reply-dialog'),
content:
`<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="left">
<a href="#" id="reply-cancel">${_t.textCancel}</a>
</div>
<div class="title">${_t.textAddReply}</div>
<div class="right">
<a href="#" class="done" id="reply-done">${ Device.android ? '<i class="icon icon-done-comment-white"></i>' : _t.textDone}</a>
</div>
</div>
</div>
<div class='wrap-comment'>
<div class="comment-header">
${Device.android ? templateInitials : ''}
<div class='name'>${userInfo.name}</div>
</div>
<div class='wrap-textarea'>
<textarea id='reply-text' placeholder='${_t.textAddReply}' autofocus></textarea>
</div>
</div>`,
on: {
opened: () => {
const cancel = document.getElementById('reply-cancel');
cancel.addEventListener('click', () => {
f7.dialog.close();
storeComments.openAddReply(false);
});
const done = document.getElementById('reply-done');
done.addEventListener('click', () => {
const value = document.getElementById('reply-text').value;
if (value.length > 0) {
onAddReply(comment, value);
f7.dialog.close();
storeComments.openAddReply(false);
}
});
const area = document.getElementById('reply-text');
area.addEventListener('input', (event) => {
if (event.target.value.length === 0 && !done.classList.contains('disabled')) {
done.classList.add('disabled');
} else if (event.target.value.length > 0 && done.classList.contains('disabled')) {
done.classList.remove('disabled');
}
});
done.classList.add('disabled');
},
open: () => {
$$('.dialog-backdrop.backdrop-in')[0].classList.add('over-popover');
},
closed: () => {
$$('.dialog-backdrop.backdrop-in')[0].classList.remove('over-popover');
}
}
}).open();
});
return (
<div id='add-reply-dialog' className="add-reply-dialog"></div>
);
}));
const AddReply = ({userInfo, comment, onAddReply}) => {
return (
Device.phone ?
<AddReplyPopup userInfo={userInfo} comment={comment} onAddReply={onAddReply}/> :
<AddReplyDialog userInfo={userInfo} comment={comment} onAddReply={onAddReply}/>
)
};
const EditReplyPopup = inject("storeComments")(observer(({storeComments, comment, reply, onEditReply}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
useEffect(() => {
f7.popup.open('.edit-reply-popup');
});
const [stateText, setText] = useState(reply.reply);
return (
<Popup className="edit-reply-popup">
<Navbar>
<NavLeft>
<Link onClick={() => {
f7.popup.close('.edit-reply-popup');
setTimeout(() => {
storeComments.openEditReply(false);
}, 500);
}}>{_t.textCancel}</Link>
</NavLeft>
<NavTitle>{_t.textEditReply}</NavTitle>
<NavRight>
<Link className={stateText.length === 0 && 'disabled'}
onClick={() => {
f7.popup.close('.edit-reply-popup');
setTimeout(() => {
storeComments.openEditReply(false);
onEditReply(comment, reply, stateText);
}, 500);
}}
>
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
</Link>
</NavRight>
</Navbar>
<div className='wrap-comment'>
<div className="comment-header">
{Device.android &&
<div className='initials' style={{backgroundColor: `${reply.userColor}`}}>{reply.userInitials}</div>
}
<div>
<div className='name'>{reply.userName}</div>
<div className='reply-date'>{reply.date}</div>
</div>
</div>
<div className='wrap-textarea'>
<Input type='textarea' placeholder={_t.textEditReply} autofocus value={stateText} onChange={(event) => {setText(event.target.value);}}></Input>
</div>
</div>
</Popup>
)
}));
const EditReplyDialog = inject("storeComments")(observer(({storeComments, comment, reply, onEditReply}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const templateInitials = `<div class="initials" style="background-color: ${reply.userColor};">${reply.userInitials}</div>`;
useEffect(() => {
f7.dialog.create({
destroyOnClose: true,
containerEl: document.getElementById('edit-reply-dialog'),
content:
`<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="left">
<a href="#" id="reply-cancel">${_t.textCancel}</a>
</div>
<div class="title">${_t.textEditReply}</div>
<div class="right">
<a href="#" class="done" id="reply-done">${ Device.android ? '<i class="icon icon-done-comment-white"></i>' : _t.textDone}</a>
</div>
</div>
</div>
<div class='wrap-comment'>
<div class="comment-header">
${Device.android ? templateInitials : ''}
<div>
<div class='name'>${reply.userName}</div>
<div class='reply-date'>${reply.date}</div>
</div>
</div>
<div class='wrap-textarea'>
<textarea id='reply-text' placeholder='${_t.textEditComment}' autofocus>${reply.reply}</textarea>
</div>
</div>`,
on: {
opened: () => {
const cancel = document.getElementById('reply-cancel');
cancel.addEventListener('click', () => {
f7.dialog.close();
storeComments.openEditReply(false);
});
const done = document.getElementById('reply-done');
done.addEventListener('click', () => {
const value = document.getElementById('reply-text').value;
if (value.length > 0) {
onEditReply(comment, reply, value);
f7.dialog.close();
storeComments.openEditReply(false);
}
});
const area = document.getElementById('reply-text');
area.addEventListener('input', (event) => {
if (event.target.value.length === 0 && !done.classList.contains('disabled')) {
done.classList.add('disabled');
} else if (event.target.value.length > 0 && done.classList.contains('disabled')) {
done.classList.remove('disabled');
}
});
},
open: () => {
$$('.dialog-backdrop.backdrop-in')[0].classList.add('over-popover');
},
closed: () => {
$$('.dialog-backdrop.backdrop-in')[0].classList.remove('over-popover');
}
}
}).open();
});
return (
<div id='edit-reply-dialog' className="edit-reply-dialog"></div>
);
}));
const EditReply = ({comment, reply, onEditReply}) => {
return (
Device.phone ?
<EditReplyPopup comment={comment} reply={reply} onEditReply={onEditReply}/> :
<EditReplyDialog comment={comment} reply={reply} onEditReply={onEditReply}/>
)
};
// View comments
const ViewComments = ({storeComments, storeAppOptions, onCommentMenuClick, onResolveComment}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const isAndroid = Device.android;
const viewMode = !storeAppOptions.canComments;
const comments = storeComments.groupCollectionFilter || storeComments.collectionComments;
const sortComments = comments.length > 0 ? [...comments].sort((a, b) => a.time > b.time ? 1 : -1) : null;
const [clickComment, setComment] = useState();
const [commentActionsOpened, openActionComment] = useState(false);
const [reply, setReply] = useState();
const [replyActionsOpened, openActionReply] = useState(false);
return (
<Page>
<Navbar title={_t.textComments} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose=".coauth__sheet">
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
{!sortComments ?
<div className='no-comments'>{_t.textNoComments}</div> :
<List className='comment-list'>
{sortComments.map((comment, indexComment) => {
return (
<ListItem key={`comment-${indexComment}`}>
<div slot='header' className='comment-header'>
<div className='left'>
{isAndroid && <div className='initials' style={{backgroundColor: `${comment.userColor ? comment.userColor : '#cfcfcf'}`}}>{comment.userInitials}</div>}
<div>
<div className='user-name'>{comment.userName}</div>
<div className='comment-date'>{comment.date}</div>
</div>
</div>
{!viewMode &&
<div className='right'>
<div className='comment-resolve' onClick={() => {onResolveComment(comment);}}><Icon icon={comment.resolved ? 'icon-resolve-comment check' : 'icon-resolve-comment'} /></div>
<div className='comment-menu'
onClick={() => {setComment(comment); openActionComment(true);}}
><Icon icon='icon-menu-comment'/></div>
</div>
}
</div>
<div slot='footer'>
{comment.quote && <div className='comment-quote'>{sliceQuote(comment.quote)}</div>}
<div className='comment-text'><pre>{comment.comment}</pre></div>
{comment.replies.length > 0 &&
<ul className='reply-list'>
{comment.replies.map((reply, indexReply) => {
return (
<li key={`reply-${indexComment}-${indexReply}`}
className='reply-item'
>
<div className='item-content'>
<div className='item-inner'>
<div className='item-title'>
<div slot='header' className='reply-header'>
<div className='left'>
{isAndroid && <div className='initials' style={{backgroundColor: `${reply.userColor ? reply.userColor : '#cfcfcf'}`}}>{reply.userInitials}</div>}
<div>
<div className='user-name'>{reply.userName}</div>
<div className='reply-date'>{reply.date}</div>
</div>
</div>
{!viewMode &&
<div className='right'>
<div className='reply-menu'
onClick={() => {setComment(comment); setReply(reply); openActionReply(true);}}
>
<Icon icon='icon-menu-comment'/>
</div>
</div>
}
</div>
<div slot='footer'>
<div className='reply-text'><pre>{reply.reply}</pre></div>
</div>
</div>
</div>
</div>
</li>
)
})}
</ul>
}
</div>
</ListItem>
)
})}
</List>
}
<CommentActions comment={clickComment} onCommentMenuClick={onCommentMenuClick} opened={commentActionsOpened} openActionComment={openActionComment}/>
<ReplyActions comment={clickComment} reply={reply} onCommentMenuClick={onCommentMenuClick} opened={replyActionsOpened} openActionReply={openActionReply}/>
</Page>
)
};
const _ViewComments = inject('storeComments', 'storeAppOptions')(observer(ViewComments));
const CommentList = inject("storeComments", "storeAppOptions")(observer(({storeComments, storeAppOptions, onCommentMenuClick, onResolveComment}) => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const isAndroid = Device.android;
const viewMode = !storeAppOptions.canComments;
const comments = storeComments.showComments;
const [currentIndex, setCurrentIndex] = useState(0);
const comment = comments[currentIndex];
const [commentActionsOpened, openActionComment] = useState(false);
const [reply, setReply] = useState();
const [replyActionsOpened, openActionReply] = useState(false);
const onViewPrevComment = () => {
if (currentIndex - 1 < 0) {
setCurrentIndex(comments.length - 1);
} else {
setCurrentIndex(currentIndex - 1);
}
};
const onViewNextComment = () => {
if (currentIndex + 1 === comments.length) {
setCurrentIndex(0);
} else {
setCurrentIndex(currentIndex + 1);
}
};
let arrayComments = []
comment.comment && comment.comment.replace(/((?:https?:\/\/|ftps?:\/\/|\bwww\.)(?:(?![.,?!;:()]*(?:\s|$))[^\s]){2,})|(\n+|(?:(?!(?:https?:\/\/|ftp:\/\/|\bwww\.)(?:(?![.,?!;:()]*(?:\s|$))[^\s]){2,}).)+)/gim,
(match, link, text) => {console.log(match); arrayComments.push(link ? <a onClick={() => window.open(link)} href={(link[0]==="w" ? "//" : "") + link} key={arrayComments.length}>{link}</a>
: text)})
return (
<Fragment>
<Toolbar position='bottom'>
{!viewMode &&
<Link className='btn-add-reply' href='#' onClick={() => {onCommentMenuClick('addReply', comment);}}>{_t.textAddReply}</Link>
}
<div className='comment-navigation row'>
<Link href='#' onClick={onViewPrevComment}><Icon slot='media' icon='icon-prev'/></Link>
<Link href='#' onClick={onViewNextComment}><Icon slot='media' icon='icon-next'/></Link>
</div>
</Toolbar>
<Page className='page-current-comment'>
<List className='comment-list'>
<ListItem>
<div slot='header' className='comment-header'>
<div className='left'>
{isAndroid && <div className='initials' style={{backgroundColor: `${comment.userColor ? comment.userColor : '#cfcfcf'}`}}>{comment.userInitials}</div>}
<div>
<div className='user-name'>{comment.userName}</div>
<div className='comment-date'>{comment.date}</div>
</div>
</div>
{!viewMode &&
<div className='right'>
<div className='comment-resolve' onClick={() => {onResolveComment(comment);}}><Icon icon={comment.resolved ? 'icon-resolve-comment check' : 'icon-resolve-comment'} /></div>
<div className='comment-menu'
onClick={() => {openActionComment(true);}}
><Icon icon='icon-menu-comment'/></div>
</div>
}
</div>
<div slot='footer'>
{comment.quote && <div className='comment-quote'>{sliceQuote(comment.quote)}</div>}
<div className='comment-text'><pre>{arrayComments}</pre></div>
{comment.replies.length > 0 &&
<ul className='reply-list'>
{comment.replies.map((reply, indexReply) => {
return (
<li key={`reply-${indexReply}`}
className='reply-item'
>
<div className='item-content'>
<div className='item-inner'>
<div className='item-title'>
<div slot='header' className='reply-header'>
<div className='left'>
{isAndroid && <div className='initials' style={{backgroundColor: `${reply.userColor ? reply.userColor : '#cfcfcf'}`}}>{reply.userInitials}</div>}
<div>
<div className='user-name'>{reply.userName}</div>
<div className='reply-date'>{reply.date}</div>
</div>
</div>
{!viewMode &&
<div className='right'>
<div className='reply-menu'
onClick={() => {setReply(reply); openActionReply(true);}}
>
<Icon icon='icon-menu-comment'/>
</div>
</div>
}
</div>
<div slot='footer'>
<div className='reply-text'><pre>{reply.reply}</pre></div>
</div>
</div>
</div>
</div>
</li>
)
})}
</ul>
}
</div>
</ListItem>
</List>
<CommentActions comment={comment} onCommentMenuClick={onCommentMenuClick} opened={commentActionsOpened} openActionComment={openActionComment}/>
<ReplyActions comment={comment} reply={reply} onCommentMenuClick={onCommentMenuClick} opened={replyActionsOpened} openActionReply={openActionReply}/>
</Page>
</Fragment>
)
}));
const ViewCommentSheet = ({closeCurComments, onCommentMenuClick, onResolveComment}) => {
useEffect(() => {
f7.sheet.open('#view-comment-sheet');
});
const [stateHeight, setHeight] = useState('45%');
const [stateOpacity, setOpacity] = useState(1);
const [stateStartY, setStartY] = useState();
const [isNeedClose, setNeedClose] = useState(false);
const handleTouchStart = (event) => {
const touchObj = event.changedTouches[0];
setStartY(parseInt(touchObj.clientY));
};
const handleTouchMove = (event) => {
const touchObj = event.changedTouches[0];
const dist = parseInt(touchObj.clientY) - stateStartY;
if (dist < 0) { // to top
setHeight('90%');
setOpacity(1);
setNeedClose(false);
} else if (dist < 80) {
setHeight('45%');
setOpacity(1);
setNeedClose(false);
} else {
setNeedClose(true);
setOpacity(0.6);
}
};
const handleTouchEnd = (event) => {
console.log('end');
const touchObj = event.changedTouches[0];
const swipeEnd = parseInt(touchObj.clientY);
const dist = swipeEnd - stateStartY;
if (isNeedClose) {
closeCurComments();
} else if (stateHeight === '90%' && dist > 20) {
setHeight('45%');
}
};
return (
<Sheet id='view-comment-sheet' style={{height: `${stateHeight}`, opacity: `${stateOpacity}`}}>
<div id='swipe-handler' className='swipe-container' onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
<Icon icon='icon-swipe'/>
</div>
<CommentList onCommentMenuClick={onCommentMenuClick} onResolveComment={onResolveComment}/>
</Sheet>
)
};
const ViewCommentPopover = ({onCommentMenuClick, onResolveComment}) => {
useEffect(() => {
f7.popover.open('#view-comment-popover', '#btn-coauth');
});
return (
<Popover id='view-comment-popover' style={{height: '410px'}} closeByOutsideClick={false}>
<CommentList onCommentMenuClick={onCommentMenuClick} onResolveComment={onResolveComment} />
</Popover>
)
};
const ViewCurrentComments = props => {
return (
Device.phone ?
<ViewCommentSheet {...props}/> :
<ViewCommentPopover {...props}/>
)
};
export {
AddComment,
EditComment,
AddReply,
EditReply,
_ViewComments as ViewComments,
ViewCurrentComments
};

View file

@ -0,0 +1,184 @@
import React, { Component, useEffect } from 'react';
import { observer, inject } from "mobx-react";
import { Page, Navbar, NavRight, List, ListItem, Icon, Toggle, Toolbar, Link } from 'framework7-react';
import { f7 } from 'framework7-react';
import { useTranslation } from 'react-i18next';
import {Device} from "../../../utils/device";
const PageReview = props => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const isDisableAllSettings = props.isReviewOnly || props.displayMode === "final" || props.displayMode === "original";
const canReview = !!props.canReview;
return (
<Page>
<Navbar title={_t.textReview} backLink={!props.noBack && _t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose=".coauth__sheet">
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
<List>
{canReview &&
<ListItem title={_t.textTrackChanges} className={isDisableAllSettings ? 'disabled' : ''}>
<Toggle checked={props.trackChanges} onToggleChange={
(prev) => {
props.onTrackChanges(!prev);
}
}/>
</ListItem>
}
{!props.isRestrictedEdit &&
<ListItem title={_t.textDisplayMode} link={'/display-mode/'} routeProps={{
onDisplayMode: props.onDisplayMode
}}/>
}
</List>
<List>
<ListItem title={_t.textReviewChange} link={'/review-change/'}>
<Icon slot="media" icon="icon-review-changes"></Icon>
</ListItem>
{canReview && !props.canUseReviewPermissions &&
<ListItem title={_t.textAcceptAllChanges} link='#'
className={'no-indicator' + (isDisableAllSettings ? ' disabled' : '')} onClick={() => {props.onAcceptAll();}}>
<Icon slot="media" icon="icon-accept-changes"></Icon>
</ListItem>
}
{canReview && !props.canUseReviewPermissions &&
<ListItem title={_t.textRejectAllChanges} link='#'
className={'no-indicator' + (isDisableAllSettings ? ' disabled' : '')} onClick={() => {props.onRejectAll();}}>
<Icon slot="media" icon="icon-reject-changes"></Icon>
</ListItem>
}
</List>
</Page>
)
};
const DisplayMode = props => {
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const mode = props.storeReview.displayMode;
return (
<Page>
<Navbar title={_t.textDisplayMode} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose=".coauth__sheet">
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
<List mediaList>
<ListItem title={_t.textMarkup}
subtitle={_t.textAllChangesEditing}
radio
checked={mode === 'markup'}
onClick={() => {
props.onDisplayMode('markup');
}}
></ListItem>
<ListItem title={_t.textFinal}
subtitle={_t.textAllChangesAcceptedPreview}
radio
checked={mode === 'final'}
onClick={() => {
props.onDisplayMode('final');
}}
></ListItem>
<ListItem title={_t.textOriginal}
subtitle={_t.textAllChangesRejectedPreview}
radio
checked={mode === 'original'}
onClick={() => {
props.onDisplayMode('original');
}}
></ListItem>
</List>
</Page>
)
};
const PageReviewChange = props => {
const isAndroid = Device.android;
const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true});
const change = props.change;
const displayMode = props.displayMode;
const isLockAcceptReject = (!change || (change && !change.editable) || (displayMode === "final" || displayMode === "original") || !props.canReview);
const isLockPrevNext = (displayMode === "final" || displayMode === "original");
return (
<Page className='page-review'>
<Navbar title={_t.textReviewChange} backLink={!props.noBack && _t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose=".coauth__sheet">
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
<Toolbar position='bottom'>
<span className='change-buttons row'>
{!props.isReviewOnly &&
<span className='accept-reject row'>
<Link id='btn-accept-change'
href='#'
className={isLockAcceptReject && 'disabled'}
onClick={() => {props.onAcceptCurrentChange()}}
>{_t.textAccept}</Link>
<Link id='btn-reject-change'
href='#'
className={isLockAcceptReject && 'disabled'}
onClick={() => {props.onRejectCurrentChange()}}
>{_t.textReject}</Link>
</span>
}
{props.isReviewOnly && change && change.editable &&
<span className='delete'>
<Link href='#' id="btn-delete-change" onClick={() => {props.onDeleteChange()}}>{_t.textDelete}</Link>
</span>
}
{props.goto && <Link href='#' id='btn-goto-change' onClick={() => {props.onGotoNextChange()}}><Icon slot='media' icon='icon-goto'/></Link>}
</span>
<span className='next-prev row'>
<Link id='btn-prev-change'
href='#'
onClick={() => {props.onPrevChange()}}
className={isLockPrevNext && 'disabled'}
><Icon slot='media' icon='icon-prev-change'/></Link>
<Link id='btn-next-change'
href='#'
onClick={() => {props.onNextChange()}}
className={isLockPrevNext && 'disabled'}
><Icon slot='media' icon='icon-next-change'/></Link>
</span>
</Toolbar>
{change ?
<div className='block-description'>
<div className='header-change'>
{isAndroid &&
<div className='initials' style={{backgroundColor: `#${change.color}`}}>{change.initials}</div>
}
<div className='info'>
<div className='user-name'>{change.userName}</div>
<div className='date-change'>{change.date}</div>
</div>
</div>
<div className='text'>{change.text}</div>
</div> :
<div className='no-changes'>{_t.textNoChanges}</div>
}
</Page>
)
};
const PageDisplayMode = inject("storeReview")(observer(DisplayMode));
export {PageReview, PageDisplayMode, PageReviewChange};

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View file

@ -1,6 +1,16 @@
// Encoded SVG Background
.encoded-svg-mask(@svg) {
.encoded-svg-mask(@svg, @color: @themeColor) {
@url: `encodeURIComponent(@{svg})`;
background-color: @themeColor;
background-color: @color;
-webkit-mask-image: url("data:image/svg+xml;charset=utf-8,@{url}");
}
.encoded-svg-uncolored-mask(@svg) {
@url: `encodeURIComponent(@{svg})`;
-webkit-mask-image: url("data:image/svg+xml;charset=utf-8,@{url}");
}
.encoded-svg-background(@svg) {
@url: `encodeURIComponent(@{svg})`;
background-image: url("data:image/svg+xml;charset=utf-8,@{url}");
}

View file

@ -0,0 +1,41 @@
@text-normal: #000;
.about {
.page-content {
text-align: center;
}
.content-block:first-child {
margin: 15px 0;
}
.content-block {
margin: 0 auto 15px;
a {
color: @text-normal;
}
}
h3 {
font-weight: normal;
margin: 0;
&.vendor {
color: @text-normal;
font-weight: bold;
margin-top: 15px;
}
}
p > label {
margin-right: 5px;
}
.logo {
display: inline-block;
width: 100%;
height: 55px;
background: url('../../../../common/mobile/resources/img/about/logo.svg') no-repeat center;
}
}

View file

@ -0,0 +1,20 @@
.page.page-users {
background-color: @white;
.block-title {
text-transform: none;
color: @black;
margin-top: 20px;
margin-bottom: 20px;
font-size: 17px;
font-weight: normal;
}
.color {
min-width: 40px;
min-height: 40px;
text-align: center;
border-radius: 50px;
line-height: 40px;
color: @white;
font-size: 18px;
}
}

View file

@ -0,0 +1,212 @@
@comment-date: #6d6d72;
@swipe-icon: rgba(0, 0, 0, 0.12);
@import './ios/comments';
@import './material/comments';
.wrap-comment {
padding: 16px 24px 0 16px;
.name {
font-weight: 600;
font-size: 16px;
}
.wrap-textarea {
margin-top: 6px;
.input {
height: 100%;
}
textarea {
font-size: 14px;
margin-top: 0;
height: 100%;
padding: 5px 0;
}
}
}
#add-comment-dialog, #edit-comment-dialog, #add-reply-dialog, #edit-reply-dialog {
.dialog {
--f7-dialog-width: 400px;
z-index: 13700;
.dialog-inner {
padding: 0;
height: 400px;
.wrap-comment {
.name, .comment-date, .reply-date {
text-align: left;
}
.wrap-textarea {
textarea {
color: @black;
width: 100%;
}
}
}
}
}
}
.comment-list {
.item-content .item-inner {
padding-right: 0;
padding-bottom: 0;
padding-top: 16px;
.comment-header {
display: flex;
justify-content: space-between;
padding-right: 16px;
.right {
display: flex;
justify-content: space-between;
width: 70px;
}
}
.reply-header {
display: flex;
justify-content: space-between;
padding-right: 16px;
}
}
.item-title {
width: 100%;
}
.user-name {
font-size: 16px;
line-height: 22px;
color: @black;
margin: 0;
font-weight: 700;
}
.comment-date, .reply-date {
font-size: 12px;
line-height: 18px;
color: @comment-date;
margin: 0;
}
.comment-quote {
color: @themeColor;
border-left: 1px solid @themeColor;
padding-left: 10px;
padding-right: 16px;
margin: 5px 0;
font-size: 14px;
}
.comment-text, .reply-text {
color: @black;
font-size: 14px;
line-height: 25px;
margin: 0;
max-width: 100%;
padding-right: 15px;
pre {
white-space: pre-wrap;
overflow-wrap: break-word;
}
}
.reply-list {
padding-left: 26px;
}
}
.edit-comment-popup, .add-reply-popup, .edit-reply-popup {
z-index: 20000;
}
#view-comment-sheet {
background-color: @white;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
height: 45%;
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.2), 0 4px 5px rgba(0, 0, 0, 0.12);
webkit-transition: height 200ms;
transition: height 200ms;
.top {
height: 90%;
}
.swipe-container {
display: flex;
justify-content: center;
height: 40px;
.icon-swipe {
margin-top: 8px;
width: 40px;
height: 4px;
background: @swipe-icon;
border-radius: 2px;
}
}
}
#view-comment-popover, #view-comment-sheet {
.toolbar {
position: fixed;
background-color: @white;
box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.2), 0px 4px 5px rgba(0, 0, 0, 0.12), 0px 2px 4px rgba(0, 0, 0, 0.14);
.link {
--f7-toolbar-link-color: @themeColor;
}
.toolbar-inner {
padding: 0 16px;
}
.btn-add-reply {
padding: 0;
min-width: 80px;
font-size: 16px;
}
.comment-navigation {
min-width: 62px;
display: flex;
justify-content: space-between;
.link {
padding: 0 12px;
}
}
}
}
#view-comment-popover {
background-color: @white;
.page .page-content {
padding: 16px;
padding-left: 0;
}
.comment-list {
.item-content {
.item-inner {
.comment-header, .reply-header {
padding-right: 0;
}
}
}
}
}
.page-current-comment {
position: relative;
.page-content {
background-color: @white;
}
.comment-list {
ul {
&:before, &:after {
content: none;
}
.item-content .item-inner {
padding-top: 0;
.reply-list .item-content .item-inner {
padding-top: 13px;
}
}
}
}
}
.dialog-backdrop.backdrop-in {
&.over-popover {
z-index: 13600;
}
}
.no-comments {
text-align: center;
margin-top: 35px;
}

View file

@ -0,0 +1,540 @@
.device-ios {
@blockTitleColor: #6d6d72;
@item-border-color: #c8c7cc;
--f7-list-item-border-color: @item-border-color;
@darkGreen: #40865c;
--f7-navbar-link-color: @themeColor;
--f7-subnavbar-link-color: @themeColor;
--f7-navbar-text-color: @black;
--f7-navbar-title-line-height: 44px;
--f7-navbar-link-line-height: 44px;
--f7-navbar-title-font-size: 17px;
--f7-list-bg-color: @white;
--f7-navbar-bg-color: #f7f7f8;
--f7-tabbar-link-inactive-color: @themeColor;
--f7-radio-active-color: @themeColor;
--f7-toggle-active-color: @themeColor;
--f7-range-bar-active-bg-color: @themeColor;
--f7-list-button-text-color: @themeColor;
--f7-dialog-button-text-color: @themeColor;
// Main Toolbar
#editor-navbar.navbar .right a + a,
#editor-navbar.navbar .left a + a {
margin-left: 0;
}
.navbar, .subnavbar {
a.btn-doc-back {
width: 22px;
}
background-color: var(--f7-navbar-bg-color);
.title {
font-weight: 600;
}
.navbar-inner, .subnavbar-inner {
z-index: auto;
}
.sheet-close {
width: 44px;
height: 44px;
display: flex;
justify-content: center;
}
}
.popover__titled {
.list {
ul {
background-color: var(--f7-list-bg-color);
li:first-child, li:last-child {
border-radius: 0;
a {
border-radius: 0;
}
}
}
&:first-child, &:last-child {
ul {
border-radius: 0;
}
li:first-child, li:last-child {
> label {
border-radius: 0;
}
}
}
}
.popover-inner {
//border-radius: var(--f7-popover-border-radius);
> .view {
border-radius: var(--f7-popover-border-radius);
}
}
.navbar-bg {
//-webkit-backdrop-filter: none;
backdrop-filter: none;
}
.list:first-child {
li:first-child {
a {
border-radius: 0;
}
}
}
.list:last-child {
li:last-child {
a {
//border-radius: 0;
}
&:after {
content: '';
position: absolute;
background-color: var(--f7-navbar-border-color, var(--f7-bars-border-color));
display: block;
//z-index: 15;
top: auto;
right: auto;
bottom: 0;
left: 0;
height: 1px;
width: 100%;
transform-origin: 50% 100%;
transform: scaleY(calc(1 / var(--f7-device-pixel-ratio)));
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
}
}
}
// Bullets and numbers
.bullets,
.numbers {
.page-content {
background: @white;
}
.row {
justify-content: space-around;
}
ul {
margin-top: 10px;
}
li {
width: 70px;
height: 70px;
margin-right: 1px;
border: 1px solid #c4c4c4;
html.pixel-ratio-2 & {
border: 0.5px solid #c4c4c4;
}
html.pixel-ratio-3 & {
border: 0.33px solid #c4c4c4;
}
.thumb {
width: 100%;
height: 100%;
background-color: @white;
background-size: cover;
label {
width: 100%;
text-align: center;
position: absolute;
top: 34%;
}
}
}
}
.popover {
li:last-child {
.segmented a {
&:first-child {
border-radius: var(--f7-button-border-radius) 0 0 var(--f7-button-border-radius);
}
&:last-child {
border-radius: 0 var(--f7-button-border-radius) var(--f7-button-border-radius) 0;
}
}
}
.page-content {
> .list {
&:last-child {
margin-bottom: 30px;
}
}
}
}
.list {
.item-content {
.color-preview {
width: 22px;
height: 8px;
display: inline-block;
margin-top: 21px;
box-sizing: border-box;
box-shadow: 0 0 0 1px rgba(0, 0, 0, .15) inset;
&.auto {
background-color: @autoColor;
}
}
.item-after {
.color-preview {
width: 75px;
height: 30px;
margin-top: -3px;
}
}
}
li.no-indicator {
.item-link {
.item-inner {
padding-right: 15px;
&:before {
content: none;
}
}
}
}
.item-inner {
padding-top: 7px;
.item-after {
color: @black;
.after-start {
margin: 0 5px;
}
.segmented {
min-width: 90px;
margin-left: 10px;
}
}
}
.buttons {
.item-inner {
padding-top: 0;
padding-bottom: 0;
align-items: stretch;
> .row {
width: 100%;
align-items: stretch;
.button {
flex: 1;
border: none;
height: inherit;
border-radius: 0;
font-size: 17px;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
.list-input-right input {
text-align: right;
}
}
.tab-buttons {
width: 100%;
display: flex;
flex-wrap: nowrap;
align-self: center;
.tab-link {
display: block;
width: 100%;
line-height: 26px;
position: relative;
overflow: hidden;
-webkit-box-flex: 1;
border: 1px solid @themeColor;
text-decoration: none;
text-align: center;
margin: 0;
padding: 0 1px;
height: 29px;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 14px;
font-family: inherit;
cursor: pointer;
outline: 0;
font-weight: 600;
&:first-child {
border-radius: 5px 0 0 5px;
border-left-width: 1px;
border-left-style: solid;
}
&:last-child {
border-radius: 0 5px 5px 0;
}
&.tab-link-active {
background: @themeColor;
color: @white;
}
}
}
.button {
border: 1px solid @themeColor;
color: @themeColor;
text-decoration: none;
text-align: center;
display: block;
border-radius: 5px;
line-height: 27px;
box-sizing: border-box;
background: 0 0;
padding: 0 10px;
margin: 0;
height: 29px;
white-space: nowrap;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px;
font-family: inherit;
cursor: pointer;
outline: 0;
&.active {
background: @themeColor;
color: @white;
i.icon {
background-color: @white;
}
}
}
.button-fill {
color: @themeColor;
background-color: @white;
}
.button-red {
color: @red;
background-color: @white;
}
.buttons-list {
li {
border: 0;
border-radius: 0;
height: 43px;
min-height: 43px;
font-size: 17px;
text-transform: initial;
padding: 0;
box-shadow: none;
}
}
.button-red .list-button {
color: red;
}
.block-title {
position: relative;
overflow: hidden;
margin: 0;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 14px;
text-transform: uppercase;
line-height: 1;
color: @blockTitleColor;
margin: 35px 15px 10px;
}
.shapes {
.page-content {
background: @white;
}
}
.dialog {
background-color: rgba(var(--f7-dialog-bg-color-rgb), 1);
}
#color-picker {
.right-block {
.button-round {
.icon {
height: 30px;
width: 30px;
}
}
}
}
.about {
.logo {
margin-top: 20px;
}
}
.content-block {
color: @blockTitleColor;
}
.dataview, #add-table, #add-shape, #add-slide, #add-chart {
&.page-content, .page-content {
background-color: @white;
}
}
// input[type="number"]
input[type="number"] {
&::placeholder,
&::-webkit-input-placeholder,
&::-moz-placeholder,
&:-moz-placeholder,
&:-ms-input-placeholder
{
color: @darkGreen;
}
}
// Regional Settings
.regional-settings {
.item-title-row {
display: flex;
justify-content: flex-start;
align-items: center;
.item-title {
margin-left: 20px;
white-space: normal;
}
}
}
// Find and Replace
.navbar {
.searchbar {
background: var(--f7-navbar-bg-color);
}
.searchbar-input-wrap {
margin-right: 10px;
height: 28px;
}
.buttons-row-replace a {
color: @themeColor;
}
}
.searchbar input[type=search] {
box-sizing: border-box;
width: 100%;
height: 100%;
display: block;
border: none;
appearance: none;
border-radius: 5px;
font-family: inherit;
color: @black;
font-size: 14px;
font-weight: 400;
padding: 0 8px;
background-color: @white;
padding: 0 28px;
}
.searchbar-inner {
&__left {
margin-right: 10px;
justify-content: center;
}
&__right {
.buttons-row a.next {
margin-left: 15px;
}
}
}
.searchbar-expandable.searchbar-enabled {
&.replace {
.searchbar-inner {
&__right {
width: 28%;
}
}
}
}
@media(max-width: 550px) {
.navbar {
.searchbar-input-wrap {
margin-right: 0;
}
}
.searchbar-expandable.searchbar-enabled {
top: 0;
.searchbar-inner {
&__center {
flex-direction: column;
}
&__right {
flex-direction: column-reverse;
margin-left: 10px;
}
}
&.replace {
height: 88px;
.searchbar-inner {
height: 100%;
&__center {
.searchbar-input-wrap {
margin: 8px 0;
}
}
&__right {
width: auto;
height: 100%;
justify-content: space-between;
.buttons-row-replace {
height: 50%;
}
}
}
}
}
}
.actions-button {
background: rgba(255,255,255,.95);
}
.actions-button-text {
height: 57px;
line-height: 57px;
font-size: 20px;
color: @themeColor;
white-space: normal;
text-overflow: ellipsis;
}
}

View file

@ -0,0 +1,464 @@
.device-android {
@tabLinkColor: rgba(255,255,255,.7);
@red: #f44336;
@white: #fff;
@darkGreen: #40865c;
@darkGrey: #757575;
--f7-navbar-shadow-image: none;
--f7-navbar-bg-color: @themeColor;
--f7-navbar-link-color: @navBarIconColor;
--f7-navbar-text-color: @navBarIconColor;
--f7-navbar-height: 56px;
--f7-subnavbar-bg-color: @themeColor;
--f7-subnavbar-link-color: @navBarIconColor;
--f7-subnavbar-text-color: @navBarIconColor;
--f7-subnavbar-height: 56px;
--f7-radio-active-color: @themeColor;
--f7-toggle-active-color: @themeColor;
--f7-range-bar-active-bg-color: @themeColor;
--f7-range-knob-color: @themeColor;
--f7-range-knob-size: 16px;
--f7-link-highlight-color: transparent;
--f7-touch-ripple-color: rgba(255,255,255,0.1);
--f7-input-focused-border-color: @themeColor;
--f7-label-focused-text-color: @themeColor;
--f7-dialog-button-text-color: @themeColor;
.navbar {
.sheet-close {
width: 56px;
height: 56px;
display: flex;
justify-content: center;
}
}
.page.page-with-subnavbar.page-with-logo {
.page-content {
--f7-page-navbar-offset: var(--f7-navbar-height);
}
}
// Buttons
.segmented {
.decrement, .increment {
display: flex;
border: none;
min-width: 40px;
margin-left: 0;
border-radius: 0;
height: 32px;
}
label {
color: @black;
margin: 0 5px;
line-height: 32px;
}
}
.button {
--f7-button-text-color: @themeColor;
color: @themeColor;
text-align: center;
display: block;
border-radius: 2px;
line-height: 36px;
box-sizing: border-box;
appearance: none;
background: 0 0;
margin: 0;
height: 36px;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 14px;
text-transform: uppercase;
font-family: inherit;
cursor: pointer;
min-width: 64px;
padding: 0 8px;
position: relative;
overflow: hidden;
outline: 0;
-webkit-transition-duration: .3s;
transition-duration: .3s;
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
.button-fill {
color: @white;
background-color: @themeColor;
}
.button-raised {
box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 1px 2px rgba(0,0,0,.24);
}
.button-red {
color: @white;
background-color: @red;
}
.buttons-list {
li {
margin: 20px 16px;
color: @white;
border-radius: 2px;
text-transform: uppercase;
height: 36px;
min-height: 36px;
font-size: 14px;
}
}
.table-presets {
.button {
min-width: 0;
}
}
.button-fill .list-button {
background-color: @themeColor;
color: @white;
height: 36px;
text-align: center;
line-height: 36px;
text-transform: uppercase;
font-size: 14px;
font-weight: 500;
border-radius: 2px;
margin: 20px 16px;
}
.button-raised .list-button {
box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 1px 2px rgba(0,0,0,.24);
}
.button-red .list-button {
background-color: @red;
}
// Tabs
.tab-buttons {
position: relative;
display: flex;
height: 100%;
width: 100%;
justify-content: space-between;
.tab-link {
justify-content: center;
height: 100%;
box-sizing: border-box;
padding-left: 0;
padding-right: 0;
font-size: 14px;
font-weight: 500;
text-transform: uppercase;
align-items: center;
color: @tabLinkColor;
i.icon {
opacity: 0.5;
}
&.tab-link-active {
color: @white;
i.icon {
opacity: 1;
}
}
}
.tab-link-highlight {
--f7-tabbar-link-active-border-color: rgba(255,255,255,0.5);
position: absolute;
left: 0;
bottom: 0;
height: 3px;
}
}
// List
.list {
li.no-indicator {
.item-link {
.item-inner{
padding-right: 15px;
&:before {
content: none;
}
}
}
}
.item-link {
.item-inner {
.item-after {
color: @black;
}
}
}
&.inputs-list {
.item-input, .item-link {
.item-inner {
display: block;
.item-title, .item-label {
width: 100%;
font-size: 12px;
}
.item-input-wrap {
margin-left: 0;
}
}
}
}
.buttons {
box-sizing: border-box;
min-height: 48px;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.item-content {
width: 100%;
.item-inner {
padding-bottom: 0;
padding-top: 0;
.row {
width: 100%;
.button {
flex: 1;
font-size: 17px;
margin-left: 5px;
&:first-child {
margin-left: 0;
}
&.active {
color: @white;
background-color: @themeColor;
i.icon {
background-color: @white;
}
}
}
}
}
}
}
.item-content {
.color-preview {
width: 30px;
height: 30px;
border-radius: 16px;
margin-top: -3px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, .15) inset;
&.auto {
background-color: @autoColor;
}
}
}
}
// Bullets and numbers
.bullets,
.numbers {
.page-content {
background: @white;
}
.row {
justify-content: space-around;
}
ul {
margin-top: 10px;
}
li {
width: 70px;
height: 70px;
margin-right: 1px;
border: 1px solid @gray;
html.pixel-ratio-2 & {
border: 0.5px solid @gray;
}
html.pixel-ratio-3 & {
border: 0.33px solid @gray;
}
.thumb {
width: 100%;
height: 100%;
background-color: @white;
background-size: cover;
label {
width: 100%;
text-align: center;
position: absolute;
top: 34%;
}
}
}
}
.popover__titled {
.list:last-child {
li:last-child {
a {
border-radius: 0;
}
}
}
}
// Color palette
#color-picker {
.right-block {
.button-round {
background-color: @themeColor;
}
}
}
// Regional Settings
.regional-settings {
.list {
.item-inner {
margin-left: 16px;
}
.item-title-row {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
flex-direction: row-reverse;
.item-title {
white-space: normal;
}
}
}
}
// Find and Replace
.searchbar-inner {
&__center {
flex-wrap: wrap;
}
// &__left {
// padding-top: 4px;
// }
}
.navbar {
.searchbar-input-wrap {
height: 32px;
margin-right: 10px;
margin: 4px 0;
}
&-inner {
overflow: initial;
}
}
.searchbar .input-clear-button {
width: 18px;
height: 18px;
&:after {
color: @white;
font-size: 19px;
}
}
.searchbar-icon {
&:after {
color: @white;
font-size: 19px;
}
}
.searchbar input[type=search] {
box-sizing: border-box;
width: 100%;
display: block;
border: none;
appearance: none;
border-radius: 0;
font-family: inherit;
color: @white;
font-size: 16px;
font-weight: 400;
padding: 0;
border-bottom: 1px solid @white;
height: 100%;
padding: 0 36px 0 24px;
background-color: transparent;
background-repeat: no-repeat;
background-position: 0 center;
opacity: 1;
background-size: 24px 24px;
transition-duration: .3s;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" fill="@{white}" height="24" viewBox="0 0 24 24" width="24"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
}
.searchbar input[type=search]::placeholder {
color: @white;
}
.navbar {
.searchbar-expandable.searchbar-enabled {
top: 0;
// height: 100%;
.searchbar-inner {
height: 100%;
&__center {
flex-direction: column;
}
&__right {
flex-direction: column-reverse;
}
}
&.replace {
height: 96px;
}
}
a.link {
padding: 0 16px;
}
a.icon-only {
width: auto;
height: 56px;
}
.buttons-row-replace a {
color: @white;
padding: 0;
}
.searchbar .buttons-row {
align-self: flex-start;
}
}
@media(max-width: 550px) {
.searchbar-expandable.searchbar-enabled {
.searchbar-inner {
&__left {
margin-right: 33px;
}
}
}
}
.actions-button-text {
cursor: pointer;
line-height: 48px;
font-size: 16px;
color: rgba(0,0,0,.87);
}
@media (min-width: 496px) {
.actions-modal {
width: 100%;
left: auto;
margin-left: 0;
}
}
}

View file

@ -0,0 +1,826 @@
@import './about';
@white: #ffffff;
@black: #000000;
@gray: #c4c4c4;
@darkGray: #6d6d72;
@green: #4cd964;
@red: #f00;
@autoColor: @black;
.navbar.main-navbar {
height: 0;
&.navbar-with-logo {
height: 26px;
}
.navbar-inner {
display: flex;
justify-content: center;
padding-top: 8px;
}
.navbar-bg {
&:before, &:after {
content: none;
}
}
}
.navbar {
.title {
text-overflow: initial;
white-space: normal;
}
}
.navbar-hidden {
transform: translate3d(0, calc(-1 * (var(--f7-navbar-height) + var(--f7-subnavbar-height))), 0);
}
.navbar-hidden+.page>.page-content, .navbar-hidden+.page-content {
padding-top: 0;
}
.page.editor>.page-content {
transition: padding-top .3s ease-in;
}
.subnavbar {
.subnavbar-inner {
padding: 0;
}
}
.page.page-with-subnavbar {
.page-content {
--f7-page-subnavbar-offset: 0px;
}
&.page-with-logo .page-content {
--f7-page-subnavbar-offset: 26px;
}
}
.popup, .popover, .sheet-modal {
.list {
&:first-child {
margin-top: 0;
}
.inner-range-title {
padding: 15px 0 0 15px;
}
}
.page-content {
&.no-padding-top {
padding-top: 0;
}
}
}
.disabled, [disabled] {
opacity: .55;
pointer-events: none;
}
.text-content {
padding: 14px 10px 0 10px;
}
.list {
.item-text {
text-overflow: initial;
white-space: normal;
height: auto;
max-height: initial;
-webkit-line-clamp: initial;
}
}
.shapes {
li {
width: 70px;
height: 70px;
margin: 0 1px;
.thumb {
width: 100%;
height: 100%;
background-color: @themeColor;
}
}
}
.chart-types {
width: 100%;
.row {
padding: 0 10px;
}
li {
width: 60px;
height: 60px;
margin: 6px;
.thumb {
width: 100%;
height: 100%;
background-size: contain;
}
}
}
.chart-styles {
.row {
li {
margin: 0;
padding: 1px;
}
img {
width: 50px;
height: 50px;
}
}
}
.segmented {
.decrement, .increment {
text-overflow: clip;
}
}
.about {
.content-block {
margin: 0 auto 15px;
a {
color: @black;
}
}
}
.content-block {
margin: 32px 0;
padding: 0 16px;
box-sizing: border-box;
}
// Color Schemes
.color-schemes-menu {
cursor: pointer;
display: block;
background-color: @white;
.item-inner {
justify-content: flex-start;
}
.color-schema-block {
display: flex;
}
.color {
min-width: 26px;
min-height: 26px;
margin: 0 2px 0 0;
box-shadow: 0 0 0 1px rgba(0,0,0,.15) inset;
}
.item-title {
margin-left: 20px;
color: #212121;
}
}
// Layout
.slide-layout {
&__list {
margin: auto;
}
ul {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
li {
position: relative;
z-index: 1;
margin-top: 12px;
img {
box-shadow: 0 0 0 1px rgba(0,0,0,.15);
}
}
.item-inner {
padding-top: 0;
}
.item-inner:after {
display: none;
}
.item-inner:before {
opacity: 0;
content: '';
position: absolute;
width: 22px;
height: 22px;
right: 11px;
bottom: 0;
z-index: 1;
background-repeat: no-repeat;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="#aa5252"><g><circle fill="#fff" cx="11" cy="11" r="11"/><path d="M11,21A10,10,0,1,1,21,11,10,10,0,0,1,11,21h0ZM17.4,7.32L17.06,7a0.48,0.48,0,0,0-.67,0l-7,6.84L6.95,11.24a0.51,0.51,0,0,0-.59.08L6,11.66a0.58,0.58,0,0,0,0,.65l3.19,3.35a0.38,0.38,0,0,0,.39,0L17.4,8a0.48,0.48,0,0,0,0-.67h0Z"/></g></svg>');
}
.active .item-inner:before {
opacity: 1;
}
}
// Theme
.slide-theme {
&__list {
margin: auto;
ul {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding-left: 18px;
padding-right: 18px;
padding-bottom: 14px;
}
}
.item-inner:after {
display: none;
}
.item-theme {
position: relative;
margin: 0;
box-shadow: 0 0 0 1px rgba(0,0,0,.15);
width: 88px;
height: 40px;
margin-top: 14px;
background-image: url(../img/themes/themes.png);
display: block;
}
.item-theme.active:before {
content: '';
position: absolute;
width: 22px;
height: 22px;
right: -5px;
bottom: -5px;
z-index: 1;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="#aa5252"><g><circle fill="#fff" cx="11" cy="11" r="11"/><path d="M11,21A10,10,0,1,1,21,11,10,10,0,0,1,11,21h0ZM17.4,7.32L17.06,7a0.48,0.48,0,0,0-.67,0l-7,6.84L6.95,11.24a0.51,0.51,0,0,0-.59.08L6,11.66a0.58,0.58,0,0,0,0,.65l3.19,3.35a0.38,0.38,0,0,0,.39,0L17.4,8a0.48,0.48,0,0,0,0-.67h0Z"/></g></svg>');
}
}
// Transition
.slide-transition {
.splitter {
display: flex;
align-items: center;
color: @black;
label {
margin: 0 5px;
}
}
.buttons-row {
display: flex;
margin: 0;
min-width: 90px;
margin-left: 10px;
.button {
width: 100%;
}
.button:first-child {
border-radius: 5px 0 0 5px;
border-left-width: 1px;
border-left-style: solid;
}
.button:last-child {
border-radius: 0 5px 5px 0;
}
}
}
.style-effect, .style-type {
.list .item-title {
font-weight: normal;
}
}
.range-slider-delay {
width: 100%;
margin: 4px 0 5px 0;
appearance: none;
background: linear-gradient(to right,#b7b8b7 0,#b7b8b7 100%);
background-position: center;
background-size: 100% 2px;
background-repeat: no-repeat;
outline: 0;
border: none;
box-sizing: content-box;
&:disabled {
opacity: .55;
}
&::-webkit-slider-thumb {
appearance: none;
height: 28px;
width: 28px;
border-radius: 50%;
background: @white;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
}
&::-ms-thumb {
appearance: none;
height: 28px;
width: 28px;
border-radius: 50%;
background: @white;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
}
}
.buttons-list {
ul {
&::before, &::after {
display: none;
}
li {
border: 0;
font-weight: normal;
.item-link {
height: 100%;
.item-content {
min-height: initial;
height: 100%;
padding: 0;
}
.item-inner {
justify-content: center;
align-items: center;
padding: 0;
min-height: initial;
&::before {
display: none;
}
}
}
}
}
}
.item-color-auto {
.color-auto {
width: 22px;
height: 22px;
background-color: @autoColor;
}
&.active {
.color-auto {
box-shadow: 0 0 0 1px @white, 0 0 0 4px @themeColor;
border-radius: 1px;
}
}
}
.color-palettes {
.palette {
padding: 8px 0px;
a {
flex-grow: 1;
position: relative;
min-width: 10px;
min-height: 26px;
margin: 1px 1px 0 0;
box-shadow: 0 0 0 1px rgba(0, 0, 0, .15) inset;
&.active:after {
content: ' ';
position: absolute;
width: 100%;
height: 100%;
box-shadow: 0 0 0 1px @white, 0 0 0 4px @themeColor;
z-index: 1;
border-radius: 1px;
}
&.transparent {
background-repeat: no-repeat;
background-size: 100% 100%;
.encoded-svg-background("<svg xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 22 22' xml:space='preserve'><line stroke='#ff0000' stroke-linecap='undefined' stroke-linejoin='undefined' id='svg_1' y2='0' x2='22' y1='22' x1='0' stroke-width='2' fill='none'/></svg>");
}
}
}
.row {
padding: 0;
}
.list .item-inner {
display: block;
}
.standart-colors, .dynamic-colors {
.palette {
display: flex;
}
}
.dynamic-colors {
.empty-color {
background-color: @white;
}
}
}
#color-picker {
display: flex;
justify-content: space-around;
align-items: center;
max-width: 300px;
margin: 0 auto;
margin-top: 4px;
.color-picker-container {
width: calc(100% - 94px);
position: relative;
max-width: 100%;
height: auto;
font-size: 0;
.color-picker-module-wheel {
margin: 0;
}
}
.right-block {
margin-left: 20px;
.color-hsb-preview {
width: 72px;
height: 72px;
overflow: hidden;
border: 1px solid @gray;
border-radius: 100px;
.new-color-hsb-preview, .current-color-hsb-preview {
height: 36px;
}
.new-color-hsb-preview {
border-radius: 100px 100px 0 0;
}
.current-color-hsb-preview {
border-radius: 0 0 100px 100px;
}
}
.button-round {
height: 72px;
width: 72px;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
border-radius: 100px;
background-color: @white;
box-shadow: 0 4px 4px rgba(0,0,0,.25);
// border-color: transparent;
border: 0;
margin-top: 20px;
}
}
}
// Table styles
.table-styles {
width: 100%;
.row {
&, li {
margin-bottom: 12px;
}
}
li,
.row div {
margin: 0;
padding: 1px;
img {
width: 70px;
height: 50px;
}
}
}
// Cell styles
.cell-styles-list {
ul {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
padding-left: 5px;
padding-right: 5px;
padding-top: 5px;
}
li {
border: 0.5px solid #c8c7cc;
padding: 2px;
background-repeat: no-repeat;
width: 106px;
height: 56px;
margin-bottom: 10px;
background-position: center;
}
.item-inner:after {
display: none;
}
.item-theme.active:before {
content: '';
position: absolute;
width: 22px;
height: 22px;
right: 2px;
bottom: 2px;
z-index: 1;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="#40865c"><g><circle fill="#fff" cx="11" cy="11" r="11"/><path d="M11,21A10,10,0,1,1,21,11,10,10,0,0,1,11,21h0ZM17.4,7.32L17.06,7a0.48,0.48,0,0,0-.67,0l-7,6.84L6.95,11.24a0.51,0.51,0,0,0-.59.08L6,11.66a0.58,0.58,0,0,0,0,.65l3.19,3.35a0.38,0.38,0,0,0,.39,0L17.4,8a0.48,0.48,0,0,0,0-.67h0Z"/></g></svg>');
}
}
// input[type="number"]
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
// Regional Settings
.icon.lang-flag {
background-size: 48px auto;
background-image: url(../img/controls/flags@2x.png);
}
.icon.lang-flag {
width: 16px;
height: 12px;
}
.lang-flag.ca,
.lang-flag.ca-ES {
background-position: 0 0;
}
.lang-flag.cs,
.lang-flag.cs-CZ {
background-position: -16px 0;
}
.lang-flag.da,
.lang-flag.da-DK {
background-position: -32px 0;
}
.lang-flag.de,
.lang-flag.de-DE {
background-position: 0 -12px;
}
.lang-flag.el,
.lang-flag.el-GR {
background-position: -16px -12px;
}
.lang-flag.en,
.lang-flag.en-US {
background-position: -32px -12px;
}
.lang-flag.fr,
.lang-flag.fr-FR {
background-position: 0 -24px;
}
.lang-flag.hu,
.lang-flag.hu-HU {
background-position: -16px -24px;
}
.lang-flag.it,
.lang-flag.it-IT {
background-position: -32px -24px;
}
.lang-flag.ko,
.lang-flag.ko-KR {
background-position: 0 -36px;
}
.lang-flag.nl,
.lang-flag.nl-NL {
background-position: -16px -36px;
}
.lang-flag.nb,
.lang-flag.nb-NO,
.lang-flag.nn,
.lang-flag.nn-NO {
background-position: -32px -36px;
}
.lang-flag.pl,
.lang-flag.pl-PL {
background-position: 0 -48px;
}
.lang-flag.pt,
.lang-flag.pt-BR {
background-position: -16px -48px;
}
.lang-flag.ro,
.lang-flag.ro-RO {
background-position: -32px -48px;
}
.lang-flag.ru,
.lang-flag.ru-RU {
background-position: 0 -60px;
}
.lang-flag.sv,
.lang-flag.sv-SE {
background-position: -32px -60px;
}
.lang-flag.tr,
.lang-flag.tr-TR {
background-position: 0 -72px;
}
.lang-flag.uk,
.lang-flag.uk-UA {
background-position: -16px -72px;
}
.lang-flag.lv,
.lang-flag.lv-LV {
background-position: -32px -72px;
}
.lang-flag.lt,
.lang-flag.lt-LT {
background-position: 0 -84px;
}
.lang-flag.vi,
.lang-flag.vi-VN {
background-position: -16px -84px;
}
.lang-flag.de-CH {
background-position: -32px -84px;
}
.lang-flag.pt-PT {
background-position: -16px -96px;
}
.lang-flag.de-AT {
background-position: -32px -96px;
}
.lang-flag.es,
.lang-flag.es-ES {
background-position: 0 -108px;
}
.lang-flag.en-GB {
background-position: -32px -108px;
}
.lang-flag.en-AU {
background-position: 0 -120px;
}
.lang-flag.az-Latn-AZ {
background-position: -16px -120px;
}
.lang-flag.id,
.lang-flag.id-ID {
background-position: -32px -120px;
}
.lang-flag.bg,
.lang-flag.bg-BG {
background-position: 0 -132px;
}
.lang-flag.ca-ES-valencia {
background-position: -16px -132px;
}
.lang-flag.en-CA {
background-position: -32px -132px;
}
.lang-flag.en-ZA {
background-position: 0 -144px;
}
.lang-flag.eu,
.lang-flag.eu-ES {
background-position: -16px -144px;
}
.lang-flag.gl,
.lang-flag.gl-ES {
background-position: -32px -144px;
}
.lang-flag.hr,
.lang-flag.hr-HR {
background-position: 0 -156px;
}
.lang-flag.lb,
.lang-flag.lb-LU {
background-position: -16px -156px;
}
.lang-flag.mn,
.lang-flag.mn-MN {
background-position: -32px -156px;
}
.lang-flag.sl,
.lang-flag.sl-SI {
background-position: 0 -168px;
}
.lang-flag.sr,
.lang-flag.sr-Cyrl-RS,
.lang-flag.sr-Latn-RS {
background-position: -16px -168px;
}
.lang-flag.sk,
.lang-flag.sk-SK {
background-position: -32px -168px;
}
.lang-flag.kk,
.lang-flag.kk-KZ {
background-position: 0 -180px;
}
.lang-flag.fi,
.lang-flag.fi-FI,
.lang-flag.sv-FI {
background-position: -16px -180px;
}
.lang-flag.zh,
.lang-flag.zh-CN {
background-position: -32px -180px;
}
.lang-flag.ja,
.lang-flag.ja-JP {
background-position: 0 -192px;
}
.lang-flag.es-MX {
background-position: -16px -192px;
}
.checkbox-in-modal {
margin-top: 10px;
display: flex;
align-items: center;
.right-text {
margin-left: 10px;
}
}
.username-tip {
height: 20px;
color: @white;
padding: 0 10px;
position: absolute;
z-index: 900;
display: none;
pointer-events: none;
transition: opacity 0.1ms ease-out;
opacity: 0;
&.active {
display: block;
opacity: 1;
}
}
.dlg-adv-options {
z-index: 13700;
.content-block {
padding: 0;
}
.picker-3d {
.picker-item {
padding: 0;
text-align: left;
font-size: 16px;
span {
padding: 0;
}
}
}
.picker-center-highlight {
width: 100%;
left: 0;
right: 0;
}
}
// Skeleton of document
@keyframes flickerAnimation {
0% { opacity:0.1; }
50% { opacity:1; }
100% { opacity:0.1; }
}
@-o-keyframes flickerAnimation{
0% { opacity:0.1; }
50% { opacity:1; }
100% { opacity:0.1; }
}
@-moz-keyframes flickerAnimation{
0% { opacity:0.1; }
50% { opacity:1; }
100% { opacity:0.1; }
}
@-webkit-keyframes flickerAnimation{
0% { opacity:0.1; }
50% { opacity:1; }
100% { opacity:0.1; }
}
.doc-placeholder-container {
position: absolute;
width: 100%;
height: 100%;
z-index: 6000;
top: 0;
left: 0;
overflow: hidden;
}

View file

@ -0,0 +1,11 @@
@import './ios/contextmenu';
@import './material/contextmenu';
.document-menu {
width: auto;
}
html.phone .document-menu .list-block .list-button {
padding: 0 10px;
}

View file

@ -0,0 +1,31 @@
// Data view
.dataview {
.row {
justify-content: space-around;
}
ul {
padding: 0 10px;
list-style: none;
li {
display: inline-block;
}
}
.active {
position: relative;
z-index: 1;
&::after {
content: '';
position: absolute;
width: 22px;
height: 22px;
right: -5px;
bottom: -5px;
.encoded-svg-background('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 22 22" fill="@{themeColor}"><g><circle fill="#fff" cx="11" cy="11" r="11"/><path d="M11,21A10,10,0,1,1,21,11,10,10,0,0,1,11,21h0ZM17.4,7.32L17.06,7a0.48,0.48,0,0,0-.67,0l-7,6.84L6.95,11.24a0.51,0.51,0,0,0-.59.08L6,11.66a0.58,0.58,0,0,0,0,.65l3.19,3.35a0.38,0.38,0,0,0,.39,0L17.4,8a0.48,0.48,0,0,0,0-.67h0Z"/></g></svg>');
}
}
}

View file

@ -0,0 +1,28 @@
@import "./ios/icons";
@import "./material/icons";
i.icon {
&.icon-paste {
width: 24px;
height: 24px;
.encoded-svg-uncolored-mask('<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" /><path d="M5 0H14V5H5V0Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" /></svg>');
}
&.icon-copy {
width: 24px;
height: 24px;
.encoded-svg-uncolored-mask('<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M1 1H15V7H16V0H0V17H8V16H1V1Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M23 8H9V23H23V8ZM8 7V24H24V7H8Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M13 5H3V4H13V5Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 9H3V8H8V9Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 13H3V12H8V13Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H11V11H21V12Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H11V15H21V16Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H11V19H21V20Z"/></svg>');
}
&.icon-cut {
width: 24px;
height: 24px;
.encoded-svg-uncolored-mask('<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#cut)"><path fill-rule="evenodd" clip-rule="evenodd" d="M3.22427 22.2702C4.51527 23.1269 6.52738 22.7183 7.6592 21.0127C8.79101 19.3071 8.38572 17.2943 7.09472 16.4376C5.80372 15.5809 3.79161 15.9896 2.65979 17.6952C1.52798 19.4008 1.93328 21.4136 3.22427 22.2702ZM2.67135 23.1035C4.51208 24.325 7.11827 23.6364 8.49243 21.5656C9.8666 19.4948 9.48837 16.8259 7.64764 15.6044C5.80691 14.3829 3.20072 15.0714 1.82656 17.1422C0.452398 19.2131 0.830625 21.882 2.67135 23.1035Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M20.9158 22.2702C19.6248 23.1269 17.6127 22.7183 16.4809 21.0127C15.349 19.3071 15.7543 17.2943 17.0453 16.4376C18.3363 15.5809 20.3484 15.9896 21.4803 17.6952C22.6121 19.4008 22.2068 21.4136 20.9158 22.2702ZM21.4687 23.1035C19.628 24.325 17.0218 23.6364 15.6476 21.5656C14.2735 19.4948 14.6517 16.8259 16.4924 15.6044C18.3331 14.3829 20.9393 15.0714 22.3135 17.1422C23.6877 19.2131 23.3094 21.882 21.4687 23.1035Z"/><path d="M16.4924 15.6044L13.9037 12.4737L19.9552 0.675715C20.0693 0.446914 19.9552 0.172352 19.727 0.0808313C19.4416 -0.0106892 19.0993 0.0808312 18.9851 0.263872L12.0233 11.4212L5.17562 0.263872C5.06149 0.035071 4.71911 -0.0564496 4.43379 0.035071C4.14847 0.126592 4.03434 0.401153 4.14847 0.629955L10.2001 12.4279L7.64761 15.6044L9.2292 18L12.0233 13.4804L14.9108 18L16.4924 15.6044Z"/></g><defs><clipPath id="cut"><rect width="24" height="24"/></clipPath></defs></svg>');
}
&.icon-prev:after, &.icon-next:after {
content: none;
}
&.icon-collaboration {
width: 24px;
height: 24px;
.encoded-svg-background('<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g><path fill-rule="evenodd" clip-rule="evenodd" d="M15.9912 6C15.9912 8.34102 15.4074 10.1346 14.6055 11.3121C13.7983 12.4974 12.8249 13 11.9912 13C11.1575 13 10.1841 12.4974 9.37695 11.3121C8.57501 10.1346 7.99121 8.34102 7.99121 6C7.99121 3.61508 9.96974 2 11.9912 2C14.0127 2 15.9912 3.61508 15.9912 6ZM14.5015 12.9506C13.7365 13.6361 12.8649 14 11.9912 14C11.1195 14 10.2499 13.6378 9.48619 12.9554C7.78363 13.6081 6.36015 14.2591 5.26963 14.9224C3.55256 15.9667 3 16.8326 3 17.5C3 18.2545 3.4257 19.0877 4.82302 19.7879C6.25015 20.5031 8.57272 20.9999 12 21C15.4273 21 17.7499 20.5031 19.177 19.7879C20.5743 19.0877 21 18.2545 21 17.5C21 16.8326 20.4474 15.9667 18.7304 14.9224C17.6372 14.2575 16.2095 13.605 14.5015 12.9506ZM15.2272 12.1594C16.2765 10.7825 16.9912 8.67814 16.9912 6C16.9912 3 14.5 1 11.9912 1C9.48242 1 6.99121 3 6.99121 6C6.99121 8.68159 7.70777 10.7879 8.75931 12.1647C4.60309 13.7964 2 15.4951 2 17.5C2 19.9852 5 21.9999 12 22C19 22 22 19.9852 22 17.5C22 15.4929 19.3913 13.7927 15.2272 12.1594Z" fill="@{themeColor}"/></g></svg>');
}
}

View file

@ -0,0 +1,37 @@
.device-ios {
.wrap-comment {
height: calc(100% - 60px);
}
.add-comment-popup, .add-reply-popup, .add-comment-dialog, .add-reply-dialog {
.wrap-textarea {
height: calc(100% - 34px);
}
}
.edit-comment-popup, .edit-reply-popup, .edit-comment-dialog, .edit-reply-dialog {
.wrap-textarea {
height: calc(100% - 52px);
}
}
.comment-list {
.reply-item {
.item-inner:after {
content: none !important;
}
&:before {
content: '';
position: absolute;
left: auto;
bottom: 0;
right: auto;
top: 0;
height: 1px;
width: 100%;
background-color: var(--f7-list-item-border-color);
display: block;
z-index: 15;
-webkit-transform-origin: 50% 100%;
transform-origin: 50% 100%;
}
}
}
}

View file

@ -0,0 +1,102 @@
.device-ios {
.document-menu {
@contextMenuBg: rgba(0, 0, 0, 0.9);
@modalHairlineColor: rgba(230, 230, 230, 0.9);
@modalButtonColor: rgba(200, 200, 200, 0.9);
background-color: @contextMenuBg;
border-radius: 8px;
.popover-angle {
&:after {
background: @contextMenuBg;
}
}
.list-block {
font-size: 14px;
white-space: pre;
&:first-child {
ul {
.hairline-remove(left);
//border-radius: 7px 0 0 7px;
}
li:first-child a {
//border-radius: 7px 0 0 7px;
border-radius: 0;
}
}
//&:last-child {
// ul {
// .hairline-remove(right);
// border-radius: 0 7px 7px 0;
// }
// li:last-child a{
// border-radius: 0 7px 7px 0;
// }
//}
//&:first-child:last-child {
// li:first-child:last-child a, ul:first-child:last-child {
// border-radius: 7px;
// }
//}
.item-link {
display: inline-block;
html:not(.watch-active-state) &:active, &.active-state {
//.transition(0ms);
background-color: #d9d9d9;
.item-inner {
.hairline-color(right, transparent);
}
}
html.phone & {
padding: 0 10px;
}
}
.list-button {
color: @white;
line-height: 36px;
.hairline(right, @modalHairlineColor);
}
// List items
li {
display: inline-flex;
}
// Last-childs
li {
&:last-child {
.list-button {
.hairline-remove(right);
}
}
&:last-child, &:last-child li:last-child {
.item-inner {
.hairline-remove(right);
}
}
li:last-child, &:last-child li {
.item-inner {
.hairline(right, @modalHairlineColor);
}
}
}
//.no-hairlines();
//.no-hairlines-between()
}
}
}

View file

@ -0,0 +1,28 @@
.device-ios {
i.icon {
&.icon_mask {
background-color: white;
}
&.icon-logo {
width: 100px;
height: 14px;
background: url('../../img/header/logo-ios.svg') no-repeat center;
}
&.icon-prev {
width: 22px;
height: 22px;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M16,20.5L15,21.5L4.5,11l0,0l0,0L15,0.5L16,1.5L6.6,11L16,20.5z"/></g></svg>');
&:after {
display: none;
}
}
&.icon-next {
width: 22px;
height: 22px;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M15.5,11L6,1.5l1.1-1.1L17.5,11l0,0l0,0L7.1,21.5L6,20.5L15.5,11z"/></g></svg>');
&:after {
display: none;
}
}
}
}

View file

@ -0,0 +1,101 @@
.device-android {
.wrap-comment {
height: calc(100% - 72px);
}
.add-comment-popup, .add-reply-popup, .add-comment-dialog, .add-reply-dialog {
.wrap-textarea {
height: calc(100% - 41px);
}
}
.edit-comment-popup, .edit-reply-popup, .edit-comment-dialog, .edit-reply-dialog {
.wrap-textarea {
height: calc(100% - 56px);
}
}
.wrap-comment, .comment-list, .reply-list {
.comment-header, .reply-header {
display: flex;
.initials {
border-radius: 50px;
color: @white;
display: flex;
justify-content: center;
align-items: center;
margin-right: 10px;
font-size: 14px;
}
}
}
.wrap-comment {
.comment-header {
align-items: center;
.initials {
height: 30px;
width: 30px;
}
}
.wrap-textarea {
.input:not(.input-outline):after {
content: none;
}
}
}
#add-comment-dialog, #edit-comment-dialog, #add-reply-dialog, #edit-reply-dialog {
.dialog {
--f7-dialog-text-color: @black;
.done {
padding-right: 6px;
}
}
}
.comment-list {
ul:after, .item-inner:after, li:last-child li .item-inner:after {
content: none;
}
.comment-header {
.left {
display: flex;
align-items: center;
.initials {
width: 40px;
height: 40px;
font-size: 18px;
}
}
}
}
.reply-list {
.reply-header {
.left {
display: flex;
.initials {
margin-top: 5px;
width: 24px;
height: 24px;
font-size: 11px;
}
}
}
}
.edit-comment-popup, .edit-reply-popup, #edit-comment-dialog, #edit-reply-dialog {
.wrap-comment {
.comment-header, .reply-header {
.initials {
height: 40px;
width: 40px;
}
}
}
}
#view-comment-popover {
.toolbar-bottom:after {
content: none;
}
}
}

View file

@ -0,0 +1,32 @@
.md {
.document-menu {
//line-height: 1 !important;
.popover-inner {
overflow: hidden;
}
.list-block {
white-space: pre;
ul {
height: 48px;
}
li {
display: inline-block;
}
.list-button {
color: #212121;
}
//.item-link {
// html.phone & {
//padding: 0 10px;
//}
//}
}
}
}

View file

@ -0,0 +1,37 @@
.device-android {
i.icon {
&.icon_mask {
background-color: black;
}
&.icon-logo {
width: 100px;
height: 14px;
background: url('../../img/header/logo-android.svg') no-repeat center;
}
&.icon-prev {
width: 20px;
height: 20px;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{white}"><g><polygon points="5.1,10.9 13.9,2 16,4.1 9.2,11.1 16,17.9 13.9,20 5.1,11.2 5,11.1 "/></g></svg>');
&:after {
display: none;
}
}
&.icon-next {
width: 20px;
height: 20px;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{white}"><g><polygon points="16.9,10.9 8.1,2 6,4.1 12.8,11.1 6,17.9 8.1,20 16.9,11.2 17,11.1 "/></g></svg>');
&:after {
display: none;
}
}
}
.navbar {
i.icon {
&.icon-collaboration {
width: 24px;
height: 24px;
.encoded-svg-background('<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M14.9912 6C14.9912 8.18203 14.4464 9.76912 13.7789 10.7492C13.101 11.7447 12.4042 12 11.9912 12C11.5782 12 10.8814 11.7447 10.2035 10.7492C9.53601 9.76912 8.99121 8.18203 8.99121 6C8.99121 4.23017 10.4571 3 11.9912 3C13.5254 3 14.9912 4.23017 14.9912 6ZM13.4917 13.6397C13.0059 13.8771 12.4989 14 11.9912 14C11.4861 14 10.9817 13.8784 10.4983 13.6434C8.53188 14.3681 6.94518 15.0737 5.78927 15.7768C4.10512 16.8011 4 17.4079 4 17.5C4 17.7664 4.1014 18.3077 5.27104 18.8939C6.50029 19.5099 8.64545 19.9999 12 20C15.3546 20 17.4997 19.5099 18.7289 18.8939C19.8986 18.3078 20 17.7664 20 17.5C20 17.4079 19.8949 16.8011 18.2107 15.7768C17.0529 15.0726 15.4627 14.3657 13.4917 13.6397ZM15.2272 12.1594C16.2765 10.7825 16.9912 8.67814 16.9912 6C16.9912 3 14.5 1 11.9912 1C9.48242 1 6.99121 3 6.99121 6C6.99121 8.68159 7.70777 10.7879 8.75931 12.1647C4.60309 13.7964 2 15.4951 2 17.5C2 19.9852 5 21.9999 12 22C19 22 22 19.9852 22 17.5C22 15.4929 19.3913 13.7927 15.2272 12.1594Z" fill="@{navBarIconColor}"/></svg>');
}
}
}
}

View file

@ -0,0 +1,75 @@
@statusBarBorderColor: #cbcbcb;
.navbar {
.searchbar {
background-color: var(--f7-navbar-bg-color);
.buttons-row {
align-self: center;
display: flex;
}
.searchbar-bg {
.hairline(bottom, @statusBarBorderColor);
}
}
.searchbar-inner {
justify-content: space-between;
&__center {
display: flex;
align-items: center;
width: 81%;
}
&__right {
display: flex;
align-items: center;
}
}
.searchbar-expandable {
transition-duration: 0s;
}
.buttons-row-replace {
display: flex;
flex-direction: column;
align-items: center;
// width: max-content;
width: 100%;
justify-content: center;
a {
font-size: 15px;
height: auto;
display: block;
line-height: normal;
}
}
@media(max-width: 550px)
{
.searchbar-expandable.searchbar-enabled {
.searchbar-inner {
&__left {
min-width: 22px;
max-width: 22px;
}
&__center {
flex-direction: column;
}
&__right {
flex-direction: column-reverse;
}
}
&.replace {
top: 0;
.searchbar-inner {
height: 100%;
&__left {
align-self: flex-start;
}
}
}
}
}
}

View file

@ -0,0 +1,9 @@
.md {
--background-normal: #f1f1f1;
}
@background-normal: var(--background-normal, #fff);
@border-regular-control: #cbcbcb;
@text-normal: #000;

View file

@ -0,0 +1,50 @@
export default class IrregularStack {
constructor (config) {
this._stack = [];
const _config = config || {};
this._strongCompare = _config.strongCompare || this._compare;
this._weakCompare = _config.weakCompare || this._compare;
}
_compare (obj1, obj2) {
if (typeof obj1 === 'object' && typeof obj2 === 'object' && window.JSON)
return window.JSON.stringify(obj1) === window.JSON.stringify(obj2);
return obj1 === obj2;
};
_indexOf (obj, compare) {
for (let i = this._stack.length - 1; i >= 0; i--) {
if (compare(this._stack[i], obj))
return i;
}
return -1;
}
push (obj) {
this._stack.push(obj);
}
pop (obj) {
const index = this._indexOf(obj, this._strongCompare);
if (index !== -1) {
const removed = this._stack.splice(index, 1);
return removed[0];
}
return undefined;
}
get (obj) {
const index = this._indexOf(obj, this._weakCompare);
if (index !== -1) {
return this._stack[index];
}
return undefined;
}
exist (obj) {
return !(this._indexOf(obj, this._strongCompare) < 0);
}
}

View file

@ -0,0 +1,80 @@
class LocalStorage {
constructor() {
Common.Gateway.on('internalcommand', data => {
if (data.type == 'localstorage') {
this._store = data.keys;
}
});
this._store = {};
try {
this._isAllowed = !!window.localStorage;
} catch (e) {
this._isAllowed = false;
}
}
get id() {
return this._storeName;
}
set id(name) {
this._storeName = name;
}
set keysFilter(value) {
this._filter = value;
}
get keysFilter() {
return this._filter;
}
sync() {
if ( !this._isAllowed )
Common.Gateway.internalMessage('localstorage', {cmd:'get', keys:this._filter});
}
save() {
if ( !this._isAllowed )
Common.Gateway.internalMessage('localstorage', {cmd:'set', keys:this._store});
}
setItem(name, value, just) {
if ( this._isAllowed ) {
try {
localStorage.setItem(name, value);
} catch (error){}
} else {
this._store[name] = value;
if ( just===true ) {
Common.Gateway.internalMessage('localstorage', {cmd:'set', keys: {name: value}});
}
}
}
getItem(name) {
if ( this._isAllowed )
return localStorage.getItem(name);
else return this._store[name]===undefined ? null : this._store[name];
};
setBool(name, value, just) {
this.setItem(name, value ? 1 : 0, just);
}
getBool(name, defValue) {
const value = this.getItem(name);
return (value !== null) ? (parseInt(value) != 0) : !!defValue;
}
itemExists(name) {
return this.getItem(name) !== null;
}
}
const instance = new LocalStorage();
export {instance as LocalStorage};

View file

@ -0,0 +1,52 @@
import React from 'react';
import { f7 } from 'framework7-react';
import { Dom7 } from 'framework7'
class WrapDevice {
constructor(){
const ua = navigator.userAgent,
isMobile = /Mobile(\/|\s|;)/.test(ua);
this.isPhone = /(iPhone|iPod)/.test(ua) ||
(!/(Silk)/.test(ua) && (/(Android)/.test(ua) && (/(Android 2)/.test(ua) || isMobile))) ||
(/(BlackBerry|BB)/.test(ua) && isMobile) ||
/(Windows Phone)/.test(ua);
this.isTablet = !this.isPhone && (/iPad/.test(ua) || /Android/.test(ua) || /(RIM Tablet OS)/.test(ua) ||
(/MSIE 10/.test(ua) && /; Touch/.test(ua)));
}
initDom() {
const $$ = Dom7;
if ( this.sailfish ) {
$$('html').addClass('sailfish');
}
$$('html').addClass(this.phone ? 'phone' : 'tablet');
// $$(window).on('resize', _.bind(this.onWindowResize, this));
}
get phone() {
return this.isPhone
}
get tablet() {
return this.isTablet
}
get sailfish() {
return /Sailfish/.test(navigator.userAgent) || /Jolla/.test(navigator.userAgent);
}
get android() {
return f7.device.android;
}
get ios() {
return f7.device.ios;
}
}
const device = new WrapDevice();
export {device as Device};

View file

@ -0,0 +1,32 @@
export default class Notifications {
constructor() {
this._events = {};
}
on(event, callback) {
const addevent = (e, c) => {
!this._events[e] && (this._events[e] = []);
this._events[e].push(c);
};
if ( typeof(event) == 'object' )
for (const i in event)
addevent(i, event[i])
else addevent(event, callback);
}
off(event, callback) {
if ( this._events[event] && this._events[event].includes(callback) ) {
this._events[event].splice(this._events[event].indexOf(callback), 1);
}
}
trigger(event/*, args*/) {
if ( this._events[event] ) {
this._events[event].forEach(callback => {
callback.apply(this, Array.prototype.slice.call(arguments, 1));
});
}
}
}

View file

@ -265,6 +265,7 @@ DE.ApplicationController = new(function(){
Common.Gateway.on('processmouse', onProcessMouse);
Common.Gateway.on('downloadas', onDownloadAs);
Common.Gateway.on('requestclose', onRequestClose);
DE.ApplicationView.tools.get('#idt-fullscreen')
.on('click', function(){
@ -509,6 +510,10 @@ DE.ApplicationController = new(function(){
}
}
function onRequestClose() {
Common.Gateway.requestClose();
}
function onDownloadAs() {
if ( permissions.download === false) {
Common.Gateway.reportError(Asc.c_oAscError.ID.AccessDeny, me.errorAccessDeny);

View file

@ -212,7 +212,7 @@ define([
onNoControlsColor: function(item) {
if (!item.isChecked())
this.api.asc_SetSpecialFormsHighlightColor(255, 192, 0);
this.api.asc_SetSpecialFormsHighlightColor(201, 200, 255);
else
this.api.asc_SetSpecialFormsHighlightColor();
Common.NotificationCenter.trigger('edit:complete', this.toolbar);

View file

@ -261,6 +261,7 @@ define([
callback: function(btn) {
if (btn == 'ok') {
me.api.asc_undoAllChanges();
me.api.asc_continueSaving();
me.showHistory();
} else
me.api.asc_continueSaving();
@ -275,9 +276,10 @@ define([
documentCaption = me.api.asc_getDocumentName();
(new Common.Views.RenameDialog({
filename: documentCaption,
maxLength: this.mode.wopi ? this.mode.wopi.FileNameMaxLength : undefined,
handler: function(result, value) {
if (result == 'ok' && !_.isEmpty(value.trim()) && documentCaption !== value.trim()) {
Common.Gateway.requestRename(value);
me.mode.wopi ? me.api.asc_wopi_renameFile(value) : Common.Gateway.requestRename(value);
}
Common.NotificationCenter.trigger('edit:complete', me);
}
@ -443,11 +445,14 @@ define([
Common.Utils.InternalSettings.set("de-settings-inputmode", value);
this.api.SetTextBoxInputMode(value);
var fast_coauth = Common.Utils.InternalSettings.get("de-settings-coauthmode");
/** coauthoring begin **/
if (this.mode.isEdit && !this.mode.isOffline && this.mode.canCoAuthoring) {
var fast_coauth = Common.localStorage.getBool("de-settings-coauthmode", true);
Common.Utils.InternalSettings.set("de-settings-coauthmode", fast_coauth);
this.api.asc_SetFastCollaborative(fast_coauth);
if (this.mode.isEdit && !this.mode.isOffline && this.mode.canCoAuthoring ) {
if (this.mode.canChangeCoAuthoring) {
fast_coauth = Common.localStorage.getBool("de-settings-coauthmode", true);
Common.Utils.InternalSettings.set("de-settings-coauthmode", fast_coauth);
this.api.asc_SetFastCollaborative(fast_coauth);
}
value = Common.localStorage.getItem((fast_coauth) ? "de-settings-showchanges-fast" : "de-settings-showchanges-strict");
Common.Utils.InternalSettings.set((fast_coauth) ? "de-settings-showchanges-fast" : "de-settings-showchanges-strict", value);
@ -483,9 +488,11 @@ define([
}
if (this.mode.isEdit) {
value = parseInt(Common.localStorage.getItem("de-settings-autosave"));
Common.Utils.InternalSettings.set("de-settings-autosave", value);
this.api.asc_setAutoSaveGap(value);
if (this.mode.canChangeCoAuthoring || !fast_coauth) {// can change co-auth. mode or for strict mode
value = parseInt(Common.localStorage.getItem("de-settings-autosave"));
Common.Utils.InternalSettings.set("de-settings-autosave", value);
this.api.asc_setAutoSaveGap(value);
}
value = Common.localStorage.getBool("de-settings-spellcheck", true);
Common.Utils.InternalSettings.set("de-settings-spellcheck", value);
@ -858,11 +865,13 @@ define([
},
showHistory: function() {
var maincontroller = DE.getController('Main');
if (!maincontroller.loadMask)
maincontroller.loadMask = new Common.UI.LoadMask({owner: $('#viewport')});
maincontroller.loadMask.setTitle(this.textLoadHistory);
maincontroller.loadMask.show();
if (!this.mode.wopi) {
var maincontroller = DE.getController('Main');
if (!maincontroller.loadMask)
maincontroller.loadMask = new Common.UI.LoadMask({owner: $('#viewport')});
maincontroller.loadMask.setTitle(this.textLoadHistory);
maincontroller.loadMask.show();
}
Common.Gateway.requestHistory();
},

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