Merge branch 'feature/mobile-apps-on-reactjs' into feature/mobile-apps-on-reactjs-fixes
This commit is contained in:
commit
5a090f8210
|
@ -1,6 +1,7 @@
|
|||
import React, { Component, Fragment } from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import { Device } from '../../../../common/mobile/utils/device'
|
||||
import {observer, inject} from "mobx-react";
|
||||
import { Device } from '../../../../common/mobile/utils/device';
|
||||
|
||||
import ContextMenuView, { idContextMenuElement, ActionsWithExtraItems } from '../view/ContextMenu';
|
||||
|
||||
|
@ -23,6 +24,8 @@ class ContextMenuController extends Component {
|
|||
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() {
|
||||
|
@ -38,6 +41,8 @@ class ContextMenuController extends Component {
|
|||
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) {
|
||||
|
@ -150,12 +155,61 @@ class ContextMenuController extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -1,17 +1,63 @@
|
|||
import React, { Component } from 'react'
|
||||
import {observer, inject} from "mobx-react"
|
||||
import { LocalStorage } from '../../../utils/LocalStorage';
|
||||
|
||||
class CollaborationController extends Component {
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
Common.Notifications.on('configOptionsFill', () => {
|
||||
const api = Common.EditorApi.get();
|
||||
// this.api = api;
|
||||
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));
|
||||
});
|
||||
|
||||
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) {
|
||||
|
@ -24,6 +70,10 @@ class CollaborationController extends Component {
|
|||
this.props.users.connection(change);
|
||||
}
|
||||
|
||||
onCoAuthoringDisconnect() {
|
||||
this.props.users.resetDisconnected(true);
|
||||
}
|
||||
|
||||
render() {
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -60,12 +60,12 @@ class CommentsController extends Component {
|
|||
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));
|
||||
});
|
||||
|
||||
Common.Notifications.on('comments:filterchange', this.onFilterChange.bind(this)); // for sse
|
||||
|
||||
Common.Notifications.on('configOptionsFill', () => {
|
||||
this.curUserId = this.appOptions.user.id;
|
||||
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', () => {
|
||||
|
@ -77,8 +77,13 @@ class CommentsController extends Component {
|
|||
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) {
|
||||
|
@ -238,6 +243,9 @@ class AddCommentController extends Component {
|
|||
}
|
||||
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,
|
||||
|
@ -264,10 +272,7 @@ class AddCommentController extends Component {
|
|||
!!comment.asc_putDocumentFlag && comment.asc_putDocumentFlag(documentFlag);
|
||||
|
||||
api.asc_addComment(comment);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
render() {
|
||||
return(
|
||||
|
@ -308,10 +313,10 @@ class EditCommentController extends Component {
|
|||
ascComment.asc_putDocumentFlag(comment.unattached);
|
||||
}
|
||||
|
||||
var reply = comment.replies;
|
||||
const reply = comment.replies;
|
||||
if (reply && reply.length > 0) {
|
||||
reply.forEach((reply) => {
|
||||
var addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
|
||||
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)));
|
||||
|
|
|
@ -7,7 +7,6 @@ export class storeComments {
|
|||
collectionComments: observable,
|
||||
groupCollectionComments: observable,
|
||||
filter: observable,
|
||||
groupCollectionFilter: observable,
|
||||
|
||||
showComments: observable,
|
||||
changeShowComment: action,
|
||||
|
@ -17,7 +16,7 @@ export class storeComments {
|
|||
changeComment: action,
|
||||
changeFilter: action,
|
||||
|
||||
sortComments: computed,
|
||||
groupCollectionFilter: computed,
|
||||
|
||||
isOpenEditComment: observable,
|
||||
openEditComment: action,
|
||||
|
@ -31,7 +30,6 @@ export class storeComments {
|
|||
groupCollectionComments = [];
|
||||
|
||||
filter = undefined;
|
||||
groupCollectionFilter = []; // for sse
|
||||
|
||||
showComments = [];
|
||||
changeShowComment (uid) {
|
||||
|
@ -42,54 +40,16 @@ export class storeComments {
|
|||
}
|
||||
|
||||
addComment (comment) {
|
||||
comment.groupName ? this.addCommentToGroupCollection(comment) : this.addCommentToCollection(comment);
|
||||
}
|
||||
|
||||
addCommentToCollection (comment) {
|
||||
this.collectionComments.push(comment);
|
||||
}
|
||||
|
||||
addCommentToGroupCollection (comment) {
|
||||
const groupName = comment.groupName;
|
||||
if (!this.groupCollectionComments[groupName]) {
|
||||
this.groupCollectionComments[groupName] = [];
|
||||
}
|
||||
this.groupCollectionComments[groupname].push(comment);
|
||||
if (this.filter.indexOf(groupname) !== -1) {
|
||||
this.groupCollectionFilter.push(comment);
|
||||
}
|
||||
comment.groupName ? this.groupCollectionComments.push(comment) : this.collectionComments.push(comment);
|
||||
}
|
||||
|
||||
removeComment (id) {
|
||||
if (this.collectionComments.length > 0) {
|
||||
this.removeCommentFromCollection(id);
|
||||
} else {
|
||||
this.removeCommentFromGroups(id);
|
||||
}
|
||||
}
|
||||
|
||||
removeCommentFromCollection (id) {
|
||||
const index = this.collectionComments.findIndex((comment) => {
|
||||
const collection = this.collectionComments.length > 0 ? this.collectionComments : this.groupCollectionComments;
|
||||
const index = collection.findIndex((comment) => {
|
||||
return comment.uid === id;
|
||||
});
|
||||
if (index !== -1) {
|
||||
this.collectionComments.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
removeCommentFromGroups (id) {
|
||||
for (let name in this.groupCollectionComments) {
|
||||
const store = this.groupCollectionComments[name];
|
||||
const comment = store.find((item) => {
|
||||
return item.uid === id;
|
||||
});
|
||||
const index = store.indexOf(comment);
|
||||
if (index !== -1) {
|
||||
this.groupCollectionComments[name].splice(index, 1);
|
||||
if (this.filter.indexOf(name) !== -1) {
|
||||
this.groupCollectionFilter.splice(this.groupCollectionFilter.indexOf(comment), 1);
|
||||
}
|
||||
}
|
||||
collection.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,43 +71,28 @@ export class storeComments {
|
|||
}
|
||||
|
||||
changeFilter (filter) {
|
||||
let comments = [];
|
||||
this.filter = filter;
|
||||
filter.forEach((item) => {
|
||||
if (!this.groupCollectionComments[item])
|
||||
this.groupCollectionComments[item] = [];
|
||||
comments = comments.concat(this.groupCollectionComments[item]);
|
||||
});
|
||||
this.groupCollectionFilter = comments;
|
||||
}
|
||||
|
||||
findComment (id) {
|
||||
let comment = this.collectionComments.find((item) => {
|
||||
const collection = this.collectionComments.length > 0 ? this.collectionComments : this.groupCollectionComments;
|
||||
let comment = collection.find((item) => {
|
||||
return item.uid === id;
|
||||
});
|
||||
if (!comment) {
|
||||
comment = this.findCommentInGroup(id);
|
||||
}
|
||||
return comment;
|
||||
}
|
||||
|
||||
findCommentInGroup (id) {
|
||||
let model;
|
||||
for (let name in this.groupCollectionComments) {
|
||||
const store = this.groupCollectionComments[name];
|
||||
const id = id.isArray() ? id[0] : id;
|
||||
model = store.find((item) => {
|
||||
return item.uid === id;
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (model) return model;
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
get sortComments () {
|
||||
const comments = (this.groupCollectionFilter.length !== 0) ? this.groupCollectionFilter : (this.collectionComments.length !== 0 ? this.collectionComments : false);
|
||||
if (comments.length > 0) {
|
||||
return [...comments].sort((a, b) => a.time > b.time ? 1 : -1);
|
||||
return arr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,15 @@ export class storeUsers {
|
|||
reset: action,
|
||||
currentUser: observable,
|
||||
setCurrentUser: action,
|
||||
connection: action
|
||||
connection: action,
|
||||
isDisconnected: observable,
|
||||
resetDisconnected: action
|
||||
})
|
||||
}
|
||||
|
||||
users = [];
|
||||
currentUser;
|
||||
isDisconnected = false;
|
||||
|
||||
reset (users) {
|
||||
this.users = Object.values(users)
|
||||
|
@ -25,6 +28,7 @@ export class storeUsers {
|
|||
this.currentUser = item;
|
||||
}
|
||||
});
|
||||
return this.currentUser;
|
||||
}
|
||||
|
||||
connection (change) {
|
||||
|
@ -41,6 +45,10 @@ export class storeUsers {
|
|||
!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();
|
||||
|
@ -62,4 +70,14 @@ export class storeUsers {
|
|||
});
|
||||
return user;
|
||||
}
|
||||
|
||||
searchUserByCurrentId (id) {
|
||||
let user = null;
|
||||
this.users.forEach((item) => {
|
||||
if (item.asc_getId() === id) {
|
||||
user = item;
|
||||
}
|
||||
});
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ import { observer, inject } from "mobx-react";
|
|||
import { Page, Navbar, Link } from "framework7-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const PageSpreadsheetAbout = props => {
|
||||
const PageAbout = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t("View.Settings", { returnObjects: true });
|
||||
const storeAppOptions = props.storeAppOptions;
|
||||
const isCanBranding = storeAppOptions.canBranding;
|
||||
const licInfo = isCanBranding ? storeAppOptions.customization : null;
|
||||
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;
|
||||
|
@ -17,27 +17,32 @@ const PageSpreadsheetAbout = props => {
|
|||
const infoCustomer = customer ? customer.info : null;
|
||||
const logoCustomer = customer ? customer.logo : null;
|
||||
|
||||
// console.log(storeAppOptions);
|
||||
// console.log(isCanBranding);
|
||||
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' ?
|
||||
{licInfo && typeof licInfo == 'object' && typeof(customer) == 'object' ? (
|
||||
<Fragment>
|
||||
<div className="content-block">
|
||||
{/* {licInfo && typeof licInfo == 'object' && typeof(customer) == 'object' ? null : (
|
||||
<i className="logo"></i>
|
||||
)} */}
|
||||
{logoCustomer && logoCustomer.length ? (
|
||||
<div id="settings-about-logo" className="settings-about-logo">
|
||||
<img src={logoCustomer} />
|
||||
<img src={logoCustomer} alt="" />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="content-block">
|
||||
<h3>SPREADSHEET EDITOR</h3>
|
||||
<h3>{_t.textVersion} 6.1.1</h3>
|
||||
<h3>{nameEditor}</h3>
|
||||
<h3>{_t.textVersion} {__PRODUCT_VERSION__}</h3>
|
||||
</div>
|
||||
<div className="content-block">
|
||||
{nameCustomer && nameCustomer.length ? (
|
||||
|
@ -45,20 +50,16 @@ const PageSpreadsheetAbout = props => {
|
|||
) : null}
|
||||
{addressCustomer && addressCustomer.length ? (
|
||||
<p>
|
||||
<label>{_t.textAddress}</label>
|
||||
<label>{_t.textAddress}:</label>
|
||||
<Link id="settings-about-address" className="external">{addressCustomer}</Link>
|
||||
</p>
|
||||
) : null}
|
||||
{mailCustomer && mailCustomer.length ? (
|
||||
<p>
|
||||
<label>{_t.textEmail}</label>
|
||||
<label>{_t.textEmail}:</label>
|
||||
<Link id="settings-about-email" className="external" target="_blank" href={"mailto:"+mailCustomer}>{mailCustomer}</Link>
|
||||
</p>
|
||||
) : null}
|
||||
<p>
|
||||
<label>{_t.textTel}</label>
|
||||
<Link id="settings-about-tel" className="external" target="_blank" href="tel:+37163399867">+371 633-99867</Link>
|
||||
</p>
|
||||
{urlCustomer && urlCustomer.length ? (
|
||||
<p>
|
||||
<Link id="settings-about-url" className="external" target="_blank"
|
||||
|
@ -78,21 +79,45 @@ const PageSpreadsheetAbout = props => {
|
|||
<p>
|
||||
<label>{_t.textPoweredBy}</label>
|
||||
</p>
|
||||
<h3 className="vendor">Ascensio System SIA</h3>
|
||||
<h3 className="vendor">{__PUBLISHER_NAME__}</h3>
|
||||
<p>
|
||||
<Link className="external" target="_blank" href="www.onlyoffice.com">www.onlyoffice.com</Link>
|
||||
<Link className="external" target="_blank" href={publisherUrl}>{publisherPrintUrl}</Link>
|
||||
</p>
|
||||
</div>
|
||||
</Fragment> :
|
||||
</Fragment>
|
||||
) : (
|
||||
<Fragment>
|
||||
<div className="content-block">
|
||||
<i className="logo"></i>
|
||||
<div className="logo"></div>
|
||||
</div>
|
||||
</Fragment>}
|
||||
<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 SpreadsheetAbout = inject("storeAppOptions")(observer(PageSpreadsheetAbout));
|
||||
const About = inject("storeAppOptions")(observer(PageAbout));
|
||||
|
||||
export default SpreadsheetAbout;
|
||||
export default About;
|
|
@ -47,7 +47,7 @@ const ActionsWithExtraItems = ({items, onMenuItemClick, opened, onActionClosed})
|
|||
<ActionsGroup>
|
||||
{items.length > 0 && items.map((item, index)=>{
|
||||
return(
|
||||
<ActionsButton key={`act-${item.caption}`} onClick={() => {onMenuItemClick(item.event)}}>{item.caption}</ActionsButton>
|
||||
<ActionsButton key={`act-${index}`} onClick={() => {onMenuItemClick(item.event)}}>{item.caption}</ActionsButton>
|
||||
)
|
||||
})}
|
||||
</ActionsGroup>
|
||||
|
|
|
@ -31,18 +31,21 @@ const AddCommentPopup = inject("storeComments")(observer(props => {
|
|||
<Navbar>
|
||||
<NavLeft>
|
||||
<Link onClick={() => {
|
||||
props.closeAddComment();
|
||||
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={() => {
|
||||
if (props.onAddNewComment(stateText, false)) {
|
||||
f7.popup.close('.add-comment-popup');
|
||||
setTimeout(() => {
|
||||
props.closeAddComment();
|
||||
f7.popup.close('.add-comment-popup');
|
||||
}
|
||||
props.onAddNewComment(stateText, false)
|
||||
}, 500);
|
||||
}}>
|
||||
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
|
||||
</Link>
|
||||
|
@ -104,9 +107,10 @@ const AddCommentDialog = inject("storeComments")(observer(props => {
|
|||
const done = document.getElementById('comment-done');
|
||||
done.addEventListener('click', () => {
|
||||
const value = document.getElementById('comment-text').value;
|
||||
if (value.length > 0 && props.onAddNewComment(value, false)) {
|
||||
if (value.length > 0) {
|
||||
f7.dialog.close();
|
||||
props.closeAddComment();
|
||||
props.onAddNewComment(value, false);
|
||||
}
|
||||
});
|
||||
const area = document.getElementById('comment-text');
|
||||
|
@ -193,16 +197,20 @@ const EditCommentPopup = inject("storeComments")(observer(({storeComments, comme
|
|||
<NavLeft>
|
||||
<Link onClick={() => {
|
||||
f7.popup.close('.edit-comment-popup');
|
||||
storeComments.openEditComment(false);
|
||||
setTimeout(() => {
|
||||
storeComments.openEditComment(false);
|
||||
}, 500);
|
||||
}}>{_t.textCancel}</Link>
|
||||
</NavLeft>
|
||||
<NavTitle>{_t.textEditComment}</NavTitle>
|
||||
<NavRight>
|
||||
<Link className={stateText.length === 0 && 'disabled'}
|
||||
onClick={() => {
|
||||
onEditComment(comment, stateText);
|
||||
f7.popup.close('.edit-comment-popup');
|
||||
storeComments.openEditComment(false);
|
||||
setTimeout(() => {
|
||||
storeComments.openEditComment(false);
|
||||
onEditComment(comment, stateText);
|
||||
}, 500);
|
||||
}}
|
||||
>
|
||||
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
|
||||
|
@ -313,17 +321,21 @@ const AddReplyPopup = inject("storeComments")(observer(({storeComments, userInfo
|
|||
<Navbar>
|
||||
<NavLeft>
|
||||
<Link onClick={() => {
|
||||
storeComments.openAddReply(false);
|
||||
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={() => {
|
||||
onAddReply(comment, stateText);
|
||||
storeComments.openAddReply(false);
|
||||
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>
|
||||
|
@ -429,16 +441,20 @@ const EditReplyPopup = inject("storeComments")(observer(({storeComments, comment
|
|||
<NavLeft>
|
||||
<Link onClick={() => {
|
||||
f7.popup.close('.edit-reply-popup');
|
||||
storeComments.openEditReply(false);
|
||||
setTimeout(() => {
|
||||
storeComments.openEditReply(false);
|
||||
}, 500);
|
||||
}}>{_t.textCancel}</Link>
|
||||
</NavLeft>
|
||||
<NavTitle>{_t.textEditReply}</NavTitle>
|
||||
<NavRight>
|
||||
<Link className={stateText.length === 0 && 'disabled'}
|
||||
onClick={() => {
|
||||
onEditReply(comment, reply, stateText);
|
||||
f7.popup.close('.edit-reply-popup');
|
||||
storeComments.openEditReply(false);
|
||||
setTimeout(() => {
|
||||
storeComments.openEditReply(false);
|
||||
onEditReply(comment, reply, stateText);
|
||||
}, 500);
|
||||
}}
|
||||
>
|
||||
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
|
||||
|
@ -544,7 +560,8 @@ const ViewComments = ({storeComments, storeAppOptions, onCommentMenuClick, onRes
|
|||
const isAndroid = Device.android;
|
||||
|
||||
const viewMode = !storeAppOptions.canComments;
|
||||
const comments = storeComments.sortComments;
|
||||
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);
|
||||
|
@ -555,10 +572,10 @@ const ViewComments = ({storeComments, storeAppOptions, onCommentMenuClick, onRes
|
|||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textComments} backLink={_t.textBack}/>
|
||||
{!comments ?
|
||||
{!sortComments ?
|
||||
<div className='no-comments'>{_t.textNoComments}</div> :
|
||||
<List className='comment-list'>
|
||||
{comments.map((comment, indexComment) => {
|
||||
{sortComments.map((comment, indexComment) => {
|
||||
return (
|
||||
<ListItem key={`comment-${indexComment}`}>
|
||||
<div slot='header' className='comment-header'>
|
||||
|
|
|
@ -391,6 +391,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.content-block {
|
||||
color: @blockTitleColor;
|
||||
}
|
||||
|
||||
.dataview, #add-table, #add-shape, #add-slide, #add-chart {
|
||||
&.page-content, .page-content {
|
||||
background-color: @white;
|
||||
|
@ -490,4 +494,17 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -431,4 +431,19 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
.about {
|
||||
.content-block {
|
||||
margin: 0 auto 15px;
|
||||
a {
|
||||
color: @black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-block {
|
||||
margin: 32px 0;
|
||||
padding: 0 16px;
|
||||
|
@ -669,6 +678,22 @@ input[type="number"]::-webkit-inner-spin-button {
|
|||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,16 @@ i.icon {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
}
|
||||
|
||||
.comment-list {
|
||||
.item-inner:after, li:last-child li .item-inner:after {
|
||||
ul:after, .item-inner:after, li:last-child li .item-inner:after {
|
||||
content: none;
|
||||
}
|
||||
.comment-header {
|
||||
|
|
|
@ -145,7 +145,9 @@
|
|||
"menuCancel": "Cancel",
|
||||
"textCopyCutPasteActions": "Copy, Cut and Paste Actions",
|
||||
"errorCopyCutPaste": "Copy, cut and paste actions using the context menu will be performed within the current file only.",
|
||||
"textDoNotShowAgain": "Don't show again"
|
||||
"textDoNotShowAgain": "Don't show again",
|
||||
"textColumns": "Columns",
|
||||
"textRows": "Rows"
|
||||
},
|
||||
"Settings": {
|
||||
"textCancel": "Cancel",
|
||||
|
@ -384,5 +386,14 @@
|
|||
"textStartAt": "Start At",
|
||||
"textLocation": "Location",
|
||||
"textFormat": "Format"
|
||||
},
|
||||
"About": {
|
||||
"textAbout": "About",
|
||||
"textVersion": "Version",
|
||||
"textEmail": "Email",
|
||||
"textAddress": "Address",
|
||||
"textTel": "Tel",
|
||||
"textPoweredBy": "Powered By",
|
||||
"textBack": "Back"
|
||||
}
|
||||
}
|
|
@ -11,7 +11,9 @@ import { Device } from '../../../../common/mobile/utils/device';
|
|||
@inject ( stores => ({
|
||||
isEdit: stores.storeAppOptions.isEdit,
|
||||
canViewComments: stores.storeAppOptions.canViewComments,
|
||||
canReview: stores.storeAppOptions.canReview
|
||||
canReview: stores.storeAppOptions.canReview,
|
||||
users: stores.users,
|
||||
isDisconnected: stores.users.isDisconnected
|
||||
}))
|
||||
class ContextMenu extends ContextMenuController {
|
||||
constructor(props) {
|
||||
|
@ -21,12 +23,18 @@ class ContextMenu extends ContextMenuController {
|
|||
this.onApiShowComment = this.onApiShowComment.bind(this);
|
||||
this.onApiHideComment = this.onApiHideComment.bind(this);
|
||||
this.onApiShowChange = this.onApiShowChange.bind(this);
|
||||
this.getUserName = this.getUserName.bind(this);
|
||||
}
|
||||
|
||||
static closeContextMenu() {
|
||||
f7.popover.close(idContextMenuElement, false);
|
||||
}
|
||||
|
||||
getUserName(id) {
|
||||
const user = this.props.users.searchUserByCurrentId(id);
|
||||
return Common.Utils.UserInfoParser.getParsedName(user.asc_getUserName());
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
|
||||
|
@ -89,6 +97,38 @@ class ContextMenu extends ContextMenuController {
|
|||
this.props.openOptions('coauth', 'cm-review-change');
|
||||
}, 400);
|
||||
break;
|
||||
case 'merge':
|
||||
api.MergeCells();
|
||||
break;
|
||||
case 'split':
|
||||
this.showSplitModal();
|
||||
break;
|
||||
case 'delete':
|
||||
api.asc_Remove();
|
||||
break;
|
||||
case 'deletetable':
|
||||
api.remTable();
|
||||
break;
|
||||
case 'edit':
|
||||
setTimeout(() => {
|
||||
this.props.openOptions('edit');
|
||||
}, 0);
|
||||
break;
|
||||
case 'addlink':
|
||||
setTimeout(() => {
|
||||
this.props.openOptions('add', 'link');
|
||||
}, 400)
|
||||
break;
|
||||
case 'openlink':
|
||||
const stack = Common.EditorApi.get().getSelectedElements();
|
||||
let value;
|
||||
stack.forEach((item) => {
|
||||
if (item.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {
|
||||
value = item.get_ObjectValue().get_Value();
|
||||
}
|
||||
});
|
||||
value && this.openLink(value);
|
||||
break;
|
||||
}
|
||||
|
||||
console.log("click context menu item: " + action);
|
||||
|
@ -117,6 +157,66 @@ class ContextMenu extends ContextMenuController {
|
|||
}).open();
|
||||
}
|
||||
|
||||
showSplitModal() {
|
||||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
let picker;
|
||||
const dialog = f7.dialog.create({
|
||||
title: _t.menuSplit,
|
||||
text: '',
|
||||
content:
|
||||
'<div class="content-block">' +
|
||||
'<div class="row">' +
|
||||
'<div class="col-50">' + _t.textColumns + '</div>' +
|
||||
'<div class="col-50">' + _t.textRows + '</div>' +
|
||||
'</div>' +
|
||||
'<div id="picker-split-size"></div>' +
|
||||
'</div>',
|
||||
buttons: [
|
||||
{
|
||||
text: _t.menuCancel
|
||||
},
|
||||
{
|
||||
text: 'OK',
|
||||
bold: true,
|
||||
onClick: function () {
|
||||
const size = picker.value;
|
||||
Common.EditorApi.get().SplitCell(parseInt(size[0]), parseInt(size[1]));
|
||||
}
|
||||
}
|
||||
]
|
||||
}).open();
|
||||
dialog.on('opened', () => {
|
||||
picker = f7.picker.create({
|
||||
containerEl: document.getElementById('picker-split-size'),
|
||||
cols: [
|
||||
{
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
values: [1,2,3,4,5,6,7,8,9,10]
|
||||
},
|
||||
{
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
values: [1,2,3,4,5,6,7,8,9,10]
|
||||
}
|
||||
],
|
||||
toolbar: false,
|
||||
rotateEffect: true,
|
||||
value: [3, 3]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
openLink(url) {
|
||||
if (Common.EditorApi.get().asc_getUrlType(url) > 0) {
|
||||
const newDocumentPage = window.open(url, '_blank');
|
||||
if (newDocumentPage) {
|
||||
newDocumentPage.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onDocumentReady() {
|
||||
super.onDocumentReady();
|
||||
|
||||
|
@ -132,7 +232,7 @@ class ContextMenu extends ContextMenuController {
|
|||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
|
||||
const { isEdit, canViewComments, canReview } = this.props;
|
||||
const { isEdit, canViewComments, canReview, isDisconnected } = this.props;
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
const stack = api.getSelectedElements();
|
||||
|
@ -202,7 +302,7 @@ class ContextMenu extends ContextMenuController {
|
|||
items[indexAfter] = items.splice(indexBefore, 1, items[indexAfter])[0];
|
||||
};
|
||||
|
||||
if ( isEdit && !this.isDisconnected ) {
|
||||
if ( isEdit && !isDisconnected ) {
|
||||
if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader && canCopy ) {
|
||||
itemsIcon.push({
|
||||
event: 'cut',
|
||||
|
@ -255,12 +355,12 @@ class ContextMenu extends ContextMenuController {
|
|||
});
|
||||
}
|
||||
|
||||
// if ( !_.isEmpty(api.can_AddHyperlink()) && !lockedHeader) {
|
||||
// arrItems.push({
|
||||
// caption: _t.menuAddLink,
|
||||
// event: 'addlink'
|
||||
// });
|
||||
// }
|
||||
if ( !!api.can_AddHyperlink() && !lockedHeader) {
|
||||
itemsText.push({
|
||||
caption: _t.menuAddLink,
|
||||
event: 'addlink'
|
||||
});
|
||||
}
|
||||
|
||||
if ( canReview ) {
|
||||
if (this.inRevisionChange) {
|
||||
|
|
|
@ -13,6 +13,8 @@ import {
|
|||
ViewCommentsController
|
||||
} from "../../../../common/mobile/lib/controller/collaboration/Comments";
|
||||
|
||||
import patch from '../lib/patch'
|
||||
|
||||
@inject(
|
||||
"storeAppOptions",
|
||||
"storeDocumentSettings",
|
||||
|
@ -56,6 +58,7 @@ class MainController extends Component {
|
|||
};
|
||||
|
||||
const loadConfig = data => {
|
||||
patch.isSupportEditFeature();
|
||||
console.log('load config');
|
||||
|
||||
this.editorConfig = Object.assign({}, this.editorConfig, data.config);
|
||||
|
|
67
apps/documenteditor/mobile/src/controller/add/AddLink.jsx
Normal file
67
apps/documenteditor/mobile/src/controller/add/AddLink.jsx
Normal file
|
@ -0,0 +1,67 @@
|
|||
import React, {Component} from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import {Device} from '../../../../../common/mobile/utils/device';
|
||||
import { withTranslation} from 'react-i18next';
|
||||
|
||||
import {PageAddLink} from '../../view/add/AddLink';
|
||||
|
||||
class AddLinkController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.onInsertLink = this.onInsertLink.bind(this);
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
if ( Device.phone ) {
|
||||
f7.sheet.close('.add-popup', true);
|
||||
} else {
|
||||
f7.popover.close('#add-popover');
|
||||
}
|
||||
}
|
||||
|
||||
getDisplayLinkText () {
|
||||
const api = Common.EditorApi.get();
|
||||
return api.can_AddHyperlink();
|
||||
}
|
||||
|
||||
onInsertLink (url, display, tip) {
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
const { t } = this.props;
|
||||
const _t = t("Add", { returnObjects: true });
|
||||
|
||||
const urltype = api.asc_getUrlType(url.trim());
|
||||
const isEmail = (urltype == 2);
|
||||
|
||||
if (urltype < 1) {
|
||||
f7.dialog.alert(_t.txtNotUrl, _t.notcriticalErrorTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
let _url = url.replace(/^\s+|\s+$/g,'');
|
||||
|
||||
if (! /(((^https?)|(^ftp)):\/\/)|(^mailto:)/i.test(_url) )
|
||||
_url = (isEmail ? 'mailto:' : 'http://' ) + _url;
|
||||
|
||||
_url = _url.replace(new RegExp("%20",'g')," ");
|
||||
|
||||
const props = new Asc.CHyperlinkProperty();
|
||||
props.put_Value(_url);
|
||||
props.put_Text(!display ? _url : display);
|
||||
props.put_ToolTip(tip);
|
||||
|
||||
api.add_Hyperlink(props);
|
||||
|
||||
this.closeModal();
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<PageAddLink closeModal={this.closeModal} onInsertLink={this.onInsertLink} getDisplayLinkText={this.getDisplayLinkText} noNavbar={this.props.noNavbar}/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const AddLinkWithTranslation = withTranslation()(AddLinkController);
|
||||
|
||||
export {AddLinkWithTranslation as AddLinkController};
|
|
@ -66,7 +66,6 @@ const _Rometo10 = (str) => {
|
|||
class AddOtherController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.onInsertLink = this.onInsertLink.bind(this);
|
||||
this.onInsertPageNumber = this.onInsertPageNumber.bind(this);
|
||||
this.onPageBreak = this.onPageBreak.bind(this);
|
||||
this.onColumnBreak = this.onColumnBreak.bind(this);
|
||||
|
@ -86,42 +85,6 @@ class AddOtherController extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
getDisplayLinkText () {
|
||||
const api = Common.EditorApi.get();
|
||||
return api.can_AddHyperlink();
|
||||
}
|
||||
|
||||
onInsertLink (url, display, tip) {
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
const { t } = this.props;
|
||||
const _t = t("Add", { returnObjects: true });
|
||||
|
||||
const urltype = api.asc_getUrlType(url.trim());
|
||||
const isEmail = (urltype == 2);
|
||||
|
||||
if (urltype < 1) {
|
||||
f7.dialog.alert(_t.txtNotUrl, _t.notcriticalErrorTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
let _url = url.replace(/^\s+|\s+$/g,'');
|
||||
|
||||
if (! /(((^https?)|(^ftp)):\/\/)|(^mailto:)/i.test(_url) )
|
||||
_url = (isEmail ? 'mailto:' : 'http://' ) + _url;
|
||||
|
||||
_url = _url.replace(new RegExp("%20",'g')," ");
|
||||
|
||||
const props = new Asc.CHyperlinkProperty();
|
||||
props.put_Value(_url);
|
||||
props.put_Text(!display ? _url : display);
|
||||
props.put_ToolTip(tip);
|
||||
|
||||
api.add_Hyperlink(props);
|
||||
|
||||
this.closeModal();
|
||||
}
|
||||
|
||||
onInsertPageNumber (type) {
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
|
@ -280,8 +243,6 @@ class AddOtherController extends Component {
|
|||
render () {
|
||||
return (
|
||||
<AddOther closeModal={this.closeModal}
|
||||
onInsertLink={this.onInsertLink}
|
||||
getDisplayLinkText={this.getDisplayLinkText}
|
||||
onInsertPageNumber={this.onInsertPageNumber}
|
||||
onPageBreak={this.onPageBreak}
|
||||
onColumnBreak={this.onColumnBreak}
|
||||
|
|
10
apps/documenteditor/mobile/src/lib/patch.jsx
Normal file
10
apps/documenteditor/mobile/src/lib/patch.jsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
const patch = () => {
|
||||
return null
|
||||
};
|
||||
|
||||
patch.isSupportEditFeature = () => {
|
||||
return false
|
||||
};
|
||||
|
||||
export default patch;
|
|
@ -18,25 +18,29 @@ export default class MainPage extends Component {
|
|||
this.state = {
|
||||
editOptionsVisible: false,
|
||||
addOptionsVisible: false,
|
||||
addShowOptions: null,
|
||||
settingsVisible: false,
|
||||
collaborationVisible: false
|
||||
};
|
||||
}
|
||||
|
||||
handleClickToOpenOptions = (opts, page) => {
|
||||
handleClickToOpenOptions = (opts, showOpts) => {
|
||||
ContextMenu.closeContextMenu();
|
||||
|
||||
this.setState(state => {
|
||||
if ( opts == 'edit' )
|
||||
return {editOptionsVisible: true};
|
||||
else if ( opts == 'add' )
|
||||
return {addOptionsVisible: true};
|
||||
return {
|
||||
addOptionsVisible: true,
|
||||
addShowOptions: showOpts
|
||||
};
|
||||
else if ( opts == 'settings' )
|
||||
return {settingsVisible: true};
|
||||
else if ( opts == 'coauth' )
|
||||
return {
|
||||
collaborationVisible: true,
|
||||
collaborationPage: page
|
||||
collaborationPage: showOpts
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -90,7 +94,7 @@ export default class MainPage extends Component {
|
|||
}
|
||||
{
|
||||
!this.state.addOptionsVisible ? null :
|
||||
<AddOptions onclosed={this.handleOptionsViewClosed.bind(this, 'add')} />
|
||||
<AddOptions onclosed={this.handleOptionsViewClosed.bind(this, 'add')} showOptions={this.state.addShowOptions} />
|
||||
}
|
||||
{
|
||||
!this.state.settingsVisible ? null :
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, {Component, useEffect} from 'react';
|
||||
import {View,Page,Navbar,NavRight,Link,Popup,Popover,Icon,Tabs,Tab} from 'framework7-react';
|
||||
import React, {Component, useEffect, Fragment} from 'react';
|
||||
import {View,Page,Navbar,NavRight, NavTitle, Link,Popup,Popover,Icon,Tabs,Tab} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {f7} from 'framework7-react';
|
||||
import { observer, inject } from "mobx-react";
|
||||
|
@ -8,10 +8,11 @@ import {Device} from '../../../../../common/mobile/utils/device';
|
|||
import {AddTableController} from "../../controller/add/AddTable";
|
||||
import AddShapeController from "../../controller/add/AddShape";
|
||||
import {AddImageController} from "../../controller/add/AddImage";
|
||||
import {AddLinkController} from "../../controller/add/AddLink";
|
||||
import {AddOtherController} from "../../controller/add/AddOther";
|
||||
|
||||
import {PageImageLinkSettings} from "../add/AddImage";
|
||||
import {PageAddLink, PageAddNumber, PageAddBreak, PageAddSectionBreak, PageAddFootnote} from "../add/AddOther";
|
||||
import {PageAddNumber, PageAddBreak, PageAddSectionBreak, PageAddFootnote} from "../add/AddOther";
|
||||
|
||||
const routes = [
|
||||
// Image
|
||||
|
@ -22,7 +23,7 @@ const routes = [
|
|||
// Other
|
||||
{
|
||||
path: '/add-link/',
|
||||
component: PageAddLink,
|
||||
component: AddLinkController,
|
||||
},
|
||||
{
|
||||
path: '/add-page-number/',
|
||||
|
@ -44,15 +45,20 @@ const routes = [
|
|||
|
||||
const AddLayoutNavbar = ({ tabs, inPopover }) => {
|
||||
const isAndroid = Device.android;
|
||||
const { t } = useTranslation();
|
||||
const _t = t('Add', {returnObjects: true});
|
||||
return (
|
||||
<Navbar>
|
||||
<div className='tab-buttons tabbar'>
|
||||
{tabs.map((item, index) =>
|
||||
<Link key={"de-link-" + item.id} tabLink={"#" + item.id} tabLinkActive={index === 0}>
|
||||
<Icon slot="media" icon={item.icon}></Icon>
|
||||
</Link>)}
|
||||
{isAndroid && <span className='tab-link-highlight' style={{width: 100 / tabs.lenght + '%'}}></span>}
|
||||
</div>
|
||||
{tabs.length > 1 ?
|
||||
<div className='tab-buttons tabbar'>
|
||||
{tabs.map((item, index) =>
|
||||
<Link key={"de-link-" + item.id} tabLink={"#" + item.id} tabLinkActive={index === 0}>
|
||||
<Icon slot="media" icon={item.icon}></Icon>
|
||||
</Link>)}
|
||||
{isAndroid && <span className='tab-link-highlight' style={{width: 100 / tabs.lenght + '%'}}></span>}
|
||||
</div> :
|
||||
<NavTitle>{ tabs[0].caption }</NavTitle>
|
||||
}
|
||||
{ !inPopover && <NavRight><Link icon='icon-expand-down' popupClose=".add-popup"></Link></NavRight> }
|
||||
</Navbar>
|
||||
)
|
||||
|
@ -73,31 +79,41 @@ const AddLayoutContent = ({ tabs }) => {
|
|||
const AddTabs = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('Add', {returnObjects: true});
|
||||
const showPanels = props.showPanels;
|
||||
const tabs = [];
|
||||
tabs.push({
|
||||
caption: _t.textTable,
|
||||
id: 'add-table',
|
||||
icon: 'icon-add-table',
|
||||
component: <AddTableController />
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textShape,
|
||||
id: 'add-shape',
|
||||
icon: 'icon-add-shape',
|
||||
component: <AddShapeController />
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textImage,
|
||||
id: 'add-image',
|
||||
icon: 'icon-add-image',
|
||||
component: <AddImageController />
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textOther,
|
||||
id: 'add-other',
|
||||
icon: 'icon-add-other',
|
||||
component: <AddOtherController />
|
||||
});
|
||||
if (!showPanels) {
|
||||
tabs.push({
|
||||
caption: _t.textTable,
|
||||
id: 'add-table',
|
||||
icon: 'icon-add-table',
|
||||
component: <AddTableController/>
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textShape,
|
||||
id: 'add-shape',
|
||||
icon: 'icon-add-shape',
|
||||
component: <AddShapeController/>
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textImage,
|
||||
id: 'add-image',
|
||||
icon: 'icon-add-image',
|
||||
component: <AddImageController/>
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textOther,
|
||||
id: 'add-other',
|
||||
icon: 'icon-add-other',
|
||||
component: <AddOtherController/>
|
||||
});
|
||||
}
|
||||
if (showPanels && showPanels === 'link') {
|
||||
tabs.push({
|
||||
caption: _t.textAddLink,
|
||||
id: 'add-link',
|
||||
component: <AddLinkController noNavbar={true}/>
|
||||
});
|
||||
}
|
||||
return (
|
||||
<View style={props.style} stackPages={true} routes={routes}>
|
||||
<Page pageContent={false}>
|
||||
|
@ -122,10 +138,10 @@ class AddView extends Component {
|
|||
return (
|
||||
show_popover ?
|
||||
<Popover id="add-popover" className="popover__titled" onPopoverClosed={() => this.props.onclosed()}>
|
||||
<AddTabs inPopover={true} onOptionClick={this.onoptionclick} style={{height: '410px'}} />
|
||||
<AddTabs inPopover={true} onOptionClick={this.onoptionclick} style={{height: '410px'}} showPanels={this.props.showPanels} />
|
||||
</Popover> :
|
||||
<Popup className="add-popup" onPopupClosed={() => this.props.onclosed()}>
|
||||
<AddTabs onOptionClick={this.onoptionclick} />
|
||||
<AddTabs onOptionClick={this.onoptionclick} showPanels={this.props.showPanels} />
|
||||
</Popup>
|
||||
)
|
||||
}
|
||||
|
@ -145,7 +161,7 @@ const Add = props => {
|
|||
if ( props.onclosed )
|
||||
props.onclosed();
|
||||
};
|
||||
return <AddView usePopover={!Device.phone} onclosed={onviewclosed} />
|
||||
return <AddView usePopover={!Device.phone} onclosed={onviewclosed} showPanels={props.showOptions} />
|
||||
};
|
||||
|
||||
export default Add;
|
51
apps/documenteditor/mobile/src/view/add/AddLink.jsx
Normal file
51
apps/documenteditor/mobile/src/view/add/AddLink.jsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
import React, {useState} from 'react';
|
||||
import {List, Page, Navbar, Icon, ListButton, ListInput} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {Device} from "../../../../../common/mobile/utils/device";
|
||||
|
||||
const PageLink = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('Add', {returnObjects: true});
|
||||
|
||||
let display = props.getDisplayLinkText();
|
||||
display = typeof display === 'string' ? display : '';
|
||||
|
||||
const [stateLink, setLink] = useState('');
|
||||
const [stateDisplay, setDisplay] = useState(display);
|
||||
const [stateTip, setTip] = useState('');
|
||||
return (
|
||||
<Page>
|
||||
{!props.noNavbar && <Navbar title={_t.textAddLink} backLink={_t.textBack}></Navbar>}
|
||||
<List inlineLabels className='inputs-list'>
|
||||
<ListInput
|
||||
label={_t.textLink}
|
||||
type="text"
|
||||
placeholder={_t.textLink}
|
||||
value={stateLink}
|
||||
onChange={(event) => {setLink(event.target.value)}}
|
||||
></ListInput>
|
||||
<ListInput
|
||||
label={_t.textDisplay}
|
||||
type="text"
|
||||
placeholder={_t.textDisplay}
|
||||
value={stateDisplay}
|
||||
onChange={(event) => {setDisplay(event.target.value)}}
|
||||
></ListInput>
|
||||
<ListInput
|
||||
label={_t.textScreenTip}
|
||||
type="text"
|
||||
placeholder={_t.textScreenTip}
|
||||
value={stateTip}
|
||||
onChange={(event) => {setTip(event.target.value)}}
|
||||
></ListInput>
|
||||
</List>
|
||||
<List>
|
||||
<ListButton className={'button-fill button-raised' + (stateLink.length < 1 ? ' disabled' : '')} title={_t.textInsert} onClick={() => {
|
||||
props.onInsertLink(stateLink, stateDisplay, stateTip)
|
||||
}}></ListButton>
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
export {PageLink as PageAddLink};
|
|
@ -4,51 +4,6 @@ import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, BlockTitle, S
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import {Device} from "../../../../../common/mobile/utils/device";
|
||||
|
||||
const PageLink = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('Add', {returnObjects: true});
|
||||
|
||||
let display = props.getDisplayLinkText();
|
||||
display = typeof display === 'string' ? display : '';
|
||||
|
||||
const [stateLink, setLink] = useState('');
|
||||
const [stateDisplay, setDisplay] = useState(display);
|
||||
const [stateTip, setTip] = useState('');
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textAddLink} backLink={_t.textBack}></Navbar>
|
||||
<List inlineLabels className='inputs-list'>
|
||||
<ListInput
|
||||
label={_t.textLink}
|
||||
type="text"
|
||||
placeholder={_t.textLink}
|
||||
value={stateLink}
|
||||
onChange={(event) => {setLink(event.target.value)}}
|
||||
></ListInput>
|
||||
<ListInput
|
||||
label={_t.textDisplay}
|
||||
type="text"
|
||||
placeholder={_t.textDisplay}
|
||||
value={stateDisplay}
|
||||
onChange={(event) => {setDisplay(event.target.value)}}
|
||||
></ListInput>
|
||||
<ListInput
|
||||
label={_t.textScreenTip}
|
||||
type="text"
|
||||
placeholder={_t.textScreenTip}
|
||||
value={stateTip}
|
||||
onChange={(event) => {setTip(event.target.value)}}
|
||||
></ListInput>
|
||||
</List>
|
||||
<List>
|
||||
<ListButton className={'button-fill button-raised' + (stateLink.length < 1 ? ' disabled' : '')} title={_t.textInsert} onClick={() => {
|
||||
props.onInsertLink(stateLink, stateDisplay, stateTip)
|
||||
}}></ListButton>
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const PageNumber = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('Add', {returnObjects: true});
|
||||
|
@ -240,7 +195,6 @@ const AddOther = props => {
|
|||
const AddOtherContainer = inject("storeComments")(observer(AddOther));
|
||||
|
||||
export {AddOtherContainer as AddOther,
|
||||
PageLink as PageAddLink,
|
||||
PageNumber as PageAddNumber,
|
||||
PageBreak as PageAddBreak,
|
||||
PageSectionBreak as PageAddSectionBreak,
|
||||
|
|
|
@ -11,6 +11,7 @@ import { DownloadController } from "../../controller/settings/Download";
|
|||
import ApplicationSettingsController from "../../controller/settings/ApplicationSettings";
|
||||
import { DocumentFormats, DocumentMargins, DocumentColorSchemes } from "./DocumentSettings";
|
||||
import { MacrosSettings } from "./ApplicationSettings";
|
||||
import About from '../../../../../common/mobile/lib/view/About';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
|
@ -48,6 +49,10 @@ const routes = [
|
|||
{
|
||||
path: '/color-schemes/',
|
||||
component: DocumentColorSchemes
|
||||
},
|
||||
{
|
||||
path: '/about/',
|
||||
component: About
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -176,7 +181,7 @@ const SettingsList = inject("storeAppOptions")( observer( withTranslation()( pro
|
|||
</ListItem>
|
||||
}
|
||||
{_canAbout &&
|
||||
<ListItem title={_t.textAbout} link="#">
|
||||
<ListItem title={_t.textAbout} link="#" onClick={onoptionclick.bind(this, "/about/")}>
|
||||
<Icon slot="media" icon="icon-about"></Icon>
|
||||
</ListItem>
|
||||
}
|
||||
|
|
|
@ -24,6 +24,19 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"ContextMenu": {
|
||||
"menuViewComment": "View Comment",
|
||||
"menuAddComment": "Add Comment",
|
||||
"menuDelete": "Delete",
|
||||
"menuEdit": "Edit",
|
||||
"menuAddLink": "Add Link",
|
||||
"menuOpenLink": "Open Link",
|
||||
"menuMore": "More",
|
||||
"menuCancel": "Cancel",
|
||||
"textCopyCutPasteActions": "Copy, Cut and Paste Actions",
|
||||
"errorCopyCutPaste": "Copy, cut and paste actions using the context menu will be performed within the current file only.",
|
||||
"textDoNotShowAgain": "Don't show again"
|
||||
},
|
||||
"View": {
|
||||
"Settings": {
|
||||
"textDone": "Done",
|
||||
|
@ -101,6 +114,7 @@
|
|||
"textColumns": "Columns",
|
||||
"textRows": "Rows",
|
||||
"textCancel": "Cancel",
|
||||
"textAddLink": "Add Link",
|
||||
"textLink": "Link",
|
||||
"textLinkType": "Link Type",
|
||||
"textExternalLink": "External Link",
|
||||
|
@ -267,6 +281,36 @@
|
|||
"textThemeColors": "Theme Colors",
|
||||
"textStandartColors": "Standard Colors",
|
||||
"textCustomColors": "Custom Colors"
|
||||
},
|
||||
"Collaboration": {
|
||||
"textCollaboration": "Collaboration",
|
||||
"textBack": "Back",
|
||||
"textUsers": "Users",
|
||||
"textEditUser": "Users who are editing the file:",
|
||||
"textComments": "Comments",
|
||||
"textAddComment": "Add Comment",
|
||||
"textCancel": "Cancel",
|
||||
"textDone": "Done",
|
||||
"textNoComments": "This document doesn't contain comments",
|
||||
"textEdit": "Edit",
|
||||
"textResolve": "Resolve",
|
||||
"textReopen": "Reopen",
|
||||
"textAddReply": "Add Reply",
|
||||
"textDeleteComment": "Delete Comment",
|
||||
"textMessageDeleteComment": "Do you really want to delete this comment?",
|
||||
"textMessageDeleteReply": "Do you really want to delete this reply?",
|
||||
"textDeleteReply": "Delete Reply",
|
||||
"textEditComment": "Edit Comment",
|
||||
"textEditReply": "Edit Reply"
|
||||
}
|
||||
},
|
||||
"About": {
|
||||
"textAbout": "About",
|
||||
"textVersion": "Version",
|
||||
"textEmail": "Email",
|
||||
"textAddress": "Address",
|
||||
"textTel": "Tel",
|
||||
"textPoweredBy": "Powered By",
|
||||
"textBack": "Back"
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ import ReactDOM from 'react-dom';
|
|||
|
||||
// Import Framework7
|
||||
import Framework7 from 'framework7/lite-bundle';
|
||||
import { Dom7 } from 'framework7';
|
||||
window.$$ = Dom7;
|
||||
|
||||
// Import Framework7-React Plugin
|
||||
import Framework7React from 'framework7-react';
|
||||
|
|
312
apps/presentationeditor/mobile/src/controller/ContextMenu.jsx
Normal file
312
apps/presentationeditor/mobile/src/controller/ContextMenu.jsx
Normal file
|
@ -0,0 +1,312 @@
|
|||
import React, { useContext } from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation} from 'react-i18next';
|
||||
import { LocalStorage } from '../../../../common/mobile/utils/LocalStorage';
|
||||
|
||||
import ContextMenuController from '../../../../common/mobile/lib/controller/ContextMenu';
|
||||
import { idContextMenuElement } from '../../../../common/mobile/lib/view/ContextMenu';
|
||||
import { Device } from '../../../../common/mobile/utils/device';
|
||||
|
||||
@inject ( stores => ({
|
||||
isEdit: stores.storeAppOptions.isEdit,
|
||||
canViewComments: stores.storeAppOptions.canViewComments,
|
||||
users: stores.users,
|
||||
isDisconnected: stores.users.isDisconnected
|
||||
}))
|
||||
class ContextMenu extends ContextMenuController {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// console.log('context menu controller created');
|
||||
this.onApiShowComment = this.onApiShowComment.bind(this);
|
||||
this.onApiHideComment = this.onApiHideComment.bind(this);
|
||||
this.getUserName = this.getUserName.bind(this);
|
||||
}
|
||||
|
||||
static closeContextMenu() {
|
||||
f7.popover.close(idContextMenuElement, false);
|
||||
}
|
||||
|
||||
getUserName(id) {
|
||||
const user = this.props.users.searchUserByCurrentId(id);
|
||||
return Common.Utils.UserInfoParser.getParsedName(user.asc_getUserName());
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_unregisterCallback('asc_onShowComment', this.onApiShowComment);
|
||||
api.asc_unregisterCallback('asc_onHideComment', this.onApiHideComment);
|
||||
}
|
||||
|
||||
|
||||
onApiShowComment(comments) {
|
||||
this.isComments = comments && comments.length > 0;
|
||||
}
|
||||
|
||||
onApiHideComment() {
|
||||
this.isComments = false;
|
||||
}
|
||||
|
||||
// onMenuClosed() {
|
||||
// super.onMenuClosed();
|
||||
// }
|
||||
|
||||
onMenuItemClick(action) {
|
||||
super.onMenuItemClick(action);
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
switch (action) {
|
||||
case 'cut':
|
||||
if (!api.Cut() && !LocalStorage.getBool("pe-hide-copy-cut-paste-warning")) {
|
||||
this.showCopyCutPasteModal();
|
||||
}
|
||||
break;
|
||||
case 'copy':
|
||||
if (!api.Copy() && !LocalStorage.getBool("pe-hide-copy-cut-paste-warning")) {
|
||||
this.showCopyCutPasteModal();
|
||||
}
|
||||
break;
|
||||
case 'paste':
|
||||
if (!api.Paste() && !LocalStorage.getBool("pe-hide-copy-cut-paste-warning")) {
|
||||
this.showCopyCutPasteModal();
|
||||
}
|
||||
break;
|
||||
case 'addcomment':
|
||||
Common.Notifications.trigger('addcomment');
|
||||
break;
|
||||
case 'viewcomment':
|
||||
Common.Notifications.trigger('viewcomment');
|
||||
break;
|
||||
case 'delete':
|
||||
api.asc_Remove();
|
||||
break;
|
||||
case 'edit':
|
||||
setTimeout(() => {
|
||||
this.props.openOptions('edit');
|
||||
}, 0);
|
||||
break;
|
||||
case 'addlink':
|
||||
setTimeout(() => {
|
||||
this.props.openOptions('add', 'link');
|
||||
}, 400)
|
||||
break;
|
||||
case 'openlink':
|
||||
const stack = Common.EditorApi.get().getSelectedElements();
|
||||
let value;
|
||||
stack.forEach((item) => {
|
||||
if (item.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {
|
||||
value = item.get_ObjectValue().get_Value();
|
||||
}
|
||||
});
|
||||
value && this.openLink(value);
|
||||
break;
|
||||
}
|
||||
|
||||
console.log("click context menu item: " + action);
|
||||
}
|
||||
|
||||
showCopyCutPasteModal() {
|
||||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
f7.dialog.create({
|
||||
title: _t.textCopyCutPasteActions,
|
||||
text: _t.errorCopyCutPaste,
|
||||
content: `<div class="checkbox-in-modal">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="checkbox-show" />
|
||||
<i class="icon-checkbox"></i>
|
||||
</label>
|
||||
<span class="right-text">${_t.textDoNotShowAgain}</span>
|
||||
</div>`,
|
||||
buttons: [{
|
||||
text: 'OK',
|
||||
onClick: () => {
|
||||
const dontShow = $$('input[name="checkbox-show"]').prop('checked');
|
||||
if (dontShow) LocalStorage.setItem("de-hide-copy-cut-paste-warning", 1);
|
||||
}
|
||||
}]
|
||||
}).open();
|
||||
}
|
||||
|
||||
openLink(url) {
|
||||
const api = Common.EditorApi.get();
|
||||
if (api.asc_getUrlType(url) > 0) {
|
||||
const newDocumentPage = window.open(url, '_blank');
|
||||
if (newDocumentPage) {
|
||||
newDocumentPage.focus();
|
||||
}
|
||||
} else {
|
||||
api.asc_GoToInternalHyperlink(url);
|
||||
}
|
||||
}
|
||||
|
||||
onDocumentReady() {
|
||||
super.onDocumentReady();
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_registerCallback('asc_onShowComment', this.onApiShowComment);
|
||||
api.asc_registerCallback('asc_onHideComment', this.onApiHideComment);
|
||||
}
|
||||
|
||||
initMenuItems() {
|
||||
if ( !Common.EditorApi ) return [];
|
||||
|
||||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
|
||||
const { isEdit, canViewComments, isDisconnected } = this.props;
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
const stack = api.getSelectedElements();
|
||||
const canCopy = api.can_CopyCut();
|
||||
|
||||
let itemsIcon = [],
|
||||
itemsText = [];
|
||||
|
||||
let isText = false,
|
||||
isTable = false,
|
||||
isImage = false,
|
||||
isChart = false,
|
||||
isShape = false,
|
||||
isLink = false,
|
||||
isSlide = false,
|
||||
isObject = false;
|
||||
|
||||
stack.forEach(item => {
|
||||
const objectType = item.get_ObjectType(),
|
||||
objectValue = item.get_ObjectValue();
|
||||
|
||||
if (objectType == Asc.c_oAscTypeSelectElement.Paragraph) {
|
||||
isText = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Image) {
|
||||
isImage = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Chart) {
|
||||
isChart = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Shape) {
|
||||
isShape = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Table) {
|
||||
isTable = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Hyperlink) {
|
||||
isLink = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Slide) {
|
||||
isSlide = true;
|
||||
}
|
||||
});
|
||||
|
||||
isObject = isText || isImage || isChart || isShape || isTable;
|
||||
|
||||
if (canCopy && isObject) {
|
||||
itemsIcon.push({
|
||||
event: 'copy',
|
||||
icon: 'icon-copy'
|
||||
});
|
||||
}
|
||||
if (canViewComments && this.isComments && !isEdit) {
|
||||
itemsText.push({
|
||||
caption: _t.menuViewComment,
|
||||
event: 'viewcomment'
|
||||
});
|
||||
}
|
||||
|
||||
if ( stack.length > 0 ) {
|
||||
let topObject = stack[stack.length - 1],
|
||||
topObjectType = topObject.get_ObjectType(),
|
||||
topObjectValue = topObject.get_ObjectValue(),
|
||||
objectLocked = typeof topObjectValue.get_Locked === 'function' ? topObjectValue.get_Locked() : false;
|
||||
|
||||
!objectLocked && (objectLocked = typeof topObjectValue.get_LockDelete === 'function' ? topObjectValue.get_LockDelete() : false);
|
||||
|
||||
const swapItems = function(items, indexBefore, indexAfter) {
|
||||
items[indexAfter] = items.splice(indexBefore, 1, items[indexAfter])[0];
|
||||
};
|
||||
|
||||
if (!objectLocked && isEdit && !isDisconnected) {
|
||||
if (canCopy && isObject) {
|
||||
itemsIcon.push({
|
||||
event: 'cut',
|
||||
icon: 'icon-cut'
|
||||
});
|
||||
|
||||
// Swap 'Copy' and 'Cut'
|
||||
swapItems(itemsIcon, 0, 1);
|
||||
}
|
||||
|
||||
itemsIcon.push({
|
||||
event: 'paste',
|
||||
icon: 'icon-paste'
|
||||
});
|
||||
|
||||
if (isObject)
|
||||
itemsText.push({
|
||||
caption: _t.menuDelete,
|
||||
event: 'delete'
|
||||
});
|
||||
|
||||
itemsText.push({
|
||||
caption: _t.menuEdit,
|
||||
event: 'edit'
|
||||
});
|
||||
|
||||
if (!isLink && api.can_AddHyperlink() !== false) {
|
||||
itemsText.push({
|
||||
caption: _t.menuAddLink,
|
||||
event: 'addlink'
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isComments && canViewComments) {
|
||||
itemsText.push({
|
||||
caption: _t.menuViewComment,
|
||||
event: 'viewcomment'
|
||||
});
|
||||
}
|
||||
|
||||
const hideAddComment = (isText && isChart) || api.can_AddQuotedComment() === false || !canViewComments;
|
||||
if (!hideAddComment) {
|
||||
itemsText.push({
|
||||
caption: _t.menuAddComment,
|
||||
event: 'addcomment'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLink) {
|
||||
itemsText.push({
|
||||
caption: _t.menuOpenLink,
|
||||
event: 'openlink'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if ( Device.phone && itemsText.length > 2 ) {
|
||||
this.extraItems = itemsText.splice(2,itemsText.length, {
|
||||
caption: _t.menuMore,
|
||||
event: 'showActionSheet'
|
||||
});
|
||||
}
|
||||
|
||||
return itemsIcon.concat(itemsText);
|
||||
// return [{
|
||||
// caption: 'Edit',
|
||||
// event: 'edit'
|
||||
// }, {
|
||||
// caption: 'View',
|
||||
// event: 'view'
|
||||
// }, {
|
||||
// icon: 'icon-paste',
|
||||
// event: 'review'
|
||||
// }];
|
||||
}
|
||||
|
||||
initExtraItems () {
|
||||
return (this.extraItems && this.extraItems.length > 0 ? this.extraItems : []);
|
||||
}
|
||||
}
|
||||
|
||||
const _ContextMenu = withTranslation()(ContextMenu);
|
||||
_ContextMenu.closeContextMenu = ContextMenu.closeContextMenu;
|
||||
export { _ContextMenu as default };
|
|
@ -1,14 +1,21 @@
|
|||
|
||||
import React, { Component } from 'react'
|
||||
import React, { Component, Fragment } from 'react'
|
||||
import { inject } from "mobx-react";
|
||||
import { f7 } from "framework7-react";
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import CollaborationController from '../../../../common/mobile/lib/controller/collaboration/Collaboration.jsx'
|
||||
import CollaborationController from '../../../../common/mobile/lib/controller/collaboration/Collaboration.jsx';
|
||||
import {
|
||||
CommentsController,
|
||||
AddCommentController,
|
||||
EditCommentController,
|
||||
ViewCommentsController
|
||||
} from "../../../../common/mobile/lib/controller/collaboration/Comments";
|
||||
|
||||
@inject("storeFocusObjects", "storeAppOptions", "storePresentationInfo", "storePresentationSettings", "storeSlideSettings", "storeTextSettings", "storeTableSettings", "storeChartSettings", "storeLinkSettings")
|
||||
class MainController extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
window.editorType = 'pe';
|
||||
}
|
||||
|
||||
initSdk() {
|
||||
|
@ -336,6 +343,8 @@ class MainController extends Component {
|
|||
|
||||
Common.Gateway.documentReady();
|
||||
f7.emit('resize');
|
||||
|
||||
Common.Notifications.trigger('document:ready');
|
||||
}
|
||||
|
||||
_onOpenDocumentProgress(progress) {
|
||||
|
@ -348,7 +357,15 @@ class MainController extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <CollaborationController />
|
||||
return (
|
||||
<Fragment>
|
||||
<CollaborationController />
|
||||
<CommentsController />
|
||||
<AddCommentController />
|
||||
<EditCommentController />
|
||||
<ViewCommentsController />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
|
|
@ -102,6 +102,7 @@ class AddLinkController extends Component {
|
|||
return (
|
||||
<PageLink onInsertLink={this.onInsertLink}
|
||||
getTextDisplay={this.getTextDisplay}
|
||||
noNavbar={this.props.noNavbar}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -88,10 +88,38 @@ class AddOtherController extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
hideAddComment () {
|
||||
const api = Common.EditorApi.get();
|
||||
const stack = api.getSelectedElements();
|
||||
let isText = false,
|
||||
isChart = false;
|
||||
|
||||
stack.forEach((item) => {
|
||||
const objectType = item.get_ObjectType();
|
||||
if (objectType === Asc.c_oAscTypeSelectElement.Paragraph) {
|
||||
isText = true;
|
||||
} else if (objectType === Asc.c_oAscTypeSelectElement.Chart) {
|
||||
isChart = true;
|
||||
}
|
||||
});
|
||||
if (stack.length > 0) {
|
||||
const topObject = stack[stack.length - 1];
|
||||
const topObjectValue = topObject.get_ObjectValue();
|
||||
let objectLocked = typeof topObjectValue.get_Locked === 'function' ? topObjectValue.get_Locked() : false;
|
||||
!objectLocked && (objectLocked = typeof topObjectValue.get_LockDelete === 'function' ? topObjectValue.get_LockDelete() : false);
|
||||
if (!objectLocked) {
|
||||
return ((isText && isChart) || api.can_AddQuotedComment() === false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<AddOther onStyleClick={this.onStyleClick}
|
||||
<AddOther closeModal={this.closeModal}
|
||||
onStyleClick={this.onStyleClick}
|
||||
initStyleTable={this.initStyleTable}
|
||||
hideAddComment={this.hideAddComment}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import PresentationAbout from "../../view/settings/PresentationAbout";
|
||||
|
||||
class PresentationAboutController extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<PresentationAbout />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default PresentationAboutController;
|
|
@ -11,6 +11,8 @@
|
|||
@import '../../../../common/mobile/resources/less/dataview.less';
|
||||
@import '../../../../common/mobile/resources/less/about.less';
|
||||
@import '../../../../common/mobile/resources/less/search.less';
|
||||
@import '../../../../common/mobile/resources/less/contextmenu.less';
|
||||
@import '../../../../common/mobile/resources/less/comments.less';
|
||||
@import './app-material.less';
|
||||
@import './app-ios.less';
|
||||
@import './icons-ios.less';
|
||||
|
|
|
@ -476,24 +476,6 @@
|
|||
.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="M7 14H16C18.2091 14 20 15.7909 20 18C20 20.2091 18.2091 22 16 22H7C4.79086 22 3 20.2091 3 18C3 15.7909 4.79086 14 7 14ZM16 13C18.7614 13 21 15.2386 21 18C21 20.7614 18.7614 23 16 23H7C4.23858 23 2 20.7614 2 18C2 15.2386 4.23858 13 7 13H16Z" fill="@{themeColor}"/><path fill-rule="evenodd" clip-rule="evenodd" d="M16 20C14.8954 20 14 19.1046 14 18C14 16.8954 14.8954 16 16 16C17.1046 16 18 16.8954 18 18C18 19.1046 17.1046 20 16 20ZM16 21C14.3431 21 13 19.6569 13 18C13 16.3431 14.3431 15 16 15C17.6569 15 19 16.3431 19 18C19 19.6569 17.6569 21 16 21Z" fill="@{themeColor}"/><path fill-rule="evenodd" clip-rule="evenodd" d="M16 3H7C4.79086 3 3 4.79086 3 7C3 9.20914 4.79086 11 7 11H16C18.2091 11 20 9.20914 20 7C20 4.79086 18.2091 3 16 3ZM7 2C4.23858 2 2 4.23858 2 7C2 9.76142 4.23858 12 7 12H16C18.7614 12 21 9.76142 21 7C21 4.23858 18.7614 2 16 2H7Z" fill="@{themeColor}"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7 9C8.10457 9 9 8.10457 9 7C9 5.89543 8.10457 5 7 5C5.89543 5 5 5.89543 5 7C5 8.10457 5.89543 9 7 9ZM7 10C8.65685 10 10 8.65685 10 7C10 5.34315 8.65685 4 7 4C5.34315 4 4 5.34315 4 7C4 8.65685 5.34315 10 7 10Z" fill="@{themeColor}"/></svg>');
|
||||
}
|
||||
|
||||
&.icon-cut {
|
||||
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 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" fill="white"/><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" fill="white"/><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" fill="white"/></g><defs><clipPath id="cut"><rect width="24" height="24" fill="white"/></clipPath></defs></svg>');
|
||||
}
|
||||
|
||||
&.icon-copy {
|
||||
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 d="M1 1H15V7H16V0H0V17H8V16H1V1Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M23 8H9V23H23V8ZM8 7V24H24V7H8Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M13 5H3V4H13V5Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 9H3V8H8V9Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 13H3V12H8V13Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H11V11H21V12Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H11V15H21V16Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H11V19H21V20Z" fill="white"/></svg>');
|
||||
}
|
||||
|
||||
&.icon-paste {
|
||||
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="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" fill="white"/><path d="M5 0H14V5H5V0Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" fill="white"/></svg>');
|
||||
}
|
||||
|
||||
//comments
|
||||
&.icon-menu-comment {
|
||||
width: 30px;
|
||||
|
|
|
@ -434,24 +434,6 @@
|
|||
.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="M7 14H16C18.2091 14 20 15.7909 20 18C20 20.2091 18.2091 22 16 22H7C4.79086 22 3 20.2091 3 18C3 15.7909 4.79086 14 7 14ZM16 13C18.7614 13 21 15.2386 21 18C21 20.7614 18.7614 23 16 23H7C4.23858 23 2 20.7614 2 18C2 15.2386 4.23858 13 7 13H16Z" fill="@{themeColor}"/><path fill-rule="evenodd" clip-rule="evenodd" d="M16 20C14.8954 20 14 19.1046 14 18C14 16.8954 14.8954 16 16 16C17.1046 16 18 16.8954 18 18C18 19.1046 17.1046 20 16 20ZM16 21C14.3431 21 13 19.6569 13 18C13 16.3431 14.3431 15 16 15C17.6569 15 19 16.3431 19 18C19 19.6569 17.6569 21 16 21Z" fill="@{themeColor}"/><path fill-rule="evenodd" clip-rule="evenodd" d="M16 3H7C4.79086 3 3 4.79086 3 7C3 9.20914 4.79086 11 7 11H16C18.2091 11 20 9.20914 20 7C20 4.79086 18.2091 3 16 3ZM7 2C4.23858 2 2 4.23858 2 7C2 9.76142 4.23858 12 7 12H16C18.7614 12 21 9.76142 21 7C21 4.23858 18.7614 2 16 2H7Z" fill="@{themeColor}"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7 9C8.10457 9 9 8.10457 9 7C9 5.89543 8.10457 5 7 5C5.89543 5 5 5.89543 5 7C5 8.10457 5.89543 9 7 9ZM7 10C8.65685 10 10 8.65685 10 7C10 5.34315 8.65685 4 7 4C5.34315 4 4 5.34315 4 7C4 8.65685 5.34315 10 7 10Z" fill="@{themeColor}"/></svg>');
|
||||
}
|
||||
|
||||
&.icon-cut {
|
||||
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 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" fill="black"/><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" fill="black"/><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" fill="black"/></g><defs><clipPath id="cut"><rect width="24" height="24" fill="black"/></clipPath></defs></svg>');
|
||||
}
|
||||
|
||||
&.icon-copy {
|
||||
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 d="M1 1H15V7H16V0H0V17H8V16H1V1Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M23 8H9V23H23V8ZM8 7V24H24V7H8Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M13 5H3V4H13V5Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 9H3V8H8V9Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 13H3V12H8V13Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H11V11H21V12Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H11V15H21V16Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H11V19H21V20Z" fill="black"/></svg>');
|
||||
}
|
||||
|
||||
&.icon-paste {
|
||||
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="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" fill="black"/><path d="M5 0H14V5H5V0Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" fill="black"/></svg>');
|
||||
}
|
||||
|
||||
//Comments
|
||||
&.icon-menu-comment {
|
||||
width: 24px;
|
||||
|
|
|
@ -7,6 +7,7 @@ import Settings from '../view/settings/Settings';
|
|||
import CollaborationView from '../../../../common/mobile/lib/view/collaboration/Collaboration.jsx';
|
||||
import { Device } from '../../../../common/mobile/utils/device';
|
||||
import { Search, SearchSettings } from '../controller/Search';
|
||||
import ContextMenu from '../controller/ContextMenu';
|
||||
|
||||
export default class MainPage extends Component {
|
||||
constructor(props) {
|
||||
|
@ -19,12 +20,17 @@ export default class MainPage extends Component {
|
|||
};
|
||||
}
|
||||
|
||||
handleClickToOpenOptions = opts => {
|
||||
handleClickToOpenOptions = (opts, showOpts) => {
|
||||
ContextMenu.closeContextMenu();
|
||||
|
||||
this.setState(state => {
|
||||
if ( opts == 'edit' )
|
||||
return {editOptionsVisible: true};
|
||||
else if ( opts == 'add' )
|
||||
return {addOptionsVisible: true};
|
||||
return {
|
||||
addOptionsVisible: true,
|
||||
addShowOptions: showOpts
|
||||
};
|
||||
else if ( opts == 'settings' )
|
||||
return {settingsVisible: true};
|
||||
else if ( opts == 'coauth' )
|
||||
|
@ -77,7 +83,7 @@ export default class MainPage extends Component {
|
|||
}
|
||||
{
|
||||
!this.state.addOptionsVisible ? null :
|
||||
<AddOptions onclosed={this.handleOptionsViewClosed.bind(this, 'add')} />
|
||||
<AddOptions onclosed={this.handleOptionsViewClosed.bind(this, 'add')} showOptions={this.state.addShowOptions} />
|
||||
}
|
||||
{
|
||||
!this.state.settingsVisible ? null :
|
||||
|
@ -87,6 +93,7 @@ export default class MainPage extends Component {
|
|||
!this.state.collaborationVisible ? null :
|
||||
<CollaborationView onclosed={this.handleOptionsViewClosed.bind(this, 'coauth')} />
|
||||
}
|
||||
<ContextMenu openOptions={this.handleClickToOpenOptions.bind(this)} />
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@ export class storeAppOptions {
|
|||
constructor() {
|
||||
makeObservable(this, {
|
||||
isEdit: observable,
|
||||
canViewComments: observable,
|
||||
setConfigOptions: action,
|
||||
setPermissionOptions: action
|
||||
});
|
||||
}
|
||||
|
||||
isEdit = false;
|
||||
canViewComments = false;
|
||||
config = {};
|
||||
|
||||
setConfigOptions (config) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import { storeLinkSettings } from "./linkSettings";
|
|||
// import {storeParagraphSettings} from "./paragraphSettings";
|
||||
// import {storeShapeSettings} from "./shapeSettings";
|
||||
// import {storeImageSettings} from "./imageSettings";
|
||||
import {storeComments} from "../../../../common/mobile/lib/store/comments";
|
||||
|
||||
export const stores = {
|
||||
storeAppOptions: new storeAppOptions(),
|
||||
|
@ -31,10 +32,11 @@ export const stores = {
|
|||
storeShapeSettings: new storeShapeSettings(),
|
||||
storeTableSettings: new storeTableSettings(),
|
||||
storeChartSettings: new storeChartSettings(),
|
||||
storeLinkSettings: new storeLinkSettings()
|
||||
storeLinkSettings: new storeLinkSettings(),
|
||||
// storeTextSettings: new storeTextSettings(),
|
||||
// storeParagraphSettings: new storeParagraphSettings(),
|
||||
// storeShapeSettings: new storeShapeSettings(),
|
||||
// storeChartSettings: new storeChartSettings(),
|
||||
storeComments: new storeComments()
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, {Component, useEffect} from 'react';
|
||||
import {View,Page,Navbar,NavRight,Link,Popup,Popover,Icon,Tabs,Tab} from 'framework7-react';
|
||||
import {View,Page,Navbar,NavRight, NavTitle, Link,Popup,Popover,Icon,Tabs,Tab} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {f7} from 'framework7-react';
|
||||
import { observer, inject } from "mobx-react";
|
||||
|
@ -43,13 +43,16 @@ const AddLayoutNavbar = ({ tabs, inPopover }) => {
|
|||
const isAndroid = Device.android;
|
||||
return (
|
||||
<Navbar>
|
||||
<div className='tab-buttons tabbar'>
|
||||
{tabs.map((item, index) =>
|
||||
<Link key={"pe-link-" + item.id} tabLink={"#" + item.id} tabLinkActive={index === 0}>
|
||||
<Icon slot="media" icon={item.icon}></Icon>
|
||||
</Link>)}
|
||||
{isAndroid && <span className='tab-link-highlight' style={{width: 100 / tabs.lenght + '%'}}></span>}
|
||||
</div>
|
||||
{tabs.length > 1 ?
|
||||
<div className='tab-buttons tabbar'>
|
||||
{tabs.map((item, index) =>
|
||||
<Link key={"pe-link-" + item.id} tabLink={"#" + item.id} tabLinkActive={index === 0}>
|
||||
<Icon slot="media" icon={item.icon}></Icon>
|
||||
</Link>)}
|
||||
{isAndroid && <span className='tab-link-highlight' style={{width: 100 / tabs.lenght + '%'}}></span>}
|
||||
</div> :
|
||||
<NavTitle>{tabs[0].caption}</NavTitle>
|
||||
}
|
||||
{ !inPopover && <NavRight><Link icon='icon-expand-down' popupClose=".add-popup"></Link></NavRight> }
|
||||
</Navbar>
|
||||
)
|
||||
|
@ -69,32 +72,42 @@ const AddLayoutContent = ({ tabs }) => {
|
|||
|
||||
const AddTabs = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('Add', {returnObjects: true});
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const showPanels = props.showPanels;
|
||||
const tabs = [];
|
||||
tabs.push({
|
||||
caption: _t.textSlide,
|
||||
id: 'add-slide',
|
||||
icon: 'icon-add-slide',
|
||||
component: <AddSlideController />
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textShape,
|
||||
id: 'add-shape',
|
||||
icon: 'icon-add-shape',
|
||||
component: <AddShapeController />
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textImage,
|
||||
id: 'add-image',
|
||||
icon: 'icon-add-image',
|
||||
component: <AddImageController />
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textOther,
|
||||
id: 'add-other',
|
||||
icon: 'icon-add-other',
|
||||
component: <AddOtherController />
|
||||
});
|
||||
if (!showPanels) {
|
||||
tabs.push({
|
||||
caption: _t.textSlide,
|
||||
id: 'add-slide',
|
||||
icon: 'icon-add-slide',
|
||||
component: <AddSlideController />
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textShape,
|
||||
id: 'add-shape',
|
||||
icon: 'icon-add-shape',
|
||||
component: <AddShapeController/>
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textImage,
|
||||
id: 'add-image',
|
||||
icon: 'icon-add-image',
|
||||
component: <AddImageController/>
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textOther,
|
||||
id: 'add-other',
|
||||
icon: 'icon-add-other',
|
||||
component: <AddOtherController/>
|
||||
});
|
||||
}
|
||||
if (showPanels && showPanels === 'link') {
|
||||
tabs.push({
|
||||
caption: _t.textAddLink,
|
||||
id: 'add-link',
|
||||
component: <AddLinkController noNavbar={true}/>
|
||||
});
|
||||
}
|
||||
return (
|
||||
<View style={props.style} stackPages={true} routes={routes}>
|
||||
<Page pageContent={false}>
|
||||
|
@ -119,10 +132,10 @@ class AddView extends Component {
|
|||
return (
|
||||
show_popover ?
|
||||
<Popover id="add-popover" className="popover__titled" onPopoverClosed={() => this.props.onclosed()}>
|
||||
<AddTabs inPopover={true} onOptionClick={this.onoptionclick} style={{height: '410px'}} />
|
||||
<AddTabs inPopover={true} onOptionClick={this.onoptionclick} style={{height: '410px'}} showPanels={this.props.showPanels} />
|
||||
</Popover> :
|
||||
<Popup className="add-popup" onPopupClosed={() => this.props.onclosed()}>
|
||||
<AddTabs onOptionClick={this.onoptionclick} />
|
||||
<AddTabs onOptionClick={this.onoptionclick} showPanels={this.props.showPanels} />
|
||||
</Popup>
|
||||
)
|
||||
}
|
||||
|
@ -142,7 +155,7 @@ const Add = props => {
|
|||
if ( props.onclosed )
|
||||
props.onclosed();
|
||||
};
|
||||
return <AddView usePopover={!Device.phone} onclosed={onviewclosed} />
|
||||
return <AddView usePopover={!Device.phone} onclosed={onviewclosed} showPanels={props.showOptions} />
|
||||
};
|
||||
|
||||
export default Add;
|
|
@ -103,7 +103,7 @@ const PageLink = props => {
|
|||
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textLink} backLink={_t.textBack}/>
|
||||
{!props.noNavbar && <Navbar title={_t.textLink} backLink={_t.textBack}/>}
|
||||
<List inlineLabels className='inputs-list'>
|
||||
<ListItem link={'/add-link-type/'} title={_t.textLinkType} after={textType} routeProps={{
|
||||
changeType: changeType,
|
||||
|
|
|
@ -33,6 +33,7 @@ const AddOther = props => {
|
|||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const showInsertLink = props.storeLinkSettings.canAddLink && !props.storeFocusObjects.paragraphLocked;
|
||||
const hideAddComment = props.hideAddComment();
|
||||
return (
|
||||
<List>
|
||||
<ListItem title={_t.textTable} link={'/add-table/'} routeProps={{
|
||||
|
@ -41,9 +42,12 @@ const AddOther = props => {
|
|||
}}>
|
||||
<Icon slot="media" icon="icon-add-table"></Icon>
|
||||
</ListItem>
|
||||
<ListItem title={_t.textComment}>
|
||||
{!hideAddComment && <ListItem title={_t.textComment} onClick={() => {
|
||||
props.closeModal();
|
||||
Common.Notifications.trigger('addcomment');
|
||||
}}>
|
||||
<Icon slot="media" icon="icon-insert-comment"></Icon>
|
||||
</ListItem>
|
||||
</ListItem>}
|
||||
{showInsertLink &&
|
||||
<ListItem title={_t.textLink} link={'/add-link/'}>
|
||||
<Icon slot="media" icon="icon-link"></Icon>
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { Page, Navbar, Link } from "framework7-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const PagePresentationAbout = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t("View.Settings", { 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}|\/$/,"");
|
||||
return (
|
||||
<Page className="about">
|
||||
<Navbar title={_t.textAbout} backLink={_t.textBack} />
|
||||
<div className="content-block">
|
||||
{licInfo && typeof licInfo == 'object' && typeof(customer)=='object' ? null : (
|
||||
<i className="logo"></i>
|
||||
)}
|
||||
{logoCustomer && logoCustomer.length ? (
|
||||
<div id="settings-about-logo" className="settings-about-logo">
|
||||
<img src={logoCustomer} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="content-block">
|
||||
<h3>PRESENTATION EDITOR</h3>
|
||||
<h3>{_t.textVersion} {__PRODUCT_VERSION__}</h3>
|
||||
</div>
|
||||
<div className="content-block">
|
||||
<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>
|
||||
{/*<p><label id="settings-about-info" style="display: none;"></label></p>*/}
|
||||
</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}
|
||||
{licInfo && typeof licInfo == 'object' && typeof(customer)=='object' ? null : (
|
||||
<p>
|
||||
<label>{_t.textTel}</label>
|
||||
<Link id="settings-about-tel" className="external" target="_blank" href="tel:+37163399867">+371 633-99867</Link>
|
||||
</p>
|
||||
)}
|
||||
{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>
|
||||
{licInfo && typeof licInfo == 'object' && typeof(customer)=='object' ? (
|
||||
<div className="content-block" id="settings-about-licensor">
|
||||
<div className="content-block-inner"></div>
|
||||
<p>
|
||||
<label>{_t.textPoweredBy}</label>
|
||||
</p>
|
||||
<h3 className="vendor">Ascensio System SIA</h3>
|
||||
<p>
|
||||
<Link className="external" target="_blank" href="www.onlyoffice.com">www.onlyoffice.com</Link>
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
const PresentationAbout = inject("storeAppOptions")(observer(PagePresentationAbout));
|
||||
|
||||
export default PresentationAbout;
|
|
@ -9,7 +9,8 @@ import DownloadController from "../../controller/settings/Download";
|
|||
import PresentationInfoController from "../../controller/settings/PresentationInfo";
|
||||
import PresentationSettingsController from "../../controller/settings/PresentationSettings";
|
||||
import { PresentationColorSchemes } from "./PresentationSettings";
|
||||
import PresentationAboutController from '../../controller/settings/PresentationAbout';
|
||||
// import PresentationAboutController from '../../controller/settings/PresentationAbout';
|
||||
import About from '../../../../../common/mobile/lib/view/About';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
|
@ -42,7 +43,7 @@ const routes = [
|
|||
},
|
||||
{
|
||||
path: '/about/',
|
||||
component: PresentationAboutController
|
||||
component: About
|
||||
}
|
||||
/*{
|
||||
path: '/presentation-settings/',
|
||||
|
|
|
@ -6,6 +6,29 @@
|
|||
"textAnonymous": "Anonymous"
|
||||
}
|
||||
},
|
||||
"ContextMenu": {
|
||||
"menuViewComment": "View Comment",
|
||||
"menuAddComment": "Add Comment",
|
||||
"menuMore": "More",
|
||||
"menuCancel": "Cancel",
|
||||
"textCopyCutPasteActions": "Copy, Cut and Paste Actions",
|
||||
"errorCopyCutPaste": "Copy, cut and paste actions using the context menu will be performed within the current file only.",
|
||||
"textDoNotShowAgain": "Don't show again",
|
||||
"warnMergeLostData": "Operation can destroy data in the selected cells. Continue?",
|
||||
"notcriticalErrorTitle": "Warning",
|
||||
"menuAddLink": "Add Link",
|
||||
"menuOpenLink": "Open Link",
|
||||
"menuUnfreezePanes": "Unfreeze Panes",
|
||||
"menuFreezePanes": "Freeze Panes",
|
||||
"menuUnwrap": "Unwrap",
|
||||
"menuWrap": "Wrap",
|
||||
"menuUnmerge": "Unmerge",
|
||||
"menuCell": "Cell",
|
||||
"menuShow": "Show",
|
||||
"menuHide": "Hide",
|
||||
"menuEdit": "Edit",
|
||||
"menuDelete": "Delete"
|
||||
},
|
||||
"View" : {
|
||||
"Add" : {
|
||||
"textChart": "Chart",
|
||||
|
@ -46,7 +69,8 @@
|
|||
"textInsert": "Insert",
|
||||
"textInvalidRange": "ERROR! Invalid cells range",
|
||||
"textSortAndFilter": "Sort and Filter",
|
||||
"textFilter": "Filter"
|
||||
"textFilter": "Filter",
|
||||
"textComment": "Comment"
|
||||
},
|
||||
"Edit" : {
|
||||
"textSelectObjectToEdit": "Select object to edit",
|
||||
|
@ -310,6 +334,25 @@
|
|||
"textReplaceAll": "Replace All"
|
||||
}
|
||||
},
|
||||
"Statusbar": {
|
||||
"textDuplicate": "Duplicate",
|
||||
"textDelete": "Delete",
|
||||
"textHide": "Hide",
|
||||
"textUnhide": "Unhide",
|
||||
"textErrorLastSheet": "Workbook must have at least one visible worksheet.",
|
||||
"textErrorRemoveSheet": "Can\"t delete the worksheet.",
|
||||
"textWarnDeleteSheet": "The worksheet maybe has data. Proceed operation?",
|
||||
"textSheet": "Sheet",
|
||||
"textRename": "Rename",
|
||||
"textErrNameExists": "Worksheet with such name already exist.",
|
||||
"textErrNameWrongChar": "A sheet name cannot contains characters: \\, \/, *, ?, [, ], :",
|
||||
"textErrNotEmpty": "Sheet name must not be empty",
|
||||
"textRenameSheet": "Rename Sheet",
|
||||
"textSheetName": "Sheet Name",
|
||||
"textCancel": "Cancel",
|
||||
"notcriticalErrorTitle": "Warning",
|
||||
"textMore": "More"
|
||||
},
|
||||
"Common": {
|
||||
"ThemeColorPalette": {
|
||||
"textThemeColors": "Theme Colors",
|
||||
|
@ -321,7 +364,30 @@
|
|||
"textBack": "Back",
|
||||
"textUsers": "Users",
|
||||
"textEditUser": "Users who are editing the file:",
|
||||
"textComments": "Comments"
|
||||
"textComments": "Comments",
|
||||
"textAddComment": "Add Comment",
|
||||
"textCancel": "Cancel",
|
||||
"textDone": "Done",
|
||||
"textNoComments": "This document doesn't contain comments",
|
||||
"textEdit": "Edit",
|
||||
"textResolve": "Resolve",
|
||||
"textReopen": "Reopen",
|
||||
"textAddReply": "Add Reply",
|
||||
"textDeleteComment": "Delete Comment",
|
||||
"textMessageDeleteComment": "Do you really want to delete this comment?",
|
||||
"textMessageDeleteReply": "Do you really want to delete this reply?",
|
||||
"textDeleteReply": "Delete Reply",
|
||||
"textEditComment": "Edit Comment",
|
||||
"textEditReply": "Edit Reply"
|
||||
}
|
||||
},
|
||||
"About": {
|
||||
"textAbout": "About",
|
||||
"textVersion": "Version",
|
||||
"textEmail": "Email",
|
||||
"textAddress": "Address",
|
||||
"textTel": "Tel",
|
||||
"textPoweredBy": "Powered By",
|
||||
"textBack": "Back"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import ReactDOM from 'react-dom';
|
|||
|
||||
// Import Framework7
|
||||
import Framework7 from 'framework7/lite-bundle';
|
||||
import { Dom7 } from 'framework7';
|
||||
window.$$ = Dom7;
|
||||
|
||||
// Import Framework7-React Plugin
|
||||
import Framework7React from 'framework7-react';
|
||||
|
|
385
apps/spreadsheeteditor/mobile/src/controller/ContextMenu.jsx
Normal file
385
apps/spreadsheeteditor/mobile/src/controller/ContextMenu.jsx
Normal file
|
@ -0,0 +1,385 @@
|
|||
import React, { useContext } from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation} from 'react-i18next';
|
||||
import { LocalStorage } from '../../../../common/mobile/utils/LocalStorage';
|
||||
|
||||
import ContextMenuController from '../../../../common/mobile/lib/controller/ContextMenu';
|
||||
import { idContextMenuElement } from '../../../../common/mobile/lib/view/ContextMenu';
|
||||
import { Device } from '../../../../common/mobile/utils/device';
|
||||
|
||||
@inject ( stores => ({
|
||||
isEdit: stores.storeAppOptions.isEdit,
|
||||
canViewComments: stores.storeAppOptions.canViewComments,
|
||||
users: stores.users,
|
||||
isDisconnected: stores.users.isDisconnected,
|
||||
storeSheets: stores.sheets
|
||||
}))
|
||||
class ContextMenu extends ContextMenuController {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// console.log('context menu controller created');
|
||||
this.onApiShowComment = this.onApiShowComment.bind(this);
|
||||
this.onApiHideComment = this.onApiHideComment.bind(this);
|
||||
this.getUserName = this.getUserName.bind(this);
|
||||
}
|
||||
|
||||
static closeContextMenu() {
|
||||
f7.popover.close(idContextMenuElement, false);
|
||||
}
|
||||
|
||||
getUserName(id) {
|
||||
const user = this.props.users.searchUserByCurrentId(id);
|
||||
return Common.Utils.UserInfoParser.getParsedName(user.asc_getUserName());
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_unregisterCallback('asc_onShowComment', this.onApiShowComment);
|
||||
api.asc_unregisterCallback('asc_onHideComment', this.onApiHideComment);
|
||||
}
|
||||
|
||||
|
||||
onApiShowComment(comments) {
|
||||
this.isComments = comments && comments.length > 0;
|
||||
}
|
||||
|
||||
onApiHideComment() {
|
||||
this.isComments = false;
|
||||
}
|
||||
|
||||
// onMenuClosed() {
|
||||
// super.onMenuClosed();
|
||||
// }
|
||||
|
||||
onMenuItemClick(action) {
|
||||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
|
||||
super.onMenuItemClick(action);
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
const info = api.asc_getCellInfo();
|
||||
switch (action) {
|
||||
case 'cut':
|
||||
if (!api.asc_Cut() && !LocalStorage.getBool("sse-hide-copy-cut-paste-warning")) {
|
||||
this.showCopyCutPasteModal();
|
||||
}
|
||||
break;
|
||||
case 'copy':
|
||||
if (!api.asc_Copy() && !LocalStorage.getBool("sse-hide-copy-cut-paste-warning")) {
|
||||
this.showCopyCutPasteModal();
|
||||
}
|
||||
break;
|
||||
case 'paste':
|
||||
if (!api.asc_Paste() && !LocalStorage.getBool("sse-hide-copy-cut-paste-warning")) {
|
||||
this.showCopyCutPasteModal();
|
||||
}
|
||||
break;
|
||||
case 'addcomment':
|
||||
Common.Notifications.trigger('addcomment');
|
||||
break;
|
||||
case 'viewcomment':
|
||||
Common.Notifications.trigger('viewcomment');
|
||||
break;
|
||||
case 'del':
|
||||
api.asc_emptyCells(Asc.c_oAscCleanOptions.All);
|
||||
break;
|
||||
case 'wrap':
|
||||
api.asc_setCellTextWrap(true);
|
||||
break;
|
||||
case 'unwrap':
|
||||
api.asc_setCellTextWrap(false);
|
||||
break;
|
||||
case 'edit':
|
||||
setTimeout(() => {
|
||||
this.props.openOptions('edit');
|
||||
}, 0);
|
||||
break;
|
||||
case 'merge':
|
||||
if (api.asc_mergeCellsDataLost(Asc.c_oAscMergeOptions.Merge)) {
|
||||
setTimeout(() => {
|
||||
f7.dialog.confirm(_t.warnMergeLostData, _t.notcriticalErrorTitle, () => {
|
||||
api.asc_mergeCells(Asc.c_oAscMergeOptions.Merge);
|
||||
});
|
||||
}, 0);
|
||||
} else {
|
||||
api.asc_mergeCells(Asc.c_oAscMergeOptions.Merge);
|
||||
}
|
||||
break;
|
||||
case 'unmerge':
|
||||
api.asc_mergeCells(Asc.c_oAscMergeOptions.None);
|
||||
break;
|
||||
case 'hide':
|
||||
api[info.asc_getSelectionType() == Asc.c_oAscSelectionType.RangeRow ? 'asc_hideRows' : 'asc_hideColumns']();
|
||||
break;
|
||||
case 'show':
|
||||
api[info.asc_getSelectionType() == Asc.c_oAscSelectionType.RangeRow ? 'asc_showRows' : 'asc_showColumns']();
|
||||
break;
|
||||
case 'addlink':
|
||||
setTimeout(() => {
|
||||
this.props.openOptions('add', 'link');
|
||||
}, 400)
|
||||
break;
|
||||
case 'openlink':
|
||||
const linkinfo = info.asc_getHyperlink();
|
||||
if ( linkinfo.asc_getType() == Asc.c_oAscHyperlinkType.RangeLink ) {
|
||||
const nameSheet = linkinfo.asc_getSheet();
|
||||
const curActiveSheet = api.asc_getActiveWorksheetIndex();
|
||||
api.asc_setWorksheetRange(linkinfo);
|
||||
const {storeSheets} = this.props;
|
||||
const tab = storeSheets.sheets.find((sheet) => sheet.name === nameSheet);
|
||||
if (tab) {
|
||||
const sdkIndex = tab.index;
|
||||
if (sdkIndex !== curActiveSheet) {
|
||||
const index = storeSheets.sheets.indexOf(tab);
|
||||
storeSheets.setActiveWorksheet(index);
|
||||
Common.Notifications.trigger('sheet:active', sdkIndex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const url = linkinfo.asc_getHyperlinkUrl().replace(/\s/g, "%20");
|
||||
api.asc_getUrlType(url) > 0 && this.openLink(url);
|
||||
}
|
||||
break;
|
||||
case 'freezePanes':
|
||||
api.asc_freezePane();
|
||||
break;
|
||||
}
|
||||
|
||||
console.log("click context menu item: " + action);
|
||||
}
|
||||
|
||||
showCopyCutPasteModal() {
|
||||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
f7.dialog.create({
|
||||
title: _t.textCopyCutPasteActions,
|
||||
text: _t.errorCopyCutPaste,
|
||||
content: `<div class="checkbox-in-modal">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="checkbox-show" />
|
||||
<i class="icon-checkbox"></i>
|
||||
</label>
|
||||
<span class="right-text">${_t.textDoNotShowAgain}</span>
|
||||
</div>`,
|
||||
buttons: [{
|
||||
text: 'OK',
|
||||
onClick: () => {
|
||||
const dontShow = $$('input[name="checkbox-show"]').prop('checked');
|
||||
if (dontShow) LocalStorage.setItem("de-hide-copy-cut-paste-warning", 1);
|
||||
}
|
||||
}]
|
||||
}).open();
|
||||
}
|
||||
|
||||
openLink(url) {
|
||||
const newDocumentPage = window.open(url, '_blank');
|
||||
|
||||
if (newDocumentPage) {
|
||||
newDocumentPage.focus();
|
||||
}
|
||||
}
|
||||
|
||||
onDocumentReady() {
|
||||
super.onDocumentReady();
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_registerCallback('asc_onShowComment', this.onApiShowComment);
|
||||
api.asc_registerCallback('asc_onHideComment', this.onApiHideComment);
|
||||
}
|
||||
|
||||
initMenuItems() {
|
||||
if ( !Common.EditorApi ) return [];
|
||||
|
||||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
|
||||
const { isEdit, canViewComments, isDisconnected } = this.props;
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
const cellinfo = api.asc_getCellInfo();
|
||||
|
||||
const itemsIcon = [];
|
||||
const itemsText = [];
|
||||
|
||||
let iscellmenu, isrowmenu, iscolmenu, isallmenu, ischartmenu, isimagemenu, istextshapemenu, isshapemenu, istextchartmenu;
|
||||
let iscelllocked = cellinfo.asc_getLocked();
|
||||
const seltype = cellinfo.asc_getSelectionType();
|
||||
const xfs = cellinfo.asc_getXfs();
|
||||
const isComments = cellinfo.asc_getComments().length > 0; //prohibit adding multiple comments in one cell;
|
||||
|
||||
switch (seltype) {
|
||||
case Asc.c_oAscSelectionType.RangeCells: iscellmenu = true; break;
|
||||
case Asc.c_oAscSelectionType.RangeRow: isrowmenu = true; break;
|
||||
case Asc.c_oAscSelectionType.RangeCol: iscolmenu = true; break;
|
||||
case Asc.c_oAscSelectionType.RangeMax: isallmenu = true; break;
|
||||
case Asc.c_oAscSelectionType.RangeImage: isimagemenu = true; break;
|
||||
case Asc.c_oAscSelectionType.RangeShape: isshapemenu = true; break;
|
||||
case Asc.c_oAscSelectionType.RangeChart: ischartmenu = true; break;
|
||||
case Asc.c_oAscSelectionType.RangeChartText: istextchartmenu = true; break;
|
||||
case Asc.c_oAscSelectionType.RangeShapeText: istextshapemenu = true; break;
|
||||
}
|
||||
|
||||
if (!isEdit) {
|
||||
if (iscellmenu || istextchartmenu || istextshapemenu) {
|
||||
itemsIcon.push({
|
||||
event: 'copy',
|
||||
icon: 'icon-copy'
|
||||
});
|
||||
}
|
||||
if (iscellmenu && cellinfo.asc_getHyperlink()) {
|
||||
itemsText.push({
|
||||
caption: _t.menuOpenLink,
|
||||
event: 'openlink'
|
||||
});
|
||||
}
|
||||
if (canViewComments && isComments) {
|
||||
itemsText.push({
|
||||
caption: _t.menuViewComment,
|
||||
event: 'viewcomment'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!iscelllocked && (isimagemenu || isshapemenu || ischartmenu || istextshapemenu || istextchartmenu)) {
|
||||
api.asc_getGraphicObjectProps().every((object) => {
|
||||
if (object.asc_getObjectType() == Asc.c_oAscTypeSelectElement.Image) {
|
||||
iscelllocked = object.asc_getObjectValue().asc_getLocked();
|
||||
}
|
||||
return !iscelllocked;
|
||||
});
|
||||
}
|
||||
|
||||
if (iscelllocked || api.isCellEdited) {
|
||||
itemsIcon.push({
|
||||
event: 'copy',
|
||||
icon: 'icon-copy'
|
||||
});
|
||||
|
||||
} else {
|
||||
itemsIcon.push({
|
||||
event: 'cut',
|
||||
icon: 'icon-cut'
|
||||
});
|
||||
itemsIcon.push({
|
||||
event: 'copy',
|
||||
icon: 'icon-copy'
|
||||
});
|
||||
itemsIcon.push({
|
||||
event: 'paste',
|
||||
icon: 'icon-paste'
|
||||
});
|
||||
itemsText.push({
|
||||
caption: _t.menuDelete,
|
||||
event: 'del'
|
||||
});
|
||||
|
||||
if (isimagemenu || isshapemenu || ischartmenu ||
|
||||
istextshapemenu || istextchartmenu) {
|
||||
itemsText.push({
|
||||
caption: _t.menuEdit,
|
||||
event: 'edit'
|
||||
});
|
||||
} else {
|
||||
if (iscolmenu || isrowmenu) {
|
||||
itemsText.push({
|
||||
caption: _t.menuHide,
|
||||
event: 'hide'
|
||||
});
|
||||
itemsText.push({
|
||||
caption: _t.menuShow,
|
||||
event: 'show'
|
||||
});
|
||||
} else if (iscellmenu) {
|
||||
if (!iscelllocked) {
|
||||
itemsText.push({
|
||||
caption: _t.menuCell,
|
||||
event: 'edit'
|
||||
});
|
||||
}
|
||||
|
||||
if (cellinfo.asc_getMerge() == Asc.c_oAscMergeOptions.None) {
|
||||
itemsText.push({
|
||||
caption: _t.menuMerge,
|
||||
event: 'merge'
|
||||
});
|
||||
}
|
||||
|
||||
if (cellinfo.asc_getMerge() == Asc.c_oAscMergeOptions.Merge) {
|
||||
itemsText.push({
|
||||
caption: _t.menuUnmerge,
|
||||
event: 'unmerge'
|
||||
});
|
||||
}
|
||||
|
||||
itemsText.push(
|
||||
xfs.asc_getWrapText() ?
|
||||
{
|
||||
caption: _t.menuUnwrap,
|
||||
event: 'unwrap'
|
||||
} :
|
||||
{
|
||||
caption: _t.menuWrap,
|
||||
event: 'wrap'
|
||||
});
|
||||
|
||||
if (cellinfo.asc_getHyperlink() && !cellinfo.asc_getMultiselect()) {
|
||||
itemsText.push({
|
||||
caption: _t.menuOpenLink,
|
||||
event: 'openlink'
|
||||
});
|
||||
} else if (!cellinfo.asc_getHyperlink() && !cellinfo.asc_getMultiselect() &&
|
||||
!cellinfo.asc_getLockText() && !!cellinfo.asc_getText()) {
|
||||
itemsText.push({
|
||||
caption: _t.menuAddLink,
|
||||
event: 'addlink'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
itemsText.push({
|
||||
caption: api.asc_getSheetViewSettings().asc_getIsFreezePane() ? _t.menuUnfreezePanes : _t.menuFreezePanes,
|
||||
event: 'freezePanes'
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (canViewComments) {
|
||||
if (isComments) {
|
||||
itemsText.push({
|
||||
caption: _t.menuViewComment,
|
||||
event: 'viewcomment'
|
||||
});
|
||||
} else if (iscellmenu) {
|
||||
itemsText.push({
|
||||
caption: _t.menuAddComment,
|
||||
event: 'addcomment'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( Device.phone && itemsText.length > 2 ) {
|
||||
this.extraItems = itemsText.splice(2,itemsText.length, {
|
||||
caption: _t.menuMore,
|
||||
event: 'showActionSheet'
|
||||
});
|
||||
}
|
||||
|
||||
return itemsIcon.concat(itemsText);
|
||||
}
|
||||
|
||||
initExtraItems () {
|
||||
return (this.extraItems && this.extraItems.length > 0 ? this.extraItems : []);
|
||||
}
|
||||
}
|
||||
|
||||
const _ContextMenu = withTranslation()(ContextMenu);
|
||||
_ContextMenu.closeContextMenu = ContextMenu.closeContextMenu;
|
||||
export { _ContextMenu as default };
|
|
@ -1,15 +1,22 @@
|
|||
|
||||
import React, { Component } from 'react'
|
||||
import React, { Component, Fragment } from 'react'
|
||||
import { inject } from "mobx-react";
|
||||
import { f7 } from 'framework7-react';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import CollaborationController from '../../../../common/mobile/lib/controller/collaboration/Collaboration.jsx'
|
||||
import { onAdvancedOptions } from './settings/Download.jsx';
|
||||
import {
|
||||
AddCommentController,
|
||||
CommentsController,
|
||||
EditCommentController,
|
||||
ViewCommentsController
|
||||
} from "../../../../common/mobile/lib/controller/collaboration/Comments";
|
||||
|
||||
@inject("storeAppOptions", "storeFocusObjects", "storeCellSettings", "storeTextSettings", "storeChartSettings", "storeSpreadsheetSettings", "storeSpreadsheetInfo")
|
||||
class MainController extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
super(props);
|
||||
window.editorType = 'sse';
|
||||
}
|
||||
|
||||
initSdk() {
|
||||
|
@ -318,7 +325,15 @@ class MainController extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <CollaborationController />
|
||||
return (
|
||||
<Fragment>
|
||||
<CollaborationController />
|
||||
<CommentsController />
|
||||
<AddCommentController />
|
||||
<EditCommentController />
|
||||
<ViewCommentsController />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
|
|
@ -1,30 +1,83 @@
|
|||
|
||||
import React, { useEffect } from 'react';
|
||||
import StatusbarView from '../view/Statusbar';
|
||||
import React, { Fragment, useEffect, useState } from 'react';
|
||||
import {StatusbarView} from '../view/Statusbar';
|
||||
import { inject } from 'mobx-react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Device } from '../../../../common/mobile/utils/device';
|
||||
|
||||
const Statusbar = inject('sheets')(props => {
|
||||
const {sheets} = props;
|
||||
const Statusbar = inject('sheets', 'storeAppOptions', 'users')(props => {
|
||||
const {sheets, storeAppOptions, users} = props;
|
||||
const {t} = useTranslation();
|
||||
const _t = t('Statusbar', {returnObjects: true});
|
||||
// console.log(props);
|
||||
|
||||
let isEdit = storeAppOptions.isEdit;
|
||||
let isDisconnected = users.isDisconnected;
|
||||
|
||||
useEffect(() => {
|
||||
console.log("status bar did mount");
|
||||
const onDocumentReady = () => {
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_registerCallback('asc_onUpdateTabColor', onApiUpdateTabColor);
|
||||
api.asc_registerCallback('asc_onWorkbookLocked', onWorkbookLocked);
|
||||
api.asc_registerCallback('asc_onWorksheetLocked', onWorksheetLocked);
|
||||
api.asc_registerCallback('asc_onSheetsChanged', onApiSheetsChanged);
|
||||
api.asc_registerCallback('asc_onHidePopMenu', onApiHideTabContextMenu);
|
||||
};
|
||||
if ( !Common.EditorApi ) {
|
||||
Common.Notifications.on('document:ready', onDocumentReady);
|
||||
Common.Notifications.on('document:ready', onApiSheetsChanged);
|
||||
} else {
|
||||
onDocumentReady();
|
||||
}
|
||||
|
||||
Common.Notifications.on('document:ready', onApiSheetsChanged);
|
||||
Common.Notifications.on('engineCreated', api => {
|
||||
api.asc_registerCallback('asc_onSheetsChanged', onApiSheetsChanged.bind(api));
|
||||
});
|
||||
const on_main_view_click = e => {
|
||||
if(!e.target.closest('.tab.active')) {
|
||||
f7.popover.close('.document-menu.modal-in', false);
|
||||
}
|
||||
};
|
||||
|
||||
$$('.view-main').on('click', on_main_view_click);
|
||||
|
||||
return () => {
|
||||
Common.Notifications.off('document:ready', onDocumentReady);
|
||||
Common.Notifications.off('document:ready', onApiSheetsChanged);
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_unregisterCallback('asc_onUpdateTabColor', onApiUpdateTabColor);
|
||||
api.asc_unregisterCallback('asc_onWorkbookLocked', onWorkbookLocked);
|
||||
api.asc_unregisterCallback('asc_onWorksheetLocked', onWorksheetLocked);
|
||||
api.asc_unregisterCallback('asc_onSheetsChanged', onApiSheetsChanged);
|
||||
api.asc_unregisterCallback('asc_onHidePopMenu', onApiHideTabContextMenu);
|
||||
|
||||
$$('.view-main').off('click', on_main_view_click);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onApiSheetsChanged = api => {
|
||||
console.log('on api sheets changed');
|
||||
const onApiHideTabContextMenu = () => {
|
||||
f7.popover.close('.document-menu.modal-in', false);
|
||||
}
|
||||
|
||||
!api && (api = Common.EditorApi.get());
|
||||
const onWorkbookLocked = locked => {
|
||||
locked ? $$('.idx-btn-addtab').addClass('disabled') : $$('.idx-btn-addtab').removeClass('disabled');
|
||||
};
|
||||
|
||||
const onWorksheetLocked = (index, locked) => {
|
||||
let model = sheets.sheets.find(sheet => sheet.index === index);
|
||||
if(model && model.locked != locked)
|
||||
model.locked = locked;
|
||||
};
|
||||
|
||||
const onApiSheetsChanged = () => {
|
||||
// console.log('on api sheets changed');
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
const sheets_count = api.asc_getWorksheetsCount();
|
||||
const active_index = api.asc_getActiveWorksheetIndex();
|
||||
let i = -1, items = [];
|
||||
|
||||
while ( ++i < sheets_count ) {
|
||||
let i = -1, items = [], hiddentems = [];
|
||||
|
||||
while (++i < sheets_count) {
|
||||
const tab = {
|
||||
index : i,
|
||||
active : active_index == i,
|
||||
|
@ -34,46 +87,261 @@ const Statusbar = inject('sheets')(props => {
|
|||
color : api.asc_getWorksheetTabColor(i)
|
||||
};
|
||||
|
||||
items.push(tab);
|
||||
(api.asc_isWorksheetHidden(i) ? hiddentems : items).push(tab);
|
||||
// items.push(tab);
|
||||
}
|
||||
|
||||
sheets.reset(items);
|
||||
// this.hiddensheets.reset(hiddentems);
|
||||
sheets.resetSheets(items);
|
||||
sheets.resetHiddenSheets(hiddentems);
|
||||
|
||||
updateTabsColors();
|
||||
};
|
||||
|
||||
// this.updateTabsColors();
|
||||
const loadTabColor = sheetindex => {
|
||||
const api = Common.EditorApi.get();
|
||||
let tab = sheets.sheets.find(sheet => sheet.index === sheetindex);
|
||||
|
||||
if (tab) {
|
||||
setTabLineColor(tab, api.asc_getWorksheetTabColor(sheetindex));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const onApiUpdateTabColor = index => {
|
||||
loadTabColor(index);
|
||||
};
|
||||
|
||||
const setTabLineColor = (tab, color) => {
|
||||
if (tab) {
|
||||
if (null !== color) {
|
||||
color = '#' + Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b());
|
||||
} else {
|
||||
color = '';
|
||||
}
|
||||
|
||||
if (color.length) {
|
||||
if (!tab.active) {
|
||||
color = '0px 4px 0 ' + Common.Utils.RGBColor(color).toRGBA(0.7) + ' inset';
|
||||
} else {
|
||||
color = '0px 4px 0 ' + color + ' inset';
|
||||
}
|
||||
|
||||
$$('.sheet-tabs .tab').eq(tab.index).css('box-shadow', color);
|
||||
} else {
|
||||
$$('.sheet-tabs .tab').eq(tab.index).css('box-shadow', '');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const updateTabsColors = () => {
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
sheets.sheets.forEach(model => {
|
||||
setTabLineColor(model, api.asc_getWorksheetTabColor(model.index));
|
||||
});
|
||||
};
|
||||
|
||||
const onTabClicked = i => {
|
||||
const model = sheets.at(i);
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
api.asc_showWorksheet(model.index);
|
||||
sheets.setActiveWorksheet(i);
|
||||
|
||||
Common.Notifications.trigger('sheet:active', model.index);
|
||||
};
|
||||
|
||||
const createSheetName = () => {
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
let items = [], wc = api.asc_getWorksheetsCount();
|
||||
while (wc--) {
|
||||
items.push(api.asc_getWorksheetName(wc).toLowerCase());
|
||||
}
|
||||
|
||||
let index = 0, name;
|
||||
while(++index < 1000) {
|
||||
name = /*this.strSheet*/ 'Sheet' + index;
|
||||
if (items.indexOf(name.toLowerCase()) < 0) break;
|
||||
}
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
const onAddTabClicked = () => {
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_closeCellEditor();
|
||||
|
||||
const createSheetName = () => {
|
||||
let items = [], wc = api.asc_getWorksheetsCount();
|
||||
while (wc--) {
|
||||
items.push(api.asc_getWorksheetName(wc).toLowerCase());
|
||||
}
|
||||
|
||||
let index = 0, name;
|
||||
while(++index < 1000) {
|
||||
name = /*this.strSheet*/ 'Sheet' + index;
|
||||
if (items.indexOf(name.toLowerCase()) < 0) break;
|
||||
}
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
createSheetName();
|
||||
api.asc_addWorksheet(createSheetName());
|
||||
};
|
||||
|
||||
return <StatusbarView onTabClicked={onTabClicked} onAddTabClicked={onAddTabClicked} />
|
||||
const onTabClick = (i, target) => {
|
||||
const api = Common.EditorApi.get();
|
||||
const model = sheets.at(i);
|
||||
// console.log(model);
|
||||
|
||||
let opened = $$('.document-menu.modal-in').length;
|
||||
let index = model.index;
|
||||
|
||||
f7.popover.close('.document-menu.modal-in', false);
|
||||
|
||||
if (index == api.asc_getActiveWorksheetIndex()) {
|
||||
if (!opened) {
|
||||
if (!isDisconnected) {
|
||||
api.asc_closeCellEditor();
|
||||
f7.popover.open('#idx-tab-context-menu-popover', target);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
f7.popover.close('#idx-tab-context-menu-popover', false);
|
||||
onTabClicked(i);
|
||||
Common.Notifications.trigger('sheet:active', index);
|
||||
}
|
||||
};
|
||||
|
||||
const deleteWorksheet = () => {
|
||||
const api = Common.EditorApi.get();
|
||||
const visibleSheets = sheets.visibleWorksheets();
|
||||
|
||||
if (sheets.sheets.length == 1 || visibleSheets.length == 1) {
|
||||
f7.dialog.alert(_t.textErrorLastSheet, _t.notcriticalErrorTitle);
|
||||
} else {
|
||||
f7.dialog.confirm(
|
||||
_t.textWarnDeleteSheet,
|
||||
_t.notcriticalErrorTitle,
|
||||
() => {
|
||||
if (!api.asc_deleteWorksheet()) {
|
||||
f7.dialog.alert(_t.textErrorRemoveSheet, _t.notcriticalErrorTitle);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const renameWorksheet = () => {
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
if (api.asc_getWorksheetsCount() > 0) {
|
||||
let sindex = api.asc_getActiveWorksheetIndex();
|
||||
|
||||
if (api.asc_isWorksheetLockedOrDeleted(sindex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let current = api.asc_getWorksheetName(api.asc_getActiveWorksheetIndex());
|
||||
|
||||
f7.dialog.create({
|
||||
title: _t.textRenameSheet,
|
||||
content: Device.ios ?
|
||||
'<div class="input-field"><input type="text" name="modal-sheet-name" maxlength="31" value="' + current + '" placeholder="' + _t.textSheetName + '" class="modal-text-input"></div>' :
|
||||
'<div class="item-content item-input" style="margin-top: 15px; position: relative; padding-bottom: 10px;"><div class="item-inner"><div class="item-input-wrap" style="min-height: initial; width: 100%;"><input type="text" style="width: 100%;" name="modal-sheet-name" value="' + current + '" maxlength="31" placeholder="' + _t.textSheetName + '" /></div></div></div>',
|
||||
buttons: [
|
||||
{
|
||||
text: 'OK',
|
||||
bold: true,
|
||||
onClick: function () {
|
||||
let s = $$('input[name="modal-sheet-name"]').val(),
|
||||
wc = api.asc_getWorksheetsCount(), items = [],
|
||||
err = !s.trim().length ? _t.textErrNotEmpty : ((s.length > 2 && s[0] == '"' && s[s.length-1] == '"' || !/[:\\\/\*\?\[\]\']/.test(s)) ? null : _t.textErrNameWrongChar);
|
||||
if (!err) {
|
||||
while (wc--) {
|
||||
if (sindex !== wc) {
|
||||
items.push(api.asc_getWorksheetName(wc).toLowerCase());
|
||||
}
|
||||
}
|
||||
if (items) {
|
||||
let testval = s.toLowerCase();
|
||||
for (var i = items.length - 1; i >= 0; --i) {
|
||||
if (items[i] === testval) {
|
||||
err = _t.textErrNameExists;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
f7.dialog.alert(err, _t.notcriticalErrorTitle, () => {
|
||||
renameWorksheet();
|
||||
});
|
||||
} else if (s != current)
|
||||
api.asc_renameWorksheet(s);
|
||||
}
|
||||
},
|
||||
{
|
||||
text: _t.textCancel
|
||||
}
|
||||
]
|
||||
}).open();
|
||||
}
|
||||
};
|
||||
|
||||
const createCopyName = (orig) => {
|
||||
const api = Common.EditorApi.get();
|
||||
let wc = api.asc_getWorksheetsCount(), names = [];
|
||||
|
||||
while (wc--) {
|
||||
names.push(api.asc_getWorksheetName(wc).toLowerCase());
|
||||
}
|
||||
|
||||
let re = /^(.*)\((\d)\)$/.exec(orig);
|
||||
let first = re ? re[1] : orig + ' ';
|
||||
let index = 1, name;
|
||||
|
||||
while(++index < 1000) {
|
||||
name = first + '(' + index + ')';
|
||||
if (names.indexOf(name.toLowerCase()) < 0) break;
|
||||
}
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
const hideWorksheet = (hide, index) => {
|
||||
const api = Common.EditorApi.get();
|
||||
const visibleSheets = sheets.visibleWorksheets();
|
||||
|
||||
if(hide) {
|
||||
visibleSheets.length == 1 ?
|
||||
f7.dialog.alert(_t.textErrorLastSheet, _t.notcriticalErrorTitle) :
|
||||
api['asc_hideWorksheet']([index]);
|
||||
} else {
|
||||
f7.popover.close('#idx-hidden-sheets-popover');
|
||||
api['asc_showWorksheet'](index);
|
||||
loadTabColor(index);
|
||||
}
|
||||
};
|
||||
|
||||
const onTabMenu = (event) => {
|
||||
const api = Common.EditorApi.get();
|
||||
let index = sheets.sheets.find(sheet => sheet.active).index;
|
||||
|
||||
f7.popover.close('.document-menu.modal-in', false);
|
||||
|
||||
switch (event) {
|
||||
case 'del': deleteWorksheet(); break;
|
||||
case 'hide': hideWorksheet(true, index); break;
|
||||
case 'ins': api.asc_insertWorksheet(createSheetName()); break;
|
||||
case 'copy':
|
||||
let name = createCopyName(api.asc_getWorksheetName(api.asc_getActiveWorksheetIndex()));
|
||||
api.asc_copyWorksheet(index, name);
|
||||
break;
|
||||
case 'ren': renameWorksheet(); break;
|
||||
case 'unhide':
|
||||
f7.popover.open('#idx-hidden-sheets-popover', '.active');
|
||||
break;
|
||||
case 'showMore':
|
||||
f7.actions.open('#idx-tab-menu-actions');
|
||||
break;
|
||||
default:
|
||||
let _re = /reveal\:(\d+)/.exec(event);
|
||||
if (_re && !!_re[1]) {
|
||||
hideWorksheet(false, parseInt(_re[1]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<StatusbarView onTabClick={onTabClick} onTabClicked={onTabClicked} onAddTabClicked={onAddTabClicked} onTabMenu={onTabMenu} />
|
||||
)
|
||||
});
|
||||
|
||||
export default Statusbar;
|
|
@ -18,9 +18,18 @@ class AddOtherController extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
hideAddComment () {
|
||||
const cellinfo = Common.EditorApi.get().asc_getCellInfo();
|
||||
const iscelllocked = cellinfo.asc_getLocked();
|
||||
const seltype = cellinfo.asc_getSelectionType();
|
||||
const isComments = cellinfo.asc_getComments().length > 0;
|
||||
return (!(seltype === Asc.c_oAscSelectionType.RangeCells && !iscelllocked) || isComments);
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<AddOther
|
||||
<AddOther closeModal={this.closeModal}
|
||||
hideAddComment={this.hideAddComment}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,23 @@
|
|||
|
||||
.device-ios {
|
||||
|
||||
input.modal-text-input {
|
||||
box-sizing: border-box;
|
||||
height: 26px;
|
||||
background: #fff;
|
||||
margin: 0;
|
||||
margin-top: 15px;
|
||||
padding: 0 5px;
|
||||
border: 1px solid rgba(0,0,0,.3);
|
||||
border-radius: 0;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-family: inherit;
|
||||
display: block;
|
||||
box-shadow: 0 0 0 transparent;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
-ms-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
@import '../../../../common/mobile/resources/less/icons.less';
|
||||
@import '../../../../common/mobile/resources/less/dataview.less';
|
||||
@import '../../../../common/mobile/resources/less/search.less';
|
||||
@import '../../../../common/mobile/resources/less/contextmenu.less';
|
||||
@import '../../../../common/mobile/resources/less/comments.less';
|
||||
@import './app-material.less';
|
||||
@import './app-ios.less';
|
||||
@import './icons-ios.less';
|
||||
|
|
|
@ -370,21 +370,6 @@
|
|||
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="M1 2H22V21H1V2ZM12 3H21V8H12V3ZM12 9H21V14H12V9ZM11 14V9H2V14H11ZM2 15V20H11V15H2ZM12 15H21V20H12V15ZM11 3V8H2V3H11Z" fill="@{themeColor}"/></svg>');
|
||||
}
|
||||
&.icon-cut {
|
||||
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 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" fill="white"/><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" fill="white"/><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" fill="white"/></g><defs><clipPath id="cut"><rect width="24" height="24" fill="white"/></clipPath></defs></svg>');
|
||||
}
|
||||
&.icon-copy {
|
||||
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 d="M1 1H15V7H16V0H0V17H8V16H1V1Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M23 8H9V23H23V8ZM8 7V24H24V7H8Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M13 5H3V4H13V5Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 9H3V8H8V9Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 13H3V12H8V13Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H11V11H21V12Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H11V15H21V16Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H11V19H21V20Z" fill="white"/></svg>');
|
||||
}
|
||||
&.icon-paste {
|
||||
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="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" fill="white"/><path d="M5 0H14V5H5V0Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" fill="white"/></svg>');
|
||||
}
|
||||
//Comments
|
||||
&.icon-menu-comment {
|
||||
width: 30px;
|
||||
|
|
|
@ -334,21 +334,6 @@
|
|||
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="M15.5 7C15.5 9.26153 14.9357 10.9518 14.201 12.0307C13.4584 13.121 12.6234 13.5 12 13.5C11.3766 13.5 10.5416 13.121 9.79901 12.0307C9.0643 10.9518 8.5 9.26153 8.5 7C8.5 4.92262 10.2222 3.5 12 3.5C13.7778 3.5 15.5 4.92262 15.5 7ZM14.8461 13.6216C14.006 14.5191 13.0044 15 12 15C10.9956 15 9.99399 14.5191 9.15395 13.6216C7.69714 14.1996 6.4782 14.7725 5.52945 15.3496C3.82884 16.3839 3.5 17.1203 3.5 17.5C3.5 18.0104 3.76355 18.6977 5.04703 19.3409C6.37522 20.0065 8.60909 20.4999 12 20.5C15.3909 20.5 17.6248 20.0065 18.953 19.3409C20.2364 18.6977 20.5 18.0104 20.5 17.5C20.5 17.1203 20.1712 16.3839 18.4705 15.3496C17.5218 14.7725 16.3029 14.1996 14.8461 13.6216ZM15.7544 12.37C16.5137 11.0279 17 9.20917 17 7C17 4 14.5088 2 12 2C9.49121 2 7 4 7 7C7 9.20917 7.48633 11.0279 8.24563 12.37C4.38973 13.9392 2 15.579 2 17.5C2 19.9852 5 21.9999 12 22C19 22 22 19.9852 22 17.5C22 15.579 19.6103 13.9392 15.7544 12.37Z" fill="@{themeColor}"/></svg>');
|
||||
}
|
||||
&.icon-cut {
|
||||
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 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" fill="black"/><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" fill="black"/><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" fill="black"/></g><defs><clipPath id="cut"><rect width="24" height="24" fill="black"/></clipPath></defs></svg>');
|
||||
}
|
||||
&.icon-copy {
|
||||
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 d="M1 1H15V7H16V0H0V17H8V16H1V1Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M23 8H9V23H23V8ZM8 7V24H24V7H8Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M13 5H3V4H13V5Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 9H3V8H8V9Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 13H3V12H8V13Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H11V11H21V12Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H11V15H21V16Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H11V19H21V20Z" fill="black"/></svg>');
|
||||
}
|
||||
&.icon-paste {
|
||||
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="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" fill="black"/><path d="M5 0H14V5H5V0Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" fill="black"/></svg>');
|
||||
}
|
||||
//Comments
|
||||
&.icon-menu-comment {
|
||||
width: 24px;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
height: @statusbar-height;
|
||||
min-height: @statusbar-height;
|
||||
background-color: @background-normal;
|
||||
|
||||
display: flex;
|
||||
|
||||
.tab {
|
||||
|
@ -26,13 +25,23 @@
|
|||
}
|
||||
|
||||
.statusbar--box-tabs {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
&::-webkit-scrollbar {
|
||||
-webkit-appearance: none;
|
||||
display: none;
|
||||
// width: 0;
|
||||
// height: 0;
|
||||
}
|
||||
> ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
|
||||
// overflow: hidden;
|
||||
// position: absolute;
|
||||
// left: 0;
|
||||
// top: 0;
|
||||
> li {
|
||||
a {
|
||||
font-size: 12px;
|
||||
|
|
|
@ -34,9 +34,8 @@ export default class extends React.Component {
|
|||
return (
|
||||
<App { ...f7params } >
|
||||
{/* Your main view, should have "view-main" class */}
|
||||
<View main className="safe-areas" url="/">
|
||||
<MainController />
|
||||
</View>
|
||||
<View main className="safe-areas" url="/" />
|
||||
<MainController />
|
||||
</App>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,8 +10,10 @@ import AddOptions from "../view/add/Add";
|
|||
import EditOptions from "../view/edit/Edit";
|
||||
import { Device } from '../../../../common/mobile/utils/device';
|
||||
import { Search, SearchSettings } from '../controller/Search';
|
||||
import { f7 } from 'framework7-react';
|
||||
|
||||
import {FunctionGroups} from "../controller/add/AddFunction";
|
||||
import ContextMenu from '../controller/ContextMenu';
|
||||
|
||||
export default class MainPage extends Component {
|
||||
constructor(props) {
|
||||
|
@ -26,6 +28,8 @@ export default class MainPage extends Component {
|
|||
}
|
||||
|
||||
handleClickToOpenOptions = (opts, showOpts) => {
|
||||
f7.popover.close('.document-menu.modal-in', false);
|
||||
|
||||
this.setState(state => {
|
||||
if ( opts == 'edit' )
|
||||
return {editOptionsVisible: true};
|
||||
|
@ -70,7 +74,7 @@ export default class MainPage extends Component {
|
|||
<Link id='btn-edit' icon='icon-edit-settings' href={false} onClick={e => this.handleClickToOpenOptions('edit')}></Link>
|
||||
<Link id='btn-add' icon='icon-plus' href={false} onClick={e => this.handleClickToOpenOptions('add')}></Link>
|
||||
{ Device.phone ? null : <Link icon='icon-search' searchbarEnable='.searchbar' href={false}></Link> }
|
||||
<Link href={false} icon='icon-collaboration' onClick={e => this.handleClickToOpenOptions('coauth')}></Link>
|
||||
<Link id='btn-coauth' href={false} icon='icon-collaboration' onClick={e => this.handleClickToOpenOptions('coauth')}></Link>
|
||||
<Link id='btn-settings' icon='icon-settings' href={false} onClick={e => this.handleClickToOpenOptions('settings')}></Link>
|
||||
</NavRight>
|
||||
<Search useSuspense={false} />
|
||||
|
@ -98,6 +102,7 @@ export default class MainPage extends Component {
|
|||
<Statusbar />
|
||||
|
||||
<FunctionGroups /> {/* hidden component*/}
|
||||
<ContextMenu openOptions={this.handleClickToOpenOptions.bind(this)} />
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,13 +3,19 @@ import {action, observable, makeObservable} from 'mobx';
|
|||
export class storeAppOptions {
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
isEdit: observable,
|
||||
canViewComments: observable,
|
||||
setConfigOptions: action,
|
||||
setPermissionOptions: action
|
||||
});
|
||||
}
|
||||
|
||||
isEdit = false;
|
||||
config = {};
|
||||
|
||||
isEdit = false;
|
||||
canViewComments = false;
|
||||
|
||||
setConfigOptions (config) {
|
||||
this.config = config;
|
||||
this.user = Common.Utils.fillUserInfo(config.user, config.lang, "Local.User"/*me.textAnonymous*/);
|
||||
|
|
|
@ -15,6 +15,7 @@ import {storeAppOptions} from "./appOptions";
|
|||
// import {storeTableSettings} from "./tableSettings";
|
||||
import {storeChartSettings} from "./chartSettings";
|
||||
import {storeSpreadsheetSettings} from "./spreadsheetSettings";
|
||||
import {storeComments} from "../../../../common/mobile/lib/store/comments";
|
||||
|
||||
export const stores = {
|
||||
storeFocusObjects: new storeFocusObjects(),
|
||||
|
@ -30,8 +31,9 @@ export const stores = {
|
|||
storeShapeSettings: new storeShapeSettings(),
|
||||
storeChartSettings: new storeChartSettings(),
|
||||
storePalette: new storePalette(),
|
||||
storeCellSettings: new storeCellSettings()
|
||||
storeCellSettings: new storeCellSettings(),
|
||||
// storeImageSettings: new storeImageSettings(),
|
||||
// storeTableSettings: new storeTableSettings()
|
||||
storeComments: new storeComments()
|
||||
};
|
||||
|
||||
|
|
|
@ -21,20 +21,28 @@ class Worksheet {
|
|||
|
||||
export class storeWorksheets {
|
||||
sheets;
|
||||
hiddensheets;
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
sheets: observable,
|
||||
reset: action,
|
||||
hiddensheets: observable,
|
||||
resetSheets: action,
|
||||
resetHiddenSheets: action,
|
||||
setActiveWorksheet: action
|
||||
});
|
||||
this.sheets = [];
|
||||
this.hiddensheets = [];
|
||||
}
|
||||
|
||||
reset(sheets) {
|
||||
resetSheets(sheets) {
|
||||
this.sheets = Object.values(sheets)
|
||||
}
|
||||
|
||||
resetHiddenSheets(hiddensheets) {
|
||||
this.hiddensheets = Object.values(hiddensheets)
|
||||
}
|
||||
|
||||
setActiveWorksheet(i) {
|
||||
if ( !this.sheets[i].active ) {
|
||||
this.sheets.forEach(model => {
|
||||
|
@ -57,4 +65,8 @@ export class storeWorksheets {
|
|||
hiddenWorksheets() {
|
||||
return this.sheets.filter(model => model.hidden);
|
||||
}
|
||||
|
||||
visibleWorksheets() {
|
||||
return this.sheets.filter(model => !model.hidden);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,100 @@
|
|||
import React from 'react';
|
||||
import { View, Toolbar, Link, Icon } from 'framework7-react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { View, Toolbar, Link, Icon, Popover, List, ListButton, Actions, ActionsGroup, ActionsButton } from 'framework7-react';
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Device } from '../../../../common/mobile/utils/device';
|
||||
|
||||
const viewStyle = {
|
||||
height: 30
|
||||
};
|
||||
|
||||
const StatusbarView = inject('sheets')(observer(props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('Statusbar', {returnObjects: true});
|
||||
const isAndroid = Device.android;
|
||||
const isPhone = Device.isPhone;
|
||||
const { sheets } = props;
|
||||
const hiddenSheets = sheets.hiddensheets;
|
||||
const getTabClassList = model => `tab ${model.active ? 'active' : ''} ${model.locked ? 'locked' : ''}`;
|
||||
// const $boxTabs = $$('.sheet-tabs');
|
||||
// const $statusBar = $$('.statusbar');
|
||||
|
||||
const getTabClassList = model =>
|
||||
`tab ${model.active ? 'active':''} ${model.locked ? 'locked':''}`;
|
||||
// $boxTabs.on('touchstart', onTouchStart);
|
||||
// $boxTabs.on('touchmove', onTouchMove);
|
||||
// $boxTabs.on('touchend', onTouchEnd);
|
||||
|
||||
return <View id="idx-statusbar" className="statusbar" style={viewStyle}>
|
||||
// let touch = {};
|
||||
|
||||
// function hasInvisible() {
|
||||
// let _left_bound_ = $boxTabs.offset().left,
|
||||
// _right_bound_ = $boxTabs.width() + _left_bound_ - $statusBar.width();
|
||||
// // _right_bound_ = _left_bound_ + $boxTabs.width();
|
||||
|
||||
// // console.log(_left_bound_);
|
||||
// console.log(_right_bound_);
|
||||
|
||||
// let tab = $$('.sheet-tabs li')[0];
|
||||
// let rect = tab.getBoundingClientRect();
|
||||
|
||||
// if (!(rect.left < _left_bound_)) {
|
||||
// // tab = $$('.sheet-tabs li')[$$('.sheet-tabs li').length - 1];
|
||||
// // rect = tab.getBoundingClientRect();
|
||||
|
||||
// // if (!((rect.right).toFixed(2) > _right_bound_))
|
||||
// // return false;
|
||||
// if(_right_bound_ <= 0) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// function onTouchStart(e) {
|
||||
// if (hasInvisible()) {
|
||||
// console.log(e);
|
||||
// let touches = e.changedTouches;
|
||||
// touch.startx = touches[0].clientX;
|
||||
// touch.scrollx = $boxTabs.scrollLeft();
|
||||
// // console.log(touch.scrollx);
|
||||
|
||||
// touch.timer = setTimeout(function () {
|
||||
// // touch.longtouch = true;
|
||||
// }, 500);
|
||||
// // e.preventDefault();
|
||||
// }
|
||||
// }
|
||||
|
||||
// function onTouchMove(e) {
|
||||
// if (touch.startx !== undefined) {
|
||||
// // console.log(e);
|
||||
// let touches = e.changedTouches;
|
||||
|
||||
// if (touch.longtouch) {}
|
||||
// else {
|
||||
// if (touch.timer) clearTimeout(touch.timer), delete touch.timer;
|
||||
// let valueLeft = touch.scrollx + (touch.startx - touches[0].clientX);
|
||||
// console.log(valueLeft);
|
||||
// // $boxTabs.scrollLeft(valueLeft);
|
||||
//
|
||||
// }
|
||||
|
||||
// // e.preventDefault();
|
||||
// }
|
||||
// }
|
||||
|
||||
// function onTouchEnd(e) {
|
||||
// if (touch.startx !== undefined) {
|
||||
// // console.log(e);
|
||||
// touch.longtouch = false;
|
||||
// delete touch.startx;
|
||||
// // e.preventDefault();
|
||||
// }
|
||||
// }
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<View id="idx-statusbar" className="statusbar" style={viewStyle}>
|
||||
<div id="idx-box-add-tab">
|
||||
<Link href="false" id="idx-btn-addtab" className="tab" onClick={e => props.onAddTabClicked()}>
|
||||
<Icon className="icon icon-plus" />
|
||||
|
@ -22,13 +104,70 @@ const StatusbarView = inject('sheets')(observer(props => {
|
|||
<ul className="sheet-tabs bottom">
|
||||
{sheets.sheets.map((model,i) =>
|
||||
model.hidden ? null :
|
||||
<li className={getTabClassList(model)} key={i}>
|
||||
<a onClick={e => props.onTabClicked(i)}>{model.name}</a>
|
||||
<li className={getTabClassList(model)} key={i} onClick={(e) => props.onTabClick(i, e.target)}>
|
||||
<a /* onClick={e => props.onTabClicked(i)} */>{model.name}</a>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</View>;
|
||||
</View>
|
||||
<Popover id="idx-tab-context-menu-popover"
|
||||
className="document-menu"
|
||||
backdrop={false}
|
||||
closeByBackdropClick={false}
|
||||
closeByOutsideClick={false}
|
||||
>
|
||||
{isPhone || isAndroid ? (
|
||||
<List className="list-block">
|
||||
<ListButton title={_t.textDuplicate} onClick={() => props.onTabMenu('copy')} />
|
||||
<ListButton title={_t.textDelete} onClick={() => props.onTabMenu('del')} />
|
||||
<ListButton title={_t.textMore} onClick={() => props.onTabMenu('showMore')} />
|
||||
</List>
|
||||
) : (
|
||||
<List className="list-block">
|
||||
<ListButton title={_t.textDuplicate} onClick={() => props.onTabMenu('copy')} />
|
||||
<ListButton title={_t.textDelete} onClick={() => props.onTabMenu('del')} />
|
||||
<ListButton title={_t.textRename} onClick={() => props.onTabMenu('ren')} />
|
||||
<ListButton title={_t.textHide} onClick={() => props.onTabMenu('hide')} />
|
||||
{hiddenSheets.length ? (
|
||||
<ListButton title={_t.textUnhide} onClick={() => props.onTabMenu('unhide')} />
|
||||
) : null}
|
||||
</List>
|
||||
)}
|
||||
</Popover>
|
||||
{isPhone || isAndroid ? (
|
||||
<Actions id="idx-tab-menu-actions" backdrop={true} closeByBackdropClick={true}>
|
||||
<ActionsGroup>
|
||||
<ActionsButton onClick={() => props.onTabMenu('ren')}>{_t.textRename}</ActionsButton>
|
||||
<ActionsButton onClick={() => props.onTabMenu('hide')}>{_t.textHide}</ActionsButton>
|
||||
{hiddenSheets.length ? (
|
||||
<ActionsButton onClick={() => props.onTabMenu('unhide')}>{_t.textUnhide}</ActionsButton>
|
||||
) : null}
|
||||
</ActionsGroup>
|
||||
<ActionsGroup>
|
||||
<ActionsButton bold={true}>{_t.textCancel}</ActionsButton>
|
||||
</ActionsGroup>
|
||||
</Actions>
|
||||
) : null}
|
||||
{hiddenSheets.length ? (
|
||||
<Popover id="idx-hidden-sheets-popover"
|
||||
className="document-menu"
|
||||
backdrop={false}
|
||||
closeByBackdropClick={false}
|
||||
closeByOutsideClick={false}
|
||||
>
|
||||
<List className="list-block">
|
||||
{hiddenSheets.map(sheet => {
|
||||
return (
|
||||
<ListButton key={sheet.index} data-event={`reveal:${sheet.index}`} title={sheet.name}
|
||||
onClick={() => props.onTabMenu(`reveal:${sheet.index}`)} />
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</Popover>
|
||||
) : null}
|
||||
</Fragment>
|
||||
)
|
||||
}));
|
||||
|
||||
export default StatusbarView;
|
||||
export {StatusbarView};
|
||||
|
|
|
@ -5,11 +5,18 @@ import { useTranslation } from 'react-i18next';
|
|||
const AddOther = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const hideAddComment = props.hideAddComment();
|
||||
return (
|
||||
<List>
|
||||
<ListItem title={_t.textImage} link={'/add-image/'}>
|
||||
<Icon slot="media" icon="icon-insimage"></Icon>
|
||||
</ListItem>
|
||||
{!hideAddComment && <ListItem title={_t.textComment} onClick={() => {
|
||||
props.closeModal();
|
||||
Common.Notifications.trigger('addcomment');
|
||||
}}>
|
||||
<Icon slot="media" icon="icon-insert-comment"></Icon>
|
||||
</ListItem>}
|
||||
<ListItem title={_t.textLink} link={'/add-link/'}>
|
||||
<Icon slot="media" icon="icon-link"></Icon>
|
||||
</ListItem>
|
||||
|
|
|
@ -9,7 +9,8 @@ import SpreadsheetInfoController from '../../controller/settings/SpreadsheetInfo
|
|||
import {DownloadWithTranslation} from '../../controller/settings/Download.jsx';
|
||||
import {SpreadsheetColorSchemes, SpreadsheetFormats, SpreadsheetMargins} from './SpreadsheetSettings.jsx';
|
||||
import {MacrosSettings, RegionalSettings, FormulaLanguage} from './ApplicationSettings.jsx';
|
||||
import SpreadsheetAbout from './SpreadsheetAbout.jsx';
|
||||
// import SpreadsheetAbout from './SpreadsheetAbout.jsx';
|
||||
import About from '../../../../../common/mobile/lib/view/About';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
|
@ -57,8 +58,8 @@ const routes = [
|
|||
component: SpreadsheetInfoController
|
||||
},
|
||||
{
|
||||
path: '/spreadsheet-about/',
|
||||
component: SpreadsheetAbout
|
||||
path: '/about/',
|
||||
component: About
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -138,7 +139,7 @@ const SettingsList = withTranslation()(props => {
|
|||
<ListItem title={_t.textHelp} link="#" onClick={showHelp}>
|
||||
<Icon slot="media" icon="icon-help"></Icon>
|
||||
</ListItem>
|
||||
<ListItem title={_t.textAbout} link="#" onClick={onoptionclick.bind(this, "/spreadsheet-about/")}>
|
||||
<ListItem title={_t.textAbout} link="#" onClick={onoptionclick.bind(this, "/about/")}>
|
||||
<Icon slot="media" icon="icon-about"></Icon>
|
||||
</ListItem>
|
||||
</List>
|
||||
|
|
16
vendor/framework7-react/build/webpack.config.js
vendored
16
vendor/framework7-react/build/webpack.config.js
vendored
|
@ -4,9 +4,10 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const WorkboxPlugin = require('workbox-webpack-plugin');
|
||||
const fs = require('fs')
|
||||
|
||||
const path = require('path');
|
||||
|
||||
|
@ -18,6 +19,7 @@ const env = process.env.NODE_ENV || 'development';
|
|||
const target = process.env.TARGET || 'web';
|
||||
const editor = process.env.TARGET_EDITOR == 'cell' ? 'spreadsheeteditor' :
|
||||
process.env.TARGET_EDITOR == 'slide' ? 'presentationeditor' : 'documenteditor';
|
||||
const targetPatch = process.env.TARGET_EDITOR || 'word';
|
||||
|
||||
module.exports = {
|
||||
mode: env,
|
||||
|
@ -53,6 +55,7 @@ module.exports = {
|
|||
minimizer: [new TerserPlugin({
|
||||
sourceMap: true,
|
||||
})],
|
||||
moduleIds: 'named',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
|
@ -163,8 +166,8 @@ module.exports = {
|
|||
}),
|
||||
|
||||
...(env === 'production' ? [
|
||||
new OptimizeCSSPlugin({
|
||||
cssProcessorOptions: {
|
||||
new CssMinimizerPlugin({
|
||||
processorOptions: {
|
||||
safe: true,
|
||||
map: { inline: false },
|
||||
},
|
||||
|
@ -173,7 +176,7 @@ module.exports = {
|
|||
] : [
|
||||
// Development only plugins
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NamedModulesPlugin(),
|
||||
// new webpack.NamedModulesPlugin(),
|
||||
]),
|
||||
// new CleanWebpackPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
|
@ -206,5 +209,10 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
}),
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
/\.{2}\/lib\/patch/,
|
||||
resource => fs.existsSync(`../../../web-apps-mobile/${targetPatch}/patch.jsx`) ?
|
||||
resource.request = `../../../../../../web-apps-mobile/${targetPatch}/patch.jsx` : resource
|
||||
),
|
||||
],
|
||||
};
|
15
vendor/framework7-react/package.json
vendored
15
vendor/framework7-react/package.json
vendored
|
@ -53,27 +53,24 @@
|
|||
"cpy-cli": "^3.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^4.3.0",
|
||||
"css-minimizer-webpack-plugin": "^1.3.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^4.5.1",
|
||||
"html-webpack-plugin": "^5.3.1",
|
||||
"less": "^3.13.1",
|
||||
"less-loader": "^6.2.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"mini-css-extract-plugin": "^1.3.9",
|
||||
"mobx": "^6.1.8",
|
||||
"mobx-react": "^7.1.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"ora": "^4.1.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"react-redux": "^7.2.2",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"style-loader": "^1.3.0",
|
||||
"terser-webpack-plugin": "^3.1.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack": "^5.26.3",
|
||||
"webpack-cli": "^4.5.0",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"workbox-webpack-plugin": "^5.1.4"
|
||||
"workbox-webpack-plugin": "^6.1.2"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue