Merge branch 'develop' into feature/de-embed-fill-form
|
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
|
355
apps/api/wopi/editor-wopi.ejs
Normal 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>
|
|
@ -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 || {};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -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 || {}));
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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>'
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>',
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -98,7 +98,8 @@ define([
|
|||
editTextInPopover : false,
|
||||
scope : null,
|
||||
editable : true,
|
||||
removable : true
|
||||
removable : true,
|
||||
hide : false
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
<% } %>
|
||||
|
||||
|
|
|
@ -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>
|
||||
<% } %>
|
|
@ -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() {
|
||||
|
|
|
@ -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 || {});
|
||||
});
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -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 || {}));
|
||||
});
|
|
@ -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) {
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 || {}))
|
||||
});
|
||||
|
|
|
@ -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>',
|
||||
|
|
|
@ -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 || {}));
|
||||
});
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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 + ') { %>',
|
||||
|
|
BIN
apps/common/main/resources/img/controls/Scroll_center@1.5x.png
Normal file
After Width: | Height: | Size: 111 B |
After Width: | Height: | Size: 433 B |
After Width: | Height: | Size: 514 B |
After Width: | Height: | Size: 561 B |
After Width: | Height: | Size: 367 B |
After Width: | Height: | Size: 717 B |
|
@ -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
|
||||
// ------------------------
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
// ---------------------------
|
||||
|
|
|
@ -51,3 +51,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.combo-color {
|
||||
.form-control:not(input) {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,7 +138,6 @@ textarea.form-control:focus {
|
|||
right: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,10 @@
|
|||
opacity: @component-disabled-opacity;
|
||||
}
|
||||
}
|
||||
|
||||
.dbl-clickable& .list-item {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.no-borders > .listview .item {
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
.icon.img-commonctrl {
|
||||
float: left;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
.table-styler {
|
||||
background-color: @canvas-content-background;
|
||||
|
||||
table {
|
||||
&.transparent {
|
||||
background-color: @canvas-content-background !important;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
186
apps/common/mobile/lib/component/ThemeColorPalette.jsx
Normal 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 };
|
|
@ -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) {
|
||||
|
|
245
apps/common/mobile/lib/controller/ContextMenu.jsx
Normal 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;
|
|
@ -269,6 +269,7 @@ define([
|
|||
arr.push(plugin);
|
||||
});
|
||||
me.api.asc_pluginsRegister('', arr);
|
||||
Common.Gateway.pluginsReady();
|
||||
},
|
||||
|
||||
getPlugins: function(pluginsData, fetchFunction) {
|
||||
|
|
288
apps/common/mobile/lib/controller/Plugins.jsx
Normal 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;
|
||||
|
||||
|
||||
|
12
apps/common/mobile/lib/controller/Search.jsx
Normal 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};
|
|
@ -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)));
|
585
apps/common/mobile/lib/controller/collaboration/Comments.jsx
Normal 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
|
||||
};
|
535
apps/common/mobile/lib/controller/collaboration/Review.jsx
Normal 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`}> <{_t.textImage}></label>);
|
||||
break;
|
||||
case 1:
|
||||
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-3`}> <{_t.textShape}></label>);
|
||||
break;
|
||||
case 2:
|
||||
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-4`}> <{_t.textChart}></label>);
|
||||
break;
|
||||
case 3:
|
||||
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextAdd}-5`}> <{_t.textEquation}></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`}> <{_t.textImage}></label>);
|
||||
break;
|
||||
case 1:
|
||||
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-3`}> <{_t.textShape}></label>);
|
||||
break;
|
||||
case 2:
|
||||
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-4`}> <{_t.textChart}></label>);
|
||||
break;
|
||||
case 3:
|
||||
changeText.push(<label key={`${Asc.c_oAscRevisionsChangeType.TextRem}-5`}> <{_t.textEquation}></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};
|
127
apps/common/mobile/lib/store/comments.js
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
129
apps/common/mobile/lib/store/users.js
Normal 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;
|
||||
}
|
||||
}
|
127
apps/common/mobile/lib/view/About.jsx
Normal 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;
|
|
@ -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',
|
||||
|
|
62
apps/common/mobile/lib/view/ContextMenu.jsx
Normal 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};
|
324
apps/common/mobile/lib/view/Search.jsx
Normal 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};
|
171
apps/common/mobile/lib/view/collaboration/Collaboration.jsx
Normal 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;
|
879
apps/common/mobile/lib/view/collaboration/Comments.jsx
Normal 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
|
||||
};
|
184
apps/common/mobile/lib/view/collaboration/Review.jsx
Normal 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};
|
BIN
apps/common/mobile/resources/img/themes/themes.png
Normal file
After Width: | Height: | Size: 46 KiB |
|
@ -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}");
|
||||
}
|
41
apps/common/mobile/resources/less/about.less
Normal 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;
|
||||
}
|
||||
}
|
20
apps/common/mobile/resources/less/collaboration.less
Normal 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;
|
||||
}
|
||||
}
|
212
apps/common/mobile/resources/less/comments.less
Normal 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;
|
||||
}
|
540
apps/common/mobile/resources/less/common-ios.less
Normal 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;
|
||||
}
|
||||
}
|
464
apps/common/mobile/resources/less/common-material.less
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
826
apps/common/mobile/resources/less/common.less
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
11
apps/common/mobile/resources/less/contextmenu.less
Normal 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;
|
||||
}
|
31
apps/common/mobile/resources/less/dataview.less
Normal 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>');
|
||||
}
|
||||
}
|
||||
}
|
28
apps/common/mobile/resources/less/icons.less
Normal 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>');
|
||||
}
|
||||
}
|
37
apps/common/mobile/resources/less/ios/comments.less
Normal 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%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
102
apps/common/mobile/resources/less/ios/contextmenu.less
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
28
apps/common/mobile/resources/less/ios/icons.less
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
apps/common/mobile/resources/less/material/comments.less
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
32
apps/common/mobile/resources/less/material/contextmenu.less
Normal 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;
|
||||
//}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
37
apps/common/mobile/resources/less/material/icons.less
Normal 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>');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
75
apps/common/mobile/resources/less/search.less
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
apps/common/mobile/resources/less/variables.less
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
.md {
|
||||
--background-normal: #f1f1f1;
|
||||
}
|
||||
|
||||
@background-normal: var(--background-normal, #fff);
|
||||
|
||||
@border-regular-control: #cbcbcb;
|
||||
@text-normal: #000;
|
50
apps/common/mobile/utils/IrregularStack.js
Normal 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);
|
||||
}
|
||||
|
||||
}
|
80
apps/common/mobile/utils/LocalStorage.js
Normal 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};
|
52
apps/common/mobile/utils/device.jsx
Normal 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};
|
32
apps/common/mobile/utils/notifications.js
Normal 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));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
},
|
||||
|
||||
|
|